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.
This commit is contained in:
Eric Anholt 2004-07-31 08:24:14 +00:00
parent 8763cca7f9
commit d690556d49
17 changed files with 4110 additions and 13 deletions

537
composite/compalloc.c Normal file
View File

@ -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;
}

408
composite/compext.c Normal file
View File

@ -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);
}

371
composite/compinit.c Normal file
View File

@ -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;
}

243
composite/compint.h Normal file
View File

@ -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_ */

708
composite/compwindow.c Normal file
View File

@ -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;
}
}
}

View File

@ -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 $ */ /* $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 NUMRED(vis) ((vis->redMask >> vis->offsetRed) + 1)
#define NUMGREEN(vis) ((vis->greenMask >> vis->offsetGreen) + 1) #define NUMGREEN(vis) ((vis->greenMask >> vis->offsetGreen) + 1)
#define NUMBLUE(vis) ((vis->blueMask >> vis->offsetBlue) + 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) -- /* GetNextBitsOrBreak(bits, mask, base) --
* (Suggestion: First read the macro, then read this explanation. * (Suggestion: First read the macro, then read this explanation.
@ -866,6 +874,9 @@ AllocColor (pmap, pred, pgreen, pblue, pPix, client)
*pPix = (pixR << pVisual->offsetRed) | *pPix = (pixR << pVisual->offsetRed) |
(pixG << pVisual->offsetGreen) | (pixG << pVisual->offsetGreen) |
(pixB << pVisual->offsetBlue); (pixB << pVisual->offsetBlue);
#ifdef COMPOSITE
*pPix |= pVisual->alphaMask;
#endif
*pred = pmap->red[pixR].co.local.red; *pred = pmap->red[pixR].co.local.red;
*pgreen = pmap->green[pixG].co.local.green; *pgreen = pmap->green[pixG].co.local.green;
*pblue = pmap->blue[pixB].co.local.blue; *pblue = pmap->blue[pixB].co.local.blue;
@ -956,6 +967,9 @@ AllocColor (pmap, pred, pgreen, pblue, pPix, client)
return (BadAlloc); return (BadAlloc);
} }
*pPix = pixR | pixG | pixB; *pPix = pixR | pixG | pixB;
#ifdef COMPOSITE
*pPix |= pVisual->alphaMask;
#endif
break; break;
} }
@ -1928,6 +1942,10 @@ AllocDirect (client, pmap, c, r, g, b, contig, pixels, prmask, pgmask, pbmask)
} }
pmap->numPixelsBlue[client] += npixB; pmap->numPixelsBlue[client] += npixB;
pmap->freeBlue -= npixB; pmap->freeBlue -= npixB;
#ifdef COMPOSITE
for (pDst = pixels; pDst < pixels + c; pDst++)
*pDst |= pmap->pVisual->alphaMask;
#endif
DEALLOCATE_LOCAL(ppixBlue); DEALLOCATE_LOCAL(ppixBlue);
DEALLOCATE_LOCAL(ppixGreen); DEALLOCATE_LOCAL(ppixGreen);

View File

@ -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 $ */ /* $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->srcBuffer = DBE_FRONT_BUFFER;
pWin->dstBuffer = DBE_FRONT_BUFFER; pWin->dstBuffer = DBE_FRONT_BUFFER;
#endif #endif
#ifdef COMPOSITE
pWin->redirectDraw = 0;
#endif
} }
static void static void
@ -1661,6 +1664,19 @@ void
SetWinSize (pWin) SetWinSize (pWin)
register WindowPtr 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, ClippedRegionFromBox(pWin->parent, &pWin->winSize,
pWin->drawable.x, pWin->drawable.y, pWin->drawable.x, pWin->drawable.y,
(int)pWin->drawable.width, (int)pWin->drawable.width,
@ -1691,6 +1707,19 @@ SetBorderSize (pWin)
if (HasBorder (pWin)) { if (HasBorder (pWin)) {
bw = wBorderWidth (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, ClippedRegionFromBox(pWin->parent, &pWin->borderSize,
pWin->drawable.x - bw, pWin->drawable.y - bw, pWin->drawable.x - bw, pWin->drawable.y - bw,
(int)(pWin->drawable.width + (bw<<1)), (int)(pWin->drawable.width + (bw<<1)),

View File

@ -79,6 +79,10 @@ typedef struct _Pixmap {
#ifdef PIXPRIV #ifdef PIXPRIV
DevUnion *devPrivates; /* real devPrivates like gcs & windows */ DevUnion *devPrivates; /* real devPrivates like gcs & windows */
#endif #endif
#ifdef COMPOSITE
short screen_x;
short screen_y;
#endif
} PixmapRec; } PixmapRec;
#endif /* PIXMAPSTRUCT_H */ #endif /* PIXMAPSTRUCT_H */

