cw_render.c revision 706f2543
1/*
2 * Copyright © 2004 Eric Anholt
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and its
5 * documentation for any purpose is hereby granted without fee, provided that
6 * the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of Eric Anholt not be used in
9 * advertising or publicity pertaining to distribution of the software without
10 * specific, written prior permission.  Eric Anholt makes no
11 * representations about the suitability of this software for any purpose.  It
12 * is provided "as is" without express or implied warranty.
13 *
14 * ERIC ANHOLT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15 * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16 * EVENT SHALL ERIC ANHOLT BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17 * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18 * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
20 * PERFORMANCE OF THIS SOFTWARE.
21 */
22
23#ifdef HAVE_DIX_CONFIG_H
24#include <dix-config.h>
25#endif
26
27#include <string.h>
28
29#include "gcstruct.h"
30#include "windowstr.h"
31#include "cw.h"
32
33#define cwPsDecl(pScreen)	\
34    PictureScreenPtr	ps = GetPictureScreen (pScreen);	\
35    cwScreenPtr		pCwScreen = getCwScreen (pScreen)
36
37#define cwPicturePrivate					\
38    cwPicturePtr    pPicturePrivate = getCwPicture(pPicture)
39
40#define cwSrcPictureDecl							\
41    int		    src_picture_x_off, src_picture_y_off;			\
42    PicturePtr	    pBackingSrcPicture = cwGetBackingPicture(pSrcPicture,	\
43							     &src_picture_x_off,\
44							     &src_picture_y_off)
45
46#define cwDstPictureDecl							\
47    int		    dst_picture_x_off, dst_picture_y_off;			\
48    PicturePtr	    pBackingDstPicture = cwGetBackingPicture(pDstPicture,	\
49							     &dst_picture_x_off,\
50							     &dst_picture_y_off)
51
52#define cwMskPictureDecl							\
53    int		    msk_picture_x_off = 0, msk_picture_y_off = 0;		\
54    PicturePtr	    pBackingMskPicture = (!pMskPicture ? 0 :	    		\
55					  cwGetBackingPicture(pMskPicture,	\
56							      &msk_picture_x_off,\
57							      &msk_picture_y_off))
58
59#define cwPsUnwrap(elt) {	\
60    ps->elt = pCwScreen->elt;	\
61}
62
63#define cwPsWrap(elt,func) {	\
64    pCwScreen->elt = ps->elt;	\
65    ps->elt = func;		\
66}
67
68static cwPicturePtr
69cwCreatePicturePrivate (PicturePtr pPicture)
70{
71    WindowPtr	    pWindow = (WindowPtr) pPicture->pDrawable;
72    PixmapPtr	    pPixmap = getCwPixmap (pWindow);
73    int		    error;
74    cwPicturePtr    pPicturePrivate;
75
76    pPicturePrivate = malloc(sizeof (cwPictureRec));
77    if (!pPicturePrivate)
78	return NULL;
79
80    pPicturePrivate->pBackingPicture = CreatePicture (0, &pPixmap->drawable,
81						      pPicture->pFormat,
82						      0, 0, serverClient,
83						      &error);
84    if (!pPicturePrivate->pBackingPicture)
85    {
86	free(pPicturePrivate);
87	return NULL;
88    }
89
90    /*
91     * Ensure that this serial number does not match the window's
92     */
93    pPicturePrivate->serialNumber = pPixmap->drawable.serialNumber;
94    pPicturePrivate->stateChanges = (1 << (CPLastBit + 1)) - 1;
95
96    setCwPicture(pPicture, pPicturePrivate);
97
98    return pPicturePrivate;
99}
100
101static void
102cwDestroyPicturePrivate (PicturePtr pPicture)
103{
104    cwPicturePrivate;
105
106    if (pPicturePrivate)
107    {
108	if (pPicturePrivate->pBackingPicture)
109	    FreePicture (pPicturePrivate->pBackingPicture, 0);
110	free(pPicturePrivate);
111	setCwPicture(pPicture, NULL);
112    }
113}
114
115static PicturePtr
116cwGetBackingPicture (PicturePtr pPicture, int *x_off, int *y_off)
117{
118    cwPicturePrivate;
119
120    if (pPicturePrivate)
121    {
122	DrawablePtr pDrawable = pPicture->pDrawable;
123	WindowPtr   pWindow = (WindowPtr) pDrawable;
124	PixmapPtr   pPixmap = getCwPixmap (pWindow);
125
126	*x_off = pDrawable->x - pPixmap->screen_x;
127	*y_off = pDrawable->y - pPixmap->screen_y;
128
129	return pPicturePrivate->pBackingPicture;
130    }
131    else
132    {
133	*x_off = *y_off = 0;
134	return pPicture;
135    }
136}
137
138static void
139cwDestroyPicture (PicturePtr pPicture)
140{
141    ScreenPtr		pScreen = pPicture->pDrawable->pScreen;
142    cwPsDecl(pScreen);
143
144    cwPsUnwrap(DestroyPicture);
145    cwDestroyPicturePrivate (pPicture);
146    (*ps->DestroyPicture) (pPicture);
147    cwPsWrap(DestroyPicture, cwDestroyPicture);
148}
149
150static void
151cwChangePicture (PicturePtr pPicture, Mask mask)
152{
153    ScreenPtr		pScreen = pPicture->pDrawable->pScreen;
154    cwPsDecl(pScreen);
155    cwPicturePtr	pPicturePrivate = getCwPicture(pPicture);
156
157    cwPsUnwrap(ChangePicture);
158    (*ps->ChangePicture) (pPicture, mask);
159    if (pPicturePrivate)
160	pPicturePrivate->stateChanges |= mask;
161    cwPsWrap(ChangePicture, cwChangePicture);
162}
163
164
165static void
166cwValidatePicture (PicturePtr pPicture,
167		   Mask       mask)
168{
169    DrawablePtr		pDrawable = pPicture->pDrawable;
170    ScreenPtr		pScreen = pDrawable->pScreen;
171    cwPsDecl(pScreen);
172    cwPicturePrivate;
173
174    cwPsUnwrap(ValidatePicture);
175
176    /*
177     * Must call ValidatePicture to ensure pPicture->pCompositeClip is valid
178     */
179    (*ps->ValidatePicture) (pPicture, mask);
180
181    if (!cwDrawableIsRedirWindow (pDrawable))
182    {
183	if (pPicturePrivate)
184	    cwDestroyPicturePrivate (pPicture);
185    }
186    else
187    {
188	PicturePtr  pBackingPicture;
189	DrawablePtr pBackingDrawable;
190	int	    x_off, y_off;
191
192	pBackingDrawable = cwGetBackingDrawable(pDrawable, &x_off, &y_off);
193
194	if (pPicturePrivate &&
195	    pPicturePrivate->pBackingPicture->pDrawable != pBackingDrawable)
196	{
197	    cwDestroyPicturePrivate (pPicture);
198	    pPicturePrivate = 0;
199	}
200
201	if (!pPicturePrivate)
202	{
203	    pPicturePrivate = cwCreatePicturePrivate (pPicture);
204	    if (!pPicturePrivate)
205	    {
206		cwPsWrap(ValidatePicture, cwValidatePicture);
207		return;
208	    }
209	}
210
211	pBackingPicture = pPicturePrivate->pBackingPicture;
212
213	/*
214	 * Always copy transform and filters because there's no
215	 * indication of when they've changed
216	 */
217	SetPictureTransform(pBackingPicture, pPicture->transform);
218
219	if (pBackingPicture->filter != pPicture->filter ||
220	    pPicture->filter_nparams > 0)
221	{
222	    char    *filter = PictureGetFilterName (pPicture->filter);
223
224	    SetPictureFilter(pBackingPicture,
225			     filter, strlen (filter),
226			     pPicture->filter_params,
227			     pPicture->filter_nparams);
228	}
229
230	pPicturePrivate->stateChanges |= mask;
231
232	if (pPicturePrivate->serialNumber != pDrawable->serialNumber ||
233	    (pPicturePrivate->stateChanges & (CPClipXOrigin|CPClipYOrigin|CPClipMask)))
234	{
235	    SetPictureClipRegion (pBackingPicture,
236				  x_off - pDrawable->x,
237				  y_off - pDrawable->y,
238				  pPicture->pCompositeClip);
239
240	    pPicturePrivate->serialNumber = pDrawable->serialNumber;
241	    pPicturePrivate->stateChanges &= ~(CPClipXOrigin | CPClipYOrigin | CPClipMask);
242	}
243
244	CopyPicture(pPicture, pPicturePrivate->stateChanges, pBackingPicture);
245
246	ValidatePicture (pBackingPicture);
247    }
248    cwPsWrap(ValidatePicture, cwValidatePicture);
249}
250
251static void
252cwComposite (CARD8	op,
253	     PicturePtr pSrcPicture,
254	     PicturePtr pMskPicture,
255	     PicturePtr pDstPicture,
256	     INT16	xSrc,
257	     INT16	ySrc,
258	     INT16	xMsk,
259	     INT16	yMsk,
260	     INT16	xDst,
261	     INT16	yDst,
262	     CARD16	width,
263	     CARD16	height)
264{
265    ScreenPtr	pScreen = pDstPicture->pDrawable->pScreen;
266    cwPsDecl(pScreen);
267    cwSrcPictureDecl;
268    cwMskPictureDecl;
269    cwDstPictureDecl;
270
271    cwPsUnwrap(Composite);
272    (*ps->Composite) (op, pBackingSrcPicture, pBackingMskPicture, pBackingDstPicture,
273		      xSrc + src_picture_x_off, ySrc + src_picture_y_off,
274		      xMsk + msk_picture_x_off, yMsk + msk_picture_y_off,
275		      xDst + dst_picture_x_off, yDst + dst_picture_y_off,
276		      width, height);
277    cwPsWrap(Composite, cwComposite);
278}
279
280static void
281cwCompositeRects (CARD8		op,
282		  PicturePtr	pDstPicture,
283		  xRenderColor  *color,
284		  int		nRect,
285		  xRectangle	*rects)
286{
287    ScreenPtr	pScreen = pDstPicture->pDrawable->pScreen;
288    cwPsDecl(pScreen);
289    cwDstPictureDecl;
290    int i;
291
292    cwPsUnwrap(CompositeRects);
293    for (i = 0; i < nRect; i++)
294    {
295	rects[i].x += dst_picture_x_off;
296	rects[i].y += dst_picture_y_off;
297    }
298    (*ps->CompositeRects) (op, pBackingDstPicture, color, nRect, rects);
299    cwPsWrap(CompositeRects, cwCompositeRects);
300}
301
302static void
303cwTrapezoids (CARD8	    op,
304	      PicturePtr    pSrcPicture,
305	      PicturePtr    pDstPicture,
306	      PictFormatPtr maskFormat,
307	      INT16	    xSrc,
308	      INT16	    ySrc,
309	      int	    ntrap,
310	      xTrapezoid    *traps)
311{
312    ScreenPtr	pScreen = pDstPicture->pDrawable->pScreen;
313    cwPsDecl(pScreen);
314    cwSrcPictureDecl;
315    cwDstPictureDecl;
316    int i;
317
318    cwPsUnwrap(Trapezoids);
319    if (dst_picture_x_off || dst_picture_y_off) {
320	for (i = 0; i < ntrap; i++)
321	{
322	    traps[i].top += dst_picture_y_off << 16;
323	    traps[i].bottom += dst_picture_y_off << 16;
324	    traps[i].left.p1.x += dst_picture_x_off << 16;
325	    traps[i].left.p1.y += dst_picture_y_off << 16;
326	    traps[i].left.p2.x += dst_picture_x_off << 16;
327	    traps[i].left.p2.y += dst_picture_y_off << 16;
328	    traps[i].right.p1.x += dst_picture_x_off << 16;
329	    traps[i].right.p1.y += dst_picture_y_off << 16;
330	    traps[i].right.p2.x += dst_picture_x_off << 16;
331	    traps[i].right.p2.y += dst_picture_y_off << 16;
332	}
333    }
334    (*ps->Trapezoids) (op, pBackingSrcPicture, pBackingDstPicture, maskFormat,
335		       xSrc + src_picture_x_off, ySrc + src_picture_y_off,
336		       ntrap, traps);
337    cwPsWrap(Trapezoids, cwTrapezoids);
338}
339
340static void
341cwTriangles (CARD8	    op,
342	     PicturePtr	    pSrcPicture,
343	     PicturePtr	    pDstPicture,
344	     PictFormatPtr  maskFormat,
345	     INT16	    xSrc,
346	     INT16	    ySrc,
347	     int	    ntri,
348	     xTriangle	   *tris)
349{
350    ScreenPtr	pScreen = pDstPicture->pDrawable->pScreen;
351    cwPsDecl(pScreen);
352    cwSrcPictureDecl;
353    cwDstPictureDecl;
354    int i;
355
356    cwPsUnwrap(Triangles);
357    if (dst_picture_x_off || dst_picture_y_off) {
358	for (i = 0; i < ntri; i++)
359	{
360	    tris[i].p1.x += dst_picture_x_off << 16;
361	    tris[i].p1.y += dst_picture_y_off << 16;
362	    tris[i].p2.x += dst_picture_x_off << 16;
363	    tris[i].p2.y += dst_picture_y_off << 16;
364	    tris[i].p3.x += dst_picture_x_off << 16;
365	    tris[i].p3.y += dst_picture_y_off << 16;
366	}
367    }
368    (*ps->Triangles) (op, pBackingSrcPicture, pBackingDstPicture, maskFormat,
369		      xSrc + src_picture_x_off, ySrc + src_picture_y_off,
370		      ntri, tris);
371    cwPsWrap(Triangles, cwTriangles);
372}
373
374static void
375cwTriStrip (CARD8	    op,
376	    PicturePtr	    pSrcPicture,
377	    PicturePtr	    pDstPicture,
378	    PictFormatPtr   maskFormat,
379	    INT16	    xSrc,
380	    INT16	    ySrc,
381	    int		    npoint,
382	    xPointFixed    *points)
383{
384    ScreenPtr	pScreen = pDstPicture->pDrawable->pScreen;
385    cwPsDecl(pScreen);
386    cwSrcPictureDecl;
387    cwDstPictureDecl;
388    int i;
389
390    cwPsUnwrap(TriStrip);
391    if (dst_picture_x_off || dst_picture_y_off) {
392	for (i = 0; i < npoint; i++)
393	{
394	    points[i].x += dst_picture_x_off << 16;
395	    points[i].y += dst_picture_y_off << 16;
396	}
397    }
398    (*ps->TriStrip) (op, pBackingSrcPicture, pBackingDstPicture, maskFormat,
399		     xSrc + src_picture_x_off, ySrc + src_picture_y_off,
400		     npoint, points);
401    cwPsWrap(TriStrip, cwTriStrip);
402}
403
404static void
405cwTriFan (CARD8		 op,
406	  PicturePtr	 pSrcPicture,
407	  PicturePtr	 pDstPicture,
408	  PictFormatPtr  maskFormat,
409	  INT16		 xSrc,
410	  INT16		 ySrc,
411	  int		 npoint,
412	  xPointFixed   *points)
413{
414    ScreenPtr	pScreen = pDstPicture->pDrawable->pScreen;
415    cwPsDecl(pScreen);
416    cwSrcPictureDecl;
417    cwDstPictureDecl;
418    int i;
419
420    cwPsUnwrap(TriFan);
421    if (dst_picture_x_off || dst_picture_y_off) {
422	for (i = 0; i < npoint; i++)
423	{
424	    points[i].x += dst_picture_x_off << 16;
425	    points[i].y += dst_picture_y_off << 16;
426	}
427    }
428    (*ps->TriFan) (op, pBackingSrcPicture, pBackingDstPicture, maskFormat,
429		   xSrc + src_picture_x_off, ySrc + src_picture_y_off,
430		   npoint, points);
431    cwPsWrap(TriFan, cwTriFan);
432}
433
434void
435cwInitializeRender (ScreenPtr pScreen)
436{
437    cwPsDecl (pScreen);
438
439    cwPsWrap(DestroyPicture, cwDestroyPicture);
440    cwPsWrap(ChangePicture, cwChangePicture);
441    cwPsWrap(ValidatePicture, cwValidatePicture);
442    cwPsWrap(Composite, cwComposite);
443    cwPsWrap(CompositeRects, cwCompositeRects);
444    cwPsWrap(Trapezoids, cwTrapezoids);
445    cwPsWrap(Triangles, cwTriangles);
446    cwPsWrap(TriStrip, cwTriStrip);
447    cwPsWrap(TriFan, cwTriFan);
448    /* There is no need to wrap AddTraps as far as we can tell.  AddTraps can
449     * only be done on alpha-only pictures, and we won't be getting
450     * alpha-only window pictures, so there's no need to translate.
451     */
452}
453
454void
455cwFiniRender (ScreenPtr pScreen)
456{
457    cwPsDecl (pScreen);
458
459    cwPsUnwrap(DestroyPicture);
460    cwPsUnwrap(ChangePicture);
461    cwPsUnwrap(ValidatePicture);
462    cwPsUnwrap(Composite);
463    cwPsUnwrap(CompositeRects);
464    cwPsUnwrap(Trapezoids);
465    cwPsUnwrap(Triangles);
466    cwPsUnwrap(TriStrip);
467    cwPsUnwrap(TriFan);
468}
469
470