summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Anholt <anholt@freebsd.org>2004-07-31 08:24:14 +0000
committerEric Anholt <anholt@freebsd.org>2004-07-31 08:24:14 +0000
commitd690556d496c7331bd112903a0c9e6553c7d3342 (patch)
tree0e0016e04d05d6cbcdfb689ddb05d8f3a928dadf
parent8763cca7f9927bd6c9caf804bf09dcfea929eed0 (diff)
Integrate COMPOSITEWRAP branch including composite wrapper. This code still
has several issues, including: - CopyWindow and PaintWindow wrappers missing (will be done soon) - Some segfaults seen in the Render wrappers. - Xprt server build breaks with Composite. - DDXs must be recompiled for Composite due to VisualRec size change. - Composite bugs pointed out by Deron Johnson in email. Also, reorder XFixes initialization according to comments by Keith which are also in xserver CVS.
-rw-r--r--composite/compalloc.c537
-rw-r--r--composite/compext.c408
-rw-r--r--composite/compinit.c371
-rw-r--r--composite/compint.h243
-rw-r--r--composite/compwindow.c708
-rw-r--r--dix/colormap.c22
-rw-r--r--dix/window.c31
-rw-r--r--include/pixmapstr.h4
-rw-r--r--include/scrnintstr.h4
-rw-r--r--include/windowstr.h3
-rw-r--r--mi/mi.h10
-rw-r--r--mi/miinitext.c25
-rw-r--r--mi/mivaltree.c39
-rw-r--r--miext/cw/cw.c570
-rw-r--r--miext/cw/cw.h164
-rw-r--r--miext/cw/cw_ops.c537
-rw-r--r--miext/cw/cw_render.c447
17 files changed, 4110 insertions, 13 deletions
diff --git a/composite/compalloc.c b/composite/compalloc.c
new file mode 100644
index 000000000..f63c475a7
--- /dev/null
+++ b/composite/compalloc.c
@@ -0,0 +1,537 @@
+/*
+ * $Id$
+ *
+ * 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_CONFIG_H
+#include <config.h>
+#endif
+#include "compint.h"
+
+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);
+
+ cs->damaged = TRUE;
+ cw->damaged = TRUE;
+}
+
+static void
+compDestroyDamage (DamagePtr pDamage, void *closure)
+{
+ WindowPtr pWin = (WindowPtr) closure;
+ CompWindowPtr cw = GetCompWindow (pWin);
+
+ cw->damage = 0;
+}
+
+/*
+ * Redirect one window for one client
+ */
+int
+compRedirectWindow (ClientPtr pClient, WindowPtr pWin, int update)
+{
+ CompWindowPtr cw = GetCompWindow (pWin);
+ CompClientWindowPtr ccw;
+ Bool wasMapped = pWin->mapped;
+
+ /*
+ * Only one Manual update is allowed
+ */
+ if (cw && update == CompositeRedirectManual)
+ for (ccw = cw->clients; ccw; ccw = ccw->next)
+ if (ccw->update == CompositeRedirectManual)
+ return BadAccess;
+
+ /*
+ * Allocate per-client per-window structure
+ * The client *could* allocate multiple, but while supported,
+ * it is not expected to be common
+ */
+ ccw = xalloc (sizeof (CompClientWindowRec));
+ if (!ccw)
+ return BadAlloc;
+ ccw->id = FakeClientID (pClient->index);
+ ccw->update = update;
+ /*
+ * Now make sure there's a per-window structure to hang this from
+ */
+ if (!cw)
+ {
+ cw = xalloc (sizeof (CompWindowRec));
+ if (!cw)
+ {
+ xfree (ccw);
+ return BadAlloc;
+ }
+ cw->damage = DamageCreate (compReportDamage,
+ compDestroyDamage,
+ DamageReportNonEmpty,
+ FALSE,
+ pWin->drawable.pScreen,
+ pWin);
+ if (!cw->damage)
+ {
+ xfree (ccw);
+ xfree (cw);
+ return BadAlloc;
+ }
+ if (wasMapped)
+ UnmapWindow (pWin, FALSE);
+
+ REGION_NULL (pScreen, &cw->borderClip);
+ cw->update = CompositeRedirectAutomatic;
+ cw->clients = 0;
+ cw->oldx = COMP_ORIGIN_INVALID;
+ cw->oldy = COMP_ORIGIN_INVALID;
+ cw->damageRegistered = FALSE;
+ cw->damaged = FALSE;
+ pWin->devPrivates[CompWindowPrivateIndex].ptr = cw;
+ }
+ ccw->next = cw->clients;
+ cw->clients = ccw;
+ if (!AddResource (ccw->id, CompositeClientWindowType, pWin))
+ return BadAlloc;
+ if (ccw->update == CompositeRedirectManual)
+ {
+ if (cw->damageRegistered)
+ {
+ DamageUnregister (&pWin->drawable, cw->damage);
+ cw->damageRegistered = FALSE;
+ }
+ cw->update = CompositeRedirectManual;
+ }
+
+ 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;
+ }
+
+ return Success;
+}
+
+/*
+ * Free one of the per-client per-window resources, clearing
+ * redirect and the per-window pointer as appropriate
+ */
+void
+compFreeClientWindow (WindowPtr pWin, XID id)
+{
+ CompWindowPtr cw = GetCompWindow (pWin);
+ CompClientWindowPtr ccw, *prev;
+ Bool wasMapped = pWin->mapped;
+
+ if (!cw)
+ return;
+ for (prev = &cw->clients; (ccw = *prev); prev = &ccw->next)
+ {
+ if (ccw->id == id)
+ {
+ *prev = ccw->next;
+ if (ccw->update == CompositeRedirectManual)
+ cw->update = CompositeRedirectAutomatic;
+ xfree (ccw);
+ break;
+ }
+ }
+ if (!cw->clients)
+ {
+ if (wasMapped)
+ UnmapWindow (pWin, FALSE);
+
+ if (pWin->redirectDraw)
+ compFreePixmap (pWin);
+
+ if (cw->damage)
+ DamageDestroy (cw->damage);
+
+ REGION_UNINIT (pScreen, &cw->borderClip);
+
+ pWin->devPrivates[CompWindowPrivateIndex].ptr = 0;
+ xfree (cw);
+ }
+ else if (cw->update == CompositeRedirectAutomatic &&
+ !cw->damageRegistered && pWin->redirectDraw)
+ {
+ DamageRegister (&pWin->drawable, cw->damage);
+ cw->damageRegistered = TRUE;
+ 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;
+ }
+}
+
+/*
+ * This is easy, just free the appropriate resource.
+ */
+
+int
+compUnredirectWindow (ClientPtr pClient, WindowPtr pWin, int update)
+{
+ CompWindowPtr cw = GetCompWindow (pWin);
+ CompClientWindowPtr ccw;
+
+ if (!cw)
+ return BadValue;
+
+ for (ccw = cw->clients; ccw; ccw = ccw->next)
+ if (ccw->update == update && CLIENT_ID(ccw->id) == pClient->index)
+ {
+ FreeResource (ccw->id, RT_NONE);
+ return Success;
+ }
+ return BadValue;
+}
+
+/*
+ * Redirect all subwindows for one client
+ */
+
+int
+compRedirectSubwindows (ClientPtr pClient, WindowPtr pWin, int update)
+{
+ CompSubwindowsPtr csw = GetCompSubwindows (pWin);
+ CompClientWindowPtr ccw;
+ WindowPtr pChild;
+
+ /*
+ * Only one Manual update is allowed
+ */
+ if (csw && update == CompositeRedirectManual)
+ for (ccw = csw->clients; ccw; ccw = ccw->next)
+ if (ccw->update == CompositeRedirectManual)
+ return BadAccess;
+ /*
+ * Allocate per-client per-window structure
+ * The client *could* allocate multiple, but while supported,
+ * it is not expected to be common
+ */
+ ccw = xalloc (sizeof (CompClientWindowRec));
+ if (!ccw)
+ return BadAlloc;
+ ccw->id = FakeClientID (pClient->index);
+ ccw->update = update;
+ /*
+ * Now make sure there's a per-window structure to hang this from
+ */
+ if (!csw)
+ {
+ csw = xalloc (sizeof (CompSubwindowsRec));
+ if (!csw)
+ {
+ xfree (ccw);
+ return BadAlloc;
+ }
+ csw->update = CompositeRedirectAutomatic;
+ csw->clients = 0;
+ pWin->devPrivates[CompSubwindowsPrivateIndex].ptr = csw;
+ }
+ /*
+ * Redirect all existing windows
+ */
+ for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib)
+ {
+ int ret = compRedirectWindow (pClient, pChild, update);
+ if (ret != Success)
+ {
+ for (pChild = pChild->nextSib; pChild; pChild = pChild->nextSib)
+ (void) compUnredirectWindow (pClient, pChild, update);
+ if (!csw->clients)
+ {
+ xfree (csw);
+ pWin->devPrivates[CompSubwindowsPrivateIndex].ptr = 0;
+ }
+ xfree (ccw);
+ return ret;
+ }
+ }
+ /*
+ * Hook into subwindows list
+ */
+ ccw->next = csw->clients;
+ csw->clients = ccw;
+ if (!AddResource (ccw->id, CompositeClientSubwindowsType, pWin))
+ return BadAlloc;
+ if (ccw->update == CompositeRedirectManual)
+ {
+ csw->update = CompositeRedirectManual;
+ /*
+ * tell damage extension that damage events for this client are
+ * critical output
+ */
+ DamageExtSetCritical (pClient, TRUE);
+ }
+ return Success;
+}
+
+/*
+ * Free one of the per-client per-subwindows resources,
+ * which frees one redirect per subwindow
+ */
+void
+compFreeClientSubwindows (WindowPtr pWin, XID id)
+{
+ CompSubwindowsPtr csw = GetCompSubwindows (pWin);
+ CompClientWindowPtr ccw, *prev;
+ WindowPtr pChild;
+
+ if (!csw)
+ return;
+ for (prev = &csw->clients; (ccw = *prev); prev = &ccw->next)
+ {
+ if (ccw->id == id)
+ {
+ ClientPtr pClient = clients[CLIENT_ID(id)];
+
+ *prev = ccw->next;
+ if (ccw->update == CompositeRedirectManual)
+ {
+ /*
+ * tell damage extension that damage events for this client are
+ * critical output
+ */
+ DamageExtSetCritical (pClient, FALSE);
+ csw->update = CompositeRedirectAutomatic;
+ if (pWin->mapped)
+ (*pWin->drawable.pScreen->ClearToBackground)(pWin, 0, 0, 0, 0, TRUE);
+ }
+
+ /*
+ * Unredirect all existing subwindows
+ */
+ for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib)
+ (void) compUnredirectWindow (pClient, pChild, ccw->update);
+
+ xfree (ccw);
+ break;
+ }
+ }
+
+ /*
+ * Check if all of the per-client records are gone
+ */
+ if (!csw->clients)
+ {
+ pWin->devPrivates[CompSubwindowsPrivateIndex].ptr = 0;
+ xfree (csw);
+ }
+}
+
+/*
+ * This is easy, just free the appropriate resource.
+ */
+
+int
+compUnredirectSubwindows (ClientPtr pClient, WindowPtr pWin, int update)
+{
+ CompSubwindowsPtr csw = GetCompSubwindows (pWin);
+ CompClientWindowPtr ccw;
+
+ if (!csw)
+ return BadValue;
+ for (ccw = csw->clients; ccw; ccw = ccw->next)
+ if (ccw->update == update && CLIENT_ID(ccw->id) == pClient->index)
+ {
+ FreeResource (ccw->id, RT_NONE);
+ return Success;
+ }
+ return BadValue;
+}
+
+/*
+ * Add redirection information for one subwindow (during reparent)
+ */
+
+int
+compRedirectOneSubwindow (WindowPtr pParent, WindowPtr pWin)
+{
+ CompSubwindowsPtr csw = GetCompSubwindows (pParent);
+ CompClientWindowPtr ccw;
+
+ if (!csw)
+ return Success;
+ for (ccw = csw->clients; ccw; ccw = ccw->next)
+ {
+ int ret = compRedirectWindow (clients[CLIENT_ID(ccw->id)],
+ pWin, ccw->update);
+ if (ret != Success)
+ return ret;
+ }
+ return Success;
+}
+
+/*
+ * Remove redirection information for one subwindow (during reparent)
+ */
+
+int
+compUnredirectOneSubwindow (WindowPtr pParent, WindowPtr pWin)
+{
+ CompSubwindowsPtr csw = GetCompSubwindows (pParent);
+ CompClientWindowPtr ccw;
+
+ if (!csw)
+ return Success;
+ for (ccw = csw->clients; ccw; ccw = ccw->next)
+ {
+ int ret = compUnredirectWindow (clients[CLIENT_ID(ccw->id)],
+ pWin, ccw->update);
+ if (ret != Success)
+ return ret;
+ }
+ return Success;
+}
+
+Bool
+compAllocPixmap (WindowPtr pWin)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ PixmapPtr pPixmap;
+ int bw = (int) pWin->borderWidth;
+ int x, y, w, h;
+ CompWindowPtr cw = GetCompWindow (pWin);
+
+ x = pWin->drawable.x - bw;
+ y = pWin->drawable.y - bw;
+ w = pWin->drawable.width + (bw << 1);
+ h = pWin->drawable.height + (bw << 1);
+ pPixmap = (*pScreen->CreatePixmap) (pScreen, w, h, pWin->drawable.depth);
+ if (!pPixmap)
+ return FALSE;
+ pPixmap->screen_x = x;
+ pPixmap->screen_y = y;
+ pWin->redirectDraw = TRUE;
+ compSetPixmap (pWin, pPixmap);
+ cw->oldx = COMP_ORIGIN_INVALID;
+ cw->oldy = COMP_ORIGIN_INVALID;
+ cw->damageRegistered = FALSE;
+ if (cw->update == CompositeRedirectAutomatic)
+ {
+ DamageRegister (&pWin->drawable, cw->damage);
+ cw->damageRegistered = TRUE;
+ }
+ return TRUE;
+}
+
+void
+compFreePixmap (WindowPtr pWin)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ PixmapPtr pRedirectPixmap, pParentPixmap;
+ CompWindowPtr cw = GetCompWindow (pWin);
+
+ if (cw->damageRegistered)
+ {
+ DamageUnregister (&pWin->drawable, cw->damage);
+ cw->damageRegistered = FALSE;
+ }
+ /*
+ * Move the parent-constrained border clip region back into
+ * the window so that ValidateTree will handle the unmap
+ * case correctly. Unmap adds the window borderClip to the
+ * parent exposed area; regions beyond the parent cause crashes
+ */
+ REGION_COPY (pScreen, &pWin->borderClip, &cw->borderClip);
+ pRedirectPixmap = (*pScreen->GetWindowPixmap) (pWin);
+ pParentPixmap = (*pScreen->GetWindowPixmap) (pWin->parent);
+ pWin->redirectDraw = FALSE;
+ compSetPixmap (pWin, pParentPixmap);
+ (*pScreen->DestroyPixmap) (pRedirectPixmap);
+}
+
+/*
+ * Make sure the pixmap is the right size and offset. Allocate a new
+ * pixmap to change size, adjust origin to change offset, leaving the
+ * old pixmap in cw->pOldPixmap so bits can be recovered
+ */
+Bool
+compReallocPixmap (WindowPtr pWin, int draw_x, int draw_y,
+ unsigned int w, unsigned int h, int bw)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ PixmapPtr pOld = (*pScreen->GetWindowPixmap) (pWin);
+ PixmapPtr pNew;
+ CompWindowPtr cw = GetCompWindow (pWin);
+ int pix_x, pix_y;
+ unsigned int pix_w, pix_h;
+
+ assert (cw && pWin->redirectDraw);
+ pix_x = draw_x - bw;
+ pix_y = draw_y - bw;
+ pix_w = w + (bw << 1);
+ pix_h = h + (bw << 1);
+ cw->oldx = pOld->screen_x;
+ cw->oldy = pOld->screen_y;
+ if (pix_w != pOld->drawable.width ||
+ pix_h != pOld->drawable.height)
+ {
+ GCPtr pGC;
+
+ pNew = (*pScreen->CreatePixmap) (pScreen, pix_w, pix_h, pWin->drawable.depth);
+ if (!pNew)
+ return FALSE;
+ cw->pOldPixmap = pOld;
+ compSetPixmap (pWin, pNew);
+ /*
+ * Copy new bits to align at same place on the screen. CopyWindow
+ * calls will patch up any differences
+ */
+ pGC = GetScratchGC (pNew->drawable.depth, pScreen);
+ if (pGC)
+ {
+ ValidateGC(&pNew->drawable, pGC);
+ (*pGC->ops->CopyArea) (&pOld->drawable,
+ &pNew->drawable,
+ pGC,
+ pWin->drawable.x - draw_x,
+ pWin->drawable.y - draw_y,
+ pix_w, pix_h,
+ 0, 0);
+ FreeScratchGC (pGC);
+ }
+ }
+ else
+ {
+ pNew = pOld;
+ cw->pOldPixmap = 0;
+ }
+ pNew->screen_x = pix_x;
+ pNew->screen_y = pix_y;
+ return TRUE;
+}
diff --git a/composite/compext.c b/composite/compext.c
new file mode 100644
index 000000000..477066024
--- /dev/null
+++ b/composite/compext.c
@@ -0,0 +1,408 @@
+/*
+ * $Id$
+ *
+ * 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_CONFIG_H
+#include <config.h>
+#endif
+#include "compint.h"
+
+static CARD8 CompositeReqCode;
+int CompositeClientPrivateIndex;
+RESTYPE CompositeClientWindowType;
+RESTYPE CompositeClientSubwindowsType;
+
+typedef struct _CompositeClient {
+ int major_version;
+ int minor_version;
+} CompositeClientRec, *CompositeClientPtr;
+
+#define GetCompositeClient(pClient) ((CompositeClientPtr) (pClient)->devPrivates[CompositeClientPrivateIndex].ptr)
+
+static void
+CompositeClientCallback (CallbackListPtr *list,
+ pointer closure,
+ pointer data)
+{
+ NewClientInfoRec *clientinfo = (NewClientInfoRec *) data;
+ ClientPtr pClient = clientinfo->client;
+ CompositeClientPtr pCompositeClient = GetCompositeClient (pClient);
+
+ pCompositeClient->major_version = 0;
+ pCompositeClient->minor_version = 0;
+}
+
+static void
+CompositeResetProc (ExtensionEntry *extEntry)
+{
+}
+
+static int
+FreeCompositeClientWindow (pointer value, XID ccwid)
+{
+ WindowPtr pWin = value;
+
+ compFreeClientWindow (pWin, ccwid);
+ return Success;
+}
+
+static int
+FreeCompositeClientSubwindows (pointer value, XID ccwid)
+{
+ WindowPtr pWin = value;
+
+ compFreeClientSubwindows (pWin, ccwid);
+ return Success;
+}
+
+static int
+ProcCompositeQueryVersion (ClientPtr client)
+{
+ CompositeClientPtr pCompositeClient = GetCompositeClient (client);
+ xCompositeQueryVersionReply rep;
+ 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) {
+ 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;
+ }
+ pCompositeClient->major_version = rep.majorVersion;
+ pCompositeClient->minor_version = rep.minorVersion;
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ swapl(&rep.majorVersion, n);
+ swapl(&rep.minorVersion, n);
+ }
+ WriteToClient(client, sizeof(xCompositeQueryVersionReply), (char *)&rep);
+ return(client->noClientException);
+}
+
+static int
+ProcCompositeRedirectWindow (ClientPtr client)
+{
+ WindowPtr pWin;
+ REQUEST(xCompositeRedirectWindowReq);
+
+ REQUEST_SIZE_MATCH(xCompositeRedirectWindowReq);
+ pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW);
+ if (!pWin)
+ {
+ client->errorValue = stuff->window;
+ return BadWindow;
+ }
+ return compRedirectWindow (client, pWin, stuff->update);
+}
+
+static int
+ProcCompositeRedirectSubwindows (ClientPtr client)
+{
+ WindowPtr pWin;
+ REQUEST(xCompositeRedirectSubwindowsReq);
+
+ REQUEST_SIZE_MATCH(xCompositeRedirectSubwindowsReq);
+ pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW);
+ if (!pWin)
+ {
+ client->errorValue = stuff->window;
+ return BadWindow;
+ }
+ return compRedirectSubwindows (client, pWin, stuff->update);
+}
+
+static int
+ProcCompositeUnredirectWindow (ClientPtr client)
+{
+ WindowPtr pWin;
+ REQUEST(xCompositeUnredirectWindowReq);
+
+ REQUEST_SIZE_MATCH(xCompositeUnredirectWindowReq);
+ pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW);
+ if (!pWin)
+ {
+ client->errorValue = stuff->window;
+ return BadWindow;
+ }
+ return compUnredirectWindow (client, pWin, stuff->update);
+}
+
+static int
+ProcCompositeUnredirectSubwindows (ClientPtr client)
+{
+ WindowPtr pWin;
+ REQUEST(xCompositeUnredirectSubwindowsReq);
+
+ REQUEST_SIZE_MATCH(xCompositeUnredirectSubwindowsReq);
+ pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW);
+ if (!pWin)
+ {
+ client->errorValue = stuff->window;
+ return BadWindow;
+ }
+ return compUnredirectSubwindows (client, pWin, stuff->update);
+}
+
+static int
+ProcCompositeCreateRegionFromBorderClip (ClientPtr client)
+{
+ WindowPtr pWin;
+ CompWindowPtr cw;
+ RegionPtr pBorderClip, pRegion;
+ REQUEST(xCompositeCreateRegionFromBorderClipReq);
+
+ REQUEST_SIZE_MATCH(xCompositeCreateRegionFromBorderClipReq);
+ pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW);
+ if (!pWin)
+ {
+ client->errorValue = stuff->window;
+ return BadWindow;
+ }
+
+ LEGAL_NEW_RESOURCE (stuff->region, client);
+
+ cw = GetCompWindow (pWin);
+ if (cw)
+ pBorderClip = &cw->borderClip;
+ else
+ pBorderClip = &pWin->borderClip;
+ pRegion = XFixesRegionCopy (pBorderClip);
+ if (!pRegion)
+ return BadAlloc;
+ REGION_TRANSLATE (pScreen, pRegion, -pWin->drawable.x, -pWin->drawable.y);
+
+ if (!AddResource (stuff->region, RegionResType, (pointer) pRegion))
+ return BadAlloc;
+
+ return(client->noClientException);
+}
+
+static int
+ProcCompositeNameWindowPixmap (ClientPtr client)
+{
+ WindowPtr pWin;
+ CompWindowPtr cw;
+ PixmapPtr pPixmap;
+ REQUEST(xCompositeNameWindowPixmapReq);
+
+ REQUEST_SIZE_MATCH(xCompositeNameWindowPixmapReq);
+ pWin = (WindowPtr) LookupIDByType (stuff->window, RT_WINDOW);
+ if (!pWin)
+ {
+ client->errorValue = stuff->window;
+ return BadWindow;
+ }
+
+ LEGAL_NEW_RESOURCE (stuff->pixmap, client);
+
+ cw = GetCompWindow (pWin);
+ if (!cw)
+ return BadMatch;
+
+ pPixmap = (*pWin->drawable.pScreen->GetWindowPixmap) (pWin);
+ if (!pPixmap)
+ return BadMatch;
+
+ ++pPixmap->refcnt;
+
+ if (!AddResource (stuff->pixmap, RT_PIXMAP, (pointer) pPixmap))
+ return BadAlloc;
+
+ return(client->noClientException);
+}
+
+int (*ProcCompositeVector[CompositeNumberRequests])(ClientPtr) = {
+ ProcCompositeQueryVersion,
+ ProcCompositeRedirectWindow,
+ ProcCompositeRedirectSubwindows,
+ ProcCompositeUnredirectWindow,
+ ProcCompositeUnredirectSubwindows,
+ ProcCompositeCreateRegionFromBorderClip,
+ ProcCompositeNameWindowPixmap,
+};
+
+static int
+ProcCompositeDispatch (ClientPtr client)
+{
+ REQUEST(xReq);
+
+ if (stuff->data < CompositeNumberRequests)
+ return (*ProcCompositeVector[stuff->data]) (client);
+ else
+ return BadRequest;
+}
+
+static int
+SProcCompositeQueryVersion (ClientPtr client)
+{
+ int n;
+ REQUEST(xCompositeQueryVersionReq);
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xCompositeQueryVersionReq);
+ swapl(&stuff->majorVersion, n);
+ swapl(&stuff->minorVersion, n);
+ return (*ProcCompositeVector[stuff->compositeReqType]) (client);
+}
+
+static int
+SProcCompositeRedirectWindow (ClientPtr client)
+{
+ int n;
+ REQUEST(xCompositeRedirectWindowReq);
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xCompositeRedirectWindowReq);
+ swapl (&stuff->window, n);
+ return (*ProcCompositeVector[stuff->compositeReqType]) (client);
+}
+
+static int
+SProcCompositeRedirectSubwindows (ClientPtr client)
+{
+ int n;
+ REQUEST(xCompositeRedirectSubwindowsReq);
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xCompositeRedirectSubwindowsReq);
+ swapl (&stuff->window, n);
+ return (*ProcCompositeVector[stuff->compositeReqType]) (client);
+}
+
+static int
+SProcCompositeUnredirectWindow (ClientPtr client)
+{
+ int n;
+ REQUEST(xCompositeUnredirectWindowReq);
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xCompositeUnredirectWindowReq);
+ swapl (&stuff->window, n);
+ return (*ProcCompositeVector[stuff->compositeReqType]) (client);
+}
+
+static int
+SProcCompositeUnredirectSubwindows (ClientPtr client)
+{
+ int n;
+ REQUEST(xCompositeUnredirectSubwindowsReq);
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xCompositeUnredirectSubwindowsReq);
+ swapl (&stuff->window, n);
+ return (*ProcCompositeVector[stuff->compositeReqType]) (client);
+}
+
+static int
+SProcCompositeCreateRegionFromBorderClip (ClientPtr client)
+{
+ int n;
+ REQUEST(xCompositeCreateRegionFromBorderClipReq);
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xCompositeCreateRegionFromBorderClipReq);
+ swapl (&stuff->region, n);
+ swapl (&stuff->window, n);
+ return (*ProcCompositeVector[stuff->compositeReqType]) (client);
+}
+
+static int
+SProcCompositeNameWindowPixmap (ClientPtr client)
+{
+ int n;
+ REQUEST(xCompositeNameWindowPixmapReq);
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xCompositeNameWindowPixmapReq);
+ swapl (&stuff->window, n);
+ swapl (&stuff->pixmap, n);
+ return (*ProcCompositeVector[stuff->compositeReqType]) (client);
+}
+
+int (*SProcCompositeVector[CompositeNumberRequests])(ClientPtr) = {
+ SProcCompositeQueryVersion,
+ SProcCompositeRedirectWindow,
+ SProcCompositeRedirectSubwindows,
+ SProcCompositeUnredirectWindow,
+ SProcCompositeUnredirectSubwindows,
+ SProcCompositeCreateRegionFromBorderClip,
+ SProcCompositeNameWindowPixmap,
+};
+
+static int
+SProcCompositeDispatch (ClientPtr client)
+{
+ REQUEST(xReq);
+
+ if (stuff->data < CompositeNumberRequests)
+ return (*SProcCompositeVector[stuff->data]) (client);
+ else
+ return BadRequest;
+}
+
+void
+CompositeExtensionInit (void)
+{
+ ExtensionEntry *extEntry;
+ int s;
+
+ CompositeClientWindowType = CreateNewResourceType (FreeCompositeClientWindow);
+ if (!CompositeClientWindowType)
+ return;
+
+ CompositeClientSubwindowsType = CreateNewResourceType (FreeCompositeClientSubwindows);
+ if (!CompositeClientSubwindowsType)
+ return;
+
+ CompositeClientPrivateIndex = AllocateClientPrivateIndex ();
+ if (!AllocateClientPrivate (CompositeClientPrivateIndex,
+ sizeof (CompositeClientRec)))
+ return;
+ if (!AddCallback (&ClientStateCallback, CompositeClientCallback, 0))
+ return;
+
+ extEntry = AddExtension (COMPOSITE_NAME, 0, 0,
+ ProcCompositeDispatch, SProcCompositeDispatch,
+ CompositeResetProc, StandardMinorOpcode);
+ if (!extEntry)
+ return;
+ CompositeReqCode = (CARD8) extEntry->base;
+
+
+ for (s = 0; s < screenInfo.numScreens; s++)
+ if (!compScreenInit (screenInfo.screens[s]))
+ return;
+ miRegisterRedirectBorderClipProc (compSetRedirectBorderClip,
+ compGetRedirectBorderClip);
+}
diff --git a/composite/compinit.c b/composite/compinit.c
new file mode 100644
index 000000000..5f899f60f
--- /dev/null
+++ b/composite/compinit.c
@@ -0,0 +1,371 @@
+/*
+ * $Id$
+ *
+ * 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_CONFIG_H
+#include <config.h>
+#endif
+#include "compint.h"
+
+int CompScreenPrivateIndex;
+int CompWindowPrivateIndex;
+int CompSubwindowsPrivateIndex;
+int CompGeneration;
+
+static Bool
+compCloseScreen (int index, ScreenPtr pScreen)
+{
+ CompScreenPtr cs = GetCompScreen (pScreen);
+ Bool ret;
+
+ pScreen->CloseScreen = cs->CloseScreen;
+ pScreen->BlockHandler = cs->BlockHandler;
+ pScreen->ReparentWindow = cs->ReparentWindow;
+ 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;
+ xfree (cs);
+ pScreen->devPrivates[CompScreenPrivateIndex].ptr = 0;
+ ret = (*pScreen->CloseScreen) (index, pScreen);
+ return ret;
+}
+
+static void
+compScreenUpdate (ScreenPtr pScreen)
+{
+ CompScreenPtr cs = GetCompScreen (pScreen);
+
+ compCheckTree (pScreen);
+ if (cs->damaged)
+ {
+ compWindowUpdate (WindowTable[pScreen->myNum]);
+ cs->damaged = FALSE;
+ }
+}
+
+static void
+compBlockHandler (int i,
+ pointer blockData,
+ pointer pTimeout,
+ pointer pReadmask)
+{
+ ScreenPtr pScreen = screenInfo.screens[i];
+ CompScreenPtr cs = GetCompScreen (pScreen);
+
+ pScreen->BlockHandler = cs->BlockHandler;
+ compScreenUpdate (pScreen);
+ (*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask);
+ cs->BlockHandler = pScreen->BlockHandler;
+ pScreen->BlockHandler = compBlockHandler;
+}
+
+/*
+ * Add alternate visuals -- always expose an ARGB32 and RGB24 visual
+ */
+
+static DepthPtr
+compFindVisuallessDepth (ScreenPtr pScreen, int d)
+{
+ int i;
+
+ for (i = 0; i < pScreen->numDepths; i++)
+ {
+ DepthPtr depth = &pScreen->allowedDepths[i];
+ if (depth->depth == d)
+ {
+ /*
+ * Make sure it doesn't have visuals already
+ */
+ if (depth->numVids)
+ return 0;
+ /*
+ * looks fine
+ */
+ return depth;
+ }
+ }
+ /*
+ * If there isn't one, then it's gonna be hard to have
+ * an associated visual
+ */
+ return 0;
+}
+
+typedef struct _alternateVisual {
+ int depth;
+ CARD32 format;
+} CompAlternateVisual;
+
+static CompAlternateVisual altVisuals[NUM_COMP_ALTERNATE_VISUALS] = {
+ { 24, PICT_r8g8b8 },
+ { 32, PICT_a8r8g8b8 },
+};
+
+static Bool
+compAddAlternateVisuals (ScreenPtr pScreen, CompScreenPtr cs)
+{
+ 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;
+
+ /*
+ * Ok, create a visual id for this format
+ */
+ cs->alternateVisuals[numAlternate] = FakeClientID (0);
+ /*
+ * Allocate vid list for this depth
+ */
+ vids[numAlternate] = xalloc (sizeof (VisualID));
+ if (!vids[numAlternate])
+ continue;
+ depths[numAlternate] = depth;
+ pPictFormats[numAlternate] = pPictFormat;
+ numAlternate++;
+ }
+
+ if (!numAlternate)
+ return TRUE;
+
+ /*
+ * Find the installed colormaps
+ */
+ installedCmaps = xalloc (pScreen->maxInstalledCmaps * sizeof (XID));
+ if (!installedCmaps)
+ {
+ for (alt = 0; alt < numAlternate; alt++)
+ xfree (vids[alt]);
+ 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);
+ 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;
+
+ for (alt = 0; alt < numAlternate; alt++)
+ {
+ DepthPtr depth = depths[alt];
+ PictFormatPtr pPictFormat = pPictFormats[alt];
+ VisualPtr visual = &visuals[numVisuals + alt];
+
+ /*
+ * Initialize the visual
+ */
+ visual->class = TrueColor;
+ 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);
+ visual->offsetRed = pPictFormat->direct.red;
+ visual->offsetGreen = pPictFormat->direct.green;
+ visual->offsetBlue = pPictFormat->direct.blue;
+ visual->alphaMask = (((unsigned long) pPictFormat->direct.alphaMask) <<
+ pPictFormat->direct.alpha);
+ visual->offsetAlpha = pPictFormat->direct.alpha;
+ /*
+ * follow GLX and set nplanes to just the bits
+ * used for the RGB value, not A
+ */
+ visual->nplanes = Ones (visual->redMask |
+ visual->greenMask |
+ visual->blueMask);
+ /*
+ * 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;
+
+ /*
+ * Fix up the depth
+ */
+ vids[alt][0] = visual->vid;
+ depth->numVids = 1;
+ depth->vids = vids[alt];
+ }
+ return TRUE;
+}
+
+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)
+ return FALSE;
+ CompGeneration = serverGeneration;
+ }
+ if (!AllocateWindowPrivate (pScreen, CompWindowPrivateIndex, 0))
+ return FALSE;
+
+ if (!AllocateWindowPrivate (pScreen, CompSubwindowsPrivateIndex, 0))
+ return FALSE;
+
+ if (GetCompScreen (pScreen))
+ return TRUE;
+ cs = (CompScreenPtr) xalloc (sizeof (CompScreenRec));
+ if (!cs)
+ return FALSE;
+
+ cs->damaged = FALSE;
+
+ if (!compAddAlternateVisuals (pScreen, cs))
+ {
+ xfree (cs);
+ return FALSE;
+ }
+
+ cs->PositionWindow = pScreen->PositionWindow;
+ pScreen->PositionWindow = compPositionWindow;
+
+ cs->CopyWindow = pScreen->CopyWindow;
+ pScreen->CopyWindow = compCopyWindow;
+
+ cs->CreateWindow = pScreen->CreateWindow;
+ pScreen->CreateWindow = compCreateWindow;
+
+ cs->DestroyWindow = pScreen->DestroyWindow;
+ pScreen->DestroyWindow = compDestroyWindow;
+
+ cs->RealizeWindow = pScreen->RealizeWindow;
+ pScreen->RealizeWindow = compRealizeWindow;
+
+ cs->UnrealizeWindow = pScreen->UnrealizeWindow;
+ pScreen->UnrealizeWindow = compUnrealizeWindow;
+
+ cs->PaintWindowBackground = pScreen->PaintWindowBackground;
+ pScreen->PaintWindowBackground = compPaintWindowBackground;
+
+ cs->ClipNotify = pScreen->ClipNotify;
+ pScreen->ClipNotify = compClipNotify;
+
+ cs->MoveWindow = pScreen->MoveWindow;
+ pScreen->MoveWindow = compMoveWindow;
+
+ cs->ResizeWindow = pScreen->ResizeWindow;
+ pScreen->ResizeWindow = compResizeWindow;
+
+ cs->ChangeBorderWidth = pScreen->ChangeBorderWidth;
+ pScreen->ChangeBorderWidth = compChangeBorderWidth;
+
+ cs->ReparentWindow = pScreen->ReparentWindow;
+ pScreen->ReparentWindow = compReparentWindow;
+
+ cs->BlockHandler = pScreen->BlockHandler;
+ pScreen->BlockHandler = compBlockHandler;
+
+ cs->CloseScreen = pScreen->CloseScreen;
+ pScreen->CloseScreen = compCloseScreen;
+
+ miInitializeCompositeWrapper(pScreen);
+
+ pScreen->devPrivates[CompScreenPrivateIndex].ptr = (pointer) cs;
+ return TRUE;
+}
diff --git a/composite/compint.h b/composite/compint.h
new file mode 100644
index 000000000..43a2f4be5
--- /dev/null
+++ b/composite/compint.h
@@ -0,0 +1,243 @@
+/*
+ * $Id$
+ *
+ * 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.
+ */
+
+#ifndef _COMPINT_H_
+#define _COMPINT_H_
+
+#include "misc.h"
+#include "scrnintstr.h"
+#include "os.h"
+#include "regionstr.h"
+#include "validate.h"
+#include "windowstr.h"
+#include "input.h"
+#include "resource.h"
+#include "colormapst.h"
+#include "cursorstr.h"
+#include "dixstruct.h"
+#include "gcstruct.h"
+#include "servermd.h"
+#include "dixevents.h"
+#include "globals.h"
+#include "picturestr.h"
+#include "extnsionst.h"
+#include "mi.h"
+#include "damage.h"
+#include "damageextint.h"
+#include "xfixes.h"
+#include <X11/extensions/compositeproto.h>
+#include <assert.h>
+
+typedef struct _CompClientWindow {
+ struct _CompClientWindow *next;
+ XID id;
+ int update;
+} CompClientWindowRec, *CompClientWindowPtr;
+
+typedef struct _CompWindow {
+ RegionRec borderClip;
+ DamagePtr damage; /* for automatic update mode */
+ Bool damageRegistered;
+ Bool damaged;
+ int update;
+ CompClientWindowPtr clients;
+ int oldx;
+ int oldy;
+ PixmapPtr pOldPixmap;
+ int borderClipX, borderClipY;
+} CompWindowRec, *CompWindowPtr;
+
+#define COMP_ORIGIN_INVALID 0x80000000
+
+typedef struct _CompSubwindows {
+ int update;
+ CompClientWindowPtr clients;
+} CompSubwindowsRec, *CompSubwindowsPtr;
+
+extern int CompPixmapPrivateIndex;
+
+#define NUM_COMP_ALTERNATE_VISUALS 2
+
+typedef struct _CompScreen {
+ PositionWindowProcPtr PositionWindow;
+ CopyWindowProcPtr CopyWindow;
+ CreateWindowProcPtr CreateWindow;
+ DestroyWindowProcPtr DestroyWindow;
+ RealizeWindowProcPtr RealizeWindow;
+ UnrealizeWindowProcPtr UnrealizeWindow;
+ PaintWindowProcPtr PaintWindowBackground;
+ ClipNotifyProcPtr ClipNotify;
+ /*
+ * Called from ConfigureWindow, these
+ * three track changes to the offscreen storage
+ * geometry
+ */
+ MoveWindowProcPtr MoveWindow;
+ ResizeWindowProcPtr ResizeWindow;
+ ChangeBorderWidthProcPtr ChangeBorderWidth;
+ /*
+ * Reparenting has an effect on Subwindows redirect
+ */
+ ReparentWindowProcPtr ReparentWindow;
+
+ ScreenBlockHandlerProcPtr BlockHandler;
+ CloseScreenProcPtr CloseScreen;
+ Bool damaged;
+ XID alternateVisuals[NUM_COMP_ALTERNATE_VISUALS];
+} CompScreenRec, *CompScreenPtr;
+
+#define HasCompRedirect(w) (wPixmap(w) != wPixmap(w->parent))
+#define wScreen(w) ((w)->drawable.pScreen)
+#define wPixmap(w) (*(wScreen(w)->GetWindowPixmap) (w))
+
+extern int CompScreenPrivateIndex;
+extern int CompWindowPrivateIndex;
+extern int CompSubwindowsPrivateIndex;
+
+#define GetCompScreen(s) ((CompScreenPtr) ((s)->devPrivates[CompScreenPrivateIndex].ptr))
+#define GetCompWindow(w) ((CompWindowPtr) ((w)->devPrivates[CompWindowPrivateIndex].ptr))
+#define GetCompSubwindows(w) ((CompSubwindowsPtr) ((w)->devPrivates[CompSubwindowsPrivateIndex].ptr))
+
+extern RESTYPE CompositeClientWindowType;
+extern RESTYPE CompositeClientSubwindowsType;
+
+/*
+ * compalloc.c
+ */
+
+void
+compReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure);
+
+Bool
+compRedirectWindow (ClientPtr pClient, WindowPtr pWin, int update);
+
+void
+compFreeClientWindow (WindowPtr pWin, XID id);
+
+int
+compUnredirectWindow (ClientPtr pClient, WindowPtr pWin, int update);
+
+int
+compRedirectSubwindows (ClientPtr pClient, WindowPtr pWin, int update);
+
+void
+compFreeClientSubwindows (WindowPtr pWin, XID id);
+
+int
+compUnredirectSubwindows (ClientPtr pClient, WindowPtr pWin, int update);
+
+int
+compRedirectOneSubwindow (WindowPtr pParent, WindowPtr pWin);
+
+int
+compUnredirectOneSubwindow (WindowPtr pParent, WindowPtr pWin);
+
+Bool
+compAllocPixmap (WindowPtr pWin);
+
+void
+compFreePixmap (WindowPtr pWin);
+
+Bool
+compReallocPixmap (WindowPtr pWin, int x, int y,
+ unsigned int w, unsigned int h, int bw);
+
+/*
+ * compext.c
+ */
+
+void
+CompositeExtensionInit (void);
+
+/*
+ * compinit.c
+ */
+
+Bool
+compScreenInit (ScreenPtr pScreen);
+
+/*
+ * compwindow.c
+ */
+
+#ifdef NDEBUG
+#define compCheckTree(s)
+#else
+void
+compCheckTree (ScreenPtr pScreen);
+#endif
+
+void
+compSetPixmap (WindowPtr pWin, PixmapPtr pPixmap);
+
+Bool
+compCheckRedirect (WindowPtr pWin);
+
+Bool
+compPositionWindow (WindowPtr pWin, int x, int y);
+
+Bool
+compRealizeWindow (WindowPtr pWin);
+
+Bool
+compUnrealizeWindow (WindowPtr pWin);
+
+void
+compPaintWindowBackground (WindowPtr pWin, RegionPtr pRegion, int what);
+
+void
+compClipNotify (WindowPtr pWin, int dx, int dy);
+
+void
+compMoveWindow (WindowPtr pWin, int x, int y, WindowPtr pSib, VTKind kind);
+
+void
+compResizeWindow (WindowPtr pWin, int x, int y,
+ unsigned int w, unsigned int h, WindowPtr pSib);
+
+void
+compChangeBorderWidth (WindowPtr pWin, unsigned int border_width);
+
+void
+compReparentWindow (WindowPtr pWin, WindowPtr pPriorParent);
+
+Bool
+compCreateWindow (WindowPtr pWin);
+
+Bool
+compDestroyWindow (WindowPtr pWin);
+
+void
+compSetRedirectBorderClip (WindowPtr pWin, RegionPtr pRegion);
+
+RegionPtr
+compGetRedirectBorderClip (WindowPtr pWin);
+
+void
+compCopyWindow (WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc);
+
+void
+compWindowUpdate (WindowPtr pWin);
+
+#endif /* _COMPINT_H_ */
diff --git a/composite/compwindow.c b/composite/compwindow.c
new file mode 100644
index 000000000..ec63fbcb1
--- /dev/null
+++ b/composite/compwindow.c
@@ -0,0 +1,708 @@
+/*
+ * $Id$
+ *
+ * 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_CONFIG_H
+#include <config.h>
+#endif
+#include "compint.h"
+
+#ifndef NDEBUG
+static int
+compCheckWindow (WindowPtr pWin, pointer data)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ PixmapPtr pWinPixmap = (*pScreen->GetWindowPixmap) (pWin);
+ PixmapPtr pParentPixmap = pWin->parent ? (*pScreen->GetWindowPixmap) (pWin->parent) : 0;
+ PixmapPtr pScreenPixmap = (*pScreen->GetScreenPixmap) (pScreen);
+
+ if (!pWin->parent)
+ {
+ assert (!pWin->redirectDraw);
+ assert (pWinPixmap == pScreenPixmap);
+ }
+ else if (pWin->redirectDraw)
+ {
+ assert (pWinPixmap != pParentPixmap);
+ assert (pWinPixmap != pScreenPixmap);
+ }
+ else
+ {
+ assert (pWinPixmap == pParentPixmap);
+ }
+ assert (0 < pWinPixmap->refcnt && pWinPixmap->refcnt < 3);
+ assert (0 < pScreenPixmap->refcnt && pScreenPixmap->refcnt < 3);
+ if (pParentPixmap)
+ assert (0 <= pParentPixmap->refcnt && pParentPixmap->refcnt < 3);
+ return WT_WALKCHILDREN;
+}
+
+void
+compCheckTree (ScreenPtr pScreen)
+{
+ WalkTree (pScreen, compCheckWindow, 0);
+}
+#endif
+
+typedef struct _compPixmapVisit {
+ WindowPtr pWindow;
+ PixmapPtr pPixmap;
+} CompPixmapVisitRec, *CompPixmapVisitPtr;
+
+static int
+compSetPixmapVisitWindow (WindowPtr pWindow, pointer data)
+{
+ CompPixmapVisitPtr pVisit = (CompPixmapVisitPtr) data;
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+
+ if (pWindow != pVisit->pWindow && pWindow->redirectDraw)
+ return WT_DONTWALKCHILDREN;
+ (*pScreen->SetWindowPixmap) (pWindow, pVisit->pPixmap);
+ /*
+ * Recompute winSize and borderSize. This is duplicate effort
+ * when resizing pixmaps, but necessary when changing redirection.
+ * Might be nice to fix this.
+ */
+ SetWinSize (pWindow);
+ SetBorderSize (pWindow);
+ return WT_WALKCHILDREN;
+}
+
+void
+compSetPixmap (WindowPtr pWindow, PixmapPtr pPixmap)
+{
+ CompPixmapVisitRec visitRec;
+
+ visitRec.pWindow = pWindow;
+ visitRec.pPixmap = pPixmap;
+ TraverseTree (pWindow, compSetPixmapVisitWindow, (pointer) &visitRec);
+ compCheckTree (pWindow->drawable.pScreen);
+}
+
+Bool
+compCheckRedirect (WindowPtr pWin)
+{
+ CompWindowPtr cw = GetCompWindow (pWin);
+ Bool should = pWin->viewable && (cw != NULL);
+
+ if (should != pWin->redirectDraw)
+ {
+ if (should)
+ return compAllocPixmap (pWin);
+ else
+ compFreePixmap (pWin);
+ }
+ return TRUE;
+}
+
+Bool
+compPositionWindow (WindowPtr pWin, int x, int y)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ CompScreenPtr cs = GetCompScreen (pScreen);
+ Bool ret = TRUE;
+
+ pScreen->PositionWindow = cs->PositionWindow;
+ /*
+ * "Shouldn't need this as all possible places should be wrapped
+ *
+ compCheckRedirect (pWin);
+ */
+ if (pWin->redirectDraw != (pWin->viewable && (GetCompWindow(pWin) != NULL)))
+ abort ();
+ if (pWin->redirectDraw)
+ {
+ PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin);
+ int bw = wBorderWidth (pWin);
+ int nx = pWin->drawable.x - bw;
+ int ny = pWin->drawable.y - bw;
+
+ if (pPixmap->screen_x != nx || pPixmap->screen_y != ny)
+ {
+ pPixmap->screen_x = nx;
+ pPixmap->screen_y = ny;
+ pPixmap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
+ }
+ }
+
+ if (!(*pScreen->PositionWindow) (pWin, x, y))
+ ret = FALSE;
+ cs->PositionWindow = pScreen->PositionWindow;
+ pScreen->PositionWindow = compPositionWindow;
+ compCheckTree (pWin->drawable.pScreen);
+ return ret;
+}
+
+Bool
+compRealizeWindow (WindowPtr pWin)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ CompScreenPtr cs = GetCompScreen (pScreen);
+ Bool ret = TRUE;
+
+ pScreen->RealizeWindow = cs->RealizeWindow;
+ compCheckRedirect (pWin);
+ if (!(*pScreen->RealizeWindow) (pWin))
+ ret = FALSE;
+ cs->RealizeWindow = pScreen->RealizeWindow;
+ pScreen->RealizeWindow = compRealizeWindow;
+ compCheckTree (pWin->drawable.pScreen);
+ return ret;
+}
+
+Bool
+compUnrealizeWindow (WindowPtr pWin)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ CompScreenPtr cs = GetCompScreen (pScreen);
+ Bool ret = TRUE;
+
+ pScreen->UnrealizeWindow = cs->UnrealizeWindow;
+ compCheckRedirect (pWin);
+ if (!(*pScreen->UnrealizeWindow) (pWin))
+ ret = FALSE;
+ cs->UnrealizeWindow = pScreen->UnrealizeWindow;
+ pScreen->UnrealizeWindow = compUnrealizeWindow;
+ compCheckTree (pWin->drawable.pScreen);
+ 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
+ */
+
+void
+compClipNotify (WindowPtr pWin, int dx, int dy)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ CompScreenPtr cs = GetCompScreen (pScreen);
+ CompWindowPtr cw = GetCompWindow (pWin);
+
+ if (cw)
+ {
+ if (cw->borderClipX != pWin->drawable.x ||
+ cw->borderClipY != pWin->drawable.y)
+ {
+ REGION_TRANSLATE (pScreen, &cw->borderClip,
+ pWin->drawable.x - cw->borderClipX,
+ pWin->drawable.y - cw->borderClipY);
+ cw->borderClipX = pWin->drawable.x;
+ cw->borderClipY = pWin->drawable.y;
+ }
+ }
+ if (cs->ClipNotify)
+ {
+ pScreen->ClipNotify = cs->ClipNotify;
+ (*pScreen->ClipNotify) (pWin, dx, dy);
+ cs->ClipNotify = pScreen->ClipNotify;
+ pScreen->ClipNotify = compClipNotify;
+ }
+}
+
+/*
+ * Returns TRUE if the window needs server-provided automatic redirect,
+ * which is true if the child and parent aren't both regular or ARGB visuals
+ */
+
+static Bool
+compIsAlternateVisual (ScreenPtr pScreen,
+ XID visual)
+{
+ CompScreenPtr cs = GetCompScreen (pScreen);
+ int i;
+
+ for (i = 0; i < NUM_COMP_ALTERNATE_VISUALS; i++)
+ if (cs->alternateVisuals[i] == visual)
+ return TRUE;
+ return FALSE;
+}
+
+static Bool
+compImplicitRedirect (WindowPtr pWin, WindowPtr pParent)
+{
+ if (pParent)
+ {
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ XID winVisual = wVisual (pWin);
+ XID parentVisual = wVisual (pParent);
+
+ if (winVisual != parentVisual &&
+ (compIsAlternateVisual (pScreen, winVisual) ||
+ compIsAlternateVisual (pScreen, parentVisual)))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void
+compMoveWindow (WindowPtr pWin, int x, int y, WindowPtr pSib, VTKind kind)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ CompScreenPtr cs = GetCompScreen (pScreen);
+
+ compCheckTree (pScreen);
+ if (pWin->redirectDraw)
+ {
+ WindowPtr pParent;
+ int draw_x, draw_y;
+ unsigned int w, h, bw;
+
+ /* 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;
+ w = pWin->drawable.width;
+ h = pWin->drawable.height;
+ compReallocPixmap (pWin, draw_x, draw_y, w, h, bw);
+ }
+ compCheckTree (pScreen);
+
+ pScreen->MoveWindow = cs->MoveWindow;
+ (*pScreen->MoveWindow) (pWin, x, y, pSib, 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;
+ }
+ }
+
+ compCheckTree (pScreen);
+}
+
+void
+compResizeWindow (WindowPtr pWin, int x, int y,
+ unsigned int w, unsigned int h, WindowPtr pSib)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ CompScreenPtr cs = GetCompScreen (pScreen);
+
+ compCheckTree (pScreen);
+ if (pWin->redirectDraw)
+ {
+ 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;
+
+ bw = wBorderWidth (pWin);
+ draw_x = pParent->drawable.x + x + (int)bw;
+ draw_y = pParent->drawable.y + y + (int)bw;
+ 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;
+ }
+ }
+ compCheckTree (pWin->drawable.pScreen);
+}
+
+void
+compChangeBorderWidth (WindowPtr pWin, unsigned int bw)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ CompScreenPtr cs = GetCompScreen (pScreen);
+
+ compCheckTree (pScreen);
+ if (pWin->redirectDraw)
+ {
+ 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);
+
+ 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;
+ }
+ }
+ compCheckTree (pWin->drawable.pScreen);
+}
+
+void
+compReparentWindow (WindowPtr pWin, WindowPtr pPriorParent)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ CompScreenPtr cs = GetCompScreen (pScreen);
+
+ pScreen->ReparentWindow = cs->ReparentWindow;
+ /*
+ * Remove any implicit redirect due to synthesized visual
+ */
+ if (compImplicitRedirect (pWin, pPriorParent))
+ compUnredirectWindow (serverClient, pWin, CompositeRedirectAutomatic);
+ /*
+ * Handle subwindows redirection
+ */
+ compUnredirectOneSubwindow (pPriorParent, pWin);
+ compRedirectOneSubwindow (pWin->parent, pWin);
+ /*
+ * Add any implict redirect due to synthesized visual
+ */
+ if (compImplicitRedirect (pWin, pWin->parent))
+ compRedirectWindow (serverClient, pWin, CompositeRedirectAutomatic);
+
+ /*
+ * Allocate any necessary redirect pixmap
+ * (this actually should never be true; pWin is always unmapped)
+ */
+ compCheckRedirect (pWin);
+
+ /*
+ * Reset pixmap pointers as appropriate
+ */
+ if (pWin->parent && !pWin->redirectDraw)
+ compSetPixmap (pWin, (*pScreen->GetWindowPixmap) (pWin->parent));
+ /*
+ * Call down to next function
+ */
+ if (pScreen->ReparentWindow)
+ (*pScreen->ReparentWindow) (pWin, pPriorParent);
+ cs->ReparentWindow = pScreen->ReparentWindow;
+ pScreen->ReparentWindow = compReparentWindow;
+ compCheckTree (pWin->drawable.pScreen);
+}
+
+void
+compCopyWindow (WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ CompScreenPtr cs = GetCompScreen (pScreen);
+ int dx = 0, dy = 0;
+
+ if (pWin->redirectDraw)
+ {
+ PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin);
+ CompWindowPtr cw = GetCompWindow (pWin);
+
+ assert (cw->oldx != COMP_ORIGIN_INVALID);
+ assert (cw->oldy != COMP_ORIGIN_INVALID);
+ if (cw->pOldPixmap)
+ {
+ /*
+ * Ok, the old bits are available in pOldPixmap and
+ * need to be copied to pNewPixmap.
+ */
+ RegionRec rgnDst;
+ PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin);
+ GCPtr pGC;
+
+ dx = ptOldOrg.x - pWin->drawable.x;
+ dy = ptOldOrg.y - pWin->drawable.y;
+ REGION_TRANSLATE(pWin->drawable.pScreen, prgnSrc, -dx, -dy);
+
+ REGION_NULL (pWin->drawable.pScreen, &rgnDst);
+
+ REGION_INTERSECT(pWin->drawable.pScreen, &rgnDst,
+ &pWin->borderClip, prgnSrc);
+
+ REGION_TRANSLATE (pWin->drawable.pScreen, &rgnDst,
+ -pPixmap->screen_x, -pPixmap->screen_y);
+
+ dx = dx + pPixmap->screen_x - cw->oldx;
+ dy = dy + pPixmap->screen_y - cw->oldy;
+ pGC = GetScratchGC (pPixmap->drawable.depth, pScreen);
+ if (pGC)
+ {
+ BoxPtr pBox = REGION_RECTS (&rgnDst);
+ int nBox = REGION_NUM_RECTS (&rgnDst);
+
+ ValidateGC(&pPixmap->drawable, pGC);
+ while (nBox--)
+ {
+ (void) (*pGC->ops->CopyArea) (&cw->pOldPixmap->drawable,
+ &pPixmap->drawable,
+ pGC,
+ pBox->x1 + dx, pBox->y1 + dy,
+ pBox->x2 - pBox->x1,
+ pBox->y2 - pBox->y1,
+ pBox->x1, pBox->y1);
+ pBox++;
+ }
+ FreeScratchGC (pGC);
+ }
+ return;
+ }
+ dx = pPixmap->screen_x - cw->oldx;
+ dy = pPixmap->screen_y - cw->oldy;
+ ptOldOrg.x += dx;
+ ptOldOrg.y += dy;
+ }
+
+ pScreen->CopyWindow = cs->CopyWindow;
+ if (ptOldOrg.x != pWin->drawable.x || ptOldOrg.y != pWin->drawable.y)
+ {
+ if (dx || dy)
+ REGION_TRANSLATE (pScreen, prgnSrc, dx, dy);
+ (*pScreen->CopyWindow) (pWin, ptOldOrg, prgnSrc);
+ if (dx || dy)
+ REGION_TRANSLATE (pScreen, prgnSrc, -dx, -dy);
+ }
+ else
+ {
+ ptOldOrg.x -= dx;
+ ptOldOrg.y -= dy;
+ REGION_TRANSLATE (prgnSrc, prgnSrc,
+ pWin->drawable.x - ptOldOrg.x,
+ pWin->drawable.y - ptOldOrg.y);
+ DamageDamageRegion (&pWin->drawable, prgnSrc);
+ }
+ cs->CopyWindow = pScreen->CopyWindow;
+ pScreen->CopyWindow = compCopyWindow;
+ compCheckTree (pWin->drawable.pScreen);
+}
+
+Bool
+compCreateWindow (WindowPtr pWin)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ CompScreenPtr cs = GetCompScreen (pScreen);
+ Bool ret;
+
+ pScreen->CreateWindow = cs->CreateWindow;
+ ret = (*pScreen->CreateWindow) (pWin);
+ if (pWin->parent && ret)
+ {
+ CompSubwindowsPtr csw = GetCompSubwindows (pWin->parent);
+ CompClientWindowPtr ccw;
+
+ (*pScreen->SetWindowPixmap) (pWin, (*pScreen->GetWindowPixmap) (pWin->parent));
+ if (csw)
+ for (ccw = csw->clients; ccw; ccw = ccw->next)
+ compRedirectWindow (clients[CLIENT_ID(ccw->id)],
+ pWin, ccw->update);
+ if (compImplicitRedirect (pWin, pWin->parent))
+ compRedirectWindow (serverClient, pWin, CompositeRedirectAutomatic);
+ }
+ cs->CreateWindow = pScreen->CreateWindow;
+ pScreen->CreateWindow = compCreateWindow;
+ compCheckTree (pWin->drawable.pScreen);
+ return ret;
+}
+
+Bool
+compDestroyWindow (WindowPtr pWin)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ CompScreenPtr cs = GetCompScreen (pScreen);
+ CompWindowPtr cw;
+ CompSubwindowsPtr csw;
+ Bool ret;
+
+ pScreen->DestroyWindow = cs->DestroyWindow;
+ while ((cw = GetCompWindow (pWin)))
+ FreeResource (cw->clients->id, RT_NONE);
+ while ((csw = GetCompSubwindows (pWin)))
+ FreeResource (csw->clients->id, RT_NONE);
+
+ if (pWin->redirectDraw)
+ compFreePixmap (pWin);
+ ret = (*pScreen->DestroyWindow) (pWin);
+ cs->DestroyWindow = pScreen->DestroyWindow;
+ pScreen->DestroyWindow = compDestroyWindow;
+/* compCheckTree (pWin->drawable.pScreen); can't check -- tree isn't good*/
+ return ret;
+}
+
+void
+compSetRedirectBorderClip (WindowPtr pWin, RegionPtr pRegion)
+{
+ CompWindowPtr cw = GetCompWindow (pWin);
+ RegionRec damage;
+
+ REGION_NULL (pScreen, &damage);
+ /*
+ * Align old border clip with new border clip
+ */
+ REGION_TRANSLATE (pScreen, &cw->borderClip,
+ pWin->drawable.x - cw->borderClipX,
+ pWin->drawable.y - cw->borderClipY);
+ /*
+ * Compute newly visible portion of window for repaint
+ */
+ REGION_SUBTRACT (pScreen, &damage, pRegion, &cw->borderClip);
+ /*
+ * Report that as damaged so it will be redrawn
+ */
+ DamageDamageRegion (&pWin->drawable, &damage);
+ REGION_UNINIT (pScreen, &damage);
+ /*
+ * Save the new border clip region
+ */
+ REGION_COPY (pScreen, &cw->borderClip, pRegion);
+ cw->borderClipX = pWin->drawable.x;
+ cw->borderClipY = pWin->drawable.y;
+}
+
+RegionPtr
+compGetRedirectBorderClip (WindowPtr pWin)
+{
+ CompWindowPtr cw = GetCompWindow (pWin);
+
+ return &cw->borderClip;
+}
+
+static VisualPtr
+compGetWindowVisual (WindowPtr pWin)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ VisualID vid = wVisual (pWin);
+ int i;
+
+ for (i = 0; i < pScreen->numVisuals; i++)
+ if (pScreen->visuals[i].vid == vid)
+ return &pScreen->visuals[i];
+ return 0;
+}
+
+static PictFormatPtr
+compWindowFormat (WindowPtr pWin)
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+
+ return PictureMatchVisual (pScreen, pWin->drawable.depth,
+ compGetWindowVisual (pWin));
+}
+
+static void
+compWindowUpdateAutomatic (WindowPtr pWin)
+{
+ CompWindowPtr cw = GetCompWindow (pWin);
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ WindowPtr pParent = pWin->parent;
+ PixmapPtr pSrcPixmap = (*pScreen->GetWindowPixmap) (pWin);
+ PixmapPtr pDstPixmap = (*pScreen->GetWindowPixmap) (pParent);
+ PictFormatPtr pSrcFormat = compWindowFormat (pWin);
+ PictFormatPtr pDstFormat = compWindowFormat (pWin->parent);
+ int error;
+ RegionPtr pRegion = DamageRegion (cw->damage);
+ PicturePtr pSrcPicture = CreatePicture (0, &pSrcPixmap->drawable,
+ pSrcFormat,
+ 0, 0,
+ serverClient,
+ &error);
+ PicturePtr pDstPicture = CreatePicture (0, &pDstPixmap->drawable,
+ pDstFormat,
+ 0, 0,
+ serverClient,
+ &error);
+
+ REGION_TRANSLATE (pScreen, pRegion,
+ pSrcPixmap->screen_x, pSrcPixmap->screen_y);
+ REGION_INTERSECT (pScreen, pRegion, pRegion, &cw->borderClip);
+ REGION_TRANSLATE (pScreen, pRegion,
+ -pSrcPixmap->screen_x, -pSrcPixmap->screen_y);
+
+ SetPictureClipRegion (pSrcPicture, 0, 0, pRegion);
+
+ CompositePicture (PictOpSrc,
+ pSrcPicture,
+ 0,
+ pDstPicture,
+ 0,
+ 0,
+ 0, 0,
+ pSrcPixmap->screen_x - pDstPixmap->screen_x,
+ pSrcPixmap->screen_y - pDstPixmap->screen_y,
+ pSrcPixmap->drawable.width,
+ pSrcPixmap->drawable.height);
+ FreePicture (pSrcPicture, 0);
+ FreePicture (pDstPicture, 0);
+ DamageEmpty (cw->damage);
+}
+
+void
+compWindowUpdate (WindowPtr pWin)
+{
+ WindowPtr pChild;
+
+ for (pChild = pWin->lastChild; pChild; pChild = pChild->prevSib)
+ compWindowUpdate (pChild);
+ if (pWin->redirectDraw)
+ {
+ CompWindowPtr cw = GetCompWindow(pWin);
+
+ if (cw->damaged)
+ {
+ compWindowUpdateAutomatic (pWin);
+ cw->damaged = FALSE;
+ }
+ }
+}
diff --git a/dix/colormap.c b/dix/colormap.c
index 1d7772188..8ea87674c 100644
--- a/dix/colormap.c
+++ b/dix/colormap.c
@@ -1,4 +1,4 @@
-/* $XdotOrg$ */
+/* $XdotOrg: xc/programs/Xserver/dix/colormap.c,v 1.2.2.1 2004/07/30 06:54:41 anholt Exp $ */
/* $XFree86: xc/programs/Xserver/dix/colormap.c,v 3.11 2003/11/03 05:10:59 tsi Exp $ */
/***********************************************************
@@ -190,7 +190,15 @@ static void FindColorInRootCmap (
#define NUMRED(vis) ((vis->redMask >> vis->offsetRed) + 1)
#define NUMGREEN(vis) ((vis->greenMask >> vis->offsetGreen) + 1)
#define NUMBLUE(vis) ((vis->blueMask >> vis->offsetBlue) + 1)
-#define RGBMASK(vis) (vis->redMask | vis->greenMask | vis->blueMask)
+#ifdef COMPOSITE
+#define NUMALPHA(vis) ((vis->alphaMask >> vis->offsetAlpha) + 1)
+#define ALPHAMASK(vis) (vis->alphaMask)
+#else
+#define NUMALPHA(vis) 0
+#define ALPHAMASK(vis) 0
+#endif
+
+#define RGBMASK(vis) (vis->redMask | vis->greenMask | vis->blueMask | ALPHAMASK(vis))
/* GetNextBitsOrBreak(bits, mask, base) --
* (Suggestion: First read the macro, then read this explanation.
@@ -866,6 +874,9 @@ AllocColor (pmap, pred, pgreen, pblue, pPix, client)
*pPix = (pixR << pVisual->offsetRed) |
(pixG << pVisual->offsetGreen) |
(pixB << pVisual->offsetBlue);
+#ifdef COMPOSITE
+ *pPix |= pVisual->alphaMask;
+#endif
*pred = pmap->red[pixR].co.local.red;
*pgreen = pmap->green[pixG].co.local.green;
*pblue = pmap->blue[pixB].co.local.blue;
@@ -956,6 +967,9 @@ AllocColor (pmap, pred, pgreen, pblue, pPix, client)
return (BadAlloc);
}
*pPix = pixR | pixG | pixB;
+#ifdef COMPOSITE
+ *pPix |= pVisual->alphaMask;
+#endif
break;
}
@@ -1928,6 +1942,10 @@ AllocDirect (client, pmap, c, r, g, b, contig, pixels, prmask, pgmask, pbmask)
}
pmap->numPixelsBlue[client] += npixB;
pmap->freeBlue -= npixB;
+#ifdef COMPOSITE
+ for (pDst = pixels; pDst < pixels + c; pDst++)
+ *pDst |= pmap->pVisual->alphaMask;
+#endif
DEALLOCATE_LOCAL(ppixBlue);
DEALLOCATE_LOCAL(ppixGreen);
diff --git a/dix/window.c b/dix/window.c
index af2d449f6..cfc821c2c 100644
--- a/dix/window.c
+++ b/dix/window.c
@@ -1,4 +1,4 @@
-/* $XdotOrg: xc/programs/Xserver/dix/window.c,v 1.4 2004/07/29 23:43:39 kem Exp $ */
+/* $XdotOrg: xc/programs/Xserver/dix/window.c,v 1.4.2.1 2004/07/30 06:54:41 anholt Exp $ */
/* $Xorg: window.c,v 1.4 2001/02/09 02:04:41 xorgcvs Exp $ */
/*
@@ -291,6 +291,9 @@ SetWindowToDefaults(register WindowPtr pWin)
pWin->srcBuffer = DBE_FRONT_BUFFER;
pWin->dstBuffer = DBE_FRONT_BUFFER;
#endif
+#ifdef COMPOSITE
+ pWin->redirectDraw = 0;
+#endif
}
static void
@@ -1661,6 +1664,19 @@ void
SetWinSize (pWin)
register WindowPtr pWin;
{
+#ifdef COMPOSITE
+ if (pWin->redirectDraw)
+ {
+ BoxRec box;
+
+ box.x1 = pWin->drawable.x;
+ box.y1 = pWin->drawable.y;
+ box.x2 = pWin->drawable.x + pWin->drawable.width;
+ box.y2 = pWin->drawable.y + pWin->drawable.height;
+ REGION_RESET (pScreen, &pWin->winSize, &box);
+ }
+ else
+#endif
ClippedRegionFromBox(pWin->parent, &pWin->winSize,
pWin->drawable.x, pWin->drawable.y,
(int)pWin->drawable.width,
@@ -1691,6 +1707,19 @@ SetBorderSize (pWin)
if (HasBorder (pWin)) {
bw = wBorderWidth (pWin);
+#ifdef COMPOSITE
+ if (pWin->redirectDraw)
+ {
+ BoxRec box;
+
+ box.x1 = pWin->drawable.x - bw;
+ box.y1 = pWin->drawable.y - bw;
+ box.x2 = pWin->drawable.x + pWin->drawable.width + bw;
+ box.y2 = pWin->drawable.y + pWin->drawable.height + bw;
+ REGION_RESET (pScreen, &pWin->borderSize, &box);
+ }
+ else
+#endif
ClippedRegionFromBox(pWin->parent, &pWin->borderSize,
pWin->drawable.x - bw, pWin->drawable.y - bw,
(int)(pWin->drawable.width + (bw<<1)),
diff --git a/include/pixmapstr.h b/include/pixmapstr.h
index 1b0df9fd3..22a1f1025 100644
--- a/include/pixmapstr.h
+++ b/include/pixmapstr.h
@@ -79,6 +79,10 @@ typedef struct _Pixmap {
#ifdef PIXPRIV
DevUnion *devPrivates; /* real devPrivates like gcs & windows */
#endif
+#ifdef COMPOSITE
+ short screen_x;
+ short screen_y;
+#endif
} PixmapRec;
#endif /* PIXMAPSTRUCT_H */
diff --git a/include/scrnintstr.h b/include/scrnintstr.h
index edd14c12f..973497330 100644
--- a/include/scrnintstr.h
+++ b/include/scrnintstr.h
@@ -75,6 +75,10 @@ typedef struct _Visual {
* it may have more or fewer */
unsigned long redMask, greenMask, blueMask;
int offsetRed, offsetGreen, offsetBlue;
+#ifdef COMPOSITE
+ unsigned long alphaMask;
+ int offsetAlpha;
+#endif
} VisualRec;
typedef struct _Depth {
diff --git a/include/windowstr.h b/include/windowstr.h
index 00f9eff7a..c89c7b18e 100644
--- a/include/windowstr.h
+++ b/include/windowstr.h
@@ -136,6 +136,9 @@ typedef struct _Window {
unsigned dstBuffer:1; /* destination buffer for rendering */
unsigned srcBuffer:1; /* source buffer for rendering */
#endif
+#ifdef COMPOSITE
+ unsigned redirectDraw:1; /* rendering is redirected from here */
+#endif
DevUnion *devPrivates;
} WindowRec;
diff --git a/mi/mi.h b/mi/mi.h
index 388a90b27..cbb158121 100644
--- a/mi/mi.h
+++ b/mi/mi.h
@@ -495,6 +495,16 @@ extern int miShapedWindowIn(
int /*y*/
);
+typedef void
+(*SetRedirectBorderClipProcPtr) (WindowPtr pWindow, RegionPtr pRegion);
+
+typedef RegionPtr
+(*GetRedirectBorderClipProcPtr) (WindowPtr pWindow);
+
+void
+miRegisterRedirectBorderClipProc (SetRedirectBorderClipProcPtr setBorderClip,
+ GetRedirectBorderClipProcPtr getBorderClip);
+
extern int miValidateTree(
WindowPtr /*pParent*/,
WindowPtr /*pChild*/,
diff --git a/mi/miinitext.c b/mi/miinitext.c
index 6afc66ea0..ec4ae1aa4 100644
--- a/mi/miinitext.c
+++ b/mi/miinitext.c
@@ -1,4 +1,4 @@
-/* $XdotOrg: xc/programs/Xserver/mi/miinitext.c,v 1.6 2004/07/31 01:37:47 stukreit Exp $ */
+/* $XdotOrg: xc/programs/Xserver/mi/miinitext.c,v 1.7 2004/07/31 04:23:21 kem Exp $ */
/* $XFree86: xc/programs/Xserver/mi/miinitext.c,v 3.67 2003/01/12 02:44:27 dawes Exp $ */
/***********************************************************
@@ -282,6 +282,9 @@ extern void XFixesExtensionInit(INITARGS);
#ifdef DAMAGE
extern void DamageExtensionInit(INITARGS);
#endif
+#ifdef COMPOSITE
+extern void CompositeExtensionInit(INITARGS);
+#endif
/* The following is only a small first step towards run-time
* configurable extensions.
@@ -456,6 +459,10 @@ InitExtensions(argc, argv)
DPSExtensionInit();
#endif
#endif
+#ifdef XFIXES
+ /* must be before Render to layer DisplayCursor correctly */
+ XFixesExtensionInit();
+#endif
#ifdef RENDER
if (!noRenderExtension) RenderExtensionInit();
#endif
@@ -471,12 +478,12 @@ InitExtensions(argc, argv)
#ifdef XEVIE
if (!noXevieExtension) XevieExtensionInit();
#endif
-#ifdef XFIXES
- XFixesExtensionInit();
-#endif
#ifdef DAMAGE
DamageExtensionInit();
#endif
+#ifdef COMPOSITE
+ CompositeExtensionInit ();
+#endif
}
void
@@ -590,6 +597,10 @@ static ExtensionModule staticExtensions[] = {
#ifdef PANORAMIX
{ PanoramiXExtensionInit, PANORAMIX_PROTOCOL_NAME, &noPanoramiXExtension, NULL, NULL },
#endif
+#ifdef XFIXES
+ /* must be before Render to layer DisplayCursor correctly */
+ { XFixesExtensionInit, "XFIXES", NULL, NULL, NULL },
+#endif
#ifdef XF86BIGFONT
{ XFree86BigfontExtensionInit, XF86BIGFONTNAME, NULL, NULL, NULL },
#endif
@@ -602,9 +613,9 @@ static ExtensionModule staticExtensions[] = {
#ifdef DAMAGE
{ DamageExtensionInit, "DAMAGE", NULL, NULL },
#endif
-#ifdef XFIXES
- { XFixesExtensionInit, "XFIXES", NULL, NULL },
-#endif
+#ifdef COMPOSITE
+ { CompositeExtensionInit, "COMPOSITE", NULL, NULL },
+#endif
#ifdef XEVIE
{ XevieExtensionInit, "XEVIE", &noXevieExtension, NULL },
#endif
diff --git a/mi/mivaltree.c b/mi/mivaltree.c
index 1bbbc20fc..6036f6057 100644
--- a/mi/mivaltree.c
+++ b/mi/mivaltree.c
@@ -1,5 +1,5 @@
/* $Xorg: mivaltree.c,v 1.4 2001/02/09 02:05:22 xorgcvs Exp $ */
-/* $XdotOrg$ */
+/* $XdotOrg: xc/programs/Xserver/mi/mivaltree.c,v 1.2.2.1 2004/07/30 06:54:42 anholt Exp $ */
/*
* mivaltree.c --
* Functions for recalculating window clip lists. Main function
@@ -167,6 +167,17 @@ miShapedWindowIn (pScreen, universe, bounding, rect, x, y)
}
#endif
+static GetRedirectBorderClipProcPtr miGetRedirectBorderClipProc;
+static SetRedirectBorderClipProcPtr miSetRedirectBorderClipProc;
+
+void
+miRegisterRedirectBorderClipProc (SetRedirectBorderClipProcPtr setBorderClip,
+ GetRedirectBorderClipProcPtr getBorderClip)
+{
+ miSetRedirectBorderClipProc = setBorderClip;
+ miGetRedirectBorderClipProc = getBorderClip;
+}
+
#define HasParentRelativeBorder(w) (!(w)->borderIsPixel && \
HasBorder(w) && \
(w)->backgroundState == ParentRelative)
@@ -264,6 +275,18 @@ miComputeClips (
((pParent->eventMask | wOtherEventMasks(pParent)) & VisibilityChangeMask))
SendVisibilityNotify(pParent);
+#ifdef COMPOSITE
+ /*
+ * In redirected drawing case, reset universe to borderSize
+ */
+ if (pParent->redirectDraw)
+ {
+ if (miSetRedirectBorderClipProc)
+ (*miSetRedirectBorderClipProc) (pParent, universe);
+ REGION_COPY(pScreen, universe, &pParent->borderSize);
+ }
+#endif
+
dx = pParent->drawable.x - pParent->valdata->before.oldAbsCorner.x;
dy = pParent->drawable.y - pParent->valdata->before.oldAbsCorner.y;
@@ -640,7 +663,12 @@ miValidateTree (pParent, pChild, kind)
{
if (pWin->valdata)
{
- REGION_APPEND( pScreen, &totalClip, &pWin->borderClip);
+ RegionPtr pBorderClip = &pWin->borderClip;
+#ifdef COMPOSITE
+ if (pWin->redirectDraw && miGetRedirectBorderClipProc)
+ pBorderClip = (*miGetRedirectBorderClipProc)(pWin);
+#endif
+ REGION_APPEND( pScreen, &totalClip, pBorderClip );
if (pWin->viewable)
viewvals++;
}
@@ -654,7 +682,12 @@ miValidateTree (pParent, pChild, kind)
{
if (pWin->valdata)
{
- REGION_APPEND( pScreen, &totalClip, &pWin->borderClip);
+ RegionPtr pBorderClip = &pWin->borderClip;
+#ifdef COMPOSITE
+ if (pWin->redirectDraw && miGetRedirectBorderClipProc)
+ pBorderClip = (*miGetRedirectBorderClipProc)(pWin);
+#endif
+ REGION_APPEND( pScreen, &totalClip, pBorderClip );
if (pWin->viewable)
viewvals++;
}
diff --git a/miext/cw/cw.c b/miext/cw/cw.c
new file mode 100644
index 000000000..8394ca8a3
--- /dev/null
+++ b/miext/cw/cw.c
@@ -0,0 +1,570 @@
+/*
+ * Copyright © 2004 Eric Anholt
+ *
+ * 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 Eric Anholt not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Eric Anholt makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * ERIC ANHOLT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL ERIC ANHOLT 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.
+ */
+/* $Header$ */
+
+#include "gcstruct.h"
+#include "windowstr.h"
+#include "cw.h"
+
+#define CW_DEBUG 1
+
+#if CW_DEBUG
+#define CW_ASSERT(x) do { \
+ if (!(x)) { \
+ ErrorF("composite wrapper: assertion failed at %s:%d\n", __FUNC__, \
+ __LINE__); \
+ } \
+} while (0)
+#else
+#define CW_ASSERT(x) do {} while (0)
+#endif
+
+int cwGCIndex;
+int cwScreenIndex;
+#ifdef RENDER
+int cwPictureIndex;
+#endif
+static unsigned long cwGeneration = 0;
+extern GCOps cwGCOps;
+
+static Bool
+cwCloseScreen (int i, ScreenPtr pScreen);
+
+static void
+cwValidateGC(GCPtr pGC, unsigned long stateChanges, DrawablePtr pDrawable);
+static void
+cwChangeGC(GCPtr pGC, unsigned long mask);
+static void
+cwCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst);
+static void
+cwDestroyGC(GCPtr pGC);
+static void
+cwChangeClip(GCPtr pGC, int type, pointer pvalue, int nrects);
+static void
+cwCopyClip(GCPtr pgcDst, GCPtr pgcSrc);
+static void
+cwDestroyClip(GCPtr pGC);
+
+static void
+cwCheapValidateGC(GCPtr pGC, unsigned long stateChanges, DrawablePtr pDrawable);
+static void
+cwCheapChangeGC(GCPtr pGC, unsigned long mask);
+static void
+cwCheapCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst);
+static void
+cwCheapDestroyGC(GCPtr pGC);
+static void
+cwCheapChangeClip(GCPtr pGC, int type, pointer pvalue, int nrects);
+static void
+cwCheapCopyClip(GCPtr pgcDst, GCPtr pgcSrc);
+static void
+cwCheapDestroyClip(GCPtr pGC);
+
+static GCFuncs cwGCFuncs = {
+ cwValidateGC,
+ cwChangeGC,
+ cwCopyGC,
+ cwDestroyGC,
+ cwChangeClip,
+ cwDestroyClip,
+ cwCopyClip,
+};
+
+static GCFuncs cwCheapGCFuncs = {
+ cwCheapValidateGC,
+ cwCheapChangeGC,
+ cwCheapCopyGC,
+ cwCheapDestroyGC,
+ cwCheapChangeClip,
+ cwCheapDestroyClip,
+ cwCheapCopyClip,
+};
+
+DrawablePtr
+cwGetBackingDrawable(DrawablePtr pDrawable, int *x_off, int *y_off)
+{
+ if (cwDrawableIsRedirWindow(pDrawable)) {
+ WindowPtr pWin = (WindowPtr)pDrawable;
+ PixmapPtr pPixmap = (*pDrawable->pScreen->GetWindowPixmap)(pWin);
+ *x_off = -pPixmap->screen_x;
+ *y_off = -pPixmap->screen_y;
+
+ return &pPixmap->drawable;
+ } else {
+ *x_off = *y_off = 0;
+
+ return pDrawable;
+ }
+}
+
+/*
+ * create the full func/op wrappers for a GC
+ */
+
+static Bool
+cwCreateGCPrivate(GCPtr pGC, DrawablePtr pDrawable)
+{
+ cwGCRec *pPriv;
+ int status, x_off, y_off;
+ XID noexpose = xFalse;
+ DrawablePtr pBackingDrawable;
+
+ pPriv = (cwGCRec *)xalloc(sizeof (cwGCRec));
+ if (!pPriv)
+ return FALSE;
+ pBackingDrawable = cwGetBackingDrawable(pDrawable, &x_off, &y_off);
+ pPriv->pBackingGC = CreateGC(pBackingDrawable, GCGraphicsExposures,
+ &noexpose, &status);
+ if (status != Success) {
+ xfree(pPriv);
+ return FALSE;
+ }
+ pPriv->guarantee = GuaranteeNothing;
+ pPriv->serialNumber = 0;
+ pPriv->stateChanges = (1 << (GCLastBit + 1)) - 1;
+ pPriv->wrapOps = pGC->ops;
+ pPriv->wrapFuncs = pGC->funcs;
+ pGC->funcs = &cwGCFuncs;
+ pGC->ops = &cwGCOps;
+ setCwGC (pGC, pPriv);
+ return TRUE;
+}
+
+static void
+cwDestroyGCPrivate(GCPtr pGC)
+{
+ cwGCPtr pPriv;
+
+ pPriv = (cwGCPtr) getCwGC (pGC);
+ pGC->funcs = &cwCheapGCFuncs;
+ pGC->ops = pPriv->wrapOps;
+ if (pPriv->pBackingGC)
+ FreeGC(pPriv->pBackingGC, (XID)0);
+ setCwGC (pGC, pPriv->wrapFuncs);
+ xfree((pointer)pPriv);
+}
+
+/* GCFuncs wrappers. These only get used when the drawable is a window with a
+ * backing pixmap, to avoid the overhead in the non-window-backing-pixmap case.
+ */
+
+#define FUNC_PROLOGUE(pGC, pPriv) \
+ ((pGC)->funcs = pPriv->wrapFuncs), \
+ ((pGC)->ops = pPriv->wrapOps)
+
+#define FUNC_EPILOGUE(pGC, pPriv) \
+ ((pGC)->funcs = &cwGCFuncs), \
+ ((pGC)->ops = &cwGCOps)
+
+static void
+cwValidateGC(GCPtr pGC, unsigned long stateChanges, DrawablePtr pDrawable)
+{
+ GCPtr pBackingGC;
+ cwGCPtr pPriv;
+ DrawablePtr pBackingDrawable;
+ int x_off, y_off;
+
+ pPriv = (cwGCPtr) getCwGC (pGC);
+
+ FUNC_PROLOGUE(pGC, pPriv);
+
+ if (pDrawable->serialNumber != pPriv->serialNumber &&
+ !cwDrawableIsRedirWindow(pDrawable))
+ {
+ /* The drawable is no longer a window with backing store, so kill the
+ * private and go back to cheap functions.
+ */
+ cwDestroyGCPrivate(pGC);
+ (*pGC->funcs->ValidateGC)(pGC, stateChanges, pDrawable);
+ return;
+ }
+ (*pGC->funcs->ValidateGC)(pGC, stateChanges, pDrawable);
+
+ /*
+ * rewrap funcs and ops as Validate may have changed them
+ */
+ pPriv->wrapFuncs = pGC->funcs;
+ pPriv->wrapOps = pGC->ops;
+
+ pBackingGC = pPriv->pBackingGC;
+ pBackingDrawable = cwGetBackingDrawable(pDrawable, &x_off, &y_off);
+
+ pPriv->stateChanges |= stateChanges;
+
+ if (pPriv->stateChanges) {
+ CopyGC(pGC, pBackingGC, pPriv->stateChanges);
+ pPriv->stateChanges = 0;
+ }
+
+ if ((pGC->patOrg.x + x_off) != pBackingGC->patOrg.x ||
+ (pGC->patOrg.y + y_off) != pBackingGC->patOrg.y)
+ {
+ XID vals[2];
+ vals[0] = pGC->patOrg.x + x_off;
+ vals[1] = pGC->patOrg.y + y_off;
+ DoChangeGC(pBackingGC, GCTileStipXOrigin|GCTileStipYOrigin, vals, 0);
+ }
+
+ if (pDrawable->serialNumber != pPriv->serialNumber) {
+ XID vals[2];
+
+ /* Either the drawable has changed, or the clip list in the drawable has
+ * changed. Copy the new clip list over and set the new translated
+ * offset for it.
+ */
+
+ (*pBackingGC->funcs->DestroyClip)(pBackingGC);
+ (*pBackingGC->funcs->CopyClip)(pBackingGC, pGC);
+ vals[0] = pGC->clipOrg.x + x_off;
+ vals[1] = pGC->clipOrg.y + y_off;
+ DoChangeGC(pBackingGC, GCClipXOrigin|GCClipYOrigin, vals, 0);
+
+ ValidateGC(pBackingDrawable, pBackingGC);
+ pPriv->serialNumber = pDrawable->serialNumber;
+ }
+
+ FUNC_EPILOGUE(pGC, pPriv);
+}
+
+static void
+cwChangeGC(GCPtr pGC, unsigned long mask)
+{
+ cwGCPtr pPriv = (cwGCPtr)(pGC)->devPrivates[cwGCIndex].ptr;
+
+ FUNC_PROLOGUE(pGC, pPriv);
+
+ (*pGC->funcs->ChangeGC) (pGC, mask);
+
+ FUNC_EPILOGUE(pGC, pPriv);
+}
+
+static void
+cwCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst)
+{
+ cwGCPtr pPriv = (cwGCPtr)(pGCDst)->devPrivates[cwGCIndex].ptr;
+
+ FUNC_PROLOGUE(pGCDst, pPriv);
+
+ (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
+
+ FUNC_EPILOGUE(pGCDst, pPriv);
+}
+
+static void
+cwDestroyGC(GCPtr pGC)
+{
+ cwGCPtr pPriv = (cwGCPtr)(pGC)->devPrivates[cwGCIndex].ptr;
+
+ FUNC_PROLOGUE(pGC, pPriv);
+
+ cwDestroyGCPrivate(pGC);
+
+ (*pGC->funcs->DestroyGC) (pGC);
+
+ /* leave it unwrapped */
+}
+
+static void
+cwChangeClip(GCPtr pGC, int type, pointer pvalue, int nrects)
+{
+ cwGCPtr pPriv = (cwGCPtr)(pGC)->devPrivates[cwGCIndex].ptr;
+
+ FUNC_PROLOGUE(pGC, pPriv);
+
+ (*pGC->funcs->ChangeClip)(pGC, type, pvalue, nrects);
+
+ FUNC_EPILOGUE(pGC, pPriv);
+}
+
+static void
+cwCopyClip(GCPtr pgcDst, GCPtr pgcSrc)
+{
+ cwGCPtr pPriv = (cwGCPtr)(pgcDst)->devPrivates[cwGCIndex].ptr;
+
+ FUNC_PROLOGUE(pgcDst, pPriv);
+
+ (*pgcDst->funcs->CopyClip)(pgcDst, pgcSrc);
+
+ FUNC_EPILOGUE(pgcDst, pPriv);
+}
+
+static void
+cwDestroyClip(GCPtr pGC)
+{
+ cwGCPtr pPriv = (cwGCPtr)(pGC)->devPrivates[cwGCIndex].ptr;
+
+ FUNC_PROLOGUE(pGC, pPriv);
+
+ (*pGC->funcs->DestroyClip)(pGC);
+
+ FUNC_EPILOGUE(pGC, pPriv);
+}
+
+/*
+ * Cheap GC func wrappers. Pass everything through unless we find a window with
+ * a backing pixmap, then turn on the real wrappers.
+ */
+
+#define CHEAP_FUNC_PROLOGUE(pGC) \
+ ((pGC)->funcs = (GCFuncs *)(pGC)->devPrivates[cwGCIndex].ptr)
+
+#define CHEAP_FUNC_EPILOGUE(pGC) \
+ ((pGC)->funcs = &cwCheapGCFuncs)
+
+static void
+cwCheapValidateGC(GCPtr pGC, unsigned long stateChanges, DrawablePtr pDrawable)
+{
+ CHEAP_FUNC_PROLOGUE(pGC);
+
+ /* Check if the drawable is a window with backing pixmap. If so,
+ * cwCreateGCPrivate will wrap with the backing-pixmap GC funcs and we won't
+ * re-wrap on return.
+ */
+ if (pDrawable->type == DRAWABLE_WINDOW &&
+cwDrawableIsRedirWindow(pDrawable) &&
+ cwCreateGCPrivate(pGC, pDrawable))
+ {
+ (*pGC->funcs->ValidateGC)(pGC, stateChanges, pDrawable);
+ }
+ else
+ {
+ (*pGC->funcs->ValidateGC)(pGC, stateChanges, pDrawable);
+
+ /* rewrap funcs as Validate may have changed them */
+ pGC->devPrivates[cwGCIndex].ptr = (pointer) pGC->funcs;
+
+ CHEAP_FUNC_EPILOGUE(pGC);
+ }
+}
+
+static void
+cwCheapChangeGC(GCPtr pGC, unsigned long mask)
+{
+ CHEAP_FUNC_PROLOGUE(pGC);
+
+ (*pGC->funcs->ChangeGC)(pGC, mask);
+
+ CHEAP_FUNC_EPILOGUE(pGC);
+}
+
+static void
+cwCheapCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst)
+{
+ CHEAP_FUNC_PROLOGUE(pGCDst);
+
+ (*pGCDst->funcs->CopyGC)(pGCSrc, mask, pGCDst);
+
+ CHEAP_FUNC_EPILOGUE(pGCDst);
+}
+
+static void
+cwCheapDestroyGC(GCPtr pGC)
+{
+ CHEAP_FUNC_PROLOGUE(pGC);
+
+ (*pGC->funcs->DestroyGC)(pGC);
+
+ /* leave it unwrapped */
+}
+
+static void
+cwCheapChangeClip(GCPtr pGC, int type, pointer pvalue, int nrects)
+{
+ CHEAP_FUNC_PROLOGUE(pGC);
+
+ (*pGC->funcs->ChangeClip)(pGC, type, pvalue, nrects);
+
+ CHEAP_FUNC_EPILOGUE(pGC);
+}
+
+static void
+cwCheapCopyClip(GCPtr pgcDst, GCPtr pgcSrc)
+{
+ CHEAP_FUNC_PROLOGUE(pgcDst);
+
+ (*pgcDst->funcs->CopyClip)(pgcDst, pgcSrc);
+
+ CHEAP_FUNC_EPILOGUE(pgcDst);
+}
+
+static void
+cwCheapDestroyClip(GCPtr pGC)
+{
+ CHEAP_FUNC_PROLOGUE(pGC);
+
+ (*pGC->funcs->DestroyClip)(pGC);
+
+ CHEAP_FUNC_EPILOGUE(pGC);
+}
+
+/*
+ * GC Create wrapper. Set up the cheap GC func wrappers to track
+ * GC validation on BackingStore windows.
+ */
+
+#define SCREEN_PROLOGUE(pScreen, field)\
+ ((pScreen)->field = ((cwScreenPtr) \
+ (pScreen)->devPrivates[cwScreenIndex].ptr)->field)
+
+#define SCREEN_EPILOGUE(pScreen, field, wrapper)\
+ ((pScreen)->field = wrapper)
+
+static Bool
+cwCreateGC(GCPtr pGC)
+{
+ ScreenPtr pScreen = pGC->pScreen;
+ Bool ret;
+
+ SCREEN_PROLOGUE(pScreen, CreateGC);
+
+ if ( (ret = (*pScreen->CreateGC)(pGC)) )
+ {
+ pGC->devPrivates[cwGCIndex].ptr = (pointer)pGC->funcs;
+ pGC->funcs = &cwCheapGCFuncs;
+ }
+
+ SCREEN_EPILOGUE(pScreen, CreateGC, cwCreateGC);
+
+ return ret;
+}
+
+static void
+cwGetImage(DrawablePtr pSrc, int sx, int sy, int w, int h, unsigned int format,
+ unsigned long planemask, char *pdstLine)
+{
+ ScreenPtr pScreen = pSrc->pScreen;
+ DrawablePtr pBackingDrawable;
+ int x_off, y_off;
+
+ SCREEN_PROLOGUE(pScreen, GetImage);
+
+ pBackingDrawable = cwGetBackingDrawable(pSrc, &x_off, &y_off);
+
+ sx += x_off;
+ sy += y_off;
+
+ (*pScreen->GetImage)(pBackingDrawable, sx, sy, w, h, format, planemask, pdstLine);
+
+ SCREEN_EPILOGUE(pScreen, GetImage, cwGetImage);
+}
+
+static void
+cwGetSpans(DrawablePtr pSrc, int wMax, DDXPointPtr ppt, int *pwidth,
+ int nspans, char *pdstStart)
+{
+ ScreenPtr pScreen = pSrc->pScreen;
+ DrawablePtr pBackingDrawable;
+ int i;
+ int x_off, y_off;
+ DDXPointPtr ppt_trans;
+
+ SCREEN_PROLOGUE(pScreen, GetSpans);
+
+ pBackingDrawable = cwGetBackingDrawable(pSrc, &x_off, &y_off);
+
+ ppt_trans = (DDXPointPtr)ALLOCATE_LOCAL(nspans * sizeof(DDXPointRec));
+ if (ppt_trans) {
+ for (i = 0; i < nspans; i++) {
+ ppt_trans[i].x = ppt[i].x + x_off;
+ ppt_trans[i].y = ppt[i].y + y_off;
+ }
+
+ (*pScreen->GetSpans)(pBackingDrawable, wMax, ppt, pwidth, nspans,
+ pdstStart);
+ DEALLOCATE_LOCAL(ppt_trans);
+ }
+
+ SCREEN_EPILOGUE(pScreen, GetSpans, cwGetSpans);
+}
+
+/* Screen initialization/teardown */
+void
+miInitializeCompositeWrapper(ScreenPtr pScreen)
+{
+ cwScreenPtr pScreenPriv;
+
+ if (cwGeneration != serverGeneration)
+ {
+ cwScreenIndex = AllocateScreenPrivateIndex();
+ if (cwScreenIndex < 0)
+ return;
+ cwGCIndex = AllocateGCPrivateIndex();
+#ifdef RENDER
+ cwPictureIndex = AllocatePicturePrivateIndex();
+#endif
+ cwGeneration = serverGeneration;
+ }
+ if (!AllocateGCPrivate(pScreen, cwGCIndex, 0))
+ return;
+ pScreenPriv = (cwScreenPtr)xalloc(sizeof(cwScreenRec));
+ if (!pScreenPriv)
+ return;
+
+ pScreenPriv->CloseScreen = pScreen->CloseScreen;
+ pScreenPriv->GetImage = pScreen->GetImage;
+ pScreenPriv->GetSpans = pScreen->GetSpans;
+ pScreenPriv->CreateGC = pScreen->CreateGC;
+
+ pScreen->CloseScreen = cwCloseScreen;
+ pScreen->GetImage = cwGetImage;
+ pScreen->GetSpans = cwGetSpans;
+ pScreen->CreateGC = cwCreateGC;
+
+ pScreen->devPrivates[cwScreenIndex].ptr = (pointer)pScreenPriv;
+
+#ifdef RENDER
+ if (GetPictureScreen (pScreen))
+ {
+ if (!cwInitializeRender (pScreen))
+ /* FIXME */;
+ }
+#endif
+
+ ErrorF("Initialized composite wrapper\n");
+}
+
+static Bool
+cwCloseScreen (int i, ScreenPtr pScreen)
+{
+ cwScreenPtr pScreenPriv;
+#ifdef RENDER
+ PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
+#endif
+
+ pScreenPriv = (cwScreenPtr)pScreen->devPrivates[cwScreenIndex].ptr;
+
+ pScreen->CloseScreen = pScreenPriv->CloseScreen;
+ pScreen->GetImage = pScreenPriv->GetImage;
+ pScreen->GetSpans = pScreenPriv->GetSpans;
+ pScreen->CreateGC = pScreenPriv->CreateGC;
+
+#ifdef RENDER
+ if (ps) {
+ ps->Composite = pScreenPriv->Composite;
+ ps->Glyphs = pScreenPriv->Glyphs;
+ }
+#endif
+
+ xfree((pointer)pScreenPriv);
+
+ return (*pScreen->CloseScreen)(i, pScreen);
+}
diff --git a/miext/cw/cw.h b/miext/cw/cw.h
new file mode 100644
index 000000000..33e62f039
--- /dev/null
+++ b/miext/cw/cw.h
@@ -0,0 +1,164 @@
+/*
+ * Copyright © 2004 Eric Anholt
+ *
+ * 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 Eric Anholt not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Eric Anholt makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * ERIC ANHOLT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL ERIC ANHOLT 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.
+ */
+/* $Header$ */
+
+#include "picturestr.h"
+
+/*
+ * One of these structures is allocated per GC that gets used with a window with
+ * backing pixmap.
+ */
+
+typedef struct {
+ GCPtr pBackingGC; /* Copy of the GC but with graphicsExposures
+ * set FALSE and the clientClip set to
+ * clip output to the valid regions of the
+ * backing pixmap. */
+ int guarantee; /* GuaranteeNothing, etc. */
+ unsigned long serialNumber; /* clientClip computed time */
+ unsigned long stateChanges; /* changes in parent gc since last copy */
+ GCOps *wrapOps; /* wrapped ops */
+ GCFuncs *wrapFuncs; /* wrapped funcs */
+} cwGCRec, *cwGCPtr;
+
+extern int cwGCIndex;
+
+#define getCwGC(pGC) ((cwGCPtr)(pGC)->devPrivates[cwGCIndex].ptr)
+#define setCwGC(pGC,p) ((pGC)->devPrivates[cwGCIndex].ptr = (pointer) (p))
+
+typedef struct {
+ PicturePtr pBackingPicture;
+ unsigned long serialNumber; /* clientClip computed time */
+ unsigned long stateChanges; /* changes in parent gc since last copy */
+} cwPictureRec, *cwPicturePtr;
+
+extern int cwPictureIndex;
+
+#define getCwPicture(pPicture) ((cwPicturePtr)(pPicture)->devPrivates[cwPictureIndex].ptr)
+#define setCwPicture(pPicture,p) ((pPicture)->devPrivates[cwPictureIndex].ptr = (pointer) (p))
+
+#define cwDrawableIsRedirWindow(pDraw) ((pDraw)->type == DRAWABLE_WINDOW && \
+ ((WindowPtr)(pDraw))->redirectDraw)
+
+typedef struct {
+ /*
+ * screen func wrappers
+ */
+ CloseScreenProcPtr CloseScreen;
+ GetImageProcPtr GetImage;
+ GetSpansProcPtr GetSpans;
+ CreateGCProcPtr CreateGC;
+
+ DestroyWindowProcPtr DestroyWindow;
+
+ StoreColorsProcPtr StoreColors;
+
+ InitIndexedProcPtr InitIndexed;
+ CloseIndexedProcPtr CloseIndexed;
+ UpdateIndexedProcPtr UpdateIndexed;
+
+#ifdef RENDER
+ CreatePictureProcPtr CreatePicture;
+ DestroyPictureProcPtr DestroyPicture;
+ ChangePictureClipProcPtr ChangePictureClip;
+ DestroyPictureClipProcPtr DestroyPictureClip;
+
+ ChangePictureProcPtr ChangePicture;
+ ValidatePictureProcPtr ValidatePicture;
+
+ CompositeProcPtr Composite;
+ GlyphsProcPtr Glyphs;
+ CompositeRectsProcPtr CompositeRects;
+
+ TrapezoidsProcPtr Trapezoids;
+ TrianglesProcPtr Triangles;
+ TriStripProcPtr TriStrip;
+ TriFanProcPtr TriFan;
+
+ RasterizeTrapezoidProcPtr RasterizeTrapezoid;
+#if 0
+ AddTrapsProcPtr AddTraps;
+#endif
+#endif
+} cwScreenRec, *cwScreenPtr;
+
+extern int cwScreenIndex;
+
+#define getCwScreen(pScreen) ((cwScreenPtr)(pScreen)->devPrivates[cwScreenIndex].ptr)
+#define setCwScreen(pScreen,p) ((cwScreenPtr)(pScreen)->devPrivates[cwScreenIndex].ptr = (p))
+
+#define CW_COPY_OFFSET_XYPOINTS(ppt_trans, ppt, npt) do { \
+ short *_origpt = (short *)(ppt); \
+ short *_transpt = (short *)(ppt_trans); \
+ int _i; \
+ for (_i = 0; _i < npt; _i++) { \
+ *_transpt++ = *_origpt++ + dst_off_x; \
+ *_transpt++ = *_origpt++ + dst_off_y; \
+ } \
+} while (0)
+
+#define CW_COPY_OFFSET_RECTS(prect_trans, prect, nrect) do { \
+ short *_origpt = (short *)(prect); \
+ short *_transpt = (short *)(prect_trans); \
+ int _i; \
+ for (_i = 0; _i < nrect; _i++) { \
+ *_transpt++ = *_origpt++ + dst_off_x; \
+ *_transpt++ = *_origpt++ + dst_off_y; \
+ _transpt += 2; \
+ _origpt += 2; \
+ } \
+} while (0)
+
+#define CW_COPY_OFFSET_ARCS(parc_trans, parc, narc) do { \
+ short *_origpt = (short *)(parc); \
+ short *_transpt = (short *)(parc_trans); \
+ int _i; \
+ for (_i = 0; _i < narc; _i++) { \
+ *_transpt++ = *_origpt++ + dst_off_x; \
+ *_transpt++ = *_origpt++ + dst_off_y; \
+ _transpt += 4; \
+ _origpt += 4; \
+ } \
+} while (0)
+
+#define CW_COPY_OFFSET_XY_DST(bx, by, x, y) do { \
+ bx = x + dst_off_x; \
+ by = y + dst_off_y; \
+} while (0)
+
+#define CW_COPY_OFFSET_XY_SRC(bx, by, x, y) do { \
+ bx = x + src_off_x; \
+ by = y + src_off_y; \
+} while (0)
+
+/* cw.c */
+DrawablePtr
+cwGetBackingDrawable(DrawablePtr pDrawable, int *x_off, int *y_off);
+
+/* cw_render.c */
+
+Bool
+cwInitializeRender (ScreenPtr pScreen);
+
+/* cw.c */
+void
+miInitializeCompositeWrapper(ScreenPtr pScreen);
diff --git a/miext/cw/cw_ops.c b/miext/cw/cw_ops.c
new file mode 100644
index 000000000..879bfb04d
--- /dev/null
+++ b/miext/cw/cw_ops.c
@@ -0,0 +1,537 @@
+/*
+ * Copyright © 2004 Eric Anholt
+ *
+ * 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 Eric Anholt not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Eric Anholt makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * ERIC ANHOLT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL ERIC ANHOLT 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.
+ */
+/* $Header$ */
+
+#include "gcstruct.h"
+#include "cw.h"
+
+#define SETUP_BACKING_DST(_pDst, _pGC) \
+ cwGCPtr pGCPrivate = getCwGC (_pGC); \
+ GCFuncs *oldFuncs = (_pGC)->funcs; \
+ GCPtr pBackingGC = pGCPrivate->pBackingGC; \
+ int dst_off_x, dst_off_y; \
+ DrawablePtr pBackingDst = cwGetBackingDrawable(pDst, &dst_off_x, \
+ &dst_off_y)
+
+#define SETUP_BACKING_SRC(pSrc, pGC) \
+ int src_off_x, src_off_y; \
+ DrawablePtr pBackingSrc = cwGetBackingDrawable(pSrc, &src_off_x, \
+ &src_off_y)
+
+#define PROLOGUE(pGC) do { \
+ pGC->ops = pGCPrivate->wrapOps;\
+ pGC->funcs = pGCPrivate->wrapFuncs; \
+} while (0)
+
+#define EPILOGUE(pGC) do { \
+ pGCPrivate->wrapOps = (pGC)->ops; \
+ (pGC)->ops = &cwGCOps; \
+ (pGC)->funcs = oldFuncs; \
+} while (0)
+
+/*
+ * GC ops -- wrap each GC operation with our own function
+ */
+
+static void cwFillSpans(DrawablePtr pDst, GCPtr pGC, int nInit,
+ DDXPointPtr pptInit, int *pwidthInit, int fSorted);
+static void cwSetSpans(DrawablePtr pDst, GCPtr pGC, char *psrc,
+ DDXPointPtr ppt, int *pwidth, int nspans, int fSorted);
+static void cwPutImage(DrawablePtr pDst, GCPtr pGC, int depth,
+ int x, int y, int w, int h, int leftPad, int format,
+ char *pBits);
+static RegionPtr cwCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
+ int srcx, int srcy, int w, int h,
+ int dstx, int dsty);
+static RegionPtr cwCopyPlane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC,
+ int srcx, int srcy, int w, int h,
+ int dstx, int dsty, unsigned long plane);
+static void cwPolyPoint(DrawablePtr pDst, GCPtr pGC, int mode, int npt,
+ xPoint *pptInit);
+static void cwPolylines(DrawablePtr pDst, GCPtr pGC, int mode, int npt,
+ DDXPointPtr pptInit);
+static void cwPolySegment(DrawablePtr pDst, GCPtr pGC, int nseg,
+ xSegment *pSegs);
+static void cwPolyRectangle(DrawablePtr pDst, GCPtr pGC,
+ int nrects, xRectangle *pRects);
+static void cwPolyArc(DrawablePtr pDst, GCPtr pGC, int narcs, xArc *parcs);
+static void cwFillPolygon(DrawablePtr pDst, GCPtr pGC, int shape, int mode,
+ int count, DDXPointPtr pPts);
+static void cwPolyFillRect(DrawablePtr pDst, GCPtr pGC,
+ int nrectFill, xRectangle *prectInit);
+static void cwPolyFillArc(DrawablePtr pDst, GCPtr pGC,
+ int narcs, xArc *parcs);
+static int cwPolyText8(DrawablePtr pDrawable, GCPtr pGC, int x, int y,
+ int count, char *chars);
+static int cwPolyText16(DrawablePtr pDst, GCPtr pGC, int x, int y,
+ int count, unsigned short *chars);
+static void cwImageText8(DrawablePtr pDst, GCPtr pGC, int x, int y,
+ int count, char *chars);
+static void cwImageText16(DrawablePtr pDst, GCPtr pGC, int x, int y,
+ int count, unsigned short *chars);
+static void cwImageGlyphBlt(DrawablePtr pDst, GCPtr pGC, int x, int y,
+ unsigned int nglyph, CharInfoPtr *ppci,
+ pointer pglyphBase);
+static void cwPolyGlyphBlt(DrawablePtr pDst, GCPtr pGC, int x, int y,
+ unsigned int nglyph, CharInfoPtr *ppci,
+ pointer pglyphBase);
+static void cwPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr pDst,
+ int w, int h, int x, int y);
+
+GCOps cwGCOps = {
+ cwFillSpans,
+ cwSetSpans,
+ cwPutImage,
+ cwCopyArea,
+ cwCopyPlane,
+ cwPolyPoint,
+ cwPolylines,
+ cwPolySegment,
+ cwPolyRectangle,
+ cwPolyArc,
+ cwFillPolygon,
+ cwPolyFillRect,
+ cwPolyFillArc,
+ cwPolyText8,
+ cwPolyText16,
+ cwImageText8,
+ cwImageText16,
+ cwImageGlyphBlt,
+ cwPolyGlyphBlt,
+ cwPushPixels
+};
+
+static void
+cwFillSpans(DrawablePtr pDst, GCPtr pGC, int nspans, DDXPointPtr ppt,
+ int *pwidth, int fSorted)
+{
+ DDXPointPtr ppt_trans;
+ SETUP_BACKING_DST(pDst, pGC);
+
+ PROLOGUE(pGC);
+
+ ppt_trans = (DDXPointPtr)ALLOCATE_LOCAL(nspans * sizeof(DDXPointRec));
+ if (ppt_trans)
+ {
+ CW_COPY_OFFSET_XYPOINTS(ppt_trans, ppt, nspans);
+
+ (*pBackingGC->ops->FillSpans)(pBackingDst, pBackingGC,
+ nspans, ppt_trans, pwidth, fSorted);
+
+ DEALLOCATE_LOCAL(ppt_trans);
+ }
+
+ EPILOGUE(pGC);
+}
+
+static void
+cwSetSpans(DrawablePtr pDst, GCPtr pGC, char *psrc, DDXPointPtr ppt,
+ int *pwidth, int nspans, int fSorted)
+{
+ DDXPointPtr ppt_trans;
+ SETUP_BACKING_DST(pDst, pGC);
+
+ PROLOGUE(pGC);
+
+ ppt_trans = (DDXPointPtr)ALLOCATE_LOCAL(nspans*sizeof(DDXPointRec));
+ if (ppt_trans)
+ {
+ CW_COPY_OFFSET_XYPOINTS(ppt_trans, ppt, nspans);
+
+ (*pBackingGC->ops->SetSpans)(pBackingDst, pBackingGC, psrc,
+ ppt_trans, pwidth, nspans, fSorted);
+
+ DEALLOCATE_LOCAL(ppt_trans);
+ }
+
+ EPILOGUE(pGC);
+}
+
+static void
+cwPutImage(DrawablePtr pDst, GCPtr pGC, int depth, int x, int y, int w, int h,
+ int leftPad, int format, char *pBits)
+{
+ int bx, by;
+
+ SETUP_BACKING_DST(pDst, pGC);
+
+ PROLOGUE(pGC);
+
+ CW_COPY_OFFSET_XY_DST(bx, by, x, y);
+
+ (*pBackingGC->ops->PutImage)(pBackingDst, pBackingGC, depth, bx, by,
+ w, h, leftPad, format, pBits);
+
+ EPILOGUE(pGC);
+}
+
+static RegionPtr
+cwCopyArea(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, int srcx, int srcy,
+ int w, int h, int dstx, int dsty)
+{
+ int bsrcx, bsrcy, bdstx, bdsty;
+ RegionPtr exposed = NULL;
+ SETUP_BACKING_DST(pDst, pGC);
+ SETUP_BACKING_SRC(pSrc, pGC);
+
+ PROLOGUE(pGC);
+
+ CW_COPY_OFFSET_XY_DST(bdstx, bdsty, dstx, dsty);
+ CW_COPY_OFFSET_XY_SRC(bsrcx, bsrcy, srcx, srcy);
+
+ exposed = (*pBackingGC->ops->CopyArea)(pBackingSrc, pBackingDst,
+ pBackingGC, bsrcx, bsrcy, w, h,
+ bdstx, bdsty);
+
+ /* XXX: Simplify? */
+ if (exposed != NULL)
+ REGION_TRANSLATE(pDst->pScreen, exposed, dstx - bdstx, dsty - bdsty);
+
+ EPILOGUE(pGC);
+
+ return exposed;
+}
+
+static RegionPtr
+cwCopyPlane(DrawablePtr pSrc, DrawablePtr pDst, GCPtr pGC, int srcx, int srcy,
+ int w, int h, int dstx, int dsty, unsigned long plane)
+{
+ int bsrcx, bsrcy, bdstx, bdsty;
+ RegionPtr exposed = NULL;
+ SETUP_BACKING_DST(pDst, pGC);
+ SETUP_BACKING_SRC(pSrc, pGC);
+
+ PROLOGUE(pGC);
+
+ CW_COPY_OFFSET_XY_DST(bdstx, bdsty, dstx, dsty);
+ CW_COPY_OFFSET_XY_SRC(bsrcx, bsrcy, srcx, srcy);
+
+ exposed = (*pBackingGC->ops->CopyPlane)(pBackingSrc, pBackingDst,
+ pBackingGC, bsrcx, bsrcy, w, h,
+ bdstx, bdsty, plane);
+
+ /* XXX: Simplify? */
+ REGION_TRANSLATE(pDst->pScreen, exposed, dstx - bdstx, dsty - bdsty);
+
+ EPILOGUE(pGC);
+
+ return exposed;
+}
+
+static void
+cwPolyPoint(DrawablePtr pDst, GCPtr pGC, int mode, int npt, xPoint *ppt)
+{
+ xPoint *ppt_trans;
+ SETUP_BACKING_DST(pDst, pGC);
+
+ PROLOGUE(pGC);
+
+ ppt_trans = (xPoint *)ALLOCATE_LOCAL(npt * sizeof(xPoint));
+ if (ppt_trans)
+ {
+ CW_COPY_OFFSET_XYPOINTS(ppt_trans, ppt, npt);
+
+ (*pBackingGC->ops->PolyPoint)(pBackingDst, pBackingGC, mode, npt,
+ ppt_trans);
+
+ DEALLOCATE_LOCAL(ppt_trans);
+ }
+
+ EPILOGUE(pGC);
+}
+
+static void
+cwPolylines(DrawablePtr pDst, GCPtr pGC, int mode, int npt, DDXPointPtr ppt)
+{
+ DDXPointPtr ppt_trans;
+ SETUP_BACKING_DST(pDst, pGC);
+
+ PROLOGUE(pGC);
+
+ ppt_trans = (DDXPointPtr)ALLOCATE_LOCAL(npt * sizeof(DDXPointRec));
+ if (ppt_trans)
+ {
+ CW_COPY_OFFSET_XYPOINTS(ppt_trans, ppt, npt);
+
+ (*pBackingGC->ops->Polylines)(pBackingDst, pBackingGC, mode, npt,
+ ppt_trans);
+
+ DEALLOCATE_LOCAL(ppt_trans);
+ }
+
+ EPILOGUE(pGC);
+}
+
+static void
+cwPolySegment(DrawablePtr pDst, GCPtr pGC, int nseg, xSegment *pSegs)
+{
+ xSegment *psegs_trans;
+ SETUP_BACKING_DST(pDst, pGC);
+
+ PROLOGUE(pGC);
+
+ psegs_trans = (xSegment *)ALLOCATE_LOCAL(nseg * sizeof(xSegment));
+ if (psegs_trans)
+ {
+ CW_COPY_OFFSET_XYPOINTS(psegs_trans, pSegs, nseg * 2);
+
+ (*pBackingGC->ops->PolySegment)(pBackingDst, pBackingGC, nseg,
+ psegs_trans);
+
+ DEALLOCATE_LOCAL(psegs_trans);
+ }
+
+ EPILOGUE(pGC);
+}
+
+static void
+cwPolyRectangle(DrawablePtr pDst, GCPtr pGC, int nrects, xRectangle *pRects)
+{
+ xRectangle *prects_trans;
+ SETUP_BACKING_DST(pDst, pGC);
+
+ PROLOGUE(pGC);
+
+ prects_trans = (xRectangle *)ALLOCATE_LOCAL(nrects * sizeof(xRectangle));
+ if (prects_trans)
+ {
+ CW_COPY_OFFSET_RECTS(prects_trans, pRects, nrects);
+
+ (*pBackingGC->ops->PolyRectangle)(pBackingDst, pBackingGC, nrects,
+ prects_trans);
+
+ DEALLOCATE_LOCAL(pRectsCopy);
+ }
+
+ EPILOGUE(pGC);
+}
+
+static void
+cwPolyArc(DrawablePtr pDst, GCPtr pGC, int narcs, xArc *pArcs)
+{
+ xArc *parcs_trans;
+ SETUP_BACKING_DST(pDst, pGC);
+
+ PROLOGUE(pGC);
+
+ parcs_trans = (xArc *)ALLOCATE_LOCAL(narcs * sizeof(xArc));
+ if (parcs_trans)
+ {
+ CW_COPY_OFFSET_RECTS(parcs_trans, pArcs, narcs);
+
+ (*pBackingGC->ops->PolyArc)(pBackingDst, pBackingGC, narcs,
+ parcs_trans);
+
+ DEALLOCATE_LOCAL(parcs_trans);
+ }
+
+ EPILOGUE(pGC);
+}
+
+static void
+cwFillPolygon(DrawablePtr pDst, GCPtr pGC, int shape, int mode, int npt,
+ DDXPointPtr ppt)
+{
+ DDXPointPtr ppt_trans;
+ SETUP_BACKING_DST(pDst, pGC);
+
+ PROLOGUE(pGC);
+
+ ppt_trans = (DDXPointPtr)ALLOCATE_LOCAL(npt * sizeof(DDXPointRec));
+ if (ppt_trans)
+ {
+ CW_COPY_OFFSET_XYPOINTS(ppt_trans, ppt, npt);
+
+ (*pBackingGC->ops->FillPolygon)(pBackingDst, pBackingGC, shape, mode,
+ npt, ppt_trans);
+
+ DEALLOCATE_LOCAL(ppt_trans);
+ }
+
+ EPILOGUE(pGC);
+}
+
+static void
+cwPolyFillRect(DrawablePtr pDst, GCPtr pGC, int nrects, xRectangle *pRects)
+{
+ xRectangle *prects_trans;
+ SETUP_BACKING_DST(pDst, pGC);
+
+ PROLOGUE(pGC);
+
+ prects_trans = (xRectangle *)ALLOCATE_LOCAL(nrects * sizeof(xRectangle));
+ if (prects_trans)
+ {
+ CW_COPY_OFFSET_RECTS(prects_trans, pRects, nrects);
+
+ (*pBackingGC->ops->PolyFillRect)(pBackingDst, pBackingGC, nrects,
+ prects_trans);
+
+ DEALLOCATE_LOCAL(pRectsCopy);
+ }
+
+ EPILOGUE(pGC);
+}
+
+static void
+cwPolyFillArc(DrawablePtr pDst, GCPtr pGC, int narcs, xArc *parcs)
+{
+ xArc *parcs_trans;
+ SETUP_BACKING_DST(pDst, pGC);
+
+ PROLOGUE(pGC);
+
+ parcs_trans = (xArc *)ALLOCATE_LOCAL(narcs * sizeof(xArc));
+ if (parcs_trans)
+ {
+ CW_COPY_OFFSET_RECTS(parcs_trans, parcs, narcs);
+
+ (*pBackingGC->ops->PolyFillArc)(pBackingDst, pBackingGC, narcs,
+ parcs_trans);
+
+ DEALLOCATE_LOCAL(parcs_trans);
+ }
+
+ EPILOGUE(pGC);
+}
+
+static int
+cwPolyText8(DrawablePtr pDst, GCPtr pGC, int x, int y, int count, char *chars)
+{
+ int result;
+ int bx, by;
+ SETUP_BACKING_DST(pDst, pGC);
+
+ PROLOGUE(pGC);
+
+ CW_COPY_OFFSET_XY_DST(bx, by, x, y);
+
+ result = (*pBackingGC->ops->PolyText8)(pBackingDst, pBackingGC, bx, by,
+ count, chars);
+
+ EPILOGUE(pGC);
+ return result;
+}
+
+static int
+cwPolyText16(DrawablePtr pDst, GCPtr pGC, int x, int y, int count,
+ unsigned short *chars)
+{
+ int result;
+ int bx, by;
+ SETUP_BACKING_DST(pDst, pGC);
+
+ PROLOGUE(pGC);
+
+ CW_COPY_OFFSET_XY_DST(bx, by, x, y);
+
+ result = (*pBackingGC->ops->PolyText16)(pBackingDst, pBackingGC, bx, by,
+ count, chars);
+
+ EPILOGUE(pGC);
+ return result;
+}
+
+static void
+cwImageText8(DrawablePtr pDst, GCPtr pGC, int x, int y, int count, char *chars)
+{
+ int bx, by;
+ SETUP_BACKING_DST(pDst, pGC);
+
+ PROLOGUE(pGC);
+
+ CW_COPY_OFFSET_XY_DST(bx, by, x, y);
+
+ (*pBackingGC->ops->ImageText8)(pBackingDst, pBackingGC, bx, by, count,
+ chars);
+
+ EPILOGUE(pGC);
+}
+
+static void
+cwImageText16(DrawablePtr pDst, GCPtr pGC, int x, int y, int count,
+ unsigned short *chars)
+{
+ int bx, by;
+ SETUP_BACKING_DST(pDst, pGC);
+
+ PROLOGUE(pGC);
+
+ CW_COPY_OFFSET_XY_DST(bx, by, x, y);
+
+ (*pBackingGC->ops->ImageText16)(pBackingDst, pBackingGC, bx, by, count,
+ chars);
+
+ EPILOGUE(pGC);
+}
+
+static void
+cwImageGlyphBlt(DrawablePtr pDst, GCPtr pGC, int x, int y, unsigned int nglyph,
+ CharInfoPtr *ppci, pointer pglyphBase)
+{
+ int bx, by;
+ SETUP_BACKING_DST(pDst, pGC);
+
+ PROLOGUE(pGC);
+
+ CW_COPY_OFFSET_XY_DST(bx, by, x, y);
+
+ (*pBackingGC->ops->ImageGlyphBlt)(pBackingDst, pBackingGC, bx, by, nglyph,
+ ppci, pglyphBase);
+
+ EPILOGUE(pGC);
+}
+
+static void
+cwPolyGlyphBlt(DrawablePtr pDst, GCPtr pGC, int x, int y, unsigned int nglyph,
+ CharInfoPtr *ppci, pointer pglyphBase)
+{
+ int bx, by;
+ SETUP_BACKING_DST(pDst, pGC);
+
+ PROLOGUE(pGC);
+
+ CW_COPY_OFFSET_XY_DST(bx, by, x, y);
+
+ (*pBackingGC->ops->PolyGlyphBlt)(pBackingDst, pBackingGC, bx, by, nglyph,
+ ppci, pglyphBase);
+
+ EPILOGUE(pGC);
+}
+
+static void
+cwPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr pDst, int w, int h,
+ int x, int y)
+{
+ int bx, by;
+ SETUP_BACKING_DST(pDst, pGC);
+
+ PROLOGUE(pGC);
+
+ CW_COPY_OFFSET_XY_DST(bx, by, x, y);
+
+ (*pBackingGC->ops->PushPixels)(pBackingGC, pBitMap, pBackingDst, w, h,
+ bx, by);
+
+ EPILOGUE(pGC);
+}
+
diff --git a/miext/cw/cw_render.c b/miext/cw/cw_render.c
new file mode 100644
index 000000000..4f8bed8e4
--- /dev/null
+++ b/miext/cw/cw_render.c
@@ -0,0 +1,447 @@
+/*
+ * Copyright © 2004 Eric Anholt
+ *
+ * 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 Eric Anholt not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Eric Anholt makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * ERIC ANHOLT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL ERIC ANHOLT 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.
+ */
+/* $Header$ */
+
+#include "gcstruct.h"
+#include "windowstr.h"
+#include "cw.h"
+
+#ifdef RENDER
+
+#define cwPsDecl(pScreen) \
+ PictureScreenPtr ps = GetPictureScreen (pScreen); \
+ cwScreenPtr pCwScreen = getCwScreen (pScreen)
+
+#define cwBackingPicture(pCwPicture, pPicture) \
+ ((pCwPicture && pCwPicture->pBackingPicture) ? \
+ pCwPicture->pBackingPicture : pPicture)
+
+#define cwPictureDecl \
+ cwPicturePtr pCwPicture = getCwPicture(pPicture); \
+ PicturePtr pBackingPicture = pCwPicture ? pCwPicture->pBackingPicture : 0
+
+#define cwSrcPictureDecl \
+ int src_picture_x_off, src_picture_y_off; \
+ PicturePtr pBackingSrcPicture = cwGetBackingPicture(pSrcPicture, \
+ &src_picture_x_off,\
+ &src_picture_y_off)
+
+#define cwDstPictureDecl \
+ int dst_picture_x_off, dst_picture_y_off; \
+ PicturePtr pBackingDstPicture = cwGetBackingPicture(pDstPicture, \
+ &dst_picture_x_off,\
+ &dst_picture_y_off)
+
+#define cwMskPictureDecl \
+ int msk_picture_x_off = 0, msk_picture_y_off = 0; \
+ PicturePtr pBackingMskPicture = (!pMskPicture ? 0 : \
+ cwGetBackingPicture(pMskPicture, \
+ &msk_picture_x_off,\
+ &msk_picture_y_off))
+
+#define cwPsUnwrap(elt) { \
+ ps->elt = pCwScreen->elt; \
+}
+
+#define cwPsWrap(elt,func) { \
+ pCwScreen->elt = ps->elt; \
+ ps->elt = func; \
+}
+
+static VisualPtr
+cwFindVisualById (ScreenPtr pScreen, VisualID visual)
+{
+ int i;
+ VisualPtr pVisual;
+ for (i = 0, pVisual = pScreen->visuals;
+ i < pScreen->numVisuals;
+ i++, pVisual++)
+ {
+ if (pVisual->vid == visual)
+ return pVisual;
+ }
+ return 0;
+}
+
+static PicturePtr
+cwCreateBackingPicture (PicturePtr pPicture)
+{
+ ScreenPtr pScreen = pPicture->pDrawable->pScreen;
+ WindowPtr pWindow = (WindowPtr) pPicture->pDrawable;
+ PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWindow);
+ VisualPtr pVisual = cwFindVisualById (pScreen, wVisual (pWindow));
+ PictFormatPtr pFormat = PictureMatchVisual (pScreen, pWindow->drawable.depth,
+ pVisual);
+ int error;
+ PicturePtr pBackingPicture = CreatePicture (0, &pPixmap->drawable, pFormat,
+ 0, 0, serverClient, &error);
+ cwPicturePtr pCwPicture = getCwPicture (pPicture);
+
+ return pCwPicture->pBackingPicture = pBackingPicture;
+}
+
+static void
+cwDestroyBackingPicture (PicturePtr pPicture)
+{
+ cwPictureDecl;
+
+ if (pBackingPicture)
+ {
+ FreePicture (pBackingPicture, 0);
+ pCwPicture->pBackingPicture = 0;
+ }
+}
+
+static PicturePtr
+cwGetBackingPicture (PicturePtr pPicture, int *x_off, int *y_off)
+{
+ cwPictureDecl;
+
+ if (pBackingPicture)
+ {
+ DrawablePtr pDrawable = pPicture->pDrawable;
+ ScreenPtr pScreen = pDrawable->pScreen;
+ WindowPtr pWin = (WindowPtr) pDrawable;
+ PixmapPtr pPixmap = (*pScreen->GetWindowPixmap) (pWin);
+
+ *x_off = -pPixmap->screen_x;
+ *y_off = -pPixmap->screen_y;
+
+ return pBackingPicture;
+ }
+ else
+ {
+ *x_off = *y_off = 0;
+ return pPicture;
+ }
+}
+
+static int
+cwCreatePicture (PicturePtr pPicture)
+{
+ int ret;
+ ScreenPtr pScreen = pPicture->pDrawable->pScreen;
+ cwPsDecl(pScreen);
+
+ cwPsUnwrap (CreatePicture);
+ setCwPicture(pPicture, 0);
+ ret = (*ps->CreatePicture) (pPicture);
+ cwPsWrap (CreatePicture, cwCreatePicture);
+ return ret;
+}
+
+static void
+cwDestroyPicture (PicturePtr pPicture)
+{
+ ScreenPtr pScreen = pPicture->pDrawable->pScreen;
+ cwPsDecl(pScreen);
+
+ cwPsUnwrap(DestroyPicture);
+ cwDestroyBackingPicture (pPicture);
+ (*ps->DestroyPicture) (pPicture);
+ cwPsWrap(DestroyPicture, cwDestroyPicture);
+}
+
+static void
+cwChangePicture (PicturePtr pPicture,
+ Mask mask)
+{
+ ScreenPtr pScreen = pPicture->pDrawable->pScreen;
+ cwPsDecl(pScreen);
+ cwPictureDecl;
+
+ cwPsUnwrap(ChangePicture);
+ if (pBackingPicture)
+ {
+ (*ps->ChangePicture) (pBackingPicture, mask);
+ }
+ else
+ {
+ (*ps->ChangePicture) (pPicture, mask);
+ }
+ cwPsWrap(ChangePicture, cwChangePicture);
+}
+
+static void
+cwValidatePicture (PicturePtr pPicture,
+ Mask mask)
+{
+ ScreenPtr pScreen = pPicture->pDrawable->pScreen;
+ cwPsDecl(pScreen);
+ cwPictureDecl;
+
+ cwPsUnwrap(ValidatePicture);
+ (*ps->ValidatePicture) (pPicture, mask);
+ if (!cwDrawableIsRedirWindow (pPicture->pDrawable))
+ {
+ if (pBackingPicture)
+ cwDestroyBackingPicture (pPicture);
+ }
+ else
+ {
+ DrawablePtr pDrawable = pPicture->pDrawable;
+ WindowPtr pWin = (WindowPtr) (pDrawable);
+ DrawablePtr pBackingDrawable;
+ int x_off, y_off;
+
+ if (pBackingPicture && pBackingPicture->pDrawable !=
+ &(*pScreen->GetWindowPixmap) ((WindowPtr) pPicture->pDrawable)->drawable)
+ {
+ cwDestroyBackingPicture (pPicture);
+ pBackingPicture = 0;
+ }
+
+ if (!pBackingPicture)
+ {
+ pBackingPicture = cwCreateBackingPicture (pPicture);
+ if (!pBackingPicture)
+ {
+ cwPsWrap(ValidatePicture, cwValidatePicture);
+ return;
+ }
+ }
+
+ pBackingDrawable = cwGetBackingDrawable (&pWin->drawable, &x_off, &y_off);
+
+ /* Check to see if a new composite clip must be generated */
+
+ if (pDrawable->serialNumber != pCwPicture->serialNumber ||
+ (mask & (CPClipXOrigin|CPClipYOrigin|CPClipMask|CPSubwindowMode)))
+ {
+ RegionPtr pCompositeClip;
+
+ pCompositeClip = REGION_CREATE(pScreen, NULL, 1);
+ /* note - CT_PIXMAP "cannot" happen because no DDX supports it*/
+ REGION_COPY (pScreen, pCompositeClip, pPicture->pCompositeClip);
+ SetPictureClipRegion (pBackingPicture, -x_off, -y_off,
+ pCompositeClip);
+ pCwPicture->serialNumber = pDrawable->serialNumber;
+ }
+ mask |= pCwPicture->stateChanges;
+ (*ps->ValidatePicture) (pBackingPicture, mask);
+ pCwPicture->stateChanges = 0;
+ pBackingPicture->serialNumber = pBackingDrawable->serialNumber;
+ }
+ cwPsWrap(ValidatePicture, cwValidatePicture);
+}
+
+static void
+cwComposite (CARD8 op,
+ PicturePtr pSrcPicture,
+ PicturePtr pMskPicture,
+ PicturePtr pDstPicture,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMsk,
+ INT16 yMsk,
+ INT16 xDst,
+ INT16 yDst,
+ CARD16 width,
+ CARD16 height)
+{
+ ScreenPtr pScreen = pDstPicture->pDrawable->pScreen;
+ cwPsDecl(pScreen);
+ cwSrcPictureDecl;
+ cwMskPictureDecl;
+ cwDstPictureDecl;
+
+ cwPsUnwrap(Composite);
+ (*ps->Composite) (op, pBackingSrcPicture, pBackingMskPicture, pBackingDstPicture,
+ xSrc + src_picture_x_off, ySrc + src_picture_y_off,
+ xMsk + msk_picture_x_off, yMsk + msk_picture_y_off,
+ xDst + dst_picture_x_off, yDst + dst_picture_y_off,
+ width, height);
+ cwPsWrap(Composite, cwComposite);
+}
+
+static void
+cwGlyphs (CARD8 op,
+ PicturePtr pSrcPicture,
+ PicturePtr pDstPicture,
+ PictFormatPtr maskFormat,
+ INT16 xSrc,
+ INT16 ySrc,
+ int nlists,
+ GlyphListPtr lists,
+ GlyphPtr *glyphs)
+{
+ ScreenPtr pScreen = pDstPicture->pDrawable->pScreen;
+ cwPsDecl(pScreen);
+ cwSrcPictureDecl;
+ cwDstPictureDecl;
+
+ cwPsUnwrap(Glyphs);
+ if (nlists)
+ {
+ lists->xOff += dst_picture_x_off;
+ lists->yOff += dst_picture_y_off;
+ }
+ (*ps->Glyphs) (op, pBackingSrcPicture, pBackingDstPicture, maskFormat,
+ xSrc + src_picture_x_off, ySrc + src_picture_y_off,
+ nlists, lists, glyphs);
+ if (nlists)
+ {
+ lists->xOff -= dst_picture_x_off;
+ lists->yOff -= dst_picture_y_off;
+ }
+ cwPsWrap(Glyphs, cwGlyphs);
+}
+
+static void
+cwCompositeRects (CARD8 op,
+ PicturePtr pDstPicture,
+ xRenderColor *color,
+ int nRect,
+ xRectangle *rects)
+{
+ ScreenPtr pScreen = pDstPicture->pDrawable->pScreen;
+ cwPsDecl(pScreen);
+ cwDstPictureDecl;
+ int i;
+
+ cwPsUnwrap(CompositeRects);
+ for (i = 0; i < nRect; i++)
+ {
+ rects[i].x += dst_picture_x_off;
+ rects[i].y += dst_picture_y_off;
+ }
+ (*ps->CompositeRects) (op, pBackingDstPicture, color, nRect, rects);
+ for (i = 0; i < nRect; i++)
+ {
+ rects[i].x -= dst_picture_x_off;
+ rects[i].y -= dst_picture_y_off;
+ }
+ cwPsWrap(CompositeRects, cwCompositeRects);
+}
+
+static void
+cwTrapezoids (CARD8 op,
+ PicturePtr pSrcPicture,
+ PicturePtr pDstPicture,
+ PictFormatPtr maskFormat,
+ INT16 xSrc,
+ INT16 ySrc,
+ int ntrap,
+ xTrapezoid *traps)
+{
+ ScreenPtr pScreen = pDstPicture->pDrawable->pScreen;
+ cwPsDecl(pScreen);
+ cwSrcPictureDecl;
+ cwDstPictureDecl;
+ int i;
+
+ cwPsUnwrap(Trapezoids);
+ if (dst_picture_x_off | dst_picture_y_off)
+ for (i = 0; i < ntrap; i++)
+ {
+ traps[i].top += dst_picture_y_off << 16;
+ traps[i].bottom += dst_picture_y_off << 16;
+ traps[i].left.p1.x += dst_picture_x_off << 16;
+ traps[i].left.p1.y += dst_picture_y_off << 16;
+ traps[i].left.p2.x += dst_picture_x_off << 16;
+ traps[i].left.p2.y += dst_picture_y_off << 16;
+ traps[i].right.p1.x += dst_picture_x_off << 16;
+ traps[i].right.p1.y += dst_picture_y_off << 16;
+ traps[i].right.p2.x += dst_picture_x_off << 16;
+ traps[i].right.p2.y += dst_picture_y_off << 16;
+ }
+ (*ps->Trapezoids) (op, pBackingSrcPicture, pBackingDstPicture, maskFormat,
+ xSrc + src_picture_x_off, ySrc + src_picture_y_off,
+ ntrap, traps);
+ if (dst_picture_x_off | dst_picture_y_off)
+ for (i = 0; i < ntrap; i++)
+ {
+ traps[i].top -= dst_picture_y_off << 16;
+ traps[i].bottom -= dst_picture_y_off << 16;
+ traps[i].left.p1.x -= dst_picture_x_off << 16;
+ traps[i].left.p1.y -= dst_picture_y_off << 16;
+ traps[i].left.p2.x -= dst_picture_x_off << 16;
+ traps[i].left.p2.y -= dst_picture_y_off << 16;
+ traps[i].right.p1.x -= dst_picture_x_off << 16;
+ traps[i].right.p1.y -= dst_picture_y_off << 16;
+ traps[i].right.p2.x -= dst_picture_x_off << 16;
+ traps[i].right.p2.y -= dst_picture_y_off << 16;
+ }
+ cwPsWrap(Trapezoids, cwTrapezoids);
+}
+
+static void
+cwTriangles (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pDst,
+ PictFormatPtr maskFormat,
+ INT16 xSrc,
+ INT16 ySrc,
+ int ntri,
+ xTriangle *tris)
+{
+ /* FIXME */
+}
+
+static void
+cwTriStrip (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pDst,
+ PictFormatPtr maskFormat,
+ INT16 xSrc,
+ INT16 ySrc,
+ int npoint,
+ xPointFixed *points)
+{
+ /* FIXME */
+}
+
+static void
+cwTriFan (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pDst,
+ PictFormatPtr maskFormat,
+ INT16 xSrc,
+ INT16 ySrc,
+ int npoint,
+ xPointFixed *points)
+{
+ /* FIXME */
+}
+
+Bool
+cwInitializeRender (ScreenPtr pScreen)
+{
+ cwPsDecl (pScreen);
+
+ if (!AllocatePicturePrivate (pScreen, cwPictureIndex, 0))
+ return FALSE;
+ cwPsWrap(CreatePicture, cwCreatePicture);
+ cwPsWrap(DestroyPicture, cwDestroyPicture);
+ cwPsWrap(ChangePicture, cwChangePicture);
+ cwPsWrap(ValidatePicture, cwValidatePicture);
+ cwPsWrap(Composite, cwComposite);
+ cwPsWrap(Glyphs, cwGlyphs);
+ cwPsWrap(CompositeRects, cwCompositeRects);
+ cwPsWrap(Trapezoids, cwTrapezoids);
+ cwPsWrap(Triangles, cwTriangles);
+ cwPsWrap(TriStrip, cwTriStrip);
+ cwPsWrap(TriFan, cwTriFan);
+ return TRUE;
+}
+
+#endif /* RENDER */