View File

@ -75,6 +75,10 @@ typedef struct _Visual {
* it may have more or fewer */ * it may have more or fewer */
unsigned long redMask, greenMask, blueMask; unsigned long redMask, greenMask, blueMask;
int offsetRed, offsetGreen, offsetBlue; int offsetRed, offsetGreen, offsetBlue;
#ifdef COMPOSITE
unsigned long alphaMask;
int offsetAlpha;
#endif
} VisualRec; } VisualRec;
typedef struct _Depth { typedef struct _Depth {

View File

@ -135,6 +135,9 @@ typedef struct _Window {
#define DBE_BACK_BUFFER 0 #define DBE_BACK_BUFFER 0
unsigned dstBuffer:1; /* destination buffer for rendering */ unsigned dstBuffer:1; /* destination buffer for rendering */
unsigned srcBuffer:1; /* source buffer for rendering */ unsigned srcBuffer:1; /* source buffer for rendering */
#endif
#ifdef COMPOSITE
unsigned redirectDraw:1; /* rendering is redirected from here */
#endif #endif
DevUnion *devPrivates; DevUnion *devPrivates;
} WindowRec; } WindowRec;

10
mi/mi.h
View File

@ -495,6 +495,16 @@ extern int miShapedWindowIn(
int /*y*/ int /*y*/
); );
typedef void
(*SetRedirectBorderClipProcPtr) (WindowPtr pWindow, RegionPtr pRegion);
typedef RegionPtr
(*GetRedirectBorderClipProcPtr) (WindowPtr pWindow);
void
miRegisterRedirectBorderClipProc (SetRedirectBorderClipProcPtr setBorderClip,
GetRedirectBorderClipProcPtr getBorderClip);
extern int miValidateTree( extern int miValidateTree(
WindowPtr /*pParent*/, WindowPtr /*pParent*/,
WindowPtr /*pChild*/, WindowPtr /*pChild*/,

View File

@ -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 $ */ /* $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 #ifdef DAMAGE
extern void DamageExtensionInit(INITARGS); extern void DamageExtensionInit(INITARGS);
#endif #endif
#ifdef COMPOSITE
extern void CompositeExtensionInit(INITARGS);
#endif
/* The following is only a small first step towards run-time /* The following is only a small first step towards run-time
* configurable extensions. * configurable extensions.
@ -456,6 +459,10 @@ InitExtensions(argc, argv)
DPSExtensionInit(); DPSExtensionInit();
#endif #endif
#endif #endif
#ifdef XFIXES
/* must be before Render to layer DisplayCursor correctly */
XFixesExtensionInit();
#endif
#ifdef RENDER #ifdef RENDER
if (!noRenderExtension) RenderExtensionInit(); if (!noRenderExtension) RenderExtensionInit();
#endif #endif
@ -471,12 +478,12 @@ InitExtensions(argc, argv)
#ifdef XEVIE #ifdef XEVIE
if (!noXevieExtension) XevieExtensionInit(); if (!noXevieExtension) XevieExtensionInit();
#endif #endif
#ifdef XFIXES
XFixesExtensionInit();
#endif
#ifdef DAMAGE #ifdef DAMAGE
DamageExtensionInit(); DamageExtensionInit();
#endif #endif
#ifdef COMPOSITE
CompositeExtensionInit ();
#endif
} }
void void
@ -590,6 +597,10 @@ static ExtensionModule staticExtensions[] = {
#ifdef PANORAMIX #ifdef PANORAMIX
{ PanoramiXExtensionInit, PANORAMIX_PROTOCOL_NAME, &noPanoramiXExtension, NULL, NULL }, { PanoramiXExtensionInit, PANORAMIX_PROTOCOL_NAME, &noPanoramiXExtension, NULL, NULL },
#endif #endif
#ifdef XFIXES
/* must be before Render to layer DisplayCursor correctly */
{ XFixesExtensionInit, "XFIXES", NULL, NULL, NULL },
#endif
#ifdef XF86BIGFONT #ifdef XF86BIGFONT
{ XFree86BigfontExtensionInit, XF86BIGFONTNAME, NULL, NULL, NULL }, { XFree86BigfontExtensionInit, XF86BIGFONTNAME, NULL, NULL, NULL },
#endif #endif
@ -602,9 +613,9 @@ static ExtensionModule staticExtensions[] = {
#ifdef DAMAGE #ifdef DAMAGE
{ DamageExtensionInit, "DAMAGE", NULL, NULL }, { DamageExtensionInit, "DAMAGE", NULL, NULL },
#endif #endif
#ifdef XFIXES #ifdef COMPOSITE
{ XFixesExtensionInit, "XFIXES", NULL, NULL }, { CompositeExtensionInit, "COMPOSITE", NULL, NULL },
#endif #endif
#ifdef XEVIE #ifdef XEVIE
{ XevieExtensionInit, "XEVIE", &noXevieExtension, NULL }, { XevieExtensionInit, "XEVIE", &noXevieExtension, NULL },
#endif #endif

View File

@ -1,5 +1,5 @@
/* $Xorg: mivaltree.c,v 1.4 2001/02/09 02:05:22 xorgcvs Exp $ */ /* $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 -- * mivaltree.c --
* Functions for recalculating window clip lists. Main function * Functions for recalculating window clip lists. Main function
@ -167,6 +167,17 @@ miShapedWindowIn (pScreen, universe, bounding, rect, x, y)
} }
#endif #endif
static GetRedirectBorderClipProcPtr miGetRedirectBorderClipProc;
static SetRedirectBorderClipProcPtr miSetRedirectBorderClipProc;
void
miRegisterRedirectBorderClipProc (SetRedirectBorderClipProcPtr setBorderClip,
GetRedirectBorderClipProcPtr getBorderClip)
{
miSetRedirectBorderClipProc = setBorderClip;
miGetRedirectBorderClipProc = getBorderClip;
}
#define HasParentRelativeBorder(w) (!(w)->borderIsPixel && \ #define HasParentRelativeBorder(w) (!(w)->borderIsPixel && \
HasBorder(w) && \ HasBorder(w) && \
(w)->backgroundState == ParentRelative) (w)->backgroundState == ParentRelative)
@ -264,6 +275,18 @@ miComputeClips (
((pParent->eventMask | wOtherEventMasks(pParent)) & VisibilityChangeMask)) ((pParent->eventMask | wOtherEventMasks(pParent)) & VisibilityChangeMask))
SendVisibilityNotify(pParent); 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; dx = pParent->drawable.x - pParent->valdata->before.oldAbsCorner.x;
dy = pParent->drawable.y - pParent->valdata->before.oldAbsCorner.y; dy = pParent->drawable.y - pParent->valdata->before.oldAbsCorner.y;
@ -640,7 +663,12 @@ miValidateTree (pParent, pChild, kind)
{ {
if (pWin->valdata) 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) if (pWin->viewable)
viewvals++; viewvals++;
} }
@ -654,7 +682,12 @@ miValidateTree (pParent, pChild, kind)
{ {
if (pWin->valdata) 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) if (pWin->viewable)
viewvals++; viewvals++;
} }

570
miext/cw/cw.c Normal file
View File

@ -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);
}

164
miext/cw/cw.h Normal file
View File

@ -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);

537
miext/cw/cw_ops.c Normal file
View File

@ -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);
}

447
miext/cw/cw_render.c Normal file
View File

@ -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 */