Initial commit
[xorg_rtime.git] / xorg-server-1.4 / composite / compext.c
blob944f8d8440409e5821ab3429aef2fef186feea76
1 /*
2 * Copyright © 2006 Sun Microsystems
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Sun Microsystems not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission. Sun Microsystems makes no
11 * representations about the suitability of this software for any purpose. It
12 * is provided "as is" without express or implied warranty.
14 * SUN MICROSYSTEMS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL SUN MICROSYSTEMS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
22 * Copyright © 2003 Keith Packard
24 * Permission to use, copy, modify, distribute, and sell this software and its
25 * documentation for any purpose is hereby granted without fee, provided that
26 * the above copyright notice appear in all copies and that both that
27 * copyright notice and this permission notice appear in supporting
28 * documentation, and that the name of Keith Packard not be used in
29 * advertising or publicity pertaining to distribution of the software without
30 * specific, written prior permission. Keith Packard makes no
31 * representations about the suitability of this software for any purpose. It
32 * is provided "as is" without express or implied warranty.
34 * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
35 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
36 * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
37 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
38 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
39 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
40 * PERFORMANCE OF THIS SOFTWARE.
43 #ifdef HAVE_DIX_CONFIG_H
44 #include <dix-config.h>
45 #endif
47 #include "compint.h"
49 #define SERVER_COMPOSITE_MAJOR 0
50 #define SERVER_COMPOSITE_MINOR 4
52 static CARD8 CompositeReqCode;
53 static int CompositeClientPrivateIndex;
54 RESTYPE CompositeClientWindowType;
55 RESTYPE CompositeClientSubwindowsType;
56 static RESTYPE CompositeClientOverlayType;
58 static void deleteCompOverlayClient (CompOverlayClientPtr pOcToDel,
59 ScreenPtr pScreen);
61 typedef struct _CompositeClient {
62 int major_version;
63 int minor_version;
64 } CompositeClientRec, *CompositeClientPtr;
66 #define GetCompositeClient(pClient) ((CompositeClientPtr) (pClient)->devPrivates[CompositeClientPrivateIndex].ptr)
68 static void
69 CompositeClientCallback (CallbackListPtr *list,
70 pointer closure,
71 pointer data)
73 NewClientInfoRec *clientinfo = (NewClientInfoRec *) data;
74 ClientPtr pClient = clientinfo->client;
75 CompositeClientPtr pCompositeClient = GetCompositeClient (pClient);
77 pCompositeClient->major_version = 0;
78 pCompositeClient->minor_version = 0;
81 static void
82 CompositeResetProc (ExtensionEntry *extEntry)
86 static int
87 FreeCompositeClientWindow (pointer value, XID ccwid)
89 WindowPtr pWin = value;
91 compFreeClientWindow (pWin, ccwid);
92 return Success;
95 static int
96 FreeCompositeClientSubwindows (pointer value, XID ccwid)
98 WindowPtr pWin = value;
100 compFreeClientSubwindows (pWin, ccwid);
101 return Success;
104 static int
105 FreeCompositeClientOverlay (pointer value, XID ccwid)
107 CompOverlayClientPtr pOc = (CompOverlayClientPtr) value;
108 ScreenPtr pScreen = pOc->pScreen;
109 CompScreenPtr cs;
111 deleteCompOverlayClient(pOc, pScreen);
113 /* Unmap overlay window when there are no more clients using it */
114 cs = GetCompScreen(pScreen);
115 if (cs->pOverlayClients == NULL) {
116 if (cs->pOverlayWin != NULL) {
117 UnmapWindow(cs->pOverlayWin, FALSE);
121 return Success;
124 static int
125 ProcCompositeQueryVersion (ClientPtr client)
127 CompositeClientPtr pCompositeClient = GetCompositeClient (client);
128 xCompositeQueryVersionReply rep;
129 register int n;
130 REQUEST(xCompositeQueryVersionReq);
132 REQUEST_SIZE_MATCH(xCompositeQueryVersionReq);
133 rep.type = X_Reply;
134 rep.length = 0;
135 rep.sequenceNumber = client->sequence;
136 if (stuff->majorVersion < SERVER_COMPOSITE_MAJOR) {
137 rep.majorVersion = stuff->majorVersion;
138 rep.minorVersion = stuff->minorVersion;
139 } else {
140 rep.majorVersion = SERVER_COMPOSITE_MAJOR;
141 rep.minorVersion = SERVER_COMPOSITE_MINOR;
143 pCompositeClient->major_version = rep.majorVersion;
144 pCompositeClient->minor_version = rep.minorVersion;
145 if (client->swapped) {
146 swaps(&rep.sequenceNumber, n);
147 swapl(&rep.length, n);
148 swapl(&rep.majorVersion, n);
149 swapl(&rep.minorVersion, n);
151 WriteToClient(client, sizeof(xCompositeQueryVersionReply), (char *)&rep);
152 return(client->noClientException);
155 static int
156 ProcCompositeRedirectWindow (ClientPtr client)
158 WindowPtr pWin;
159 REQUEST(xCompositeRedirectWindowReq);
161 REQUEST_SIZE_MATCH(xCompositeRedirectWindowReq);
162 pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW);
163 if (!pWin)
165 client->errorValue = stuff->window;
166 return BadWindow;
168 return compRedirectWindow (client, pWin, stuff->update);
171 static int
172 ProcCompositeRedirectSubwindows (ClientPtr client)
174 WindowPtr pWin;
175 REQUEST(xCompositeRedirectSubwindowsReq);
177 REQUEST_SIZE_MATCH(xCompositeRedirectSubwindowsReq);
178 pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW);
179 if (!pWin)
181 client->errorValue = stuff->window;
182 return BadWindow;
184 return compRedirectSubwindows (client, pWin, stuff->update);
187 static int
188 ProcCompositeUnredirectWindow (ClientPtr client)
190 WindowPtr pWin;
191 REQUEST(xCompositeUnredirectWindowReq);
193 REQUEST_SIZE_MATCH(xCompositeUnredirectWindowReq);
194 pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW);
195 if (!pWin)
197 client->errorValue = stuff->window;
198 return BadWindow;
200 return compUnredirectWindow (client, pWin, stuff->update);
203 static int
204 ProcCompositeUnredirectSubwindows (ClientPtr client)
206 WindowPtr pWin;
207 REQUEST(xCompositeUnredirectSubwindowsReq);
209 REQUEST_SIZE_MATCH(xCompositeUnredirectSubwindowsReq);
210 pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW);
211 if (!pWin)
213 client->errorValue = stuff->window;
214 return BadWindow;
216 return compUnredirectSubwindows (client, pWin, stuff->update);
219 static int
220 ProcCompositeCreateRegionFromBorderClip (ClientPtr client)
222 WindowPtr pWin;
223 CompWindowPtr cw;
224 RegionPtr pBorderClip, pRegion;
225 REQUEST(xCompositeCreateRegionFromBorderClipReq);
227 REQUEST_SIZE_MATCH(xCompositeCreateRegionFromBorderClipReq);
228 pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW);
229 if (!pWin)
231 client->errorValue = stuff->window;
232 return BadWindow;
235 LEGAL_NEW_RESOURCE (stuff->region, client);
237 cw = GetCompWindow (pWin);
238 if (cw)
239 pBorderClip = &cw->borderClip;
240 else
241 pBorderClip = &pWin->borderClip;
242 pRegion = XFixesRegionCopy (pBorderClip);
243 if (!pRegion)
244 return BadAlloc;
245 REGION_TRANSLATE (pScreen, pRegion, -pWin->drawable.x, -pWin->drawable.y);
247 if (!AddResource (stuff->region, RegionResType, (pointer) pRegion))
248 return BadAlloc;
250 return(client->noClientException);
253 static int
254 ProcCompositeNameWindowPixmap (ClientPtr client)
256 WindowPtr pWin;
257 CompWindowPtr cw;
258 PixmapPtr pPixmap;
259 REQUEST(xCompositeNameWindowPixmapReq);
261 REQUEST_SIZE_MATCH(xCompositeNameWindowPixmapReq);
262 pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW);
263 if (!pWin)
265 client->errorValue = stuff->window;
266 return BadWindow;
269 if (!pWin->viewable)
270 return BadMatch;
272 LEGAL_NEW_RESOURCE (stuff->pixmap, client);
274 cw = GetCompWindow (pWin);
275 if (!cw)
276 return BadMatch;
278 pPixmap = (*pWin->drawable.pScreen->GetWindowPixmap) (pWin);
279 if (!pPixmap)
280 return BadMatch;
282 ++pPixmap->refcnt;
284 if (!AddResource (stuff->pixmap, RT_PIXMAP, (pointer) pPixmap))
285 return BadAlloc;
287 return(client->noClientException);
292 * Routines for manipulating the per-screen overlay clients list.
293 * This list indicates which clients have called GetOverlayWindow
294 * for this screen.
297 /* Return the screen's overlay client list element for the given client */
298 static CompOverlayClientPtr
299 findCompOverlayClient (ClientPtr pClient, ScreenPtr pScreen)
301 CompScreenPtr cs = GetCompScreen(pScreen);
302 CompOverlayClientPtr pOc;
304 for (pOc = cs->pOverlayClients; pOc != NULL; pOc = pOc->pNext) {
305 if (pOc->pClient == pClient) {
306 return pOc;
310 return NULL;
313 static int
314 createCompOverlayClient (ClientPtr pClient, ScreenPtr pScreen)
316 CompScreenPtr cs = GetCompScreen(pScreen);
317 CompOverlayClientPtr pOc;
319 pOc = (CompOverlayClientPtr) xalloc(sizeof(CompOverlayClientRec));
320 if (pOc == NULL) {
321 return BadAlloc;
323 pOc->pClient = pClient;
324 pOc->pScreen = pScreen;
325 pOc->resource = FakeClientID(pClient->index);
326 pOc->pNext = cs->pOverlayClients;
327 cs->pOverlayClients = pOc;
330 * Create a resource for this element so it can be deleted
331 * when the client goes away.
333 if (!AddResource (pOc->resource, CompositeClientOverlayType,
334 (pointer) pOc)) {
335 xfree(pOc);
336 return BadAlloc;
339 return Success;
343 * Delete the given overlay client list element from its screen list.
345 static void
346 deleteCompOverlayClient (CompOverlayClientPtr pOcToDel, ScreenPtr pScreen)
348 CompScreenPtr cs = GetCompScreen(pScreen);
349 CompOverlayClientPtr pOc, pNext;
350 CompOverlayClientPtr pOcLast = NULL;
352 pOc = cs->pOverlayClients;
353 while (pOc != NULL) {
354 pNext = pOc->pNext;
355 if (pOc == pOcToDel) {
356 xfree(pOc);
357 if (pOcLast == NULL) {
358 cs->pOverlayClients = pNext;
359 } else {
360 pOcLast->pNext = pNext;
362 break;
364 pOcLast = pOc;
365 pOc = pNext;
370 * Delete all the hide-counts list elements for this screen.
372 void
373 deleteCompOverlayClientsForScreen (ScreenPtr pScreen)
375 CompScreenPtr cs = GetCompScreen(pScreen);
376 CompOverlayClientPtr pOc, pTmp;
378 pOc = cs->pOverlayClients;
379 while (pOc != NULL) {
380 pTmp = pOc->pNext;
381 FreeResource(pOc->resource, 0);
382 pOc = pTmp;
384 cs->pOverlayClients = NULL;
388 ** If necessary, create the overlay window. And map it
389 ** Note: I found it excessively difficult to destroy this window
390 ** during compCloseScreen; DeleteWindow can't be called because
391 ** the input devices are already shut down. So we are going to
392 ** just allocate an overlay window once per screen per X server
393 ** invocation.
396 static WindowPtr
397 createOverlayWindow (ScreenPtr pScreen)
399 int wid = FakeClientID(0);
400 WindowPtr pWin;
401 XID overrideRedirect = TRUE;
402 int result;
404 pWin = CreateWindow (
405 wid, WindowTable[pScreen->myNum],
406 0, 0, pScreen->width, pScreen->height, 0,
407 InputOutput, CWOverrideRedirect, &overrideRedirect,
408 WindowTable[pScreen->myNum]->drawable.depth,
409 serverClient, pScreen->rootVisual, &result);
410 if (pWin == NULL) {
411 return NULL;
414 if (!AddResource(wid, RT_WINDOW, (pointer)pWin)) {
415 DeleteWindow(pWin, None);
416 return NULL;
419 return pWin;
422 static int
423 ProcCompositeGetOverlayWindow (ClientPtr client)
425 REQUEST(xCompositeGetOverlayWindowReq);
426 xCompositeGetOverlayWindowReply rep;
427 WindowPtr pWin;
428 ScreenPtr pScreen;
429 CompScreenPtr cs;
430 CompOverlayClientPtr pOc;
432 REQUEST_SIZE_MATCH(xCompositeGetOverlayWindowReq);
433 pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW);
434 if (!pWin)
436 client->errorValue = stuff->window;
437 return BadWindow;
439 pScreen = pWin->drawable.pScreen;
441 cs = GetCompScreen(pScreen);
442 if (cs->pOverlayWin == NULL) {
443 cs->pOverlayWin = createOverlayWindow(pScreen);
444 if (cs->pOverlayWin == NULL) {
445 return BadAlloc;
448 MapWindow(cs->pOverlayWin, serverClient);
450 /* Record that client is using this overlay window */
451 pOc = findCompOverlayClient(client, pScreen);
452 if (pOc == NULL) {
453 int ret = createCompOverlayClient(client, pScreen);
454 if (ret != Success) {
455 return ret;
459 rep.type = X_Reply;
460 rep.sequenceNumber = client->sequence;
461 rep.length = 0;
462 rep.overlayWin = cs->pOverlayWin->drawable.id;
464 if (client->swapped)
466 int n;
467 swaps(&rep.sequenceNumber, n);
468 swapl(&rep.length, n);
469 swapl(&rep.overlayWin, n);
471 (void) WriteToClient(client, sz_xCompositeGetOverlayWindowReply, (char *)&rep);
473 return client->noClientException;
476 static int
477 ProcCompositeReleaseOverlayWindow (ClientPtr client)
479 REQUEST(xCompositeReleaseOverlayWindowReq);
480 WindowPtr pWin;
481 ScreenPtr pScreen;
482 CompOverlayClientPtr pOc;
483 CompScreenPtr cs;
485 REQUEST_SIZE_MATCH(xCompositeReleaseOverlayWindowReq);
486 pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW);
487 if (!pWin)
489 client->errorValue = stuff->window;
490 return BadWindow;
492 pScreen = pWin->drawable.pScreen;
495 * Has client queried a reference to the overlay window
496 * on this screen? If not, generate an error.
498 pOc = findCompOverlayClient(client, pWin->drawable.pScreen);
499 if (pOc == NULL) {
500 return BadMatch;
503 /* The delete function will free the client structure */
504 FreeResource (pOc->resource, 0);
506 cs = GetCompScreen(pScreen);
507 if (cs->pOverlayClients == NULL) {
508 UnmapWindow(cs->pOverlayWin, FALSE);
511 return client->noClientException;
514 static int (*ProcCompositeVector[CompositeNumberRequests])(ClientPtr) = {
515 ProcCompositeQueryVersion,
516 ProcCompositeRedirectWindow,
517 ProcCompositeRedirectSubwindows,
518 ProcCompositeUnredirectWindow,
519 ProcCompositeUnredirectSubwindows,
520 ProcCompositeCreateRegionFromBorderClip,
521 ProcCompositeNameWindowPixmap,
522 ProcCompositeGetOverlayWindow,
523 ProcCompositeReleaseOverlayWindow,
526 static int
527 ProcCompositeDispatch (ClientPtr client)
529 REQUEST(xReq);
531 if (stuff->data < CompositeNumberRequests)
532 return (*ProcCompositeVector[stuff->data]) (client);
533 else
534 return BadRequest;
537 static int
538 SProcCompositeQueryVersion (ClientPtr client)
540 int n;
541 REQUEST(xCompositeQueryVersionReq);
543 swaps(&stuff->length, n);
544 REQUEST_SIZE_MATCH(xCompositeQueryVersionReq);
545 swapl(&stuff->majorVersion, n);
546 swapl(&stuff->minorVersion, n);
547 return (*ProcCompositeVector[stuff->compositeReqType]) (client);
550 static int
551 SProcCompositeRedirectWindow (ClientPtr client)
553 int n;
554 REQUEST(xCompositeRedirectWindowReq);
556 swaps(&stuff->length, n);
557 REQUEST_SIZE_MATCH(xCompositeRedirectWindowReq);
558 swapl (&stuff->window, n);
559 return (*ProcCompositeVector[stuff->compositeReqType]) (client);
562 static int
563 SProcCompositeRedirectSubwindows (ClientPtr client)
565 int n;
566 REQUEST(xCompositeRedirectSubwindowsReq);
568 swaps(&stuff->length, n);
569 REQUEST_SIZE_MATCH(xCompositeRedirectSubwindowsReq);
570 swapl (&stuff->window, n);
571 return (*ProcCompositeVector[stuff->compositeReqType]) (client);
574 static int
575 SProcCompositeUnredirectWindow (ClientPtr client)
577 int n;
578 REQUEST(xCompositeUnredirectWindowReq);
580 swaps(&stuff->length, n);
581 REQUEST_SIZE_MATCH(xCompositeUnredirectWindowReq);
582 swapl (&stuff->window, n);
583 return (*ProcCompositeVector[stuff->compositeReqType]) (client);
586 static int
587 SProcCompositeUnredirectSubwindows (ClientPtr client)
589 int n;
590 REQUEST(xCompositeUnredirectSubwindowsReq);
592 swaps(&stuff->length, n);
593 REQUEST_SIZE_MATCH(xCompositeUnredirectSubwindowsReq);
594 swapl (&stuff->window, n);
595 return (*ProcCompositeVector[stuff->compositeReqType]) (client);
598 static int
599 SProcCompositeCreateRegionFromBorderClip (ClientPtr client)
601 int n;
602 REQUEST(xCompositeCreateRegionFromBorderClipReq);
604 swaps(&stuff->length, n);
605 REQUEST_SIZE_MATCH(xCompositeCreateRegionFromBorderClipReq);
606 swapl (&stuff->region, n);
607 swapl (&stuff->window, n);
608 return (*ProcCompositeVector[stuff->compositeReqType]) (client);
611 static int
612 SProcCompositeNameWindowPixmap (ClientPtr client)
614 int n;
615 REQUEST(xCompositeNameWindowPixmapReq);
617 swaps(&stuff->length, n);
618 REQUEST_SIZE_MATCH(xCompositeNameWindowPixmapReq);
619 swapl (&stuff->window, n);
620 swapl (&stuff->pixmap, n);
621 return (*ProcCompositeVector[stuff->compositeReqType]) (client);
624 static int
625 SProcCompositeGetOverlayWindow (ClientPtr client)
627 int n;
628 REQUEST(xCompositeGetOverlayWindowReq);
630 swaps (&stuff->length, n);
631 REQUEST_SIZE_MATCH(xCompositeGetOverlayWindowReq);
632 swapl(&stuff->window, n);
633 return (*ProcCompositeVector[stuff->compositeReqType]) (client);
636 static int
637 SProcCompositeReleaseOverlayWindow (ClientPtr client)
639 int n;
640 REQUEST(xCompositeReleaseOverlayWindowReq);
642 swaps (&stuff->length, n);
643 REQUEST_SIZE_MATCH(xCompositeReleaseOverlayWindowReq);
644 swapl(&stuff->window, n);
645 return (*ProcCompositeVector[stuff->compositeReqType]) (client);
648 static int (*SProcCompositeVector[CompositeNumberRequests])(ClientPtr) = {
649 SProcCompositeQueryVersion,
650 SProcCompositeRedirectWindow,
651 SProcCompositeRedirectSubwindows,
652 SProcCompositeUnredirectWindow,
653 SProcCompositeUnredirectSubwindows,
654 SProcCompositeCreateRegionFromBorderClip,
655 SProcCompositeNameWindowPixmap,
656 SProcCompositeGetOverlayWindow,
657 SProcCompositeReleaseOverlayWindow,
660 static int
661 SProcCompositeDispatch (ClientPtr client)
663 REQUEST(xReq);
665 if (stuff->data < CompositeNumberRequests)
666 return (*SProcCompositeVector[stuff->data]) (client);
667 else
668 return BadRequest;
671 void
672 CompositeExtensionInit (void)
674 ExtensionEntry *extEntry;
675 int s;
677 for (s = 0; s < screenInfo.numScreens; s++) {
678 ScreenPtr pScreen = screenInfo.screens[s];
679 VisualPtr vis;
681 /* Composite on 8bpp pseudocolor root windows appears to fail, so
682 * just disable it on anything pseudocolor for safety.
684 for (vis = pScreen->visuals; vis->vid != pScreen->rootVisual; vis++)
686 if ((vis->class | DynamicClass) == PseudoColor)
687 return;
689 /* Ensure that Render is initialized, which is required for automatic
690 * compositing.
692 if (GetPictureScreenIfSet(pScreen) == NULL)
693 return;
695 #ifdef PANORAMIX
696 /* Xinerama's rewriting of window drawing before Composite gets to it
697 * breaks Composite.
699 if (!noPanoramiXExtension)
700 return;
701 #endif
703 CompositeClientWindowType = CreateNewResourceType (FreeCompositeClientWindow);
704 if (!CompositeClientWindowType)
705 return;
707 CompositeClientSubwindowsType = CreateNewResourceType (FreeCompositeClientSubwindows);
708 if (!CompositeClientSubwindowsType)
709 return;
711 CompositeClientOverlayType = CreateNewResourceType (FreeCompositeClientOverlay);
712 if (!CompositeClientOverlayType)
713 return;
715 CompositeClientPrivateIndex = AllocateClientPrivateIndex ();
716 if (!AllocateClientPrivate (CompositeClientPrivateIndex,
717 sizeof (CompositeClientRec)))
718 return;
719 if (!AddCallback (&ClientStateCallback, CompositeClientCallback, 0))
720 return;
722 extEntry = AddExtension (COMPOSITE_NAME, 0, 0,
723 ProcCompositeDispatch, SProcCompositeDispatch,
724 CompositeResetProc, StandardMinorOpcode);
725 if (!extEntry)
726 return;
727 CompositeReqCode = (CARD8) extEntry->base;
729 for (s = 0; s < screenInfo.numScreens; s++)
730 if (!compScreenInit (screenInfo.screens[s]))
731 return;
732 miRegisterRedirectBorderClipProc (compSetRedirectBorderClip,
733 compGetRedirectBorderClip);