1706f2543Smrg/*
2706f2543Smrg * Copyright © 2004 Eric Anholt
3706f2543Smrg *
4706f2543Smrg * Permission to use, copy, modify, distribute, and sell this software and its
5706f2543Smrg * documentation for any purpose is hereby granted without fee, provided that
6706f2543Smrg * the above copyright notice appear in all copies and that both that
7706f2543Smrg * copyright notice and this permission notice appear in supporting
8706f2543Smrg * documentation, and that the name of Eric Anholt not be used in
9706f2543Smrg * advertising or publicity pertaining to distribution of the software without
10706f2543Smrg * specific, written prior permission.  Eric Anholt makes no
11706f2543Smrg * representations about the suitability of this software for any purpose.  It
12706f2543Smrg * is provided "as is" without express or implied warranty.
13706f2543Smrg *
14706f2543Smrg * ERIC ANHOLT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15706f2543Smrg * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16706f2543Smrg * EVENT SHALL ERIC ANHOLT BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17706f2543Smrg * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18706f2543Smrg * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19706f2543Smrg * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20706f2543Smrg * PERFORMANCE OF THIS SOFTWARE.
21706f2543Smrg */
22706f2543Smrg
23706f2543Smrg#ifdef HAVE_DIX_CONFIG_H
24706f2543Smrg#include <dix-config.h>
25706f2543Smrg#endif
26706f2543Smrg
27706f2543Smrg#include <string.h>
28706f2543Smrg
29706f2543Smrg#include "gcstruct.h"
30706f2543Smrg#include "windowstr.h"
31706f2543Smrg#include "cw.h"
32706f2543Smrg
33706f2543Smrg#define CW_DEBUG 1
34706f2543Smrg
35706f2543Smrg#if CW_DEBUG
36706f2543Smrg#define CW_ASSERT(x) do {						\
37706f2543Smrg    if (!(x)) {								\
38706f2543Smrg	ErrorF("composite wrapper: assertion failed at %s:%d\n", __FUNC__, \
39706f2543Smrg	    __LINE__);							\
40706f2543Smrg    }									\
41706f2543Smrg} while (0)
42706f2543Smrg#else
43706f2543Smrg#define CW_ASSERT(x) do {} while (0)
44706f2543Smrg#endif
45706f2543Smrg
46706f2543SmrgDevPrivateKeyRec cwGCKeyRec;
47706f2543SmrgDevPrivateKeyRec cwScreenKeyRec;
48706f2543SmrgDevPrivateKeyRec cwWindowKeyRec;
49706f2543SmrgDevPrivateKeyRec cwPictureKeyRec;
50706f2543Smrg
51706f2543Smrgextern GCOps cwGCOps;
52706f2543Smrg
53706f2543Smrgstatic Bool
54706f2543SmrgcwCloseScreen (int i, ScreenPtr pScreen);
55706f2543Smrg
56706f2543Smrgstatic void
57706f2543SmrgcwValidateGC(GCPtr pGC, unsigned long stateChanges, DrawablePtr pDrawable);
58706f2543Smrgstatic void
59706f2543SmrgcwChangeGC(GCPtr pGC, unsigned long mask);
60706f2543Smrgstatic void
61706f2543SmrgcwCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst);
62706f2543Smrgstatic void
63706f2543SmrgcwDestroyGC(GCPtr pGC);
64706f2543Smrgstatic void
65706f2543SmrgcwChangeClip(GCPtr pGC, int type, pointer pvalue, int nrects);
66706f2543Smrgstatic void
67706f2543SmrgcwCopyClip(GCPtr pgcDst, GCPtr pgcSrc);
68706f2543Smrgstatic void
69706f2543SmrgcwDestroyClip(GCPtr pGC);
70706f2543Smrg
71706f2543SmrgGCFuncs cwGCFuncs = {
72706f2543Smrg    cwValidateGC,
73706f2543Smrg    cwChangeGC,
74706f2543Smrg    cwCopyGC,
75706f2543Smrg    cwDestroyGC,
76706f2543Smrg    cwChangeClip,
77706f2543Smrg    cwDestroyClip,
78706f2543Smrg    cwCopyClip,
79706f2543Smrg};
80706f2543Smrg
81706f2543Smrg/* Find the real drawable to draw to, and provide offsets that will translate
82706f2543Smrg * window coordinates to backing pixmap coordinates.
83706f2543Smrg */
84706f2543SmrgDrawablePtr
85706f2543SmrgcwGetBackingDrawable(DrawablePtr pDrawable, int *x_off, int *y_off)
86706f2543Smrg{
87706f2543Smrg    PixmapPtr	pPixmap;
88706f2543Smrg
89706f2543Smrg    if (pDrawable->type == DRAWABLE_WINDOW &&
90706f2543Smrg	(pPixmap = getCwPixmap ((WindowPtr) pDrawable)))
91706f2543Smrg    {
92706f2543Smrg	*x_off = pDrawable->x - pPixmap->screen_x;
93706f2543Smrg	*y_off = pDrawable->y - pPixmap->screen_y;
94706f2543Smrg	return &pPixmap->drawable;
95706f2543Smrg    } else {
96706f2543Smrg	*x_off = *y_off = 0;
97706f2543Smrg	return pDrawable;
98706f2543Smrg    }
99706f2543Smrg}
100706f2543Smrg
101706f2543Smrg#define FUNC_PROLOGUE(pGC, pPriv) do {					\
102706f2543Smrg    (pGC)->funcs = (pPriv)->wrapFuncs;					\
103706f2543Smrg    (pGC)->ops = (pPriv)->wrapOps;					\
104706f2543Smrg} while (0)
105706f2543Smrg
106706f2543Smrg#define FUNC_EPILOGUE(pGC, pPriv) do {					\
107706f2543Smrg    (pPriv)->wrapFuncs = (pGC)->funcs;					\
108706f2543Smrg    (pPriv)->wrapOps = (pGC)->ops;					\
109706f2543Smrg    (pGC)->funcs = &cwGCFuncs;						\
110706f2543Smrg    (pGC)->ops = &cwGCOps;						\
111706f2543Smrg} while (0)
112706f2543Smrg
113706f2543Smrg
114706f2543Smrgstatic Bool
115706f2543SmrgcwCreateBackingGC(GCPtr pGC, DrawablePtr pDrawable)
116706f2543Smrg{
117706f2543Smrg    cwGCRec *pPriv = getCwGC(pGC);
118706f2543Smrg    int status, x_off, y_off;
119706f2543Smrg    XID noexpose = xFalse;
120706f2543Smrg    DrawablePtr pBackingDrawable;
121706f2543Smrg
122706f2543Smrg    pBackingDrawable = cwGetBackingDrawable(pDrawable, &x_off, &y_off);
123706f2543Smrg    pPriv->pBackingGC = CreateGC(pBackingDrawable, GCGraphicsExposures,
124706f2543Smrg				 &noexpose, &status, (XID)0, serverClient);
125706f2543Smrg    if (status != Success)
126706f2543Smrg	return FALSE;
127706f2543Smrg
128706f2543Smrg    pPriv->serialNumber = 0;
129706f2543Smrg    pPriv->stateChanges = GCAllBits;
130706f2543Smrg
131706f2543Smrg    return TRUE;
132706f2543Smrg}
133706f2543Smrg
134706f2543Smrgstatic void
135706f2543SmrgcwDestroyBackingGC(GCPtr pGC)
136706f2543Smrg{
137706f2543Smrg    cwGCPtr pPriv;
138706f2543Smrg
139706f2543Smrg    pPriv = (cwGCPtr) getCwGC (pGC);
140706f2543Smrg
141706f2543Smrg    if (pPriv->pBackingGC) {
142706f2543Smrg	FreeGC(pPriv->pBackingGC, (XID)0);
143706f2543Smrg	pPriv->pBackingGC = NULL;
144706f2543Smrg    }
145706f2543Smrg}
146706f2543Smrg
147706f2543Smrgstatic void
148706f2543SmrgcwValidateGC(GCPtr pGC, unsigned long stateChanges, DrawablePtr pDrawable)
149706f2543Smrg{
150706f2543Smrg    GCPtr   	  	pBackingGC;
151706f2543Smrg    cwGCPtr		pPriv;
152706f2543Smrg    DrawablePtr		pBackingDrawable;
153706f2543Smrg    int			x_off, y_off;
154706f2543Smrg
155706f2543Smrg    pPriv = (cwGCPtr) getCwGC (pGC);
156706f2543Smrg
157706f2543Smrg    FUNC_PROLOGUE(pGC, pPriv);
158706f2543Smrg
159706f2543Smrg    /*
160706f2543Smrg     * Must call ValidateGC to ensure pGC->pCompositeClip is valid
161706f2543Smrg     */
162706f2543Smrg    (*pGC->funcs->ValidateGC)(pGC, stateChanges, pDrawable);
163706f2543Smrg
164706f2543Smrg    if (!cwDrawableIsRedirWindow(pDrawable)) {
165706f2543Smrg	cwDestroyBackingGC(pGC);
166706f2543Smrg	FUNC_EPILOGUE(pGC, pPriv);
167706f2543Smrg	return;
168706f2543Smrg    } else {
169706f2543Smrg	if (!pPriv->pBackingGC && !cwCreateBackingGC(pGC, pDrawable)) {
170706f2543Smrg	    FUNC_EPILOGUE(pGC, pPriv);
171706f2543Smrg	    return;
172706f2543Smrg	}
173706f2543Smrg    }
174706f2543Smrg
175706f2543Smrg    pBackingGC = pPriv->pBackingGC;
176706f2543Smrg    pBackingDrawable = cwGetBackingDrawable(pDrawable, &x_off, &y_off);
177706f2543Smrg
178706f2543Smrg    pPriv->stateChanges |= stateChanges;
179706f2543Smrg
180706f2543Smrg    /*
181706f2543Smrg     * Copy the composite clip into the backing GC if either
182706f2543Smrg     * the drawable clip list has changed or the client has changed
183706f2543Smrg     * the client clip data
184706f2543Smrg     */
185706f2543Smrg    if (pDrawable->serialNumber != pPriv->serialNumber ||
186706f2543Smrg	(pPriv->stateChanges & (GCClipXOrigin|GCClipYOrigin|GCClipMask)))
187706f2543Smrg    {
188706f2543Smrg	ChangeGCVal vals[2];
189706f2543Smrg	RegionPtr   pCompositeClip;
190706f2543Smrg
191706f2543Smrg	pCompositeClip = RegionCreate(NULL, 0);
192706f2543Smrg	RegionCopy(pCompositeClip, pGC->pCompositeClip);
193706f2543Smrg
194706f2543Smrg	/* Either the drawable has changed, or the clip list in the drawable has
195706f2543Smrg	 * changed.  Copy the new clip list over and set the new translated
196706f2543Smrg	 * offset for it.
197706f2543Smrg	 */
198706f2543Smrg
199706f2543Smrg	(*pBackingGC->funcs->ChangeClip) (pBackingGC, CT_REGION,
200706f2543Smrg					  (pointer) pCompositeClip, 0);
201706f2543Smrg
202706f2543Smrg	vals[0].val = x_off - pDrawable->x;
203706f2543Smrg	vals[1].val = y_off - pDrawable->y;
204706f2543Smrg	ChangeGC(NullClient, pBackingGC,
205706f2543Smrg		    (GCClipXOrigin | GCClipYOrigin), vals);
206706f2543Smrg
207706f2543Smrg	pPriv->serialNumber = pDrawable->serialNumber;
208706f2543Smrg	/*
209706f2543Smrg	 * Mask off any client clip changes to make sure
210706f2543Smrg	 * the clip list set above remains in effect
211706f2543Smrg	 */
212706f2543Smrg	pPriv->stateChanges &= ~(GCClipXOrigin|GCClipYOrigin|GCClipMask);
213706f2543Smrg    }
214706f2543Smrg
215706f2543Smrg    if (pPriv->stateChanges) {
216706f2543Smrg	CopyGC(pGC, pBackingGC, pPriv->stateChanges);
217706f2543Smrg	pPriv->stateChanges = 0;
218706f2543Smrg    }
219706f2543Smrg
220706f2543Smrg    if ((pGC->patOrg.x + x_off) != pBackingGC->patOrg.x ||
221706f2543Smrg	(pGC->patOrg.y + y_off) != pBackingGC->patOrg.y)
222706f2543Smrg    {
223706f2543Smrg	ChangeGCVal vals[2];
224706f2543Smrg	vals[0].val = pGC->patOrg.x + x_off;
225706f2543Smrg	vals[1].val = pGC->patOrg.y + y_off;
226706f2543Smrg	ChangeGC(NullClient, pBackingGC,
227706f2543Smrg		    (GCTileStipXOrigin | GCTileStipYOrigin), vals);
228706f2543Smrg    }
229706f2543Smrg
230706f2543Smrg    ValidateGC(pBackingDrawable, pBackingGC);
231706f2543Smrg
232706f2543Smrg    FUNC_EPILOGUE(pGC, pPriv);
233706f2543Smrg}
234706f2543Smrg
235706f2543Smrgstatic void
236706f2543SmrgcwChangeGC(GCPtr pGC, unsigned long mask)
237706f2543Smrg{
238706f2543Smrg    cwGCPtr pPriv = (cwGCPtr)dixLookupPrivate(&pGC->devPrivates, cwGCKey);
239706f2543Smrg
240706f2543Smrg    FUNC_PROLOGUE(pGC, pPriv);
241706f2543Smrg
242706f2543Smrg    (*pGC->funcs->ChangeGC) (pGC, mask);
243706f2543Smrg
244706f2543Smrg    FUNC_EPILOGUE(pGC, pPriv);
245706f2543Smrg}
246706f2543Smrg
247706f2543Smrgstatic void
248706f2543SmrgcwCopyGC(GCPtr pGCSrc, unsigned long mask, GCPtr pGCDst)
249706f2543Smrg{
250706f2543Smrg    cwGCPtr pPriv = (cwGCPtr)dixLookupPrivate(&pGCDst->devPrivates, cwGCKey);
251706f2543Smrg
252706f2543Smrg    FUNC_PROLOGUE(pGCDst, pPriv);
253706f2543Smrg
254706f2543Smrg    (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst);
255706f2543Smrg
256706f2543Smrg    FUNC_EPILOGUE(pGCDst, pPriv);
257706f2543Smrg}
258706f2543Smrg
259706f2543Smrgstatic void
260706f2543SmrgcwDestroyGC(GCPtr pGC)
261706f2543Smrg{
262706f2543Smrg    cwGCPtr pPriv = (cwGCPtr)dixLookupPrivate(&pGC->devPrivates, cwGCKey);
263706f2543Smrg
264706f2543Smrg    FUNC_PROLOGUE(pGC, pPriv);
265706f2543Smrg
266706f2543Smrg    cwDestroyBackingGC(pGC);
267706f2543Smrg
268706f2543Smrg    (*pGC->funcs->DestroyGC) (pGC);
269706f2543Smrg
270706f2543Smrg    /* leave it unwrapped */
271706f2543Smrg}
272706f2543Smrg
273706f2543Smrgstatic void
274706f2543SmrgcwChangeClip(GCPtr pGC, int type, pointer pvalue, int nrects)
275706f2543Smrg{
276706f2543Smrg    cwGCPtr pPriv = (cwGCPtr)dixLookupPrivate(&pGC->devPrivates, cwGCKey);
277706f2543Smrg
278706f2543Smrg    FUNC_PROLOGUE(pGC, pPriv);
279706f2543Smrg
280706f2543Smrg    (*pGC->funcs->ChangeClip)(pGC, type, pvalue, nrects);
281706f2543Smrg
282706f2543Smrg    FUNC_EPILOGUE(pGC, pPriv);
283706f2543Smrg}
284706f2543Smrg
285706f2543Smrgstatic void
286706f2543SmrgcwCopyClip(GCPtr pgcDst, GCPtr pgcSrc)
287706f2543Smrg{
288706f2543Smrg    cwGCPtr pPriv = (cwGCPtr)dixLookupPrivate(&pgcDst->devPrivates, cwGCKey);
289706f2543Smrg
290706f2543Smrg    FUNC_PROLOGUE(pgcDst, pPriv);
291706f2543Smrg
292706f2543Smrg    (*pgcDst->funcs->CopyClip)(pgcDst, pgcSrc);
293706f2543Smrg
294706f2543Smrg    FUNC_EPILOGUE(pgcDst, pPriv);
295706f2543Smrg}
296706f2543Smrg
297706f2543Smrgstatic void
298706f2543SmrgcwDestroyClip(GCPtr pGC)
299706f2543Smrg{
300706f2543Smrg    cwGCPtr pPriv = (cwGCPtr)dixLookupPrivate(&pGC->devPrivates, cwGCKey);
301706f2543Smrg
302706f2543Smrg    FUNC_PROLOGUE(pGC, pPriv);
303706f2543Smrg
304706f2543Smrg    (*pGC->funcs->DestroyClip)(pGC);
305706f2543Smrg
306706f2543Smrg    FUNC_EPILOGUE(pGC, pPriv);
307706f2543Smrg}
308706f2543Smrg
309706f2543Smrg/*
310706f2543Smrg * Screen wrappers.
311706f2543Smrg */
312706f2543Smrg
313706f2543Smrg#define SCREEN_PROLOGUE(pScreen, field)				\
314706f2543Smrg  ((pScreen)->field = getCwScreen(pScreen)->field)
315706f2543Smrg
316706f2543Smrg#define SCREEN_EPILOGUE(pScreen, field, wrapper) do {		\
317706f2543Smrg    getCwScreen(pScreen)->field = (pScreen)->field;		\
318706f2543Smrg    (pScreen)->field = (wrapper);				\
319706f2543Smrg} while (0)
320706f2543Smrg
321706f2543Smrgstatic Bool
322706f2543SmrgcwCreateGC(GCPtr pGC)
323706f2543Smrg{
324706f2543Smrg    cwGCPtr	pPriv = getCwGC(pGC);
325706f2543Smrg    ScreenPtr	pScreen = pGC->pScreen;
326706f2543Smrg    Bool	ret;
327706f2543Smrg
328706f2543Smrg    SCREEN_PROLOGUE(pScreen, CreateGC);
329706f2543Smrg
330706f2543Smrg    if ( (ret = (*pScreen->CreateGC)(pGC)) )
331706f2543Smrg	FUNC_EPILOGUE(pGC, pPriv);
332706f2543Smrg
333706f2543Smrg    SCREEN_EPILOGUE(pScreen, CreateGC, cwCreateGC);
334706f2543Smrg
335706f2543Smrg    return ret;
336706f2543Smrg}
337706f2543Smrg
338706f2543Smrgstatic void
339706f2543SmrgcwGetImage(DrawablePtr pSrc, int x, int y, int w, int h, unsigned int format,
340706f2543Smrg	   unsigned long planemask, char *pdstLine)
341706f2543Smrg{
342706f2543Smrg    ScreenPtr pScreen = pSrc->pScreen;
343706f2543Smrg    DrawablePtr pBackingDrawable;
344706f2543Smrg    int src_off_x, src_off_y;
345706f2543Smrg
346706f2543Smrg    SCREEN_PROLOGUE(pScreen, GetImage);
347706f2543Smrg
348706f2543Smrg    pBackingDrawable = cwGetBackingDrawable(pSrc, &src_off_x, &src_off_y);
349706f2543Smrg
350706f2543Smrg    CW_OFFSET_XY_SRC(x, y);
351706f2543Smrg
352706f2543Smrg    (*pScreen->GetImage)(pBackingDrawable, x, y, w, h, format, planemask,
353706f2543Smrg			 pdstLine);
354706f2543Smrg
355706f2543Smrg    SCREEN_EPILOGUE(pScreen, GetImage, cwGetImage);
356706f2543Smrg}
357706f2543Smrg
358706f2543Smrgstatic void
359706f2543SmrgcwGetSpans(DrawablePtr pSrc, int wMax, DDXPointPtr ppt, int *pwidth,
360706f2543Smrg	   int nspans, char *pdstStart)
361706f2543Smrg{
362706f2543Smrg    ScreenPtr pScreen = pSrc->pScreen;
363706f2543Smrg    DrawablePtr pBackingDrawable;
364706f2543Smrg    int i;
365706f2543Smrg    int src_off_x, src_off_y;
366706f2543Smrg
367706f2543Smrg    SCREEN_PROLOGUE(pScreen, GetSpans);
368706f2543Smrg
369706f2543Smrg    pBackingDrawable = cwGetBackingDrawable(pSrc, &src_off_x, &src_off_y);
370706f2543Smrg
371706f2543Smrg    for (i = 0; i < nspans; i++)
372706f2543Smrg	CW_OFFSET_XY_SRC(ppt[i].x, ppt[i].y);
373706f2543Smrg
374706f2543Smrg    (*pScreen->GetSpans)(pBackingDrawable, wMax, ppt, pwidth, nspans,
375706f2543Smrg			 pdstStart);
376706f2543Smrg
377706f2543Smrg    SCREEN_EPILOGUE(pScreen, GetSpans, cwGetSpans);
378706f2543Smrg}
379706f2543Smrg
380706f2543Smrg
381706f2543Smrgstatic void
382706f2543SmrgcwCopyWindow(WindowPtr pWin, DDXPointRec ptOldOrg, RegionPtr prgnSrc)
383706f2543Smrg{
384706f2543Smrg    ScreenPtr pScreen = pWin->drawable.pScreen;
385706f2543Smrg
386706f2543Smrg    SCREEN_PROLOGUE(pScreen, CopyWindow);
387706f2543Smrg
388706f2543Smrg    if (!cwDrawableIsRedirWindow((DrawablePtr)pWin)) {
389706f2543Smrg	(*pScreen->CopyWindow)(pWin, ptOldOrg, prgnSrc);
390706f2543Smrg    } else {
391706f2543Smrg	GCPtr	    pGC;
392706f2543Smrg	BoxPtr	    pExtents;
393706f2543Smrg	int	    x_off, y_off;
394706f2543Smrg	int	    dx, dy;
395706f2543Smrg	PixmapPtr   pBackingPixmap;
396706f2543Smrg	RegionPtr   pClip;
397706f2543Smrg	int	    src_x, src_y, dst_x, dst_y, w, h;
398706f2543Smrg
399706f2543Smrg	dx = ptOldOrg.x - pWin->drawable.x;
400706f2543Smrg	dy = ptOldOrg.y - pWin->drawable.y;
401706f2543Smrg
402706f2543Smrg	pExtents = RegionExtents(prgnSrc);
403706f2543Smrg
404706f2543Smrg	pBackingPixmap = (PixmapPtr) cwGetBackingDrawable((DrawablePtr)pWin,
405706f2543Smrg							  &x_off, &y_off);
406706f2543Smrg
407706f2543Smrg	src_x = pExtents->x1 - pBackingPixmap->screen_x;
408706f2543Smrg	src_y = pExtents->y1 - pBackingPixmap->screen_y;
409706f2543Smrg	w = pExtents->x2 - pExtents->x1;
410706f2543Smrg	h = pExtents->y2 - pExtents->y1;
411706f2543Smrg	dst_x = src_x - dx;
412706f2543Smrg	dst_y = src_y - dy;
413706f2543Smrg
414706f2543Smrg	/* Translate region (as required by API) */
415706f2543Smrg	RegionTranslate(prgnSrc, -dx, -dy);
416706f2543Smrg
417706f2543Smrg	pGC = GetScratchGC(pBackingPixmap->drawable.depth, pScreen);
418706f2543Smrg	/*
419706f2543Smrg	 * Copy region to GC as clip, aligning as dest clip
420706f2543Smrg	 */
421706f2543Smrg	pClip = RegionCreate(NULL, 0);
422706f2543Smrg	RegionIntersect(pClip, &pWin->borderClip, prgnSrc);
423706f2543Smrg	RegionTranslate(pClip,
424706f2543Smrg			 -pBackingPixmap->screen_x,
425706f2543Smrg			 -pBackingPixmap->screen_y);
426706f2543Smrg
427706f2543Smrg	(*pGC->funcs->ChangeClip) (pGC, CT_REGION, pClip, 0);
428706f2543Smrg
429706f2543Smrg	ValidateGC(&pBackingPixmap->drawable, pGC);
430706f2543Smrg
431706f2543Smrg	(*pGC->ops->CopyArea) (&pBackingPixmap->drawable,
432706f2543Smrg			       &pBackingPixmap->drawable, pGC,
433706f2543Smrg			       src_x, src_y, w, h, dst_x, dst_y);
434706f2543Smrg
435706f2543Smrg	(*pGC->funcs->DestroyClip) (pGC);
436706f2543Smrg
437706f2543Smrg	FreeScratchGC(pGC);
438706f2543Smrg    }
439706f2543Smrg
440706f2543Smrg    SCREEN_EPILOGUE(pScreen, CopyWindow, cwCopyWindow);
441706f2543Smrg}
442706f2543Smrg
443706f2543Smrgstatic PixmapPtr
444706f2543SmrgcwGetWindowPixmap (WindowPtr pWin)
445706f2543Smrg{
446706f2543Smrg    PixmapPtr	pPixmap = getCwPixmap (pWin);
447706f2543Smrg
448706f2543Smrg    if (!pPixmap)
449706f2543Smrg    {
450706f2543Smrg	ScreenPtr   pScreen = pWin->drawable.pScreen;
451706f2543Smrg	SCREEN_PROLOGUE(pScreen, GetWindowPixmap);
452706f2543Smrg	if (pScreen->GetWindowPixmap)
453706f2543Smrg	    pPixmap = (*pScreen->GetWindowPixmap) (pWin);
454706f2543Smrg	SCREEN_EPILOGUE(pScreen, GetWindowPixmap, cwGetWindowPixmap);
455706f2543Smrg    }
456706f2543Smrg    return pPixmap;
457706f2543Smrg}
458706f2543Smrg
459706f2543Smrgstatic void
460706f2543SmrgcwSetWindowPixmap (WindowPtr pWindow, PixmapPtr pPixmap)
461706f2543Smrg{
462706f2543Smrg    ScreenPtr	pScreen = pWindow->drawable.pScreen;
463706f2543Smrg
464706f2543Smrg    if (pPixmap == (*pScreen->GetScreenPixmap) (pScreen))
465706f2543Smrg	pPixmap = NULL;
466706f2543Smrg    setCwPixmap (pWindow, pPixmap);
467706f2543Smrg}
468706f2543Smrg
469706f2543Smrg/* Screen initialization/teardown */
470706f2543Smrgvoid
471706f2543SmrgmiInitializeCompositeWrapper(ScreenPtr pScreen)
472706f2543Smrg{
473706f2543Smrg    cwScreenPtr pScreenPriv;
474706f2543Smrg    Bool has_render = GetPictureScreenIfSet(pScreen) != NULL;
475706f2543Smrg
476706f2543Smrg    if (!dixRegisterPrivateKey(&cwScreenKeyRec, PRIVATE_SCREEN, 0))
477706f2543Smrg	return;
478706f2543Smrg
479706f2543Smrg    if (!dixRegisterPrivateKey(&cwGCKeyRec, PRIVATE_GC, sizeof(cwGCRec)))
480706f2543Smrg	return;
481706f2543Smrg
482706f2543Smrg    if (!dixRegisterPrivateKey(&cwWindowKeyRec, PRIVATE_WINDOW, 0))
483706f2543Smrg	return;
484706f2543Smrg
485706f2543Smrg    if (!dixRegisterPrivateKey(&cwPictureKeyRec, PRIVATE_PICTURE, 0))
486706f2543Smrg	return;
487706f2543Smrg
488706f2543Smrg    pScreenPriv = malloc(sizeof(cwScreenRec));
489706f2543Smrg    if (!pScreenPriv)
490706f2543Smrg	return;
491706f2543Smrg
492706f2543Smrg    dixSetPrivate(&pScreen->devPrivates, cwScreenKey, pScreenPriv);
493706f2543Smrg
494706f2543Smrg    SCREEN_EPILOGUE(pScreen, CloseScreen, cwCloseScreen);
495706f2543Smrg    SCREEN_EPILOGUE(pScreen, GetImage, cwGetImage);
496706f2543Smrg    SCREEN_EPILOGUE(pScreen, GetSpans, cwGetSpans);
497706f2543Smrg    SCREEN_EPILOGUE(pScreen, CreateGC, cwCreateGC);
498706f2543Smrg    SCREEN_EPILOGUE(pScreen, CopyWindow, cwCopyWindow);
499706f2543Smrg
500706f2543Smrg    SCREEN_EPILOGUE(pScreen, SetWindowPixmap, cwSetWindowPixmap);
501706f2543Smrg    SCREEN_EPILOGUE(pScreen, GetWindowPixmap, cwGetWindowPixmap);
502706f2543Smrg
503706f2543Smrg    if (has_render)
504706f2543Smrg	cwInitializeRender(pScreen);
505706f2543Smrg}
506706f2543Smrg
507706f2543Smrgstatic Bool
508706f2543SmrgcwCloseScreen (int i, ScreenPtr pScreen)
509706f2543Smrg{
510706f2543Smrg    cwScreenPtr   pScreenPriv;
511706f2543Smrg    PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
512706f2543Smrg
513706f2543Smrg    pScreenPriv = (cwScreenPtr)dixLookupPrivate(&pScreen->devPrivates,
514706f2543Smrg						cwScreenKey);
515706f2543Smrg    pScreen->CloseScreen = pScreenPriv->CloseScreen;
516706f2543Smrg    pScreen->GetImage = pScreenPriv->GetImage;
517706f2543Smrg    pScreen->GetSpans = pScreenPriv->GetSpans;
518706f2543Smrg    pScreen->CreateGC = pScreenPriv->CreateGC;
519706f2543Smrg    pScreen->CopyWindow = pScreenPriv->CopyWindow;
520706f2543Smrg
521706f2543Smrg    if (ps)
522706f2543Smrg	cwFiniRender(pScreen);
523706f2543Smrg
524706f2543Smrg    free((pointer)pScreenPriv);
525706f2543Smrg
526706f2543Smrg    return (*pScreen->CloseScreen)(i, pScreen);
527706f2543Smrg}
528