diff options
author | Mike Gabriel <mike.gabriel@das-netzwerkteam.de> | 2016-05-31 12:09:23 +0200 |
---|---|---|
committer | Mike Gabriel <mike.gabriel@das-netzwerkteam.de> | 2016-05-31 12:09:23 +0200 |
commit | 4a9c1b9465f189a1477b1ecce7cdfacfd266cd65 (patch) | |
tree | 4688606f66a7e3a79944bd23299dddda06c2a219 /nx-X11/programs/Xserver | |
parent | aba2a534f630f5b65a53e0ea7cdba17b77263f87 (diff) | |
parent | cad9f4ef87ddf4e2865783ce7ea7e772d7b196b7 (diff) | |
download | nx-libs-4a9c1b9465f189a1477b1ecce7cdfacfd266cd65.tar.gz nx-libs-4a9c1b9465f189a1477b1ecce7cdfacfd266cd65.tar.bz2 nx-libs-4a9c1b9465f189a1477b1ecce7cdfacfd266cd65.zip |
Merge branch 'Ionic-feature/composite-update' into 3.6.x
Diffstat (limited to 'nx-X11/programs/Xserver')
-rw-r--r-- | nx-X11/programs/Xserver/composite/Imakefile | 6 | ||||
-rw-r--r-- | nx-X11/programs/Xserver/composite/compalloc.c | 295 | ||||
-rw-r--r-- | nx-X11/programs/Xserver/composite/compext.c | 741 | ||||
-rw-r--r-- | nx-X11/programs/Xserver/composite/compinit.c | 466 | ||||
-rw-r--r-- | nx-X11/programs/Xserver/composite/compint.h | 156 | ||||
-rw-r--r-- | nx-X11/programs/Xserver/composite/compositeext.h | 44 | ||||
-rw-r--r-- | nx-X11/programs/Xserver/composite/compoverlay.c | 178 | ||||
-rw-r--r-- | nx-X11/programs/Xserver/composite/compwindow.c | 316 | ||||
-rw-r--r-- | nx-X11/programs/Xserver/dix/colormap.c | 77 | ||||
-rw-r--r-- | nx-X11/programs/Xserver/dix/window.c | 12 | ||||
-rw-r--r-- | nx-X11/programs/Xserver/hw/nxagent/NXcompositeext.h | 8 | ||||
-rw-r--r-- | nx-X11/programs/Xserver/hw/nxagent/NXpicture.c | 98 | ||||
-rw-r--r-- | nx-X11/programs/Xserver/hw/nxagent/NXwindow.c | 8 | ||||
-rw-r--r-- | nx-X11/programs/Xserver/include/colormap.h | 4 | ||||
-rw-r--r-- | nx-X11/programs/Xserver/include/window.h | 4 | ||||
-rw-r--r-- | nx-X11/programs/Xserver/include/windowstr.h | 29 | ||||
-rw-r--r-- | nx-X11/programs/Xserver/render/picture.c | 98 |
17 files changed, 2147 insertions, 393 deletions
diff --git a/nx-X11/programs/Xserver/composite/Imakefile b/nx-X11/programs/Xserver/composite/Imakefile index f121e0bbe..911950182 100644 --- a/nx-X11/programs/Xserver/composite/Imakefile +++ b/nx-X11/programs/Xserver/composite/Imakefile @@ -1,8 +1,8 @@ #include <Server.tmpl> - SRCS = compalloc.c compext.c compinit.c compwindow.c + SRCS = compalloc.c compext.c compinit.c compoverlay.c compwindow.c - OBJS = compalloc.o compext.o compinit.o compwindow.o + OBJS = compalloc.o compext.o compinit.o compoverlay.o compwindow.o INCLUDES = -I../include -I../mi -I../Xext -I../render -I../xfixes \ -I../damageext -I../miext/damage -I$(EXTINCSRC) \ @@ -11,6 +11,8 @@ LINTLIBS = ../dix/llib-ldix.ln ../os/llib-los.ln + DEFINES = -DNXAGENT_SERVER + NormalLibraryTarget(composite,$(OBJS)) NormalLibraryObjectRule() LintLibraryTarget(composite,$(SRCS)) diff --git a/nx-X11/programs/Xserver/composite/compalloc.c b/nx-X11/programs/Xserver/composite/compalloc.c index f66a90989..9279a5248 100644 --- a/nx-X11/programs/Xserver/composite/compalloc.c +++ b/nx-X11/programs/Xserver/composite/compalloc.c @@ -28,36 +28,110 @@ #include "compint.h" -void -compReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure) +static void +compScreenUpdate(ScreenPtr pScreen) { - WindowPtr pWin = (WindowPtr) closure; - ScreenPtr pScreen = pWin->drawable.pScreen; - CompScreenPtr cs = GetCompScreen (pScreen); - CompWindowPtr cw = GetCompWindow (pWin); + compCheckTree(pScreen); + compPaintChildrenToWindow(pScreen, WindowTable[pScreen->myNum]); +} + +static void +compBlockHandler(int i, void *blockData, void *pTimeout, void *pReadmask) +{ + ScreenPtr pScreen = screenInfo.screens[i]; + CompScreenPtr cs = GetCompScreen(pScreen); + pScreen->BlockHandler = cs->BlockHandler; + compScreenUpdate(pScreen); + (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask); + + /* Next damage will restore the block handler */ + cs->BlockHandler = NULL; +} + +static void +compReportDamage(DamagePtr pDamage, RegionPtr pRegion, void *closure) +{ + WindowPtr pWin = (WindowPtr) closure; + ScreenPtr pScreen = pWin->drawable.pScreen; + CompScreenPtr cs = GetCompScreen(pScreen); + CompWindowPtr cw = GetCompWindow(pWin); + + if (!cs->BlockHandler) { + cs->BlockHandler = pScreen->BlockHandler; + pScreen->BlockHandler = compBlockHandler; + } cs->damaged = TRUE; cw->damaged = TRUE; + + /* Mark the ancestors */ + /* We can't do this, Dave. No damagedDescendants support. */ + /* + pWin = pWin->parent; + while (pWin) { + if (pWin->damagedDescendants) + break; + pWin->damagedDescendants = TRUE; + pWin = pWin->parent; + } + */ } static void -compDestroyDamage (DamagePtr pDamage, void *closure) +compDestroyDamage(DamagePtr pDamage, void *closure) { - WindowPtr pWin = (WindowPtr) closure; - CompWindowPtr cw = GetCompWindow (pWin); + WindowPtr pWin = (WindowPtr) closure; + CompWindowPtr cw = GetCompWindow(pWin); cw->damage = 0; } +static Bool +compMarkWindows(WindowPtr pWin, WindowPtr *ppLayerWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + WindowPtr pLayerWin = pWin; + + if (!pWin->viewable) + return FALSE; + + (*pScreen->MarkOverlappedWindows) (pWin, pWin, &pLayerWin); + (*pScreen->MarkWindow) (pLayerWin->parent); + + *ppLayerWin = pLayerWin; + + return TRUE; +} + +static void +compHandleMarkedWindows(WindowPtr pWin, WindowPtr pLayerWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + + (*pScreen->ValidateTree) (pLayerWin->parent, pLayerWin, VTOther); + (*pScreen->HandleExposures) (pLayerWin->parent); + if (pScreen->PostValidateTree) + (*pScreen->PostValidateTree) (pLayerWin->parent, pLayerWin, VTOther); +} + /* * Redirect one window for one client */ int -compRedirectWindow (ClientPtr pClient, WindowPtr pWin, int update) +compRedirectWindow(ClientPtr pClient, WindowPtr pWin, int update) { - CompWindowPtr cw = GetCompWindow (pWin); - CompClientWindowPtr ccw; - Bool wasMapped = pWin->mapped; + CompWindowPtr cw = GetCompWindow(pWin); + CompClientWindowPtr ccw; + CompScreenPtr cs = GetCompScreen(pWin->drawable.pScreen); + WindowPtr pLayerWin; + Bool anyMarked = FALSE; + + if (pWin == cs->pOverlayWin) { + return Success; + } + + if (!pWin->parent) + return BadMatch; /* * Only one Manual update is allowed @@ -100,8 +174,8 @@ compRedirectWindow (ClientPtr pClient, WindowPtr pWin, int update) xfree (cw); return BadAlloc; } - if (wasMapped) - UnmapWindow (pWin, FALSE); + + anyMarked = compMarkWindows(pWin, &pLayerWin); RegionNull(&cw->borderClip); cw->update = CompositeRedirectAutomatic; @@ -110,7 +184,8 @@ compRedirectWindow (ClientPtr pClient, WindowPtr pWin, int update) cw->oldy = COMP_ORIGIN_INVALID; cw->damageRegistered = FALSE; cw->damaged = FALSE; - pWin->devPrivates[CompWindowPrivateIndex].ptr = cw; + cw->pOldPixmap = NullPixmap; + FAKE_DIX_SET_WINDOW_PRIVATE(pWin, cw); } ccw->next = cw->clients; cw->clients = ccw; @@ -118,30 +193,59 @@ compRedirectWindow (ClientPtr pClient, WindowPtr pWin, int update) return BadAlloc; if (ccw->update == CompositeRedirectManual) { - if (cw->damageRegistered) - { + if (!anyMarked) + anyMarked = compMarkWindows(pWin, &pLayerWin); + + if (cw->damageRegistered) { DamageUnregister (&pWin->drawable, cw->damage); cw->damageRegistered = FALSE; } cw->update = CompositeRedirectManual; } + else if (cw->update == CompositeRedirectAutomatic && !cw->damageRegistered) { + if (!anyMarked) + anyMarked = compMarkWindows(pWin, &pLayerWin); + } if (!compCheckRedirect (pWin)) { FreeResource (ccw->id, RT_NONE); return BadAlloc; } - if (wasMapped && !pWin->mapped) - { - Bool overrideRedirect = pWin->overrideRedirect; - pWin->overrideRedirect = TRUE; - MapWindow (pWin, pClient); - pWin->overrideRedirect = overrideRedirect; - } + + if (anyMarked) + compHandleMarkedWindows(pWin, pLayerWin); return Success; } +void +compRestoreWindow(WindowPtr pWin, PixmapPtr pPixmap) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + WindowPtr pParent = pWin->parent; + + if (pParent->drawable.depth == pWin->drawable.depth) { + GCPtr pGC = GetScratchGC(pWin->drawable.depth, pScreen); + int bw = (int) pWin->borderWidth; + int x = bw; + int y = bw; + int w = pWin->drawable.width; + int h = pWin->drawable.height; + + if (pGC) { + ChangeGCVal val; + + val.val = IncludeInferiors; + dixChangeGC(NullClient, pGC, GCSubwindowMode, NULL, &val); + ValidateGC(&pWin->drawable, pGC); + (*pGC->ops->CopyArea) (&pPixmap->drawable, + &pWin->drawable, pGC, x, y, w, h, 0, 0); + FreeScratchGC(pGC); + } + } +} + /* * Free one of the per-client per-window resources, clearing * redirect and the per-window pointer as appropriate @@ -149,9 +253,12 @@ compRedirectWindow (ClientPtr pClient, WindowPtr pWin, int update) void compFreeClientWindow (WindowPtr pWin, XID id) { + ScreenPtr pScreen = pWin->drawable.pScreen; CompWindowPtr cw = GetCompWindow (pWin); CompClientWindowPtr ccw, *prev; - Bool wasMapped = pWin->mapped; + Bool anyMarked = FALSE; + WindowPtr pLayerWin; + PixmapPtr pPixmap = NULL; if (!cw) return; @@ -168,33 +275,38 @@ compFreeClientWindow (WindowPtr pWin, XID id) } if (!cw->clients) { - if (wasMapped) - UnmapWindow (pWin, FALSE); - - if (pWin->redirectDraw) - compFreePixmap (pWin); + anyMarked = compMarkWindows(pWin, &pLayerWin); + + if (pWin->redirectDraw != RedirectDrawNone) { + pPixmap = (*pScreen->GetWindowPixmap) (pWin); + compSetParentPixmap(pWin); + } if (cw->damage) DamageDestroy (cw->damage); RegionUninit(&cw->borderClip); - pWin->devPrivates[CompWindowPrivateIndex].ptr = 0; + FAKE_DIX_SET_WINDOW_PRIVATE(pWin, NULL); xfree (cw); } else if (cw->update == CompositeRedirectAutomatic && - !cw->damageRegistered && pWin->redirectDraw) + !cw->damageRegistered && pWin->redirectDraw != RedirectDrawNone) { + anyMarked = compMarkWindows(pWin, &pLayerWin); + DamageRegister (&pWin->drawable, cw->damage); cw->damageRegistered = TRUE; + pWin->redirectDraw = RedirectDrawAutomatic; DamageDamageRegion (&pWin->drawable, &pWin->borderSize); } - if (wasMapped && !pWin->mapped) - { - Bool overrideRedirect = pWin->overrideRedirect; - pWin->overrideRedirect = TRUE; - MapWindow (pWin, clients[CLIENT_ID(id)]); - pWin->overrideRedirect = overrideRedirect; + + if (anyMarked) + compHandleMarkedWindows(pWin, pLayerWin); + + if (pPixmap) { + compRestoreWindow(pWin, pPixmap); + (*pScreen->DestroyPixmap) (pPixmap); } } @@ -261,7 +373,7 @@ compRedirectSubwindows (ClientPtr pClient, WindowPtr pWin, int update) } csw->update = CompositeRedirectAutomatic; csw->clients = 0; - pWin->devPrivates[CompSubwindowsPrivateIndex].ptr = csw; + FAKE_DIX_SET_SUBWINDOWS_PRIVATE(pWin, csw); } /* * Redirect all existing windows @@ -276,7 +388,7 @@ compRedirectSubwindows (ClientPtr pClient, WindowPtr pWin, int update) if (!csw->clients) { xfree (csw); - pWin->devPrivates[CompSubwindowsPrivateIndex].ptr = 0; + FAKE_DIX_SET_SUBWINDOWS_PRIVATE(pWin, NULL); } xfree (ccw); return ret; @@ -349,7 +461,7 @@ compFreeClientSubwindows (WindowPtr pWin, XID id) */ if (!csw->clients) { - pWin->devPrivates[CompSubwindowsPrivateIndex].ptr = 0; + FAKE_DIX_SET_SUBWINDOWS_PRIVATE(pWin, NULL); xfree (csw); } } @@ -425,9 +537,10 @@ compNewPixmap (WindowPtr pWin, int x, int y, int w, int h) ScreenPtr pScreen = pWin->drawable.pScreen; WindowPtr pParent = pWin->parent; PixmapPtr pPixmap; - GCPtr pGC; - pPixmap = (*pScreen->CreatePixmap) (pScreen, w, h, pWin->drawable.depth); + /* usage_hint unsupported by our old server infrastructure. */ + pPixmap = (*pScreen->CreatePixmap) (pScreen, w, h, pWin->drawable.depth /*, + CREATE_PIXMAP_USAGE_BACKING_PIXMAP */); if (!pPixmap) return 0; @@ -435,25 +548,60 @@ compNewPixmap (WindowPtr pWin, int x, int y, int w, int h) pPixmap->screen_x = x; pPixmap->screen_y = y; - pGC = GetScratchGC (pWin->drawable.depth, pScreen); + if (pParent->drawable.depth == pWin->drawable.depth) { + GCPtr pGC = GetScratchGC (pWin->drawable.depth, pScreen); - /* - * Copy bits from the parent into the new pixmap so that it will - * have "reasonable" contents in case for background None areas. - */ - if (pGC) - { - XID val = IncludeInferiors; - - ValidateGC(&pPixmap->drawable, pGC); - dixChangeGC (serverClient, pGC, GCSubwindowMode, &val, NULL); - (*pGC->ops->CopyArea) (&pParent->drawable, - &pPixmap->drawable, - pGC, - x - pParent->drawable.x, - y - pParent->drawable.y, - w, h, 0, 0); - FreeScratchGC (pGC); + /* + * Copy bits from the parent into the new pixmap so that it will + * have "reasonable" contents in case for background None areas. + */ + if (pGC) + { + ChangeGCVal val; + + val.val = IncludeInferiors; + dixChangeGC(NullClient, pGC, GCSubwindowMode, NULL, &val); + ValidateGC(&pPixmap->drawable, pGC); + (*pGC->ops->CopyArea) (&pParent->drawable, + &pPixmap->drawable, + pGC, + x - pParent->drawable.x, + y - pParent->drawable.y, + w, h, 0, 0); + FreeScratchGC (pGC); + } + } + else { + PictFormatPtr pSrcFormat = compWindowFormat (pParent); + PictFormatPtr pDstFormat = compWindowFormat (pWin); + XID inferiors = IncludeInferiors; + int error; + + PicturePtr pSrcPicture = CreatePicture(None, + &pParent->drawable, + pSrcFormat, + CPSubwindowMode, + &inferiors, + serverClient, &error); + + PicturePtr pDstPicture = CreatePicture(None, + &pPixmap->drawable, + pDstFormat, + 0, 0, + serverClient, &error); + + if (pSrcPicture && pDstPicture) { + CompositePicture(PictOpSrc, + pSrcPicture, + NULL, + pDstPicture, + x - pParent->drawable.x, + y - pParent->drawable.y, 0, 0, 0, 0, w, h); + } + if (pSrcPicture) + FreePicture(pSrcPicture, 0); + if (pDstPicture) + FreePicture(pDstPicture, 0); } return pPixmap; } @@ -471,7 +619,11 @@ compAllocPixmap (WindowPtr pWin) if (!pPixmap) return FALSE; - pWin->redirectDraw = TRUE; + if (cw->update == CompositeRedirectAutomatic) + pWin->redirectDraw = RedirectDrawAutomatic; + else + pWin->redirectDraw = RedirectDrawManual; + compSetPixmap (pWin, pPixmap); cw->oldx = COMP_ORIGIN_INVALID; cw->oldy = COMP_ORIGIN_INVALID; @@ -481,14 +633,21 @@ compAllocPixmap (WindowPtr pWin) DamageRegister (&pWin->drawable, cw->damage); cw->damageRegistered = TRUE; } + + /* Make sure our borderClip is up to date */ + RegionUninit(&cw->borderClip); + RegionCopy(&cw->borderClip, &pWin->borderClip); + cw->borderClipX = pWin->drawable.x; + cw->borderClipY = pWin->drawable.y; + return TRUE; } void -compFreePixmap (WindowPtr pWin) +compSetParentPixmap (WindowPtr pWin) { ScreenPtr pScreen = pWin->drawable.pScreen; - PixmapPtr pRedirectPixmap, pParentPixmap; + PixmapPtr pParentPixmap; CompWindowPtr cw = GetCompWindow (pWin); if (cw->damageRegistered) @@ -504,11 +663,9 @@ compFreePixmap (WindowPtr pWin) * parent exposed area; regions beyond the parent cause crashes */ RegionCopy(&pWin->borderClip, &cw->borderClip); - pRedirectPixmap = (*pScreen->GetWindowPixmap) (pWin); pParentPixmap = (*pScreen->GetWindowPixmap) (pWin->parent); - pWin->redirectDraw = FALSE; + pWin->redirectDraw = RedirectDrawNone; compSetPixmap (pWin, pParentPixmap); - (*pScreen->DestroyPixmap) (pRedirectPixmap); } /* @@ -527,7 +684,7 @@ compReallocPixmap (WindowPtr pWin, int draw_x, int draw_y, int pix_x, pix_y; int pix_w, pix_h; - assert (cw && pWin->redirectDraw); + assert (cw && pWin->redirectDraw != RedirectDrawNone); cw->oldx = pOld->screen_x; cw->oldy = pOld->screen_y; pix_x = draw_x - bw; diff --git a/nx-X11/programs/Xserver/composite/compext.c b/nx-X11/programs/Xserver/composite/compext.c index f57235d46..d5f8fd6d4 100644 --- a/nx-X11/programs/Xserver/composite/compext.c +++ b/nx-X11/programs/Xserver/composite/compext.c @@ -27,18 +27,44 @@ #endif #include "compint.h" +#include "XI.h" +#include "XIproto.h" +#include "extinit.h" + +#ifndef SERVER_COMPOSITE_MAJOR_VERSION +#define SERVER_COMPOSITE_MAJOR_VERSION 0 +#endif + +#ifndef SERVER_COMPOSITE_MINOR_VERSION +#define SERVER_COMPOSITE_MINOR_VERSION 4 +#endif static CARD8 CompositeReqCode; -int CompositeClientPrivateIndex; + +#ifndef NXAGENT_SERVER +static DevPrivateKeyRec CompositeClientPrivateKeyRec; + +#define CompositeClientPrivateKey (&CompositeClientPrivateKeyRec) +#else /* !defined(NXAGENT_SERVER) */ +static int CompositeClientPrivIndex = -1; +#endif /* !defined(NXAGENT_SERVER) */ + RESTYPE CompositeClientWindowType; RESTYPE CompositeClientSubwindowsType; +RESTYPE CompositeClientOverlayType; typedef struct _CompositeClient { int major_version; int minor_version; } CompositeClientRec, *CompositeClientPtr; -#define GetCompositeClient(pClient) ((CompositeClientPtr) (pClient)->devPrivates[CompositeClientPrivateIndex].ptr) +#ifndef NXAGENT_SERVER +#define GetCompositeClient(pClient) ((CompositeClientPtr) \ + dixLookupPrivate(&(pClient)->devPrivates, CompositeClientPrivateKey)) +#else /* !defined(NXAGENT_SERVER) */ +#define GetCompositeClient(pClient) ((CompositeClientPtr) \ + (pClient)->devPrivates[CompositeClientPrivIndex].ptr) +#endif /* !edefined(NXAGENT_SERVER) */ static void CompositeClientCallback (CallbackListPtr *list, @@ -57,22 +83,31 @@ static void CompositeResetProc (ExtensionEntry *extEntry) { } + +static int +FreeCompositeClientWindow(void *value, XID ccwid) +{ + WindowPtr pWin = value; + + compFreeClientWindow(pWin, ccwid); + return Success; +} static int -FreeCompositeClientWindow (void * value, XID ccwid) +FreeCompositeClientSubwindows(void *value, XID ccwid) { WindowPtr pWin = value; - compFreeClientWindow (pWin, ccwid); + compFreeClientSubwindows(pWin, ccwid); return Success; } static int -FreeCompositeClientSubwindows (void * value, XID ccwid) +FreeCompositeClientOverlay(void *value, XID ccwid) { - WindowPtr pWin = value; + CompOverlayClientPtr pOc = (CompOverlayClientPtr) value; - compFreeClientSubwindows (pWin, ccwid); + compFreeOverlayClient(pOc); return Success; } @@ -80,24 +115,22 @@ static int ProcCompositeQueryVersion (ClientPtr client) { CompositeClientPtr pCompositeClient = GetCompositeClient (client); - xCompositeQueryVersionReply rep; + xCompositeQueryVersionReply rep = { + .type = X_Reply, + .sequenceNumber = client->sequence, + .length = 0 + }; register int n; + REQUEST(xCompositeQueryVersionReq); REQUEST_SIZE_MATCH(xCompositeQueryVersionReq); - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - if (stuff->majorVersion < COMPOSITE_MAJOR) { + if (stuff->majorVersion < SERVER_COMPOSITE_MAJOR_VERSION) { rep.majorVersion = stuff->majorVersion; rep.minorVersion = stuff->minorVersion; } else { - rep.majorVersion = COMPOSITE_MAJOR; - if (stuff->majorVersion == COMPOSITE_MAJOR && - stuff->minorVersion < COMPOSITE_MINOR) - rep.minorVersion = stuff->minorVersion; - else - rep.minorVersion = COMPOSITE_MINOR; + rep.majorVersion = SERVER_COMPOSITE_MAJOR_VERSION; + rep.minorVersion = SERVER_COMPOSITE_MINOR_VERSION; } pCompositeClient->major_version = rep.majorVersion; pCompositeClient->minor_version = rep.minorVersion; @@ -108,9 +141,23 @@ ProcCompositeQueryVersion (ClientPtr client) swapl(&rep.minorVersion, n); } WriteToClient(client, sizeof(xCompositeQueryVersionReply), (char *)&rep); - return(client->noClientException); + return Success; } +/* Unsupported by current architecture and porting is too much effort. */ +#if 0 +#define VERIFY_WINDOW(pWindow, wid, client, mode) \ + do { \ + int err; \ + err = dixLookupResourceByType((void **) &pWindow, wid, \ + RT_WINDOW, client, mode); \ + if (err != Success) { \ + client->errorValue = wid; \ + return err; \ + } \ + } while (0) +#endif /* 0 */ + static int ProcCompositeRedirectWindow (ClientPtr client) { @@ -118,12 +165,18 @@ ProcCompositeRedirectWindow (ClientPtr client) REQUEST(xCompositeRedirectWindowReq); REQUEST_SIZE_MATCH(xCompositeRedirectWindowReq); + /* Unsupported by current architecture and porting is too much effort. */ + /* + VERIFY_WINDOW(pWin, stuff->window, client, + DixSetAttrAccess | DixManageAccess | DixBlendAccess); + */ pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW); if (!pWin) { client->errorValue = stuff->window; return BadWindow; } + return compRedirectWindow (client, pWin, stuff->update); } @@ -134,12 +187,18 @@ ProcCompositeRedirectSubwindows (ClientPtr client) REQUEST(xCompositeRedirectSubwindowsReq); REQUEST_SIZE_MATCH(xCompositeRedirectSubwindowsReq); + /* Unsupported by current architecture and porting is too much effort. */ + /* + VERIFY_WINDOW(pWin, stuff->window, client, + DixSetAttrAccess | DixManageAccess | DixBlendAccess); + */ pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW); if (!pWin) { client->errorValue = stuff->window; return BadWindow; } + return compRedirectSubwindows (client, pWin, stuff->update); } @@ -150,12 +209,18 @@ ProcCompositeUnredirectWindow (ClientPtr client) REQUEST(xCompositeUnredirectWindowReq); REQUEST_SIZE_MATCH(xCompositeUnredirectWindowReq); + /* Unsupported by current architecture and porting is too much effort. */ + /* + VERIFY_WINDOW(pWin, stuff->window, client, + DixSetAttrAccess | DixManageAccess | DixBlendAccess); + */ pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW); if (!pWin) { client->errorValue = stuff->window; return BadWindow; } + return compUnredirectWindow (client, pWin, stuff->update); } @@ -166,12 +231,18 @@ ProcCompositeUnredirectSubwindows (ClientPtr client) REQUEST(xCompositeUnredirectSubwindowsReq); REQUEST_SIZE_MATCH(xCompositeUnredirectSubwindowsReq); + /* Unsupported by current architecture and porting is too much effort. */ + /* + VERIFY_WINDOW(pWin, stuff->window, client, + DixSetAttrAccess | DixManageAccess | DixBlendAccess); + */ pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW); if (!pWin) { client->errorValue = stuff->window; return BadWindow; } + return compUnredirectSubwindows (client, pWin, stuff->update); } @@ -184,13 +255,16 @@ ProcCompositeCreateRegionFromBorderClip (ClientPtr client) REQUEST(xCompositeCreateRegionFromBorderClipReq); REQUEST_SIZE_MATCH(xCompositeCreateRegionFromBorderClipReq); + /* Unsupported by current architecture and porting is too much effort. */ + /* + VERIFY_WINDOW(pWin, stuff->window, client, DixGetAttrAccess); + */ pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW); if (!pWin) { client->errorValue = stuff->window; return BadWindow; } - LEGAL_NEW_RESOURCE (stuff->region, client); cw = GetCompWindow (pWin); @@ -206,7 +280,7 @@ ProcCompositeCreateRegionFromBorderClip (ClientPtr client) if (!AddResource (stuff->region, RegionResType, (void *) pRegion)) return BadAlloc; - return(client->noClientException); + return Success; } static int @@ -215,35 +289,170 @@ ProcCompositeNameWindowPixmap (ClientPtr client) WindowPtr pWin; CompWindowPtr cw; PixmapPtr pPixmap; + ScreenPtr pScreen; + int rc; + REQUEST(xCompositeNameWindowPixmapReq); REQUEST_SIZE_MATCH(xCompositeNameWindowPixmapReq); + /* Unsupported by current architecture and porting is too much effort. */ + /* + VERIFY_WINDOW(pWin, stuff->window, client, DixGetAttrAccess); + */ pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW); if (!pWin) { client->errorValue = stuff->window; return BadWindow; } - + + pScreen = pWin->drawable.pScreen; + + if (!pWin->viewable) + return BadMatch; + LEGAL_NEW_RESOURCE (stuff->pixmap, client); cw = GetCompWindow (pWin); if (!cw) return BadMatch; - pPixmap = (*pWin->drawable.pScreen->GetWindowPixmap) (pWin); + pPixmap = (*pScreen->GetWindowPixmap) (pWin); if (!pPixmap) return BadMatch; + /* security creation/labeling check */ + /* + rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pixmap, RT_PIXMAP, + pPixmap, RT_WINDOW, pWin, DixCreateAccess); + */ + rc = Success; + if (rc != Success) + return rc; + ++pPixmap->refcnt; if (!AddResource (stuff->pixmap, RT_PIXMAP, (void *) pPixmap)) return BadAlloc; - return(client->noClientException); + /* Unsupported by current architecture. */ + /* + if (pScreen->NameWindowPixmap) { + rc = pScreen->NameWindowPixmap(pWin, pPixmap, stuff->pixmap); + if (rc != Success) { + FreeResource(stuff->pixmap, RT_NONE); + return rc; + } + } + */ + + return Success; +} + +static int +ProcCompositeGetOverlayWindow(ClientPtr client) +{ + REQUEST(xCompositeGetOverlayWindowReq); + xCompositeGetOverlayWindowReply rep; + WindowPtr pWin; + ScreenPtr pScreen; + CompScreenPtr cs; + CompOverlayClientPtr pOc; + int rc; + int n = 0; + + REQUEST_SIZE_MATCH(xCompositeGetOverlayWindowReq); + /* Unsupported by current architecture and porting is too much effort. */ + /* + VERIFY_WINDOW(pWin, stuff->window, client, DixGetAttrAccess); + */ + pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW); + if (!pWin) + { + client->errorValue = stuff->window; + return BadWindow; + } + pScreen = pWin->drawable.pScreen; + + /* + * Create an OverlayClient structure to mark this client's + * interest in the overlay window + */ + pOc = compCreateOverlayClient(pScreen, client); + if (pOc == NULL) + return BadAlloc; + + /* + * Make sure the overlay window exists + */ + cs = GetCompScreen(pScreen); + if (cs->pOverlayWin == NULL) + if (!compCreateOverlayWindow(pScreen)) { + FreeResource(pOc->resource, RT_NONE); + return BadAlloc; + } + + /* + rc = XaceHook(XACE_RESOURCE_ACCESS, client, cs->pOverlayWin->drawable.id, + RT_WINDOW, cs->pOverlayWin, RT_NONE, NULL, DixGetAttrAccess); + */ + rc = Success; + if (rc != Success) { + FreeResource(pOc->resource, RT_NONE); + return rc; + } + + rep = (xCompositeGetOverlayWindowReply) { + .type = X_Reply, + .sequenceNumber = client->sequence, + .length = 0, + .overlayWin = cs->pOverlayWin->drawable.id + }; + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.overlayWin, n); + } + WriteToClient(client, sz_xCompositeGetOverlayWindowReply, (char *)&rep); + + return Success; } -int (*ProcCompositeVector[CompositeNumberRequests])(ClientPtr) = { +static int +ProcCompositeReleaseOverlayWindow(ClientPtr client) +{ + REQUEST(xCompositeReleaseOverlayWindowReq); + WindowPtr pWin; + CompOverlayClientPtr pOc; + + REQUEST_SIZE_MATCH(xCompositeReleaseOverlayWindowReq); + /* Unsupported by current architecture and porting is too much effort. */ + /* + VERIFY_WINDOW(pWin, stuff->window, client, DixGetAttrAccess); + */ + pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW); + if (!pWin) + { + client->errorValue = stuff->window; + return BadWindow; + } + + /* + * Has client queried a reference to the overlay window + * on this screen? If not, generate an error. + */ + pOc = compFindOverlayClient(pWin->drawable.pScreen, client); + if (pOc == NULL) + return BadMatch; + + /* The delete function will free the client structure */ + FreeResource(pOc->resource, RT_NONE); + + return Success; +} + +static int (*ProcCompositeVector[CompositeNumberRequests])(ClientPtr) = { ProcCompositeQueryVersion, ProcCompositeRedirectWindow, ProcCompositeRedirectSubwindows, @@ -251,6 +460,7 @@ int (*ProcCompositeVector[CompositeNumberRequests])(ClientPtr) = { ProcCompositeUnredirectSubwindows, ProcCompositeCreateRegionFromBorderClip, ProcCompositeNameWindowPixmap, + ProcCompositeGetOverlayWindow, ProcCompositeReleaseOverlayWindow, }; static int @@ -351,7 +561,31 @@ SProcCompositeNameWindowPixmap (ClientPtr client) return (*ProcCompositeVector[stuff->compositeReqType]) (client); } -int (*SProcCompositeVector[CompositeNumberRequests])(ClientPtr) = { +static int +SProcCompositeGetOverlayWindow(ClientPtr client) +{ + int n = 0; + REQUEST(xCompositeGetOverlayWindowReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xCompositeGetOverlayWindowReq); + swapl(&stuff->window, n); + return (*ProcCompositeVector[stuff->compositeReqType]) (client); +} + +static int +SProcCompositeReleaseOverlayWindow(ClientPtr client) +{ + int n = 0; + REQUEST(xCompositeReleaseOverlayWindowReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xCompositeReleaseOverlayWindowReq); + swapl(&stuff->window, n); + return (*ProcCompositeVector[stuff->compositeReqType]) (client); +} + +static int (*SProcCompositeVector[CompositeNumberRequests])(ClientPtr) = { SProcCompositeQueryVersion, SProcCompositeRedirectWindow, SProcCompositeRedirectSubwindows, @@ -359,6 +593,7 @@ int (*SProcCompositeVector[CompositeNumberRequests])(ClientPtr) = { SProcCompositeUnredirectSubwindows, SProcCompositeCreateRegionFromBorderClip, SProcCompositeNameWindowPixmap, + SProcCompositeGetOverlayWindow, SProcCompositeReleaseOverlayWindow, }; static int @@ -372,27 +607,104 @@ SProcCompositeDispatch (ClientPtr client) return BadRequest; } +/* Both unused and incompatible due to architecture, disabled. */ +#if 0 +/** @see GetDefaultBytes */ +static void +GetCompositeClientWindowBytes(void *value, XID id, ResourceSizePtr size) +{ + WindowPtr window = value; + + /* Currently only pixmap bytes are reported to clients. */ + size->resourceSize = 0; + + /* Calculate pixmap reference sizes. */ + size->pixmapRefSize = 0; + if (window->redirectDraw != RedirectDrawNone) + { + SizeType pixmapSizeFunc = GetResourceTypeSizeFunc(RT_PIXMAP); + ResourceSizeRec pixmapSize = { 0, 0 }; + ScreenPtr screen = window->drawable.pScreen; + PixmapPtr pixmap = screen->GetWindowPixmap(window); + pixmapSizeFunc(pixmap, pixmap->drawable.id, &pixmapSize); + size->pixmapRefSize += pixmapSize.pixmapRefSize; + } +} +#endif /* 0 */ + void CompositeExtensionInit (void) { ExtensionEntry *extEntry; int s; + /* Assume initialization is going to fail */ + noCompositeExtension = TRUE; + + fprintf(stderr, "COMPOSITE: trying to initialize extension.\n"); + + for (s = 0; s < screenInfo.numScreens; s++) { + ScreenPtr pScreen = screenInfo.screens[s]; + VisualPtr vis; + + /* Composite on 8bpp pseudocolor root windows appears to fail, so + * just disable it on anything pseudocolor for safety. + */ + for (vis = pScreen->visuals; vis->vid != pScreen->rootVisual; vis++); + if ((vis->class | DynamicClass) == PseudoColor) + return; + + /* Ensure that Render is initialized, which is required for automatic + * compositing. + */ + if (GetPictureScreenIfSet(pScreen) == NULL) + return; + } +#ifdef PANORAMIX + /* Xinerama's rewriting of window drawing before Composite gets to it + * breaks Composite. + */ + if (!noPanoramiXExtension) + return; +#endif + CompositeClientWindowType = CreateNewResourceType (FreeCompositeClientWindow); if (!CompositeClientWindowType) return; + /* SetResourceTypeSizeFunc(CompositeClientWindowType, + GetCompositeClientWindowBytes); + */ + CompositeClientSubwindowsType = CreateNewResourceType (FreeCompositeClientSubwindows); if (!CompositeClientSubwindowsType) return; - CompositeClientPrivateIndex = AllocateClientPrivateIndex (); - if (!AllocateClientPrivate (CompositeClientPrivateIndex, + CompositeClientOverlayType = CreateNewResourceType + (FreeCompositeClientOverlay); + if (!CompositeClientOverlayType) + return; + +#ifndef NXAGENT_SERVER + if (!dixRegisterPrivateKey(&CompositeClientPrivateKeyRec, PRIVATE_CLIENT, sizeof (CompositeClientRec))) return; +#else /* !defined(NXAGENT_SERVER) */ + if ((CompositeClientPrivIndex = AllocateClientPrivateIndex()) < 0) + return; + if (!AllocateClientPrivate(CompositeClientPrivIndex, sizeof (CompositeClientRec))) + return; +#endif /* !defined(NXAGENT_SERVER) */ + if (!AddCallback (&ClientStateCallback, CompositeClientCallback, 0)) return; + for (s = 0; s < screenInfo.numScreens; s++) + if (!compScreenInit (screenInfo.screens[s])) { + fprintf (stderr, "COMPOSITE: could not initialize via compScreenInit() for screen %d\n", s); + return; + } + extEntry = AddExtension (COMPOSITE_NAME, 0, 0, ProcCompositeDispatch, SProcCompositeDispatch, CompositeResetProc, StandardMinorOpcode); @@ -400,10 +712,371 @@ CompositeExtensionInit (void) return; CompositeReqCode = (CARD8) extEntry->base; - - for (s = 0; s < screenInfo.numScreens; s++) - if (!compScreenInit (screenInfo.screens[s])) - return; - miRegisterRedirectBorderClipProc (compSetRedirectBorderClip, - compGetRedirectBorderClip); + /* Initialization succeeded */ + noCompositeExtension = FALSE; +} + +/* + * This code requires features the current infrastructure does not provide + * and will thus be disabled. + */ +#if 0 + +#ifdef PANORAMIX +#include "panoramiXsrv.h" + +int (*PanoramiXSaveCompositeVector[CompositeNumberRequests]) (ClientPtr); + +static int +PanoramiXCompositeRedirectWindow(ClientPtr client) +{ + PanoramiXRes *win; + int rc = 0, j; + + REQUEST(xCompositeRedirectWindowReq); + + REQUEST_SIZE_MATCH(xCompositeRedirectWindowReq); + + if ((rc = dixLookupResourceByType((void **) &win, stuff->window, XRT_WINDOW, + client, DixUnknownAccess))) { + client->errorValue = stuff->window; + return rc; + } + + FOR_NSCREENS_FORWARD(j) { + stuff->window = win->info[j].id; + rc = (*PanoramiXSaveCompositeVector[stuff->compositeReqType]) (client); + if (rc != Success) + break; + } + + return rc; +} + +static int +PanoramiXCompositeRedirectSubwindows(ClientPtr client) +{ + PanoramiXRes *win; + int rc = 0, j; + + REQUEST(xCompositeRedirectSubwindowsReq); + + REQUEST_SIZE_MATCH(xCompositeRedirectSubwindowsReq); + + if ((rc = dixLookupResourceByType((void **) &win, stuff->window, XRT_WINDOW, + client, DixUnknownAccess))) { + client->errorValue = stuff->window; + return rc; + } + + FOR_NSCREENS_FORWARD(j) { + stuff->window = win->info[j].id; + rc = (*PanoramiXSaveCompositeVector[stuff->compositeReqType]) (client); + if (rc != Success) + break; + } + + return rc; +} + +static int +PanoramiXCompositeUnredirectWindow(ClientPtr client) +{ + PanoramiXRes *win; + int rc = 0, j; + + REQUEST(xCompositeUnredirectWindowReq); + + REQUEST_SIZE_MATCH(xCompositeUnredirectWindowReq); + + if ((rc = dixLookupResourceByType((void **) &win, stuff->window, XRT_WINDOW, + client, DixUnknownAccess))) { + client->errorValue = stuff->window; + return rc; + } + + FOR_NSCREENS_FORWARD(j) { + stuff->window = win->info[j].id; + rc = (*PanoramiXSaveCompositeVector[stuff->compositeReqType]) (client); + if (rc != Success) + break; + } + + return rc; +} + +static int +PanoramiXCompositeUnredirectSubwindows(ClientPtr client) +{ + PanoramiXRes *win; + int rc = 0, j; + + REQUEST(xCompositeUnredirectSubwindowsReq); + + REQUEST_SIZE_MATCH(xCompositeUnredirectSubwindowsReq); + + if ((rc = dixLookupResourceByType((void **) &win, stuff->window, XRT_WINDOW, + client, DixUnknownAccess))) { + client->errorValue = stuff->window; + return rc; + } + + FOR_NSCREENS_FORWARD(j) { + stuff->window = win->info[j].id; + rc = (*PanoramiXSaveCompositeVector[stuff->compositeReqType]) (client); + if (rc != Success) + break; + } + + return rc; } + +static int +PanoramiXCompositeNameWindowPixmap(ClientPtr client) +{ + WindowPtr pWin; + CompWindowPtr cw; + PixmapPtr pPixmap; + int rc; + PanoramiXRes *win, *newPix; + int i; + + REQUEST(xCompositeNameWindowPixmapReq); + + REQUEST_SIZE_MATCH(xCompositeNameWindowPixmapReq); + + if ((rc = dixLookupResourceByType((void **) &win, stuff->window, XRT_WINDOW, + client, DixUnknownAccess))) { + client->errorValue = stuff->window; + return rc; + } + + LEGAL_NEW_RESOURCE(stuff->pixmap, client); + + if (!(newPix = malloc(sizeof(PanoramiXRes)))) + return BadAlloc; + + newPix->type = XRT_PIXMAP; + newPix->u.pix.shared = FALSE; + panoramix_setup_ids(newPix, client, stuff->pixmap); + + FOR_NSCREENS(i) { + rc = dixLookupResourceByType((void **) &pWin, win->info[i].id, + RT_WINDOW, client, DixGetAttrAccess); + if (rc != Success) { + client->errorValue = stuff->window; + free(newPix); + return rc; + } + + if (!pWin->viewable) { + free(newPix); + return BadMatch; + } + + cw = GetCompWindow(pWin); + if (!cw) { + free(newPix); + return BadMatch; + } + + pPixmap = (*pWin->drawable.pScreen->GetWindowPixmap) (pWin); + if (!pPixmap) { + free(newPix); + return BadMatch; + } + + if (!AddResource(newPix->info[i].id, RT_PIXMAP, (void *) pPixmap)) + return BadAlloc; + + ++pPixmap->refcnt; + } + + if (!AddResource(stuff->pixmap, XRT_PIXMAP, (void *) newPix)) + return BadAlloc; + + return Success; +} + +static int +PanoramiXCompositeGetOverlayWindow(ClientPtr client) +{ + REQUEST(xCompositeGetOverlayWindowReq); + xCompositeGetOverlayWindowReply rep; + WindowPtr pWin; + ScreenPtr pScreen; + CompScreenPtr cs; + CompOverlayClientPtr pOc; + int rc; + PanoramiXRes *win, *overlayWin = NULL; + int i; + int n = 0; + + REQUEST_SIZE_MATCH(xCompositeGetOverlayWindowReq); + + if ((rc = dixLookupResourceByType((void **) &win, stuff->window, XRT_WINDOW, + client, DixUnknownAccess))) { + client->errorValue = stuff->window; + return rc; + } + + cs = GetCompScreen(screenInfo.screens[0]); + if (!cs->pOverlayWin) { + if (!(overlayWin = malloc(sizeof(PanoramiXRes)))) + return BadAlloc; + + overlayWin->type = XRT_WINDOW; + overlayWin->u.win.root = FALSE; + } + + FOR_NSCREENS_BACKWARD(i) { + rc = dixLookupResourceByType((void **) &pWin, win->info[i].id, + RT_WINDOW, client, DixGetAttrAccess); + if (rc != Success) { + client->errorValue = stuff->window; + free(overlayWin); + return rc; + } + pScreen = pWin->drawable.pScreen; + + /* + * Create an OverlayClient structure to mark this client's + * interest in the overlay window + */ + pOc = compCreateOverlayClient(pScreen, client); + if (pOc == NULL) { + free(overlayWin); + return BadAlloc; + } + + /* + * Make sure the overlay window exists + */ + cs = GetCompScreen(pScreen); + if (cs->pOverlayWin == NULL) + if (!compCreateOverlayWindow(pScreen)) { + FreeResource(pOc->resource, RT_NONE); + free(overlayWin); + return BadAlloc; + } + + /* + rc = XaceHook(XACE_RESOURCE_ACCESS, client, + cs->pOverlayWin->drawable.id, + RT_WINDOW, cs->pOverlayWin, RT_NONE, NULL, + DixGetAttrAccess); + */ + rc = Success; + if (rc != Success) { + FreeResource(pOc->resource, RT_NONE); + free(overlayWin); + return rc; + } + } + + if (overlayWin) { + FOR_NSCREENS(i) { + cs = GetCompScreen(screenInfo.screens[i]); + overlayWin->info[i].id = cs->pOverlayWin->drawable.id; + } + + AddResource(overlayWin->info[0].id, XRT_WINDOW, overlayWin); + } + + cs = GetCompScreen(screenInfo.screens[0]); + + rep = (xCompositeGetOverlayWindowReply) { + .type = X_Reply, + .sequenceNumber = client->sequence, + .length = 0, + .overlayWin = cs->pOverlayWin->drawable.id + }; + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.overlayWin, n); + } + WriteToClient(client, sz_xCompositeGetOverlayWindowReply, &rep); + + return Success; +} + +static int +PanoramiXCompositeReleaseOverlayWindow(ClientPtr client) +{ + REQUEST(xCompositeReleaseOverlayWindowReq); + WindowPtr pWin; + CompOverlayClientPtr pOc; + PanoramiXRes *win; + int i, rc; + + REQUEST_SIZE_MATCH(xCompositeReleaseOverlayWindowReq); + + if ((rc = dixLookupResourceByType((void **) &win, stuff->window, XRT_WINDOW, + client, DixUnknownAccess))) { + client->errorValue = stuff->window; + return rc; + } + + FOR_NSCREENS_BACKWARD(i) { + if ((rc = dixLookupResourceByType((void **) &pWin, win->info[i].id, + XRT_WINDOW, client, + DixUnknownAccess))) { + client->errorValue = stuff->window; + return rc; + } + + /* + * Has client queried a reference to the overlay window + * on this screen? If not, generate an error. + */ + pOc = compFindOverlayClient(pWin->drawable.pScreen, client); + if (pOc == NULL) + return BadMatch; + + /* The delete function will free the client structure */ + FreeResource(pOc->resource, RT_NONE); + } + + return Success; +} + +void +PanoramiXCompositeInit(void) +{ + int i; + + for (i = 0; i < CompositeNumberRequests; i++) + PanoramiXSaveCompositeVector[i] = ProcCompositeVector[i]; + /* + * Stuff in Xinerama aware request processing hooks + */ + ProcCompositeVector[X_CompositeRedirectWindow] = + PanoramiXCompositeRedirectWindow; + ProcCompositeVector[X_CompositeRedirectSubwindows] = + PanoramiXCompositeRedirectSubwindows; + ProcCompositeVector[X_CompositeUnredirectWindow] = + PanoramiXCompositeUnredirectWindow; + ProcCompositeVector[X_CompositeUnredirectSubwindows] = + PanoramiXCompositeUnredirectSubwindows; + ProcCompositeVector[X_CompositeNameWindowPixmap] = + PanoramiXCompositeNameWindowPixmap; + ProcCompositeVector[X_CompositeGetOverlayWindow] = + PanoramiXCompositeGetOverlayWindow; + ProcCompositeVector[X_CompositeReleaseOverlayWindow] = + PanoramiXCompositeReleaseOverlayWindow; +} + +void +PanoramiXCompositeReset(void) +{ + int i; + + for (i = 0; i < CompositeNumberRequests; i++) + ProcCompositeVector[i] = PanoramiXSaveCompositeVector[i]; +} + +#endif + +#endif /* 0 */ diff --git a/nx-X11/programs/Xserver/composite/compinit.c b/nx-X11/programs/Xserver/composite/compinit.c index 13a6d6c01..c86aaed5a 100644 --- a/nx-X11/programs/Xserver/composite/compinit.c +++ b/nx-X11/programs/Xserver/composite/compinit.c @@ -27,11 +27,17 @@ #endif #include "compint.h" - -int CompScreenPrivateIndex; -int CompWindowPrivateIndex; -int CompSubwindowsPrivateIndex; -int CompGeneration; +#include "compositeext.h" + +#ifndef NXAGENT_SERVER +DevPrivateKeyRec CompScreenPrivateKeyRec; +DevPrivateKeyRec CompWindowPrivateKeyRec; +DevPrivateKeyRec CompSubwindowsPrivateKeyRec; +#else /* !defined(NXAGENT_SERVER) */ +int CompScreenPrivIndex = -1; +int CompWindowPrivIndex = -1; +int CompSubwindowsPrivIndex = -1; +#endif static Bool compCloseScreen (int index, ScreenPtr pScreen) @@ -39,24 +45,39 @@ compCloseScreen (int index, ScreenPtr pScreen) CompScreenPtr cs = GetCompScreen (pScreen); Bool ret; + free(cs->alternateVisuals); + pScreen->CloseScreen = cs->CloseScreen; - pScreen->BlockHandler = cs->BlockHandler; pScreen->InstallColormap = cs->InstallColormap; + pScreen->ChangeWindowAttributes = cs->ChangeWindowAttributes; pScreen->ReparentWindow = cs->ReparentWindow; + + /* + * Unsupported by our old Xserver infrastructure, replaced with direct calls to + * compReallocPixmap(). + */ + /* + pScreen->ConfigNotify = cs->ConfigNotify; + */ + pScreen->MoveWindow = cs->MoveWindow; pScreen->ResizeWindow = cs->ResizeWindow; pScreen->ChangeBorderWidth = cs->ChangeBorderWidth; pScreen->ClipNotify = cs->ClipNotify; - pScreen->PaintWindowBackground = cs->PaintWindowBackground; pScreen->UnrealizeWindow = cs->UnrealizeWindow; pScreen->RealizeWindow = cs->RealizeWindow; pScreen->DestroyWindow = cs->DestroyWindow; pScreen->CreateWindow = cs->CreateWindow; pScreen->CopyWindow = cs->CopyWindow; pScreen->PositionWindow = cs->PositionWindow; + + pScreen->GetImage = cs->GetImage; + pScreen->GetSpans = cs->GetSpans; + pScreen->SourceValidate = cs->SourceValidate; + xfree (cs); - pScreen->devPrivates[CompScreenPrivateIndex].ptr = 0; + FAKE_DIX_SET_SCREEN_PRIVATE(pScreen, NULL); ret = (*pScreen->CloseScreen) (index, pScreen); return ret; } @@ -69,7 +90,7 @@ compInstallColormap (ColormapPtr pColormap) CompScreenPtr cs = GetCompScreen (pScreen); int a; - for (a = 0; a < NUM_COMP_ALTERNATE_VISUALS; a++) + for (a = 0; a < cs->numAlternateVisuals; a++) if (pVisual->vid == cs->alternateVisuals[a]) return; pScreen->InstallColormap = cs->InstallColormap; @@ -78,33 +99,91 @@ compInstallColormap (ColormapPtr pColormap) pScreen->InstallColormap = compInstallColormap; } +/* Unsupported by current architecture, drop for now. */ +#if 0 static void -compScreenUpdate (ScreenPtr pScreen) +compCheckBackingStore(WindowPtr pWin) { - CompScreenPtr cs = GetCompScreen (pScreen); - - compCheckTree (pScreen); - if (cs->damaged) - { - compWindowUpdate (WindowTable[pScreen->myNum]); - cs->damaged = FALSE; + if (pWin->backingStore != NotUseful && !pWin->backStorage) { + compRedirectWindow(serverClient, pWin, CompositeRedirectAutomatic); + pWin->backStorage = TRUE; + } + else if (pWin->backingStore == NotUseful && pWin->backStorage) { + compUnredirectWindow(serverClient, pWin, + CompositeRedirectAutomatic); + pWin->backStorage = FALSE; } } +/* Fake backing store via automatic redirection */ +static Bool +compChangeWindowAttributes(WindowPtr pWin, unsigned long mask) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + CompScreenPtr cs = GetCompScreen(pScreen); + Bool ret; + + pScreen->ChangeWindowAttributes = cs->ChangeWindowAttributes; + ret = pScreen->ChangeWindowAttributes(pWin, mask); + + if (ret && (mask & CWBackingStore) && + pScreen->backingStoreSupport != NotUseful) + compCheckBackingStore(pWin); + + pScreen->ChangeWindowAttributes = compChangeWindowAttributes; + + return ret; +} +#endif /* 0 */ + static void -compBlockHandler (int i, - void *blockData, - void *pTimeout, - void *pReadmask) +compGetImage(DrawablePtr pDrawable, + int sx, int sy, + int w, int h, + unsigned int format, unsigned long planemask, char *pdstLine) { - ScreenPtr pScreen = screenInfo.screens[i]; - CompScreenPtr cs = GetCompScreen (pScreen); + ScreenPtr pScreen = pDrawable->pScreen; + CompScreenPtr cs = GetCompScreen(pScreen); + + pScreen->GetImage = cs->GetImage; + if (pDrawable->type == DRAWABLE_WINDOW) + compPaintChildrenToWindow(pScreen, (WindowPtr) pDrawable); + (*pScreen->GetImage) (pDrawable, sx, sy, w, h, format, planemask, pdstLine); + cs->GetImage = pScreen->GetImage; + pScreen->GetImage = compGetImage; +} + +static void +compGetSpans(DrawablePtr pDrawable, int wMax, DDXPointPtr ppt, int *pwidth, + int nspans, char *pdstStart) +{ + ScreenPtr pScreen = pDrawable->pScreen; + CompScreenPtr cs = GetCompScreen(pScreen); + + pScreen->GetSpans = cs->GetSpans; + if (pDrawable->type == DRAWABLE_WINDOW) + compPaintChildrenToWindow(pScreen, (WindowPtr) pDrawable); + (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart); + cs->GetSpans = pScreen->GetSpans; + pScreen->GetSpans = compGetSpans; +} - pScreen->BlockHandler = cs->BlockHandler; - compScreenUpdate (pScreen); - (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask); - cs->BlockHandler = pScreen->BlockHandler; - pScreen->BlockHandler = compBlockHandler; +static void +compSourceValidate(DrawablePtr pDrawable, + int x, int y, + int width, int height /* , unsigned int subWindowMode */ /* unsupported */) +{ + ScreenPtr pScreen = pDrawable->pScreen; + CompScreenPtr cs = GetCompScreen(pScreen); + + pScreen->SourceValidate = cs->SourceValidate; + if (pDrawable->type == DRAWABLE_WINDOW /* && subWindowMode == IncludeInferiors */ /* unsupported */) + compPaintChildrenToWindow(pScreen, (WindowPtr) pDrawable); + if (pScreen->SourceValidate) + (*pScreen->SourceValidate) (pDrawable, x, y, width, height /*, + subWindowMode */ /* unsupported */); + cs->SourceValidate = pScreen->SourceValidate; + pScreen->SourceValidate = compSourceValidate; } /* @@ -139,192 +218,190 @@ compFindVisuallessDepth (ScreenPtr pScreen, int d) return 0; } +/* + * Add a list of visual IDs to the list of visuals to implicitly redirect. + */ +static Bool +compRegisterAlternateVisuals(CompScreenPtr cs, VisualID * vids, int nVisuals) +{ + VisualID *p; + +#ifndef NXAGENT_SERVER + p = reallocarray(cs->alternateVisuals, + cs->numAlternateVisuals + nVisuals, sizeof(VisualID)); +#else + p = xrealloc(cs->alternateVisuals, + sizeof(VisualID) * (cs->numAlternateVisuals + nVisuals)); +#endif + if (p == NULL) + return FALSE; + + memcpy(&p[cs->numAlternateVisuals], vids, sizeof(VisualID) * nVisuals); + + cs->alternateVisuals = p; + cs->numAlternateVisuals += nVisuals; + + return TRUE; +} + +Bool +CompositeRegisterAlternateVisuals(ScreenPtr pScreen, VisualID * vids, + int nVisuals) +{ + CompScreenPtr cs = GetCompScreen(pScreen); + + return compRegisterAlternateVisuals(cs, vids, nVisuals); +} + +Bool +CompositeRegisterImplicitRedirectionException(ScreenPtr pScreen, + VisualID parentVisual, + VisualID winVisual) +{ + CompScreenPtr cs = GetCompScreen(pScreen); + CompImplicitRedirectException *p; + +#ifndef NXAGENT_SERVER + p = reallocarray(cs->implicitRedirectExceptions, + cs->numImplicitRedirectExceptions + 1, sizeof(p[0])); +#else + p = xrealloc(cs->implicitRedirectExceptions, + sizeof(p[0]) * (cs->numImplicitRedirectExceptions + 1)); +#endif + if (p == NULL) + return FALSE; + + p[cs->numImplicitRedirectExceptions].parentVisual = parentVisual; + p[cs->numImplicitRedirectExceptions].winVisual = winVisual; + + cs->implicitRedirectExceptions = p; + cs->numImplicitRedirectExceptions++; + + return TRUE; +} + typedef struct _alternateVisual { int depth; CARD32 format; } CompAlternateVisual; -static CompAlternateVisual altVisuals[NUM_COMP_ALTERNATE_VISUALS] = { +static CompAlternateVisual altVisuals[] = { #if COMP_INCLUDE_RGB24_VISUAL { 24, PICT_r8g8b8 }, #endif { 32, PICT_a8r8g8b8 }, }; +static const int NUM_COMP_ALTERNATE_VISUALS = sizeof(altVisuals) / + sizeof(CompAlternateVisual); + static Bool -compAddAlternateVisuals (ScreenPtr pScreen, CompScreenPtr cs) +compAddAlternateVisual (ScreenPtr pScreen, CompScreenPtr cs, + CompAlternateVisual * alt) { - VisualPtr visuals; - DepthPtr depths[NUM_COMP_ALTERNATE_VISUALS]; - PictFormatPtr pPictFormats[NUM_COMP_ALTERNATE_VISUALS]; - int i; - int numVisuals; - VisualID *vids[NUM_COMP_ALTERNATE_VISUALS]; - XID *installedCmaps; - ColormapPtr installedCmap; - int numInstalledCmaps; - int numAlternate = 0; - int alt; - - memset (cs->alternateVisuals, '\0', sizeof (cs->alternateVisuals)); - - for (alt = 0; alt < NUM_COMP_ALTERNATE_VISUALS; alt++) - { - DepthPtr depth; - PictFormatPtr pPictFormat; - - depth = compFindVisuallessDepth (pScreen, altVisuals[alt].depth); - if (!depth) - continue; - /* - * Find the right picture format - */ - pPictFormat = PictureMatchFormat (pScreen, altVisuals[alt].depth, - altVisuals[alt].format); - if (!pPictFormat) - continue; + VisualPtr visual; + DepthPtr depth; + PictFormatPtr pPictFormat; + unsigned long alphaMask; - /* - * Allocate vid list for this depth - */ - vids[numAlternate] = xalloc (sizeof (VisualID)); - if (!vids[numAlternate]) - continue; - depths[numAlternate] = depth; - pPictFormats[numAlternate] = pPictFormat; - numAlternate++; - } + /* + * The ARGB32 visual is always available. Other alternate depth visuals + * are only provided if their depth is less than the root window depth. + * There's no deep reason for this. + */ + if (alt->depth >= pScreen->rootDepth && alt->depth != 32) + return FALSE; - if (!numAlternate) + depth = compFindVisuallessDepth(pScreen, alt->depth); + if (!depth) + /* alt->depth doesn't exist or already has alternate visuals. */ return TRUE; - /* - * Find the installed colormaps - */ - installedCmaps = xalloc (pScreen->maxInstalledCmaps * sizeof (XID)); - if (!installedCmaps) - { - for (alt = 0; alt < numAlternate; alt++) - xfree (vids[alt]); + pPictFormat = PictureMatchFormat(pScreen, alt->depth, alt->format); + if (!pPictFormat) return FALSE; - } - numInstalledCmaps = (*pScreen->ListInstalledColormaps) (pScreen, - installedCmaps); - /* - * realloc the visual array to fit the new one in place - */ - numVisuals = pScreen->numVisuals; - visuals = xrealloc (pScreen->visuals, - (numVisuals + numAlternate) * sizeof (VisualRec)); - if (!visuals) - { - for (alt = 0; alt < numAlternate; alt++) - xfree (vids[alt]); - xfree (installedCmaps); + if (ResizeVisualArray(pScreen, 1, depth) == FALSE) { return FALSE; } - /* - * Fix up any existing installed colormaps -- we'll assume that - * the only ones created so far have been installed. If this - * isn't true, we'll have to walk the resource database looking - * for all colormaps. - */ - for (i = 0; i < numInstalledCmaps; i++) - { - int j; - - installedCmap = LookupIDByType (installedCmaps[i], RT_COLORMAP); - if (!installedCmap) - continue; - j = installedCmap->pVisual - pScreen->visuals; - installedCmap->pVisual = &visuals[j]; - } - - xfree (installedCmaps); - - pScreen->visuals = visuals; - pScreen->numVisuals = numVisuals + numAlternate; + visual = pScreen->visuals + (pScreen->numVisuals - 1); /* the new one */ - for (alt = 0; alt < numAlternate; alt++) - { - DepthPtr depth = depths[alt]; - PictFormatPtr pPictFormat = pPictFormats[alt]; - VisualPtr visual = &visuals[numVisuals + alt]; - unsigned long alphaMask; - - /* - * Initialize the visual - */ - visual->class = TrueColor; + /* Initialize the visual */ visual->bitsPerRGBValue = 8; - - visual->vid = FakeClientID (0); - visual->redMask = (((unsigned long) pPictFormat->direct.redMask) << - pPictFormat->direct.red); - visual->greenMask = (((unsigned long) pPictFormat->direct.greenMask) << - pPictFormat->direct.green); - visual->blueMask = (((unsigned long) pPictFormat->direct.blueMask) << - pPictFormat->direct.blue); - alphaMask = (((unsigned long) pPictFormat->direct.alphaMask) << - pPictFormat->direct.alpha); - visual->offsetRed = pPictFormat->direct.red; - visual->offsetGreen = pPictFormat->direct.green; - visual->offsetBlue = pPictFormat->direct.blue; + if (PICT_FORMAT_TYPE(alt->format) == PICT_TYPE_COLOR) { + visual->class = PseudoColor; + visual->nplanes = PICT_FORMAT_BPP(alt->format); + visual->ColormapEntries = 1 << visual->nplanes; + } + else { + DirectFormatRec *direct = &pPictFormat->direct; + + visual->class = TrueColor; + visual->redMask = ((unsigned long) direct->redMask) << direct->red; + visual->greenMask = + ((unsigned long) direct->greenMask) << direct->green; + visual->blueMask = ((unsigned long) direct->blueMask) << direct->blue; + alphaMask = ((unsigned long) direct->alphaMask) << direct->alpha; + visual->offsetRed = direct->red; + visual->offsetGreen = direct->green; + visual->offsetBlue = direct->blue; /* * Include A bits in this (unlike GLX which includes only RGB) * This lets DIX compute suitable masks for colormap allocations */ - visual->nplanes = Ones (visual->redMask | + visual->nplanes = Ones(visual->redMask | visual->greenMask | - visual->blueMask | - alphaMask); - /* - * find widest component - */ - visual->ColormapEntries = (1 << max (Ones (visual->redMask), - max (Ones (visual->greenMask), - Ones (visual->blueMask)))); + visual->blueMask | alphaMask); + /* find widest component */ + visual->ColormapEntries = (1 << max(Ones(visual->redMask), + max(Ones(visual->greenMask), + Ones(visual->blueMask)))); + } - /* - * remember the visual ID to detect auto-update windows - */ - cs->alternateVisuals[alt] = visual->vid; + /* remember the visual ID to detect auto-update windows */ + compRegisterAlternateVisuals(cs, &visual->vid, 1); - /* - * Fix up the depth - */ - vids[alt][0] = visual->vid; - depth->numVids = 1; - depth->vids = vids[alt]; - } return TRUE; } +static Bool +compAddAlternateVisuals(ScreenPtr pScreen, CompScreenPtr cs) +{ + int alt, ret = 0; + + for (alt = 0; alt < NUM_COMP_ALTERNATE_VISUALS; alt++) + ret |= compAddAlternateVisual(pScreen, cs, altVisuals + alt); + + return ! !ret; +} + Bool compScreenInit (ScreenPtr pScreen) { CompScreenPtr cs; - if (CompGeneration != serverGeneration) - { - CompScreenPrivateIndex = AllocateScreenPrivateIndex (); - if (CompScreenPrivateIndex == -1) - return FALSE; - CompWindowPrivateIndex = AllocateWindowPrivateIndex (); - if (CompWindowPrivateIndex == -1) - return FALSE; - CompSubwindowsPrivateIndex = AllocateWindowPrivateIndex (); - if (CompSubwindowsPrivateIndex == -1) +#ifndef NXAGENT_SERVER + if (!dixRegisterPrivateKey(&CompScreenPrivateKeyRec, PRIVATE_SCREEN, 0)) return FALSE; - CompGeneration = serverGeneration; - } - if (!AllocateWindowPrivate (pScreen, CompWindowPrivateIndex, 0)) + if (!dixRegisterPrivateKey(&CompWindowPrivateKeyRec, PRIVATE_WINDOW, 0)) + return FALSE; + if (!dixRegisterPrivateKey(&CompSubwindowsPrivateKeyRec, PRIVATE_WINDOW, 0)) + return FALSE; +#else /* !defined(NXAGENT_SERVER) */ + if ((CompScreenPrivIndex = AllocateScreenPrivateIndex()) < 0) + return FALSE; + if ((CompWindowPrivIndex = AllocateWindowPrivateIndex()) < 0) + return FALSE; + if ((CompSubwindowsPrivIndex = AllocateWindowPrivateIndex()) < 0) + return FALSE; + + if (!AllocateWindowPrivate (pScreen, CompWindowPrivIndex, 0)) return FALSE; - if (!AllocateWindowPrivate (pScreen, CompSubwindowsPrivateIndex, 0)) + if (!AllocateWindowPrivate (pScreen, CompSubwindowsPrivIndex, 0)) return FALSE; +#endif if (GetCompScreen (pScreen)) return TRUE; @@ -334,12 +411,24 @@ compScreenInit (ScreenPtr pScreen) cs->damaged = FALSE; + cs->overlayWid = FakeClientID(0); + cs->pOverlayWin = NULL; + cs->pOverlayClients = NULL; + + cs->numAlternateVisuals = 0; + cs->alternateVisuals = NULL; + cs->numImplicitRedirectExceptions = 0; + cs->implicitRedirectExceptions = NULL; + if (!compAddAlternateVisuals (pScreen, cs)) { xfree (cs); return FALSE; } + if (!disableBackingStore) + pScreen->backingStoreSupport = WhenMapped; + cs->PositionWindow = pScreen->PositionWindow; pScreen->PositionWindow = compPositionWindow; @@ -358,12 +447,18 @@ compScreenInit (ScreenPtr pScreen) cs->UnrealizeWindow = pScreen->UnrealizeWindow; pScreen->UnrealizeWindow = compUnrealizeWindow; - cs->PaintWindowBackground = pScreen->PaintWindowBackground; - pScreen->PaintWindowBackground = compPaintWindowBackground; - cs->ClipNotify = pScreen->ClipNotify; pScreen->ClipNotify = compClipNotify; + /* + * Unsupported by our old Xserver infrastructure, replaced with direct calls to + * compReallocPixmap(). + */ + /* + cs->ConfigNotify = pScreen->ConfigNotify; + pScreen->ConfigNotify = compConfigNotify; + */ + cs->MoveWindow = pScreen->MoveWindow; pScreen->MoveWindow = compMoveWindow; @@ -379,12 +474,29 @@ compScreenInit (ScreenPtr pScreen) cs->InstallColormap = pScreen->InstallColormap; pScreen->InstallColormap = compInstallColormap; - cs->BlockHandler = pScreen->BlockHandler; - pScreen->BlockHandler = compBlockHandler; + /* Unsupported by our current architecture, drop for now. */ + /* + cs->ChangeWindowAttributes = pScreen->ChangeWindowAttributes; + pScreen->ChangeWindowAttributes = compChangeWindowAttributes; + */ + + cs->BlockHandler = NULL; cs->CloseScreen = pScreen->CloseScreen; pScreen->CloseScreen = compCloseScreen; - pScreen->devPrivates[CompScreenPrivateIndex].ptr = (void *) cs; + cs->GetImage = pScreen->GetImage; + pScreen->GetImage = compGetImage; + + cs->GetSpans = pScreen->GetSpans; + pScreen->GetSpans = compGetSpans; + + cs->SourceValidate = pScreen->SourceValidate; + pScreen->SourceValidate = compSourceValidate; + + FAKE_DIX_SET_SCREEN_PRIVATE(pScreen, cs); + + RegisterRealChildHeadProc(CompositeRealChildHead); + return TRUE; } diff --git a/nx-X11/programs/Xserver/composite/compint.h b/nx-X11/programs/Xserver/composite/compint.h index 262d95108..2834dad4e 100644 --- a/nx-X11/programs/Xserver/composite/compint.h +++ b/nx-X11/programs/Xserver/composite/compint.h @@ -51,6 +51,7 @@ #include "damageextint.h" #include "xfixes.h" #include <nx-X11/extensions/compositeproto.h> +#include "compositeext.h" #include <assert.h> /* @@ -58,6 +59,7 @@ #define COMPOSITE_DEBUG */ +#define COMPOSITE_DEBUG typedef struct _CompClientWindow { struct _CompClientWindow *next; @@ -89,11 +91,19 @@ typedef struct _CompSubwindows { #define COMP_INCLUDE_RGB24_VISUAL 0 #endif -#if COMP_INCLUDE_RGB24_VISUAL -#define NUM_COMP_ALTERNATE_VISUALS 2 -#else -#define NUM_COMP_ALTERNATE_VISUALS 1 -#endif +typedef struct _CompOverlayClientRec *CompOverlayClientPtr; + +typedef struct _CompOverlayClientRec { + CompOverlayClientPtr pNext; + ClientPtr pClient; + ScreenPtr pScreen; + XID resource; +} CompOverlayClientRec; + +typedef struct _CompImplicitRedirectException { + XID parentVisual; + XID winVisual; +} CompImplicitRedirectException; typedef struct _CompScreen { PositionWindowProcPtr PositionWindow; @@ -102,13 +112,21 @@ typedef struct _CompScreen { DestroyWindowProcPtr DestroyWindow; RealizeWindowProcPtr RealizeWindow; UnrealizeWindowProcPtr UnrealizeWindow; - PaintWindowProcPtr PaintWindowBackground; ClipNotifyProcPtr ClipNotify; /* * Called from ConfigureWindow, these * three track changes to the offscreen storage * geometry */ + + /* + * Unsupported by our old Xserver infrastructure, replaced with direct calls to + * compReallocPixmap(). + */ + /* + ConfigNotifyProcPtr ConfigNotify; + */ + MoveWindowProcPtr MoveWindow; ResizeWindowProcPtr ResizeWindow; ChangeBorderWidthProcPtr ChangeBorderWidth; @@ -122,30 +140,79 @@ typedef struct _CompScreen { */ InstallColormapProcPtr InstallColormap; + /* + * Fake backing store via automatic redirection + */ + ChangeWindowAttributesProcPtr ChangeWindowAttributes; + ScreenBlockHandlerProcPtr BlockHandler; CloseScreenProcPtr CloseScreen; - Bool damaged; - XID alternateVisuals[NUM_COMP_ALTERNATE_VISUALS]; + Bool damaged; + int numAlternateVisuals; + VisualID *alternateVisuals; + int numImplicitRedirectExceptions; + CompImplicitRedirectException *implicitRedirectExceptions; + + WindowPtr pOverlayWin; + Window overlayWid; + CompOverlayClientPtr pOverlayClients; + + GetImageProcPtr GetImage; + GetSpansProcPtr GetSpans; + SourceValidateProcPtr SourceValidate; } CompScreenRec, *CompScreenPtr; -extern int CompScreenPrivateIndex; -extern int CompWindowPrivateIndex; -extern int CompSubwindowsPrivateIndex; +#ifndef NXAGENT_SERVER +extern DevPrivateKeyRec CompScreenPrivateKeyRec; -#define GetCompScreen(s) ((CompScreenPtr) ((s)->devPrivates[CompScreenPrivateIndex].ptr)) -#define GetCompWindow(w) ((CompWindowPtr) ((w)->devPrivates[CompWindowPrivateIndex].ptr)) -#define GetCompSubwindows(w) ((CompSubwindowsPtr) ((w)->devPrivates[CompSubwindowsPrivateIndex].ptr)) +#define CompScreenPrivateKey (&CompScreenPrivateKeyRec) + +extern DevPrivateKeyRec CompWindowPrivateKeyRec; + +#define CompWindowPrivateKey (&CompWindowPrivateKeyRec) + +extern DevPrivateKeyRec CompSubwindowsPrivateKeyRec; + +#define CompSubwindowsPrivateKey (&CompSubwindowsPrivateKeyRec) + +#define GetCompScreen(s) ((CompScreenPtr) \ + dixLookupPrivate(&(s)->devPrivates, CompScreenPrivateKey)) +#define GetCompWindow(w) ((CompWindowPtr) \ + dixLookupPrivate(&(w)->devPrivates, CompWindowPrivateKey)) +#define GetCompSubwindows(w) ((CompSubwindowsPtr) \ + dixLookupPrivate(&(w)->devPrivates, CompSubwindowsPrivateKey)) +#else /* !defined(NXAGENT_SERVER) */ +extern int CompScreenPrivIndex; +extern int CompWindowPrivIndex; +extern int CompSubwindowsPrivIndex; + +#define GetCompScreen(s) ((CompScreenPtr) (s)->devPrivates[CompScreenPrivIndex].ptr) +#define GetCompWindow(w) ((CompWindowPtr) (w)->devPrivates[CompWindowPrivIndex].ptr) +#define GetCompSubwindows(w) ((CompSubwindowsPtr) (w)->devPrivates[CompSubwindowsPrivIndex].ptr) +#endif /* !defined(NXAGENT_SERVER) */ -extern RESTYPE CompositeClientWindowType; extern RESTYPE CompositeClientSubwindowsType; +extern RESTYPE CompositeClientOverlayType; + +/* Shim for less ifdefs within the actual code. */ +#ifndef NXAGENT_SERVER +#define FAKE_DIX_SET_PRIVATE_IMPL(obj, privateKey, ptr_val) do { dixSetPrivate(&(obj)->devPrivates, privateKey, ptr_val); } while (0) + +#define FAKE_DIX_SET_SCREEN_PRIVATE(pScreen, ptr_val) FAKE_DIX_SET_PRIVATE_IMPL(pScreen, CompScreenPrivateKey, ptr_val) +#define FAKE_DIX_SET_WINDOW_PRIVATE(pWin, ptr_val) FAKE_DIX_SET_PRIVATE_IMPL(pWin, CompWindowPrivateKey, ptr_val) +#define FAKE_DIX_SET_SUBWINDOWS_PRIVATE(pWin, ptr_val) FAKE_DIX_SET_PRIVATE_IMPL(pWin, CompSubwindowsPrivateKey, ptr_val) +#else /* !defined(NXAGENT_SERVER) */ +#define FAKE_DIX_SET_PRIVATE_IMPL(obj, privIndex, ptr_val) do { (obj)->devPrivates[privIndex].ptr = (void *) (ptr_val); } while (0) + +#define FAKE_DIX_SET_SCREEN_PRIVATE(pScreen, ptr_val) FAKE_DIX_SET_PRIVATE_IMPL(pScreen, CompScreenPrivIndex, ptr_val) +#define FAKE_DIX_SET_WINDOW_PRIVATE(pWin, ptr_val) FAKE_DIX_SET_PRIVATE_IMPL(pWin, CompWindowPrivIndex, ptr_val) +#define FAKE_DIX_SET_SUBWINDOWS_PRIVATE(pWin, ptr_val) FAKE_DIX_SET_PRIVATE_IMPL(pWin, CompSubwindowsPrivIndex, ptr_val) +#endif /* !defined(NXAGENT_SERVER) */ /* * compalloc.c */ -void -compReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure); - Bool compRedirectWindow (ClientPtr pClient, WindowPtr pWin, int update); @@ -174,25 +241,40 @@ Bool compAllocPixmap (WindowPtr pWin); void -compFreePixmap (WindowPtr pWin); + compSetParentPixmap(WindowPtr pWin); + +void + compRestoreWindow(WindowPtr pWin, PixmapPtr pPixmap); Bool compReallocPixmap (WindowPtr pWin, int x, int y, unsigned int w, unsigned int h, int bw); /* - * compext.c + * compinit.c */ -void -CompositeExtensionInit (void); +Bool + compScreenInit(ScreenPtr pScreen); /* - * compinit.c + * compoverlay.c */ +void + compFreeOverlayClient(CompOverlayClientPtr pOcToDel); + +CompOverlayClientPtr +compFindOverlayClient(ScreenPtr pScreen, ClientPtr pClient); + +CompOverlayClientPtr +compCreateOverlayClient(ScreenPtr pScreen, ClientPtr pClient); + Bool -compScreenInit (ScreenPtr pScreen); + compCreateOverlayWindow(ScreenPtr pScreen); + +void + compDestroyOverlayWindow(ScreenPtr pScreen); /* * compwindow.c @@ -205,6 +287,9 @@ compCheckTree (ScreenPtr pScreen); #define compCheckTree(s) #endif +PictFormatPtr +compWindowFormat (WindowPtr pWin); + void compSetPixmap (WindowPtr pWin, PixmapPtr pPixmap); @@ -220,8 +305,6 @@ compRealizeWindow (WindowPtr pWin); Bool compUnrealizeWindow (WindowPtr pWin); -void -compPaintWindowBackground (WindowPtr pWin, RegionPtr pRegion, int what); void compClipNotify (WindowPtr pWin, int dx, int dy); @@ -255,6 +338,25 @@ void compCopyWindow (WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc); void -compWindowUpdate (WindowPtr pWin); + compPaintChildrenToWindow(ScreenPtr pScreen, WindowPtr pWin); + +WindowPtr + CompositeRealChildHead(WindowPtr pWin); + +int + DeleteWindowNoInputDevices(void *value, XID wid); + +/* + * Unsupported by our old Xserver infrastructure, replaced with direct calls to + * compReallocPixmap(). + */ +/* +int +compConfigNotify(WindowPtr pWin, int x, int y, int w, int h, + int bw, WindowPtr pSib); +*/ + +void PanoramiXCompositeInit(void); +void PanoramiXCompositeReset(void); #endif /* _COMPINT_H_ */ diff --git a/nx-X11/programs/Xserver/composite/compositeext.h b/nx-X11/programs/Xserver/composite/compositeext.h new file mode 100644 index 000000000..b96cb1d68 --- /dev/null +++ b/nx-X11/programs/Xserver/composite/compositeext.h @@ -0,0 +1,44 @@ +/* + * Copyright © 2009 NVIDIA Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#ifndef _COMPOSITEEXT_H_ +#define _COMPOSITEEXT_H_ + +#include "misc.h" +#include "scrnintstr.h" + +extern _X_EXPORT Bool CompositeRegisterAlternateVisuals(ScreenPtr pScreen, + VisualID * vids, + int nVisuals); + +extern _X_EXPORT Bool CompositeRegisterImplicitRedirectionException(ScreenPtr pScreen, + VisualID parentVisual, + VisualID winVisual); + +extern _X_EXPORT RESTYPE CompositeClientWindowType; + +#endif /* _COMPOSITEEXT_H_ */ diff --git a/nx-X11/programs/Xserver/composite/compoverlay.c b/nx-X11/programs/Xserver/composite/compoverlay.c new file mode 100644 index 000000000..dfe59f3cf --- /dev/null +++ b/nx-X11/programs/Xserver/composite/compoverlay.c @@ -0,0 +1,178 @@ +/* + * Copyright (c) 2006, Oracle and/or its affiliates. All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Copyright © 2003 Keith Packard + * + * Permission to use, copy, modify, distribute, and sell this software and its + * documentation for any purpose is hereby granted without fee, provided that + * the above copyright notice appear in all copies and that both that + * copyright notice and this permission notice appear in supporting + * documentation, and that the name of Keith Packard not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Keith Packard makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR + * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, + * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER + * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR + * PERFORMANCE OF THIS SOFTWARE. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include "compint.h" +#ifndef NXAGENT_SERVER +#include "xace.h" +#endif + +#ifdef PANORAMIX +#include "panoramiXsrv.h" +#endif + +/* + * Delete the given overlay client list element from its screen list. + */ +void +compFreeOverlayClient(CompOverlayClientPtr pOcToDel) +{ + ScreenPtr pScreen = pOcToDel->pScreen; + CompScreenPtr cs = GetCompScreen(pScreen); + CompOverlayClientPtr *pPrev, pOc; + + for (pPrev = &cs->pOverlayClients; (pOc = *pPrev); pPrev = &pOc->pNext) { + if (pOc == pOcToDel) { + *pPrev = pOc->pNext; + free(pOc); + break; + } + } + + /* Destroy overlay window when there are no more clients using it */ + if (cs->pOverlayClients == NULL) + compDestroyOverlayWindow(pScreen); +} + +/* + * Return the client's first overlay client rec from the given screen + */ +CompOverlayClientPtr +compFindOverlayClient(ScreenPtr pScreen, ClientPtr pClient) +{ + CompScreenPtr cs = GetCompScreen(pScreen); + CompOverlayClientPtr pOc; + + for (pOc = cs->pOverlayClients; pOc != NULL; pOc = pOc->pNext) + if (pOc->pClient == pClient) + return pOc; + + return NULL; +} + +/* + * Create an overlay client object for the given client + */ +CompOverlayClientPtr +compCreateOverlayClient(ScreenPtr pScreen, ClientPtr pClient) +{ + CompScreenPtr cs = GetCompScreen(pScreen); + CompOverlayClientPtr pOc; + + pOc = (CompOverlayClientPtr) malloc(sizeof(CompOverlayClientRec)); + if (pOc == NULL) + return NULL; + + pOc->pClient = pClient; + pOc->pScreen = pScreen; + pOc->resource = FakeClientID(pClient->index); + pOc->pNext = cs->pOverlayClients; + cs->pOverlayClients = pOc; + + /* + * Create a resource for this element so it can be deleted + * when the client goes away. + */ + if (!AddResource(pOc->resource, CompositeClientOverlayType, (void *) pOc)) + return NULL; + + return pOc; +} + +/* + * Create the overlay window and map it + */ +Bool +compCreateOverlayWindow(ScreenPtr pScreen) +{ + CompScreenPtr cs = GetCompScreen(pScreen); + WindowPtr pRoot = WindowTable[pScreen->myNum]; + WindowPtr pWin; + XID attrs[] = { None, TRUE }; /* backPixmap, overrideRedirect */ + int result; + int w = pScreen->width; + int h = pScreen->height; + int x = 0, y = 0; + + /* Unsupported by current architecture, disabled. */ +#if 0 +#ifdef PANORAMIX + if (!noPanoramiXExtension) { + x = -pScreen->x; + y = -pScreen->y; + w = PanoramiXPixWidth; + h = PanoramiXPixHeight; + } +#endif +#endif + + pWin = cs->pOverlayWin = + CreateWindow(cs->overlayWid, pRoot, x, y, w, h, 0, + InputOutput, CWBackPixmap | CWOverrideRedirect, &attrs[0], + pRoot->drawable.depth, + serverClient, pScreen->rootVisual, &result); + if (pWin == NULL) + return FALSE; + + if (!AddResource(pWin->drawable.id, RT_WINDOW, (void *) pWin)) + return FALSE; + + MapWindow(pWin, serverClient); + + return TRUE; +} + +/* + * Destroy the overlay window + */ +void +compDestroyOverlayWindow(ScreenPtr pScreen) +{ + CompScreenPtr cs = GetCompScreen(pScreen); + + cs->pOverlayWin = NullWindow; + FreeResource(cs->overlayWid, RT_NONE); +} diff --git a/nx-X11/programs/Xserver/composite/compwindow.c b/nx-X11/programs/Xserver/composite/compwindow.c index fbdc44420..799aad023 100644 --- a/nx-X11/programs/Xserver/composite/compwindow.c +++ b/nx-X11/programs/Xserver/composite/compwindow.c @@ -28,6 +28,10 @@ #include "compint.h" +#ifdef PANORAMIX +#include "panoramiXsrv.h" +#endif + #ifdef COMPOSITE_DEBUG static int compCheckWindow (WindowPtr pWin, void * data) @@ -39,10 +43,10 @@ compCheckWindow (WindowPtr pWin, void * data) if (!pWin->parent) { - assert (!pWin->redirectDraw); + assert (pWin->redirectDraw == RedriectDrawNone); assert (pWinPixmap == pScreenPixmap); } - else if (pWin->redirectDraw) + else if (pWin->redirectDraw != RedirectDrawNone) { assert (pWinPixmap != pParentPixmap); assert (pWinPixmap != pScreenPixmap); @@ -73,15 +77,27 @@ typedef struct _compPixmapVisit { static Bool compRepaintBorder (ClientPtr pClient, void * closure) { - WindowPtr pWindow = LookupWindow ((XID) closure, pClient); + WindowPtr pWindow; +#ifndef NXAGENT_SERVER + int rc = + dixLookupWindow(&pWindow, (XID) (intptr_t) closure, pClient, + DixWriteAccess); +#else + pWindow = SecurityLookupWindow((XID) (intptr_t) closure, pClient, SecurityWriteAccess); + int rc = pWindow ? Success : BadWindow; +#endif - if (pWindow) + if (rc == Success) { RegionRec exposed; RegionNull(&exposed); RegionSubtract(&exposed, &pWindow->borderClip, &pWindow->winSize); +#ifndef NXAGENT_SERVER + pWindow->drawable.pScreen->PaintWindowBorder(pWindow, &exposed, PW_BORDER); +#else (*pWindow->drawable.pScreen->PaintWindowBorder)(pWindow, &exposed, PW_BORDER); +#endif RegionUninit(&exposed); } return TRUE; @@ -93,7 +109,7 @@ compSetPixmapVisitWindow (WindowPtr pWindow, void * data) CompPixmapVisitPtr pVisit = (CompPixmapVisitPtr) data; ScreenPtr pScreen = pWindow->drawable.pScreen; - if (pWindow != pVisit->pWindow && pWindow->redirectDraw) + if (pWindow != pVisit->pWindow && pWindow->redirectDraw != RedirectDrawNone) return WT_DONTWALKCHILDREN; (*pScreen->SetWindowPixmap) (pWindow, pVisit->pPixmap); /* @@ -105,7 +121,7 @@ compSetPixmapVisitWindow (WindowPtr pWindow, void * data) SetBorderSize (pWindow); if (HasBorder (pWindow)) QueueWorkProc (compRepaintBorder, serverClient, - (void *) pWindow->drawable.id); + (void *) (intptr_t) pWindow->drawable.id); return WT_WALKCHILDREN; } @@ -124,21 +140,73 @@ Bool compCheckRedirect (WindowPtr pWin) { CompWindowPtr cw = GetCompWindow (pWin); + CompScreenPtr cs = GetCompScreen(pWin->drawable.pScreen); Bool should; should = pWin->realized && (pWin->drawable.class != InputOnly) && - (cw != NULL); + (cw != NULL) && (pWin->parent != NULL); - if (should != pWin->redirectDraw) + /* Never redirect the overlay window */ + if (cs->pOverlayWin != NULL) { + if (pWin == cs->pOverlayWin) { + should = FALSE; + } + } + + if (should != (pWin->redirectDraw != RedirectDrawNone)) { if (should) return compAllocPixmap (pWin); + else { + ScreenPtr pScreen = pWin->drawable.pScreen; + PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin); + + compSetParentPixmap(pWin); + compRestoreWindow(pWin, pPixmap); + (*pScreen->DestroyPixmap) (pPixmap); + } + } + else if (should) { + if (cw->update == CompositeRedirectAutomatic) + pWin->redirectDraw = RedirectDrawAutomatic; else - compFreePixmap (pWin); + pWin->redirectDraw = RedirectDrawManual; } return TRUE; } +static int +updateOverlayWindow(ScreenPtr pScreen) +{ + CompScreenPtr cs; + WindowPtr pWin; /* overlay window */ + XID vlist[2]; + int w = pScreen->width; + int h = pScreen->height; + +#ifdef PANORAMIX + if (!noPanoramiXExtension) { + w = PanoramiXPixWidth; + h = PanoramiXPixHeight; + } +#endif + + cs = GetCompScreen(pScreen); + if ((pWin = cs->pOverlayWin) != NULL) { + if ((pWin->drawable.width == w) && (pWin->drawable.height == h)) + return Success; + + /* Let's resize the overlay window. */ + vlist[0] = w; + vlist[1] = h; + return ConfigureWindow(pWin, CWWidth | CWHeight, vlist, wClient(pWin)); + } + + /* Let's be on the safe side and not assume an overlay window is + always allocated. */ + return Success; +} + Bool compPositionWindow (WindowPtr pWin, int x, int y) { @@ -153,10 +221,11 @@ compPositionWindow (WindowPtr pWin, int x, int y) compCheckRedirect (pWin); */ #ifdef COMPOSITE_DEBUG - if (pWin->redirectDraw != (pWin->viewable && (GetCompWindow(pWin) != NULL))) + if ((pWin->redirectDraw != RedirectDrawNone) != + (pWin->viewable && (GetCompWindow(pWin) != NULL))) abort (); #endif - if (pWin->redirectDraw) + if (pWin->redirectDraw != RedirectDrawNone) { PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin); int bw = wBorderWidth (pWin); @@ -176,6 +245,8 @@ compPositionWindow (WindowPtr pWin, int x, int y) cs->PositionWindow = pScreen->PositionWindow; pScreen->PositionWindow = compPositionWindow; compCheckTree (pWin->drawable.pScreen); + if (updateOverlayWindow(pScreen) != Success) + ret = FALSE; return ret; } @@ -213,21 +284,6 @@ compUnrealizeWindow (WindowPtr pWin) return ret; } -void -compPaintWindowBackground (WindowPtr pWin, RegionPtr pRegion, int what) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - CompSubwindowsPtr csw = GetCompSubwindows (pWin); - CompScreenPtr cs = GetCompScreen (pScreen); - - if (csw && csw->update == CompositeRedirectManual) - return; - pScreen->PaintWindowBackground = cs->PaintWindowBackground; - (*pScreen->PaintWindowBackground) (pWin, pRegion, what); - cs->PaintWindowBackground = pScreen->PaintWindowBackground; - pScreen->PaintWindowBackground = compPaintWindowBackground; -} - /* * Called after the borderClip for the window has settled down * We use this to make sure our extra borderClip has the right origin @@ -273,13 +329,28 @@ compIsAlternateVisual (ScreenPtr pScreen, CompScreenPtr cs = GetCompScreen (pScreen); int i; - for (i = 0; i < NUM_COMP_ALTERNATE_VISUALS; i++) + for (i = 0; i < cs->numAlternateVisuals; i++) if (cs->alternateVisuals[i] == visual) return TRUE; return FALSE; } static Bool +compIsImplicitRedirectException(ScreenPtr pScreen, + XID parentVisual, XID winVisual) +{ + CompScreenPtr cs = GetCompScreen(pScreen); + int i; + + for (i = 0; i < cs->numImplicitRedirectExceptions; i++) + if (cs->implicitRedirectExceptions[i].parentVisual == parentVisual && + cs->implicitRedirectExceptions[i].winVisual == winVisual) + return TRUE; + + return FALSE; +} + +static Bool compImplicitRedirect (WindowPtr pWin, WindowPtr pParent) { if (pParent) @@ -287,6 +358,9 @@ compImplicitRedirect (WindowPtr pWin, WindowPtr pParent) ScreenPtr pScreen = pWin->drawable.pScreen; XID winVisual = wVisual (pWin); XID parentVisual = wVisual (pParent); + + if (compIsImplicitRedirectException(pScreen, parentVisual, winVisual)) + return FALSE; if (winVisual != parentVisual && (compIsAlternateVisual (pScreen, winVisual) || @@ -296,6 +370,21 @@ compImplicitRedirect (WindowPtr pWin, WindowPtr pParent) return FALSE; } +static void +compFreeOldPixmap(WindowPtr pWin) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + + if (pWin->redirectDraw != RedirectDrawNone) { + CompWindowPtr cw = GetCompWindow(pWin); + + if (cw->pOldPixmap) { + (*pScreen->DestroyPixmap) (cw->pOldPixmap); + cw->pOldPixmap = NullPixmap; + } + } +} + void compMoveWindow (WindowPtr pWin, int x, int y, WindowPtr pSib, VTKind kind) { @@ -303,8 +392,7 @@ compMoveWindow (WindowPtr pWin, int x, int y, WindowPtr pSib, VTKind kind) CompScreenPtr cs = GetCompScreen (pScreen); compCheckTree (pScreen); - if (pWin->redirectDraw) - { + if (pWin->redirectDraw != RedirectDrawNone) { WindowPtr pParent; int draw_x, draw_y; unsigned int w, h, bw; @@ -312,7 +400,7 @@ compMoveWindow (WindowPtr pWin, int x, int y, WindowPtr pSib, VTKind kind) /* if this is a root window, can't be moved */ if (!(pParent = pWin->parent)) return; - + bw = wBorderWidth (pWin); draw_x = pParent->drawable.x + x + (int)bw; draw_y = pParent->drawable.y + y + (int)bw; @@ -327,16 +415,7 @@ compMoveWindow (WindowPtr pWin, int x, int y, WindowPtr pSib, VTKind kind) cs->MoveWindow = pScreen->MoveWindow; pScreen->MoveWindow = compMoveWindow; - if (pWin->redirectDraw) - { - CompWindowPtr cw = GetCompWindow (pWin); - if (cw->pOldPixmap) - { - (*pScreen->DestroyPixmap) (cw->pOldPixmap); - cw->pOldPixmap = NullPixmap; - } - } - + compFreeOldPixmap(pWin); compCheckTree (pScreen); } @@ -348,12 +427,12 @@ compResizeWindow (WindowPtr pWin, int x, int y, CompScreenPtr cs = GetCompScreen (pScreen); compCheckTree (pScreen); - if (pWin->redirectDraw) + if (pWin->redirectDraw != RedirectDrawNone) { WindowPtr pParent; int draw_x, draw_y; unsigned int bw; - + /* if this is a root window, can't be moved */ if (!(pParent = pWin->parent)) return; @@ -364,20 +443,13 @@ compResizeWindow (WindowPtr pWin, int x, int y, compReallocPixmap (pWin, draw_x, draw_y, w, h, bw); } compCheckTree (pScreen); - + pScreen->ResizeWindow = cs->ResizeWindow; (*pScreen->ResizeWindow) (pWin, x, y, w, h, pSib); cs->ResizeWindow = pScreen->ResizeWindow; pScreen->ResizeWindow = compResizeWindow; - if (pWin->redirectDraw) - { - CompWindowPtr cw = GetCompWindow (pWin); - if (cw->pOldPixmap) - { - (*pScreen->DestroyPixmap) (cw->pOldPixmap); - cw->pOldPixmap = NullPixmap; - } - } + + compFreeOldPixmap(pWin); compCheckTree (pWin->drawable.pScreen); } @@ -388,37 +460,30 @@ compChangeBorderWidth (WindowPtr pWin, unsigned int bw) CompScreenPtr cs = GetCompScreen (pScreen); compCheckTree (pScreen); - if (pWin->redirectDraw) + if (pWin->redirectDraw != RedirectDrawNone) { WindowPtr pParent; int draw_x, draw_y; unsigned int w, h; - + /* if this is a root window, can't be moved */ if (!(pParent = pWin->parent)) return; - + draw_x = pWin->drawable.x; draw_y = pWin->drawable.y; w = pWin->drawable.width; h = pWin->drawable.height; compReallocPixmap (pWin, draw_x, draw_y, w, h, bw); } - compCheckTree (pScreen); + compCheckTree (pScreen); pScreen->ChangeBorderWidth = cs->ChangeBorderWidth; (*pScreen->ChangeBorderWidth) (pWin, bw); cs->ChangeBorderWidth = pScreen->ChangeBorderWidth; pScreen->ChangeBorderWidth = compChangeBorderWidth; - if (pWin->redirectDraw) - { - CompWindowPtr cw = GetCompWindow (pWin); - if (cw->pOldPixmap) - { - (*pScreen->DestroyPixmap) (cw->pOldPixmap); - cw->pOldPixmap = NullPixmap; - } - } + + compFreeOldPixmap(pWin); compCheckTree (pWin->drawable.pScreen); } @@ -454,7 +519,7 @@ compReparentWindow (WindowPtr pWin, WindowPtr pPriorParent) /* * Reset pixmap pointers as appropriate */ - if (pWin->parent && !pWin->redirectDraw) + if (pWin->parent && pWin->redirectDraw == RedirectDrawNone) compSetPixmap (pWin, (*pScreen->GetWindowPixmap) (pWin->parent)); /* * Call down to next function @@ -473,7 +538,7 @@ compCopyWindow (WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) CompScreenPtr cs = GetCompScreen (pScreen); int dx = 0, dy = 0; - if (pWin->redirectDraw) + if (pWin->redirectDraw != RedirectDrawNone) { PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin); CompWindowPtr cw = GetCompWindow (pWin); @@ -487,7 +552,6 @@ compCopyWindow (WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) * need to be copied to pNewPixmap. */ RegionRec rgnDst; - PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin); GCPtr pGC; dx = ptOldOrg.x - pWin->drawable.x; @@ -524,6 +588,7 @@ compCopyWindow (WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc) } FreeScratchGC (pGC); } + RegionUninit (&rgnDst); return; } dx = pPixmap->screen_x - cw->oldx; @@ -568,8 +633,11 @@ compCreateWindow (WindowPtr pWin) { CompSubwindowsPtr csw = GetCompSubwindows (pWin->parent); CompClientWindowPtr ccw; + PixmapPtr parent_pixmap = (*pScreen->GetWindowPixmap)(pWin->parent); + PixmapPtr window_pixmap = (*pScreen->GetWindowPixmap)(pWin); - (*pScreen->SetWindowPixmap) (pWin, (*pScreen->GetWindowPixmap) (pWin->parent)); + if (window_pixmap != parent_pixmap) + (*pScreen->SetWindowPixmap) (pWin, parent_pixmap); if (csw) for (ccw = csw->clients; ccw; ccw = ccw->next) compRedirectWindow (clients[CLIENT_ID(ccw->id)], @@ -598,8 +666,12 @@ compDestroyWindow (WindowPtr pWin) while ((csw = GetCompSubwindows (pWin))) FreeResource (csw->clients->id, RT_NONE); - if (pWin->redirectDraw) - compFreePixmap (pWin); + if (pWin->redirectDraw != RedirectDrawNone) { + PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin); + + compSetParentPixmap (pWin); + (*pScreen->DestroyPixmap) (pPixmap); + } ret = (*pScreen->DestroyWindow) (pWin); cs->DestroyWindow = pScreen->DestroyWindow; pScreen->DestroyWindow = compDestroyWindow; @@ -658,7 +730,7 @@ compGetWindowVisual (WindowPtr pWin) return 0; } -static PictFormatPtr +PictFormatPtr compWindowFormat (WindowPtr pWin) { ScreenPtr pScreen = pWin->drawable.pScreen; @@ -735,21 +807,103 @@ compWindowUpdateAutomatic (WindowPtr pWin) DamageEmpty (cw->damage); } +static void +compPaintWindowToParent(WindowPtr pWin) +{ + compPaintChildrenToWindow(pWin->drawable.pScreen, pWin); + + if (pWin->redirectDraw != RedirectDrawNone) { + CompWindowPtr cw = GetCompWindow(pWin); + + if (cw->damaged) { + compWindowUpdateAutomatic(pWin); + cw->damaged = FALSE; + } + } +} + void -compWindowUpdate (WindowPtr pWin) +compPaintChildrenToWindow(ScreenPtr pScreen, WindowPtr pWin) { WindowPtr pChild; + CompScreenPtr cs = GetCompScreen(pScreen); + + if (!cs->damaged) + return; for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib) - compWindowUpdate (pChild); - if (pWin->redirectDraw) - { - CompWindowPtr cw = GetCompWindow(pWin); + compPaintWindowToParent(pChild); - if (cw->damaged) - { - compWindowUpdateAutomatic (pWin); - cw->damaged = FALSE; + cs->damaged = FALSE; +} + +WindowPtr +CompositeRealChildHead(WindowPtr pWin) +{ + WindowPtr pChild, pChildBefore; + CompScreenPtr cs; + + if (!pWin->parent && + (screenIsSaved == SCREEN_SAVER_ON) && + (HasSaverWindow(pWin->drawable.pScreen->myNum))) { + + /* First child is the screen saver; see if next child is the overlay */ + pChildBefore = pWin->firstChild; + pChild = pChildBefore->nextSib; + + } + else { + pChildBefore = NullWindow; + pChild = pWin->firstChild; + } + + if (!pChild) { + return NullWindow; + } + + cs = GetCompScreen(pWin->drawable.pScreen); + if (pChild == cs->pOverlayWin) { + return pChild; + } + else { + return pChildBefore; } +} + +/* ConfigNotify not implemented... replace with the old pixmap reallocation algorithm... */ +/* +int +compConfigNotify(WindowPtr pWin, int x, int y, int w, int h, + int bw, WindowPtr pSib) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + CompScreenPtr cs = GetCompScreen(pScreen); + Bool ret = 0; + WindowPtr pParent = pWin->parent; + int draw_x, draw_y; + Bool alloc_ret; + + if (cs->ConfigNotify) { + pScreen->ConfigNotify = cs->ConfigNotify; + ret = (*pScreen->ConfigNotify) (pWin, x, y, w, h, bw, pSib); + cs->ConfigNotify = pScreen->ConfigNotify; + pScreen->ConfigNotify = compConfigNotify; + + if (ret) + return ret; } + + if (pWin->redirectDraw == RedirectDrawNone) + return Success; + + compCheckTree(pScreen); + + draw_x = pParent->drawable.x + x + bw; + draw_y = pParent->drawable.y + y + bw; + alloc_ret = compReallocPixmap(pWin, draw_x, draw_y, w, h, bw); + + if (alloc_ret == FALSE) + return BadAlloc; + return Success; } +*/ diff --git a/nx-X11/programs/Xserver/dix/colormap.c b/nx-X11/programs/Xserver/dix/colormap.c index 11a353f84..cd5e1dc49 100644 --- a/nx-X11/programs/Xserver/dix/colormap.c +++ b/nx-X11/programs/Xserver/dix/colormap.c @@ -2791,3 +2791,80 @@ IsMapInstalled(Colormap map, WindowPtr pWin) DEALLOCATE_LOCAL(pmaps); return (found); } + +struct colormap_lookup_data { + ScreenPtr pScreen; + VisualPtr visuals; +}; + +static void +_colormap_find_resource(void *value, XID id, void *cdata) +{ + struct colormap_lookup_data *cmap_data = cdata; + VisualPtr visuals = cmap_data->visuals; + ScreenPtr pScreen = cmap_data->pScreen; + ColormapPtr cmap = value; + int j; + + if (pScreen != cmap->pScreen) + return; + + j = cmap->pVisual - pScreen->visuals; + cmap->pVisual = &visuals[j]; +} + +/* something has realloced the visuals, instead of breaking + ABI fix it up here - glx and compsite did this wrong */ +Bool +ResizeVisualArray(ScreenPtr pScreen, int new_visual_count, DepthPtr depth) +{ + struct colormap_lookup_data cdata; + int numVisuals; + VisualPtr visuals; + XID *vids, vid; + int first_new_vid, first_new_visual, i; + + first_new_vid = depth->numVids; + first_new_visual = pScreen->numVisuals; + +#if 0 /* !defined(NXAGENT_SERVER) */ + vids = reallocarray(depth->vids, depth->numVids + new_visual_count, + sizeof(XID)); +#else + vids = xrealloc(depth->vids, sizeof(XID) * + (depth->numVids + new_visual_count)); +#endif + if (!vids) + return FALSE; + + /* its realloced now no going back if we fail the next one */ + depth->vids = vids; + + numVisuals = pScreen->numVisuals + new_visual_count; +#if 0 /* !defined(NXAGENT_SERVER) */ + visuals = reallocarray(pScreen->visuals, numVisuals, sizeof(VisualRec)); +#else + visuals = xrealloc(pScreen->visuals, sizeof(VisualRec) * numVisuals); +#endif + if (!visuals) { + return FALSE; + } + + cdata.visuals = visuals; + cdata.pScreen = pScreen; + FindClientResourcesByType(serverClient, RT_COLORMAP, + _colormap_find_resource, &cdata); + + pScreen->visuals = visuals; + + for (i = 0; i < new_visual_count; i++) { + vid = FakeClientID(0); + pScreen->visuals[first_new_visual + i].vid = vid; + vids[first_new_vid + i] = vid; + } + + depth->numVids += new_visual_count; + pScreen->numVisuals += new_visual_count; + + return TRUE; +} diff --git a/nx-X11/programs/Xserver/dix/window.c b/nx-X11/programs/Xserver/dix/window.c index 916d7e276..c3d901fb9 100644 --- a/nx-X11/programs/Xserver/dix/window.c +++ b/nx-X11/programs/Xserver/dix/window.c @@ -535,9 +535,21 @@ ClippedRegionFromBox(register WindowPtr pWin, RegionPtr Rgn, RegionIntersect(Rgn, Rgn, &pWin->winSize); } +static RealChildHeadProc realChildHeadProc = NULL; + +void +RegisterRealChildHeadProc (RealChildHeadProc proc) +{ + realChildHeadProc = proc; +} + WindowPtr RealChildHead(register WindowPtr pWin) { + if (realChildHeadProc) { + return realChildHeadProc (pWin); + } + if (!pWin->parent && (screenIsSaved == SCREEN_SAVER_ON) && (HasSaverWindow (pWin->drawable.pScreen->myNum))) diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXcompositeext.h b/nx-X11/programs/Xserver/hw/nxagent/NXcompositeext.h index b4433d6c1..38ac87e9b 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/NXcompositeext.h +++ b/nx-X11/programs/Xserver/hw/nxagent/NXcompositeext.h @@ -33,7 +33,7 @@ #define COMPOSITE_NAME "Composite" #define COMPOSITE_MAJOR 0 -#define COMPOSITE_MINOR 2 +#define COMPOSITE_MINOR 4 #define CompositeRedirectAutomatic 0 #define CompositeRedirectManual 1 @@ -45,7 +45,11 @@ #define X_CompositeUnredirectSubwindows 4 #define X_CompositeCreateRegionFromBorderClip 5 #define X_CompositeNameWindowPixmap 6 +#define X_CompositeGetOverlayWindow 7 +#define X_CompositeReleaseOverlayWindow 8 -#define CompositeNumberRequests (X_CompositeNameWindowPixmap + 1) +#define CompositeNumberRequests (X_CompositeReleaseOverlayWindow + 1) + +#define CompositeNumberEvents 0 #endif /* _COMPOSITE_H_ */ diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXpicture.c b/nx-X11/programs/Xserver/hw/nxagent/NXpicture.c index 67cd5d6ed..5087fa493 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/NXpicture.c +++ b/nx-X11/programs/Xserver/hw/nxagent/NXpicture.c @@ -1800,6 +1800,99 @@ FreePictFormat (void * pPictFormat, return Success; } +/** + * ReduceCompositeOp is used to choose simpler ops for cases where alpha + * channels are always one and so math on the alpha channel per pixel becomes + * unnecessary. It may also avoid destination reads sometimes if apps aren't + * being careful to avoid these cases. + */ +static CARD8 +ReduceCompositeOp (CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst) +{ + Bool no_src_alpha, no_dst_alpha; + + no_src_alpha = PICT_FORMAT_COLOR(pSrc->format) && + PICT_FORMAT_A(pSrc->format) == 0 && + pSrc->alphaMap == NULL && + pMask == NULL; + no_dst_alpha = PICT_FORMAT_COLOR(pDst->format) && + PICT_FORMAT_A(pDst->format) == 0 && + pDst->alphaMap == NULL; + + /* TODO, maybe: Conjoint and Disjoint op reductions? */ + + /* Deal with simplifications where the source alpha is always 1. */ + if (no_src_alpha) + { + switch (op) { + case PictOpOver: + op = PictOpSrc; + break; + case PictOpInReverse: + op = PictOpDst; + break; + case PictOpOutReverse: + op = PictOpClear; + break; + case PictOpAtop: + op = PictOpIn; + break; + case PictOpAtopReverse: + op = PictOpOverReverse; + break; + case PictOpXor: + op = PictOpOut; + break; + default: + break; + } + } + + /* Deal with simplifications when the destination alpha is always 1 */ + if (no_dst_alpha) + { + switch (op) { + case PictOpOverReverse: + op = PictOpDst; + break; + case PictOpIn: + op = PictOpSrc; + break; + case PictOpOut: + op = PictOpClear; + break; + case PictOpAtop: + op = PictOpOver; + break; + case PictOpXor: + op = PictOpOutReverse; + break; + default: + break; + } + } + + /* Reduce some con/disjoint ops to the basic names. */ + switch (op) { + case PictOpDisjointClear: + case PictOpConjointClear: + op = PictOpClear; + break; + case PictOpDisjointSrc: + case PictOpConjointSrc: + op = PictOpSrc; + break; + case PictOpDisjointDst: + case PictOpConjointDst: + op = PictOpDst; + break; + default: + break; + } + + return op; +} + void CompositePicture (CARD8 op, PicturePtr pSrc, @@ -1820,6 +1913,11 @@ CompositePicture (CARD8 op, if (pMask) ValidatePicture (pMask); ValidatePicture (pDst); + + op = ReduceCompositeOp (op, pSrc, pMask, pDst); + if (op == PictOpDst) + return; + (*ps->Composite) (op, pSrc, pMask, diff --git a/nx-X11/programs/Xserver/hw/nxagent/NXwindow.c b/nx-X11/programs/Xserver/hw/nxagent/NXwindow.c index b2da4e97c..70c378b9e 100644 --- a/nx-X11/programs/Xserver/hw/nxagent/NXwindow.c +++ b/nx-X11/programs/Xserver/hw/nxagent/NXwindow.c @@ -717,6 +717,14 @@ ClippedRegionFromBox(register WindowPtr pWin, RegionPtr Rgn, RegionIntersect(Rgn, Rgn, &pWin->winSize); } +static RealChildHeadProc realChildHeadProc = NULL; + +void +RegisterRealChildHeadProc (RealChildHeadProc proc) +{ + realChildHeadProc = proc; +} + WindowPtr RealChildHead(register WindowPtr pWin) { diff --git a/nx-X11/programs/Xserver/include/colormap.h b/nx-X11/programs/Xserver/include/colormap.h index 67f44193d..bfc6667db 100644 --- a/nx-X11/programs/Xserver/include/colormap.h +++ b/nx-X11/programs/Xserver/include/colormap.h @@ -181,4 +181,8 @@ extern int IsMapInstalled( Colormap /*map*/, WindowPtr /*pWin*/); +extern Bool ResizeVisualArray(ScreenPtr /* pScreen */ , + int /* new_vis_count */ , + DepthPtr /* depth */ ); + #endif /* CMAP_H */ diff --git a/nx-X11/programs/Xserver/include/window.h b/nx-X11/programs/Xserver/include/window.h index 571115365..9e670995d 100644 --- a/nx-X11/programs/Xserver/include/window.h +++ b/nx-X11/programs/Xserver/include/window.h @@ -102,6 +102,10 @@ extern void ClippedRegionFromBox( int /*w*/, int /*h*/); +typedef WindowPtr (* RealChildHeadProc) (WindowPtr pWin); + +void RegisterRealChildHeadProc (RealChildHeadProc proc); + extern WindowPtr RealChildHead( WindowPtr /*pWin*/); diff --git a/nx-X11/programs/Xserver/include/windowstr.h b/nx-X11/programs/Xserver/include/windowstr.h index 5c181bc51..c32842fe3 100644 --- a/nx-X11/programs/Xserver/include/windowstr.h +++ b/nx-X11/programs/Xserver/include/windowstr.h @@ -96,6 +96,33 @@ typedef struct _WindowOpt { #define BackgroundPixel 2L #define BackgroundPixmap 3L +/* + * The redirectDraw field can have one of three values: + * + * RedirectDrawNone + * A normal window; painted into the same pixmap as the parent + * and clipping parent and siblings to its geometry. These + * windows get a clip list equal to the intersection of their + * geometry with the parent geometry, minus the geometry + * of overlapping None and Clipped siblings. + * RedirectDrawAutomatic + * A redirected window which clips parent and sibling drawing. + * Contents for these windows are manage inside the server. + * These windows get an internal clip list equal to their + * geometry. + * RedirectDrawManual + * A redirected window which does not clip parent and sibling + * drawing; the window must be represented within the parent + * geometry by the client performing the redirection management. + * Contents for these windows are managed outside the server. + * These windows get an internal clip list equal to their + * geometry. + */ + +#define RedirectDrawNone 0 +#define RedirectDrawAutomatic 1 +#define RedirectDrawManual 2 + typedef struct _Window { DrawableRec drawable; WindowPtr parent; /* ancestor chain */ @@ -138,7 +165,7 @@ typedef struct _Window { unsigned srcBuffer:1; /* source buffer for rendering */ #endif #ifdef COMPOSITE - unsigned redirectDraw:1; /* rendering is redirected from here */ + unsigned redirectDraw:2; /* rendering is redirected from here */ #endif DevUnion *devPrivates; } WindowRec; diff --git a/nx-X11/programs/Xserver/render/picture.c b/nx-X11/programs/Xserver/render/picture.c index 5d8496610..ddb21a07c 100644 --- a/nx-X11/programs/Xserver/render/picture.c +++ b/nx-X11/programs/Xserver/render/picture.c @@ -1649,6 +1649,99 @@ FreePictFormat (void * pPictFormat, return Success; } +/** + * ReduceCompositeOp is used to choose simpler ops for cases where alpha + * channels are always one and so math on the alpha channel per pixel becomes + * unnecessary. It may also avoid destination reads sometimes if apps aren't + * being careful to avoid these cases. + */ +static CARD8 +ReduceCompositeOp (CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst) +{ + Bool no_src_alpha, no_dst_alpha; + + no_src_alpha = PICT_FORMAT_COLOR(pSrc->format) && + PICT_FORMAT_A(pSrc->format) == 0 && + pSrc->alphaMap == NULL && + pMask == NULL; + no_dst_alpha = PICT_FORMAT_COLOR(pDst->format) && + PICT_FORMAT_A(pDst->format) == 0 && + pDst->alphaMap == NULL; + + /* TODO, maybe: Conjoint and Disjoint op reductions? */ + + /* Deal with simplifications where the source alpha is always 1. */ + if (no_src_alpha) + { + switch (op) { + case PictOpOver: + op = PictOpSrc; + break; + case PictOpInReverse: + op = PictOpDst; + break; + case PictOpOutReverse: + op = PictOpClear; + break; + case PictOpAtop: + op = PictOpIn; + break; + case PictOpAtopReverse: + op = PictOpOverReverse; + break; + case PictOpXor: + op = PictOpOut; + break; + default: + break; + } + } + + /* Deal with simplifications when the destination alpha is always 1 */ + if (no_dst_alpha) + { + switch (op) { + case PictOpOverReverse: + op = PictOpDst; + break; + case PictOpIn: + op = PictOpSrc; + break; + case PictOpOut: + op = PictOpClear; + break; + case PictOpAtop: + op = PictOpOver; + break; + case PictOpXor: + op = PictOpOutReverse; + break; + default: + break; + } + } + + /* Reduce some con/disjoint ops to the basic names. */ + switch (op) { + case PictOpDisjointClear: + case PictOpConjointClear: + op = PictOpClear; + break; + case PictOpDisjointSrc: + case PictOpConjointSrc: + op = PictOpSrc; + break; + case PictOpDisjointDst: + case PictOpConjointDst: + op = PictOpDst; + break; + default: + break; + } + + return op; +} + void CompositePicture (CARD8 op, PicturePtr pSrc, @@ -1669,6 +1762,11 @@ CompositePicture (CARD8 op, if (pMask) ValidatePicture (pMask); ValidatePicture (pDst); + + op = ReduceCompositeOp (op, pSrc, pMask, pDst); + if (op == PictOpDst) + return; + (*ps->Composite) (op, pSrc, pMask, |