diff options
author | Eric Anholt <anholt@freebsd.org> | 2004-07-31 08:24:14 +0000 |
---|---|---|
committer | Eric Anholt <anholt@freebsd.org> | 2004-07-31 08:24:14 +0000 |
commit | d690556d496c7331bd112903a0c9e6553c7d3342 (patch) | |
tree | 0e0016e04d05d6cbcdfb689ddb05d8f3a928dadf | |
parent | 8763cca7f9927bd6c9caf804bf09dcfea929eed0 (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.c | 537 | ||||
-rw-r--r-- | composite/compext.c | 408 | ||||
-rw-r--r-- | composite/compinit.c | 371 | ||||
-rw-r--r-- | composite/compint.h | 243 | ||||
-rw-r--r-- | composite/compwindow.c | 708 | ||||
-rw-r--r-- | dix/colormap.c | 22 | ||||
-rw-r--r-- | dix/window.c | 31 | ||||
-rw-r--r-- | include/pixmapstr.h | 4 | ||||
-rw-r--r-- | include/scrnintstr.h | 4 | ||||
-rw-r--r-- | include/windowstr.h | 3 | ||||
-rw-r--r-- | mi/mi.h | 10 | ||||
-rw-r--r-- | mi/miinitext.c | 25 | ||||
-rw-r--r-- | mi/mivaltree.c | 39 | ||||
-rw-r--r-- | miext/cw/cw.c | 570 | ||||
-rw-r--r-- | miext/cw/cw.h | 164 | ||||
-rw-r--r-- | miext/cw/cw_ops.c | 537 | ||||
-rw-r--r-- | miext/cw/cw_render.c | 447 |
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; @@ -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 */ |