dmxpict.c revision 706f2543
1706f2543Smrg/*
2706f2543Smrg * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina.
3706f2543Smrg *
4706f2543Smrg * All Rights Reserved.
5706f2543Smrg *
6706f2543Smrg * Permission is hereby granted, free of charge, to any person obtaining
7706f2543Smrg * a copy of this software and associated documentation files (the
8706f2543Smrg * "Software"), to deal in the Software without restriction, including
9706f2543Smrg * without limitation on the rights to use, copy, modify, merge,
10706f2543Smrg * publish, distribute, sublicense, and/or sell copies of the Software,
11706f2543Smrg * and to permit persons to whom the Software is furnished to do so,
12706f2543Smrg * subject to the following conditions:
13706f2543Smrg *
14706f2543Smrg * The above copyright notice and this permission notice (including the
15706f2543Smrg * next paragraph) shall be included in all copies or substantial
16706f2543Smrg * portions of the Software.
17706f2543Smrg *
18706f2543Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19706f2543Smrg * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20706f2543Smrg * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21706f2543Smrg * NON-INFRINGEMENT.  IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
22706f2543Smrg * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23706f2543Smrg * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24706f2543Smrg * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25706f2543Smrg * SOFTWARE.
26706f2543Smrg */
27706f2543Smrg
28706f2543Smrg/*
29706f2543Smrg * Authors:
30706f2543Smrg *   Kevin E. Martin <kem@redhat.com>
31706f2543Smrg *
32706f2543Smrg */
33706f2543Smrg
34706f2543Smrg/** \file
35706f2543Smrg *  Provide support for the RENDER extension (version 0.8).
36706f2543Smrg */
37706f2543Smrg
38706f2543Smrg#ifdef HAVE_DMX_CONFIG_H
39706f2543Smrg#include <dmx-config.h>
40706f2543Smrg#endif
41706f2543Smrg
42706f2543Smrg#include "dmx.h"
43706f2543Smrg#include "dmxsync.h"
44706f2543Smrg#include "dmxpict.h"
45706f2543Smrg#include "dmxwindow.h"
46706f2543Smrg#include "dmxpixmap.h"
47706f2543Smrg
48706f2543Smrg#include "fb.h"
49706f2543Smrg#include "pixmapstr.h"
50706f2543Smrg#include "dixstruct.h"
51706f2543Smrg
52706f2543Smrg#include <X11/extensions/render.h>
53706f2543Smrg#include <X11/extensions/renderproto.h>
54706f2543Smrg#include <X11/extensions/Xfixes.h>
55706f2543Smrg#include "picture.h"
56706f2543Smrg#include "picturestr.h"
57706f2543Smrg#include "mipict.h"
58706f2543Smrg#include "fbpict.h"
59706f2543Smrg
60706f2543Smrg
61706f2543Smrgextern int RenderErrBase;
62706f2543Smrgextern int (*ProcRenderVector[RenderNumberRequests])(ClientPtr);
63706f2543Smrg
64706f2543Smrgstatic int (*dmxSaveRenderVector[RenderNumberRequests])(ClientPtr);
65706f2543Smrg
66706f2543Smrg
67706f2543Smrgstatic int dmxProcRenderCreateGlyphSet(ClientPtr client);
68706f2543Smrgstatic int dmxProcRenderFreeGlyphSet(ClientPtr client);
69706f2543Smrgstatic int dmxProcRenderAddGlyphs(ClientPtr client);
70706f2543Smrgstatic int dmxProcRenderFreeGlyphs(ClientPtr client);
71706f2543Smrgstatic int dmxProcRenderCompositeGlyphs(ClientPtr client);
72706f2543Smrgstatic int dmxProcRenderSetPictureTransform(ClientPtr client);
73706f2543Smrgstatic int dmxProcRenderSetPictureFilter(ClientPtr client);
74706f2543Smrg#if 0
75706f2543Smrg/* FIXME: Not (yet) supported */
76706f2543Smrgstatic int dmxProcRenderCreateCursor(ClientPtr client);
77706f2543Smrgstatic int dmxProcRenderCreateAnimCursor(ClientPtr client);
78706f2543Smrg#endif
79706f2543Smrg
80706f2543Smrg/** Catch errors that might occur when allocating Glyph Sets.  Errors
81706f2543Smrg *  are saved in dmxGlyphLastError for later handling. */
82706f2543Smrgstatic int dmxGlyphLastError;
83706f2543Smrgstatic int dmxGlyphErrorHandler(Display *dpy, XErrorEvent *ev)
84706f2543Smrg{
85706f2543Smrg    dmxGlyphLastError = ev->error_code;
86706f2543Smrg    return 0;
87706f2543Smrg}
88706f2543Smrg
89706f2543Smrg
90706f2543Smrg/** Initialize the Proc Vector for the RENDER extension.  The functions
91706f2543Smrg *  here cannot be handled by the mi layer RENDER hooks either because
92706f2543Smrg *  the required information is no longer available when it reaches the
93706f2543Smrg *  mi layer or no mi layer hooks exist.  This function is called from
94706f2543Smrg *  InitOutput() since it should be initialized only once per server
95706f2543Smrg *  generation. */
96706f2543Smrgvoid dmxInitRender(void)
97706f2543Smrg{
98706f2543Smrg    int i;
99706f2543Smrg
100706f2543Smrg    for (i = 0; i < RenderNumberRequests; i++)
101706f2543Smrg        dmxSaveRenderVector[i] = ProcRenderVector[i];
102706f2543Smrg
103706f2543Smrg    ProcRenderVector[X_RenderCreateGlyphSet]
104706f2543Smrg	= dmxProcRenderCreateGlyphSet;
105706f2543Smrg    ProcRenderVector[X_RenderFreeGlyphSet]
106706f2543Smrg	= dmxProcRenderFreeGlyphSet;
107706f2543Smrg    ProcRenderVector[X_RenderAddGlyphs]
108706f2543Smrg	= dmxProcRenderAddGlyphs;
109706f2543Smrg    ProcRenderVector[X_RenderFreeGlyphs]
110706f2543Smrg	= dmxProcRenderFreeGlyphs;
111706f2543Smrg    ProcRenderVector[X_RenderCompositeGlyphs8]
112706f2543Smrg	= dmxProcRenderCompositeGlyphs;
113706f2543Smrg    ProcRenderVector[X_RenderCompositeGlyphs16]
114706f2543Smrg	= dmxProcRenderCompositeGlyphs;
115706f2543Smrg    ProcRenderVector[X_RenderCompositeGlyphs32]
116706f2543Smrg	= dmxProcRenderCompositeGlyphs;
117706f2543Smrg    ProcRenderVector[X_RenderSetPictureTransform]
118706f2543Smrg	= dmxProcRenderSetPictureTransform;
119706f2543Smrg    ProcRenderVector[X_RenderSetPictureFilter]
120706f2543Smrg	= dmxProcRenderSetPictureFilter;
121706f2543Smrg}
122706f2543Smrg
123706f2543Smrg/** Reset the Proc Vector for the RENDER extension back to the original
124706f2543Smrg *  functions.  This function is called from dmxCloseScreen() during the
125706f2543Smrg *  server reset (only for screen #0). */
126706f2543Smrgvoid dmxResetRender(void)
127706f2543Smrg{
128706f2543Smrg    int i;
129706f2543Smrg
130706f2543Smrg    for (i = 0; i < RenderNumberRequests; i++)
131706f2543Smrg        ProcRenderVector[i] = dmxSaveRenderVector[i];
132706f2543Smrg}
133706f2543Smrg
134706f2543Smrg/** Initialize the RENDER extension, allocate the picture privates and
135706f2543Smrg *  wrap mi function hooks.  If the shadow frame buffer is used, then
136706f2543Smrg *  call the appropriate fb initialization function. */
137706f2543SmrgBool dmxPictureInit(ScreenPtr pScreen, PictFormatPtr formats, int nformats)
138706f2543Smrg{
139706f2543Smrg    DMXScreenInfo    *dmxScreen = &dmxScreens[pScreen->myNum];
140706f2543Smrg    PictureScreenPtr  ps;
141706f2543Smrg
142706f2543Smrg    /* The shadow framebuffer only relies on FB to be initialized */
143706f2543Smrg    if (dmxShadowFB) return fbPictureInit(pScreen, formats, nformats);
144706f2543Smrg
145706f2543Smrg    if (!miPictureInit(pScreen, formats, nformats))
146706f2543Smrg	return FALSE;
147706f2543Smrg
148706f2543Smrg    if (!dixRegisterPrivateKey(&dmxPictPrivateKeyRec, PRIVATE_PICTURE, sizeof(dmxPictPrivRec)))
149706f2543Smrg	return FALSE;
150706f2543Smrg
151706f2543Smrg    ps = GetPictureScreen(pScreen);
152706f2543Smrg
153706f2543Smrg    DMX_WRAP(CreatePicture,      dmxCreatePicture,      dmxScreen, ps);
154706f2543Smrg    DMX_WRAP(DestroyPicture,     dmxDestroyPicture,     dmxScreen, ps);
155706f2543Smrg
156706f2543Smrg    DMX_WRAP(ChangePictureClip,  dmxChangePictureClip,  dmxScreen, ps);
157706f2543Smrg    DMX_WRAP(DestroyPictureClip, dmxDestroyPictureClip, dmxScreen, ps);
158706f2543Smrg
159706f2543Smrg    DMX_WRAP(ChangePicture,      dmxChangePicture,      dmxScreen, ps);
160706f2543Smrg    DMX_WRAP(ValidatePicture,    dmxValidatePicture,    dmxScreen, ps);
161706f2543Smrg
162706f2543Smrg    DMX_WRAP(Composite,          dmxComposite,          dmxScreen, ps);
163706f2543Smrg    DMX_WRAP(Glyphs,             dmxGlyphs,             dmxScreen, ps);
164706f2543Smrg    DMX_WRAP(CompositeRects,     dmxCompositeRects,     dmxScreen, ps);
165706f2543Smrg
166706f2543Smrg    DMX_WRAP(Trapezoids,         dmxTrapezoids,         dmxScreen, ps);
167706f2543Smrg    DMX_WRAP(Triangles,          dmxTriangles,          dmxScreen, ps);
168706f2543Smrg    DMX_WRAP(TriStrip,           dmxTriStrip,           dmxScreen, ps);
169706f2543Smrg    DMX_WRAP(TriFan,             dmxTriFan,             dmxScreen, ps);
170706f2543Smrg
171706f2543Smrg    return TRUE;
172706f2543Smrg}
173706f2543Smrg
174706f2543Smrg
175706f2543Smrg/** Find the appropriate format on the requested screen given the
176706f2543Smrg *  internal format requested.  The list of formats is searched
177706f2543Smrg *  sequentially as the XRenderFindFormat() function does not always
178706f2543Smrg *  find the appropriate format when a specific format is requested. */
179706f2543Smrgstatic XRenderPictFormat *dmxFindFormat(DMXScreenInfo *dmxScreen,
180706f2543Smrg					PictFormatPtr pFmt)
181706f2543Smrg{
182706f2543Smrg    XRenderPictFormat *pFormat = NULL;
183706f2543Smrg    int                i       = 0;
184706f2543Smrg
185706f2543Smrg    if (!pFmt || !dmxScreen->beDisplay) return pFormat;
186706f2543Smrg
187706f2543Smrg    while (1) {
188706f2543Smrg	pFormat = XRenderFindFormat(dmxScreen->beDisplay, 0, 0, i++);
189706f2543Smrg	if (!pFormat) break;
190706f2543Smrg
191706f2543Smrg	if (pFormat->type             != pFmt->type)             continue;
192706f2543Smrg	if (pFormat->depth            != pFmt->depth)            continue;
193706f2543Smrg	if (pFormat->direct.red       != pFmt->direct.red)       continue;
194706f2543Smrg	if (pFormat->direct.redMask   != pFmt->direct.redMask)   continue;
195706f2543Smrg	if (pFormat->direct.green     != pFmt->direct.green)     continue;
196706f2543Smrg	if (pFormat->direct.greenMask != pFmt->direct.greenMask) continue;
197706f2543Smrg	if (pFormat->direct.blue      != pFmt->direct.blue)      continue;
198706f2543Smrg	if (pFormat->direct.blueMask  != pFmt->direct.blueMask)  continue;
199706f2543Smrg	if (pFormat->direct.alpha     != pFmt->direct.alpha)     continue;
200706f2543Smrg	if (pFormat->direct.alphaMask != pFmt->direct.alphaMask) continue;
201706f2543Smrg
202706f2543Smrg	/* We have a match! */
203706f2543Smrg	break;
204706f2543Smrg    }
205706f2543Smrg
206706f2543Smrg    return pFormat;
207706f2543Smrg}
208706f2543Smrg
209706f2543Smrg/** Free \a glyphSet on back-end screen number \a idx. */
210706f2543SmrgBool dmxBEFreeGlyphSet(ScreenPtr pScreen, GlyphSetPtr glyphSet)
211706f2543Smrg{
212706f2543Smrg    dmxGlyphPrivPtr  glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
213706f2543Smrg    int              idx       = pScreen->myNum;
214706f2543Smrg    DMXScreenInfo   *dmxScreen = &dmxScreens[idx];
215706f2543Smrg
216706f2543Smrg    if (glyphPriv->glyphSets[idx]) {
217706f2543Smrg	XRenderFreeGlyphSet(dmxScreen->beDisplay, glyphPriv->glyphSets[idx]);
218706f2543Smrg	glyphPriv->glyphSets[idx] = (GlyphSet)0;
219706f2543Smrg	return TRUE;
220706f2543Smrg    }
221706f2543Smrg
222706f2543Smrg    return FALSE;
223706f2543Smrg}
224706f2543Smrg
225706f2543Smrg/** Create \a glyphSet on the backend screen number \a idx. */
226706f2543Smrgint dmxBECreateGlyphSet(int idx, GlyphSetPtr glyphSet)
227706f2543Smrg{
228706f2543Smrg    XRenderPictFormat *pFormat;
229706f2543Smrg    DMXScreenInfo     *dmxScreen = &dmxScreens[idx];
230706f2543Smrg    dmxGlyphPrivPtr    glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
231706f2543Smrg    PictFormatPtr      pFmt      = glyphSet->format;
232706f2543Smrg    int              (*oldErrorHandler)(Display *, XErrorEvent *);
233706f2543Smrg
234706f2543Smrg    pFormat = dmxFindFormat(dmxScreen, pFmt);
235706f2543Smrg    if (!pFormat) {
236706f2543Smrg	return BadMatch;
237706f2543Smrg    }
238706f2543Smrg
239706f2543Smrg    dmxGlyphLastError = 0;
240706f2543Smrg    oldErrorHandler = XSetErrorHandler(dmxGlyphErrorHandler);
241706f2543Smrg
242706f2543Smrg    /* Catch when this fails */
243706f2543Smrg    glyphPriv->glyphSets[idx]
244706f2543Smrg	= XRenderCreateGlyphSet(dmxScreen->beDisplay, pFormat);
245706f2543Smrg
246706f2543Smrg    XSetErrorHandler(oldErrorHandler);
247706f2543Smrg
248706f2543Smrg    if (dmxGlyphLastError) {
249706f2543Smrg	return dmxGlyphLastError;
250706f2543Smrg    }
251706f2543Smrg
252706f2543Smrg    return Success;
253706f2543Smrg}
254706f2543Smrg
255706f2543Smrg/** Create a Glyph Set on each screen.  Save the glyphset ID from each
256706f2543Smrg *  screen in the Glyph Set's private structure.  Fail if the format
257706f2543Smrg *  requested is not available or if the Glyph Set cannot be created on
258706f2543Smrg *  the screen. */
259706f2543Smrgstatic int dmxProcRenderCreateGlyphSet(ClientPtr client)
260706f2543Smrg{
261706f2543Smrg    int  ret;
262706f2543Smrg    REQUEST(xRenderCreateGlyphSetReq);
263706f2543Smrg
264706f2543Smrg    ret = dmxSaveRenderVector[stuff->renderReqType](client);
265706f2543Smrg
266706f2543Smrg    if (ret == Success) {
267706f2543Smrg	GlyphSetPtr        glyphSet;
268706f2543Smrg	dmxGlyphPrivPtr    glyphPriv;
269706f2543Smrg	int                i;
270706f2543Smrg
271706f2543Smrg	/* Look up glyphSet that was just created ???? */
272706f2543Smrg	/* Store glyphsets from backends in glyphSet->devPrivate ????? */
273706f2543Smrg	/* Make sure we handle all errors here!! */
274706f2543Smrg
275706f2543Smrg	dixLookupResourceByType((pointer*) &glyphSet,
276706f2543Smrg				stuff->gsid, GlyphSetType,
277706f2543Smrg				client, DixDestroyAccess);
278706f2543Smrg
279706f2543Smrg	glyphPriv = malloc(sizeof(dmxGlyphPrivRec));
280706f2543Smrg	if (!glyphPriv) return BadAlloc;
281706f2543Smrg        glyphPriv->glyphSets = NULL;
282706f2543Smrg        MAXSCREENSALLOC_RETURN(glyphPriv->glyphSets, BadAlloc);
283706f2543Smrg	DMX_SET_GLYPH_PRIV(glyphSet, glyphPriv);
284706f2543Smrg
285706f2543Smrg	for (i = 0; i < dmxNumScreens; i++) {
286706f2543Smrg	    DMXScreenInfo *dmxScreen = &dmxScreens[i];
287706f2543Smrg	    int beret;
288706f2543Smrg
289706f2543Smrg	    if (!dmxScreen->beDisplay) {
290706f2543Smrg		glyphPriv->glyphSets[i] = 0;
291706f2543Smrg		continue;
292706f2543Smrg	    }
293706f2543Smrg
294706f2543Smrg	    if ((beret = dmxBECreateGlyphSet(i, glyphSet)) != Success) {
295706f2543Smrg		int  j;
296706f2543Smrg
297706f2543Smrg		/* Free the glyph sets we've allocated thus far */
298706f2543Smrg		for (j = 0; j < i; j++)
299706f2543Smrg		    dmxBEFreeGlyphSet(screenInfo.screens[j], glyphSet);
300706f2543Smrg
301706f2543Smrg		/* Free the resource created by render */
302706f2543Smrg		FreeResource(stuff->gsid, RT_NONE);
303706f2543Smrg
304706f2543Smrg		return beret;
305706f2543Smrg	    }
306706f2543Smrg	}
307706f2543Smrg    }
308706f2543Smrg
309706f2543Smrg    return ret;
310706f2543Smrg}
311706f2543Smrg
312706f2543Smrg/** Free the previously allocated Glyph Sets for each screen. */
313706f2543Smrgstatic int dmxProcRenderFreeGlyphSet(ClientPtr client)
314706f2543Smrg{
315706f2543Smrg    GlyphSetPtr  glyphSet;
316706f2543Smrg    REQUEST(xRenderFreeGlyphSetReq);
317706f2543Smrg
318706f2543Smrg    REQUEST_SIZE_MATCH(xRenderFreeGlyphSetReq);
319706f2543Smrg    dixLookupResourceByType((pointer*) &glyphSet,
320706f2543Smrg			    stuff->glyphset, GlyphSetType,
321706f2543Smrg			    client, DixDestroyAccess);
322706f2543Smrg
323706f2543Smrg    if (glyphSet && glyphSet->refcnt == 1) {
324706f2543Smrg	dmxGlyphPrivPtr  glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
325706f2543Smrg	int              i;
326706f2543Smrg
327706f2543Smrg	for (i = 0; i < dmxNumScreens; i++) {
328706f2543Smrg	    DMXScreenInfo *dmxScreen = &dmxScreens[i];
329706f2543Smrg
330706f2543Smrg	    if (dmxScreen->beDisplay) {
331706f2543Smrg		if (dmxBEFreeGlyphSet(screenInfo.screens[i], glyphSet))
332706f2543Smrg		    dmxSync(dmxScreen, FALSE);
333706f2543Smrg	    }
334706f2543Smrg	}
335706f2543Smrg
336706f2543Smrg        MAXSCREENSFREE(glyphPriv->glyphSets);
337706f2543Smrg	free(glyphPriv);
338706f2543Smrg	DMX_SET_GLYPH_PRIV(glyphSet, NULL);
339706f2543Smrg    }
340706f2543Smrg
341706f2543Smrg    return dmxSaveRenderVector[stuff->renderReqType](client);
342706f2543Smrg}
343706f2543Smrg
344706f2543Smrg/** Add glyphs to the Glyph Set on each screen. */
345706f2543Smrgstatic int dmxProcRenderAddGlyphs(ClientPtr client)
346706f2543Smrg{
347706f2543Smrg    int  ret;
348706f2543Smrg    REQUEST(xRenderAddGlyphsReq);
349706f2543Smrg
350706f2543Smrg    ret = dmxSaveRenderVector[stuff->renderReqType](client);
351706f2543Smrg
352706f2543Smrg    if (ret == Success) {
353706f2543Smrg	GlyphSetPtr      glyphSet;
354706f2543Smrg	dmxGlyphPrivPtr  glyphPriv;
355706f2543Smrg	int              i;
356706f2543Smrg	int              nglyphs;
357706f2543Smrg	CARD32          *gids;
358706f2543Smrg	Glyph           *gidsCopy;
359706f2543Smrg	xGlyphInfo      *gi;
360706f2543Smrg	CARD8           *bits;
361706f2543Smrg	int              nbytes;
362706f2543Smrg
363706f2543Smrg	dixLookupResourceByType((pointer*) &glyphSet,
364706f2543Smrg				stuff->glyphset, GlyphSetType,
365706f2543Smrg				client, DixReadAccess);
366706f2543Smrg	glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
367706f2543Smrg
368706f2543Smrg	nglyphs = stuff->nglyphs;
369706f2543Smrg	gids = (CARD32 *)(stuff + 1);
370706f2543Smrg	gi = (xGlyphInfo *)(gids + nglyphs);
371706f2543Smrg	bits = (CARD8 *)(gi + nglyphs);
372706f2543Smrg	nbytes = ((stuff->length << 2) -
373706f2543Smrg		  sizeof(xRenderAddGlyphsReq) -
374706f2543Smrg		  (sizeof(CARD32) + sizeof(xGlyphInfo)) * nglyphs);
375706f2543Smrg
376706f2543Smrg        gidsCopy = malloc(sizeof(*gidsCopy) * nglyphs);
377706f2543Smrg        for (i = 0; i < nglyphs; i++) gidsCopy[i] = gids[i];
378706f2543Smrg
379706f2543Smrg	/* FIXME: Will this ever fail? */
380706f2543Smrg	for (i = 0; i < dmxNumScreens; i++) {
381706f2543Smrg	    DMXScreenInfo *dmxScreen = &dmxScreens[i];
382706f2543Smrg
383706f2543Smrg	    if (dmxScreen->beDisplay) {
384706f2543Smrg		XRenderAddGlyphs(dmxScreen->beDisplay,
385706f2543Smrg				 glyphPriv->glyphSets[i],
386706f2543Smrg				 gidsCopy,
387706f2543Smrg				 (XGlyphInfo *)gi,
388706f2543Smrg				 nglyphs,
389706f2543Smrg				 (char *)bits,
390706f2543Smrg				 nbytes);
391706f2543Smrg		dmxSync(dmxScreen, FALSE);
392706f2543Smrg	    }
393706f2543Smrg	}
394706f2543Smrg        free(gidsCopy);
395706f2543Smrg    }
396706f2543Smrg
397706f2543Smrg    return ret;
398706f2543Smrg}
399706f2543Smrg
400706f2543Smrg/** Free glyphs from the Glyph Set for each screen. */
401706f2543Smrgstatic int dmxProcRenderFreeGlyphs(ClientPtr client)
402706f2543Smrg{
403706f2543Smrg    GlyphSetPtr  glyphSet;
404706f2543Smrg    REQUEST(xRenderFreeGlyphsReq);
405706f2543Smrg
406706f2543Smrg    REQUEST_AT_LEAST_SIZE(xRenderFreeGlyphsReq);
407706f2543Smrg    dixLookupResourceByType((pointer*) &glyphSet,
408706f2543Smrg			    stuff->glyphset, GlyphSetType,
409706f2543Smrg			    client, DixWriteAccess);
410706f2543Smrg
411706f2543Smrg    if (glyphSet) {
412706f2543Smrg	dmxGlyphPrivPtr  glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
413706f2543Smrg	int              i;
414706f2543Smrg	int              nglyphs;
415706f2543Smrg	Glyph           *gids;
416706f2543Smrg
417706f2543Smrg	nglyphs = ((client->req_len << 2) - sizeof(xRenderFreeGlyphsReq)) >> 2;
418706f2543Smrg	if (nglyphs) {
419706f2543Smrg            gids    = malloc(sizeof(*gids) * nglyphs);
420706f2543Smrg            for (i = 0; i < nglyphs; i++)
421706f2543Smrg                gids[i] = ((CARD32 *)(stuff + 1))[i];
422706f2543Smrg
423706f2543Smrg	    for (i = 0; i < dmxNumScreens; i++) {
424706f2543Smrg		DMXScreenInfo *dmxScreen = &dmxScreens[i];
425706f2543Smrg
426706f2543Smrg		if (dmxScreen->beDisplay) {
427706f2543Smrg		    XRenderFreeGlyphs(dmxScreen->beDisplay,
428706f2543Smrg				      glyphPriv->glyphSets[i], gids, nglyphs);
429706f2543Smrg		    dmxSync(dmxScreen, FALSE);
430706f2543Smrg		}
431706f2543Smrg	    }
432706f2543Smrg            free(gids);
433706f2543Smrg	}
434706f2543Smrg    }
435706f2543Smrg
436706f2543Smrg    return dmxSaveRenderVector[stuff->renderReqType](client);
437706f2543Smrg}
438706f2543Smrg
439706f2543Smrg/** Composite glyphs on each screen into the requested picture.  If
440706f2543Smrg *  either the src or dest picture has not been allocated due to lazy
441706f2543Smrg *  window creation, this request will gracefully return. */
442706f2543Smrgstatic int dmxProcRenderCompositeGlyphs(ClientPtr client)
443706f2543Smrg{
444706f2543Smrg    int  ret;
445706f2543Smrg    REQUEST(xRenderCompositeGlyphsReq);
446706f2543Smrg
447706f2543Smrg    ret = dmxSaveRenderVector[stuff->renderReqType](client);
448706f2543Smrg
449706f2543Smrg    /* For the following to work with PanoramiX, it assumes that Render
450706f2543Smrg     * wraps the ProcRenderVector after dmxRenderInit has been called.
451706f2543Smrg     */
452706f2543Smrg    if (ret == Success) {
453706f2543Smrg	PicturePtr         pSrc;
454706f2543Smrg	dmxPictPrivPtr     pSrcPriv;
455706f2543Smrg	PicturePtr         pDst;
456706f2543Smrg	dmxPictPrivPtr     pDstPriv;
457706f2543Smrg	PictFormatPtr      pFmt;
458706f2543Smrg	XRenderPictFormat *pFormat;
459706f2543Smrg	int                size;
460706f2543Smrg
461706f2543Smrg	int                scrnNum;
462706f2543Smrg	DMXScreenInfo     *dmxScreen;
463706f2543Smrg
464706f2543Smrg	CARD8             *buffer;
465706f2543Smrg	CARD8             *end;
466706f2543Smrg	int                space;
467706f2543Smrg
468706f2543Smrg	int                nglyph;
469706f2543Smrg	char              *glyphs;
470706f2543Smrg	char              *curGlyph;
471706f2543Smrg
472706f2543Smrg	xGlyphElt         *elt;
473706f2543Smrg	int                nelt;
474706f2543Smrg	XGlyphElt8        *elts;
475706f2543Smrg	XGlyphElt8        *curElt;
476706f2543Smrg
477706f2543Smrg	GlyphSetPtr        glyphSet;
478706f2543Smrg	dmxGlyphPrivPtr    glyphPriv;
479706f2543Smrg
480706f2543Smrg	dixLookupResourceByType((pointer*) &pSrc,
481706f2543Smrg				stuff->src, PictureType,
482706f2543Smrg				client, DixReadAccess);
483706f2543Smrg
484706f2543Smrg	pSrcPriv = DMX_GET_PICT_PRIV(pSrc);
485706f2543Smrg	if (!pSrcPriv->pict)
486706f2543Smrg	    return ret;
487706f2543Smrg
488706f2543Smrg	dixLookupResourceByType((pointer*) &pDst,
489706f2543Smrg				stuff->dst, PictureType,
490706f2543Smrg				client, DixWriteAccess);
491706f2543Smrg
492706f2543Smrg	pDstPriv = DMX_GET_PICT_PRIV(pDst);
493706f2543Smrg	if (!pDstPriv->pict)
494706f2543Smrg	    return ret;
495706f2543Smrg
496706f2543Smrg	scrnNum = pDst->pDrawable->pScreen->myNum;
497706f2543Smrg	dmxScreen = &dmxScreens[scrnNum];
498706f2543Smrg
499706f2543Smrg	/* Note: If the back-end display has been detached, then it
500706f2543Smrg	 * should not be possible to reach here since the pSrcPriv->pict
501706f2543Smrg	 * and pDstPriv->pict will have already been set to 0.
502706f2543Smrg	 */
503706f2543Smrg	if (!dmxScreen->beDisplay)
504706f2543Smrg	    return ret;
505706f2543Smrg
506706f2543Smrg	if (stuff->maskFormat)
507706f2543Smrg	    dixLookupResourceByType((pointer*) &pFmt,
508706f2543Smrg				    stuff->maskFormat, PictFormatType,
509706f2543Smrg				    client, DixReadAccess);
510706f2543Smrg	else
511706f2543Smrg	    pFmt = NULL;
512706f2543Smrg
513706f2543Smrg	pFormat = dmxFindFormat(dmxScreen, pFmt);
514706f2543Smrg
515706f2543Smrg	switch (stuff->renderReqType) {
516706f2543Smrg	case X_RenderCompositeGlyphs8:  size = sizeof(CARD8);  break;
517706f2543Smrg	case X_RenderCompositeGlyphs16: size = sizeof(CARD16); break;
518706f2543Smrg	case X_RenderCompositeGlyphs32: size = sizeof(CARD32); break;
519706f2543Smrg        default:                        return BadPictOp; /* Can't happen */
520706f2543Smrg	}
521706f2543Smrg
522706f2543Smrg	buffer = (CARD8 *)(stuff + 1);
523706f2543Smrg	end = (CARD8 *)stuff + (stuff->length << 2);
524706f2543Smrg	nelt = 0;
525706f2543Smrg	nglyph = 0;
526706f2543Smrg	while (buffer + sizeof(xGlyphElt) < end) {
527706f2543Smrg	    elt = (xGlyphElt *)buffer;
528706f2543Smrg	    buffer += sizeof(xGlyphElt);
529706f2543Smrg
530706f2543Smrg	    if (elt->len == 0xff) {
531706f2543Smrg		buffer += 4;
532706f2543Smrg	    } else {
533706f2543Smrg		nelt++;
534706f2543Smrg		nglyph += elt->len;
535706f2543Smrg		space = size * elt->len;
536706f2543Smrg		if (space & 3) space += 4 - (space & 3);
537706f2543Smrg		buffer += space;
538706f2543Smrg	    }
539706f2543Smrg	}
540706f2543Smrg
541706f2543Smrg	/* The following only works for Render version > 0.2 */
542706f2543Smrg
543706f2543Smrg	/* All of the XGlyphElt* structure sizes are identical */
544706f2543Smrg	elts = malloc(nelt * sizeof(XGlyphElt8));
545706f2543Smrg	if (!elts)
546706f2543Smrg	    return BadAlloc;
547706f2543Smrg
548706f2543Smrg	glyphs = malloc(nglyph * size);
549706f2543Smrg	if (!glyphs) {
550706f2543Smrg	    free(elts);
551706f2543Smrg	    return BadAlloc;
552706f2543Smrg	}
553706f2543Smrg
554706f2543Smrg	buffer = (CARD8 *)(stuff + 1);
555706f2543Smrg	end = (CARD8 *)stuff + (stuff->length << 2);
556706f2543Smrg	curGlyph = glyphs;
557706f2543Smrg	curElt = elts;
558706f2543Smrg
559706f2543Smrg	dixLookupResourceByType((pointer*) &glyphSet,
560706f2543Smrg				stuff->glyphset, GlyphSetType,
561706f2543Smrg				client, DixReadAccess);
562706f2543Smrg	glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
563706f2543Smrg
564706f2543Smrg	while (buffer + sizeof(xGlyphElt) < end) {
565706f2543Smrg	    elt = (xGlyphElt *)buffer;
566706f2543Smrg	    buffer += sizeof(xGlyphElt);
567706f2543Smrg
568706f2543Smrg	    if (elt->len == 0xff) {
569706f2543Smrg		dixLookupResourceByType((pointer*) &glyphSet,
570706f2543Smrg					*((CARD32 *)buffer),
571706f2543Smrg					GlyphSetType,
572706f2543Smrg					client,
573706f2543Smrg					DixReadAccess);
574706f2543Smrg		glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
575706f2543Smrg		buffer += 4;
576706f2543Smrg	    } else {
577706f2543Smrg		curElt->glyphset = glyphPriv->glyphSets[scrnNum];
578706f2543Smrg		curElt->xOff = elt->deltax;
579706f2543Smrg		curElt->yOff = elt->deltay;
580706f2543Smrg		curElt->nchars = elt->len;
581706f2543Smrg		curElt->chars = curGlyph;
582706f2543Smrg
583706f2543Smrg		memcpy(curGlyph, buffer, size*elt->len);
584706f2543Smrg		curGlyph += size * elt->len;
585706f2543Smrg
586706f2543Smrg		curElt++;
587706f2543Smrg
588706f2543Smrg		space = size * elt->len;
589706f2543Smrg		if (space & 3) space += 4 - (space & 3);
590706f2543Smrg		buffer += space;
591706f2543Smrg	    }
592706f2543Smrg	}
593706f2543Smrg
594706f2543Smrg	switch (stuff->renderReqType) {
595706f2543Smrg	case X_RenderCompositeGlyphs8:
596706f2543Smrg	    XRenderCompositeText8(dmxScreen->beDisplay, stuff->op,
597706f2543Smrg				  pSrcPriv->pict, pDstPriv->pict,
598706f2543Smrg				  pFormat,
599706f2543Smrg				  stuff->xSrc, stuff->ySrc,
600706f2543Smrg				  0, 0, elts, nelt);
601706f2543Smrg	    break;
602706f2543Smrg	case X_RenderCompositeGlyphs16:
603706f2543Smrg	    XRenderCompositeText16(dmxScreen->beDisplay, stuff->op,
604706f2543Smrg				   pSrcPriv->pict, pDstPriv->pict,
605706f2543Smrg				   pFormat,
606706f2543Smrg				   stuff->xSrc, stuff->ySrc,
607706f2543Smrg				   0, 0, (XGlyphElt16 *)elts, nelt);
608706f2543Smrg	    break;
609706f2543Smrg	case X_RenderCompositeGlyphs32:
610706f2543Smrg	    XRenderCompositeText32(dmxScreen->beDisplay, stuff->op,
611706f2543Smrg				   pSrcPriv->pict, pDstPriv->pict,
612706f2543Smrg				   pFormat,
613706f2543Smrg				   stuff->xSrc, stuff->ySrc,
614706f2543Smrg				   0, 0, (XGlyphElt32 *)elts, nelt);
615706f2543Smrg	    break;
616706f2543Smrg	}
617706f2543Smrg
618706f2543Smrg	dmxSync(dmxScreen, FALSE);
619706f2543Smrg
620706f2543Smrg	free(elts);
621706f2543Smrg	free(glyphs);
622706f2543Smrg    }
623706f2543Smrg
624706f2543Smrg    return ret;
625706f2543Smrg}
626706f2543Smrg
627706f2543Smrg/** Set the picture transform on each screen. */
628706f2543Smrgstatic int dmxProcRenderSetPictureTransform(ClientPtr client)
629706f2543Smrg{
630706f2543Smrg    DMXScreenInfo  *dmxScreen;
631706f2543Smrg    PicturePtr      pPicture;
632706f2543Smrg    dmxPictPrivPtr  pPictPriv;
633706f2543Smrg    XTransform      xform;
634706f2543Smrg    REQUEST(xRenderSetPictureTransformReq);
635706f2543Smrg
636706f2543Smrg    REQUEST_SIZE_MATCH(xRenderSetPictureTransformReq);
637706f2543Smrg    VERIFY_PICTURE(pPicture, stuff->picture, client, DixWriteAccess);
638706f2543Smrg
639706f2543Smrg    /* For the following to work with PanoramiX, it assumes that Render
640706f2543Smrg     * wraps the ProcRenderVector after dmxRenderInit has been called.
641706f2543Smrg     */
642706f2543Smrg    dmxScreen = &dmxScreens[pPicture->pDrawable->pScreen->myNum];
643706f2543Smrg    pPictPriv = DMX_GET_PICT_PRIV(pPicture);
644706f2543Smrg
645706f2543Smrg    if (pPictPriv->pict) {
646706f2543Smrg	xform.matrix[0][0] = stuff->transform.matrix11;
647706f2543Smrg	xform.matrix[0][1] = stuff->transform.matrix12;
648706f2543Smrg	xform.matrix[0][2] = stuff->transform.matrix13;
649706f2543Smrg	xform.matrix[1][0] = stuff->transform.matrix21;
650706f2543Smrg	xform.matrix[1][1] = stuff->transform.matrix22;
651706f2543Smrg	xform.matrix[1][2] = stuff->transform.matrix23;
652706f2543Smrg	xform.matrix[2][0] = stuff->transform.matrix31;
653706f2543Smrg	xform.matrix[2][1] = stuff->transform.matrix32;
654706f2543Smrg	xform.matrix[2][2] = stuff->transform.matrix33;
655706f2543Smrg
656706f2543Smrg	XRenderSetPictureTransform(dmxScreen->beDisplay,
657706f2543Smrg				   pPictPriv->pict,
658706f2543Smrg				   &xform);
659706f2543Smrg	dmxSync(dmxScreen, FALSE);
660706f2543Smrg    }
661706f2543Smrg
662706f2543Smrg    return dmxSaveRenderVector[stuff->renderReqType](client);
663706f2543Smrg}
664706f2543Smrg
665706f2543Smrg/** Set the picture filter on each screen. */
666706f2543Smrgstatic int dmxProcRenderSetPictureFilter(ClientPtr client)
667706f2543Smrg{
668706f2543Smrg    DMXScreenInfo  *dmxScreen;
669706f2543Smrg    PicturePtr      pPicture;
670706f2543Smrg    dmxPictPrivPtr  pPictPriv;
671706f2543Smrg    char           *filter;
672706f2543Smrg    XFixed         *params;
673706f2543Smrg    int             nparams;
674706f2543Smrg    REQUEST(xRenderSetPictureFilterReq);
675706f2543Smrg
676706f2543Smrg    REQUEST_AT_LEAST_SIZE(xRenderSetPictureFilterReq);
677706f2543Smrg    VERIFY_PICTURE(pPicture, stuff->picture, client, DixWriteAccess);
678706f2543Smrg
679706f2543Smrg    /* For the following to work with PanoramiX, it assumes that Render
680706f2543Smrg     * wraps the ProcRenderVector after dmxRenderInit has been called.
681706f2543Smrg     */
682706f2543Smrg    dmxScreen = &dmxScreens[pPicture->pDrawable->pScreen->myNum];
683706f2543Smrg    pPictPriv = DMX_GET_PICT_PRIV(pPicture);
684706f2543Smrg
685706f2543Smrg    if (pPictPriv->pict) {
686706f2543Smrg	filter  = (char *)(stuff + 1);
687706f2543Smrg	params  = (XFixed *)(filter + ((stuff->nbytes + 3) & ~3));
688706f2543Smrg	nparams = ((XFixed *)stuff + client->req_len) - params;
689706f2543Smrg
690706f2543Smrg	XRenderSetPictureFilter(dmxScreen->beDisplay,
691706f2543Smrg				pPictPriv->pict,
692706f2543Smrg				filter,
693706f2543Smrg				params,
694706f2543Smrg				nparams);
695706f2543Smrg	dmxSync(dmxScreen, FALSE);
696706f2543Smrg    }
697706f2543Smrg
698706f2543Smrg    return dmxSaveRenderVector[stuff->renderReqType](client);
699706f2543Smrg}
700706f2543Smrg
701706f2543Smrg
702706f2543Smrg/** Create a picture on the appropriate screen.  This is the actual
703706f2543Smrg *  function that creates the picture.  However, if the associated
704706f2543Smrg *  window has not yet been created due to lazy window creation, then
705706f2543Smrg *  delay the picture creation until the window is mapped. */
706706f2543Smrgstatic Picture dmxDoCreatePicture(PicturePtr pPicture)
707706f2543Smrg{
708706f2543Smrg    DrawablePtr               pDraw     = pPicture->pDrawable;
709706f2543Smrg    ScreenPtr                 pScreen   = pDraw->pScreen;
710706f2543Smrg    DMXScreenInfo            *dmxScreen = &dmxScreens[pScreen->myNum];
711706f2543Smrg    XRenderPictFormat        *pFormat;
712706f2543Smrg    Drawable                  draw;
713706f2543Smrg
714706f2543Smrg    if (pPicture->pDrawable->type == DRAWABLE_WINDOW) {
715706f2543Smrg	dmxWinPrivPtr  pWinPriv = DMX_GET_WINDOW_PRIV((WindowPtr)(pDraw));
716706f2543Smrg
717706f2543Smrg	if (!(draw = pWinPriv->window)) {
718706f2543Smrg	    /* Window has not been created yet due to the window
719706f2543Smrg	     * optimization.  Delay picture creation until window is
720706f2543Smrg	     * mapped.
721706f2543Smrg	     */
722706f2543Smrg	    pWinPriv->hasPict = TRUE;
723706f2543Smrg	    return 0;
724706f2543Smrg	}
725706f2543Smrg    } else {
726706f2543Smrg	dmxPixPrivPtr  pPixPriv = DMX_GET_PIXMAP_PRIV((PixmapPtr)(pDraw));
727706f2543Smrg
728706f2543Smrg	if (!(draw = pPixPriv->pixmap)) {
729706f2543Smrg	    /* FIXME: Zero width/height pixmap?? */
730706f2543Smrg	    return 0;
731706f2543Smrg	}
732706f2543Smrg    }
733706f2543Smrg
734706f2543Smrg    /* This should not be reached if the back-end display has been
735706f2543Smrg     * detached because the pWinPriv->window or the pPixPriv->pixmap
736706f2543Smrg     * will be NULL; however, we add it here for completeness
737706f2543Smrg     */
738706f2543Smrg    if (!dmxScreen->beDisplay)
739706f2543Smrg	return 0;
740706f2543Smrg
741706f2543Smrg    pFormat = dmxFindFormat(dmxScreen, pPicture->pFormat);
742706f2543Smrg
743706f2543Smrg    return XRenderCreatePicture(dmxScreen->beDisplay, draw, pFormat, 0, 0);
744706f2543Smrg}
745706f2543Smrg
746706f2543Smrg/** Create a list of pictures.  This function is called by
747706f2543Smrg *  dmxCreateAndRealizeWindow() during the lazy window creation
748706f2543Smrg *  realization process.  It creates the entire list of pictures that
749706f2543Smrg *  are associated with the given window. */
750706f2543Smrgvoid dmxCreatePictureList(WindowPtr pWindow)
751706f2543Smrg{
752706f2543Smrg    PicturePtr  pPicture = GetPictureWindow(pWindow);
753706f2543Smrg
754706f2543Smrg    while (pPicture) {
755706f2543Smrg	dmxPictPrivPtr  pPictPriv = DMX_GET_PICT_PRIV(pPicture);
756706f2543Smrg
757706f2543Smrg	/* Create the picture for this window */
758706f2543Smrg	pPictPriv->pict = dmxDoCreatePicture(pPicture);
759706f2543Smrg
760706f2543Smrg	/* ValidatePicture takes care of the state changes */
761706f2543Smrg
762706f2543Smrg	pPicture = pPicture->pNext;
763706f2543Smrg    }
764706f2543Smrg}
765706f2543Smrg
766706f2543Smrg/** Create \a pPicture on the backend. */
767706f2543Smrgint dmxBECreatePicture(PicturePtr pPicture)
768706f2543Smrg{
769706f2543Smrg    dmxPictPrivPtr    pPictPriv = DMX_GET_PICT_PRIV(pPicture);
770706f2543Smrg
771706f2543Smrg    /* Create picutre on BE */
772706f2543Smrg    pPictPriv->pict = dmxDoCreatePicture(pPicture);
773706f2543Smrg
774706f2543Smrg    /* Flush changes to the backend server */
775706f2543Smrg    dmxValidatePicture(pPicture, (1 << (CPLastBit+1)) - 1);
776706f2543Smrg
777706f2543Smrg    return Success;
778706f2543Smrg}
779706f2543Smrg
780706f2543Smrg/** Create a picture.  This function handles the CreatePicture
781706f2543Smrg *  unwrapping/wrapping and calls dmxDoCreatePicture to actually create
782706f2543Smrg *  the picture on the appropriate screen.  */
783706f2543Smrgint dmxCreatePicture(PicturePtr pPicture)
784706f2543Smrg{
785706f2543Smrg    ScreenPtr         pScreen   = pPicture->pDrawable->pScreen;
786706f2543Smrg    DMXScreenInfo    *dmxScreen = &dmxScreens[pScreen->myNum];
787706f2543Smrg    PictureScreenPtr  ps        = GetPictureScreen(pScreen);
788706f2543Smrg    dmxPictPrivPtr    pPictPriv = DMX_GET_PICT_PRIV(pPicture);
789706f2543Smrg    int               ret       = Success;
790706f2543Smrg
791706f2543Smrg    DMX_UNWRAP(CreatePicture, dmxScreen, ps);
792706f2543Smrg#if 1
793706f2543Smrg    if (ps->CreatePicture)
794706f2543Smrg	ret = ps->CreatePicture(pPicture);
795706f2543Smrg#endif
796706f2543Smrg
797706f2543Smrg    /* Create picture on back-end server */
798706f2543Smrg    pPictPriv->pict      = dmxDoCreatePicture(pPicture);
799706f2543Smrg    pPictPriv->savedMask = 0;
800706f2543Smrg
801706f2543Smrg    DMX_WRAP(CreatePicture, dmxCreatePicture, dmxScreen, ps);
802706f2543Smrg
803706f2543Smrg    return ret;
804706f2543Smrg}
805706f2543Smrg
806706f2543Smrg/** Destroy \a pPicture on the back-end server. */
807706f2543SmrgBool dmxBEFreePicture(PicturePtr pPicture)
808706f2543Smrg{
809706f2543Smrg    ScreenPtr      pScreen   = pPicture->pDrawable->pScreen;
810706f2543Smrg    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
811706f2543Smrg    dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
812706f2543Smrg
813706f2543Smrg    if (pPictPriv->pict) {
814706f2543Smrg	XRenderFreePicture(dmxScreen->beDisplay, pPictPriv->pict);
815706f2543Smrg	pPictPriv->pict = (Picture)0;
816706f2543Smrg	return TRUE;
817706f2543Smrg    }
818706f2543Smrg
819706f2543Smrg    return FALSE;
820706f2543Smrg}
821706f2543Smrg
822706f2543Smrg/** Destroy a list of pictures that are associated with the window that
823706f2543Smrg *  is being destroyed.  This function is called by #dmxDestroyWindow().
824706f2543Smrg *  */
825706f2543SmrgBool dmxDestroyPictureList(WindowPtr pWindow)
826706f2543Smrg{
827706f2543Smrg    PicturePtr  pPicture = GetPictureWindow(pWindow);
828706f2543Smrg    Bool        ret      = FALSE;
829706f2543Smrg
830706f2543Smrg    while (pPicture) {
831706f2543Smrg	ret |= dmxBEFreePicture(pPicture);
832706f2543Smrg	pPicture = pPicture->pNext;
833706f2543Smrg    }
834706f2543Smrg
835706f2543Smrg    return ret;
836706f2543Smrg}
837706f2543Smrg
838706f2543Smrg/** Destroy a picture.  This function calls the wrapped function that
839706f2543Smrg *  frees the resources in the DMX server associated with this
840706f2543Smrg *  picture. */
841706f2543Smrgvoid dmxDestroyPicture(PicturePtr pPicture)
842706f2543Smrg{
843706f2543Smrg    ScreenPtr         pScreen   = pPicture->pDrawable->pScreen;
844706f2543Smrg    DMXScreenInfo    *dmxScreen = &dmxScreens[pScreen->myNum];
845706f2543Smrg    PictureScreenPtr  ps        = GetPictureScreen(pScreen);
846706f2543Smrg
847706f2543Smrg    DMX_UNWRAP(DestroyPicture, dmxScreen, ps);
848706f2543Smrg
849706f2543Smrg    /* Destroy picture on back-end server */
850706f2543Smrg    if (dmxBEFreePicture(pPicture))
851706f2543Smrg	dmxSync(dmxScreen, FALSE);
852706f2543Smrg
853706f2543Smrg#if 1
854706f2543Smrg    if (ps->DestroyPicture)
855706f2543Smrg	ps->DestroyPicture(pPicture);
856706f2543Smrg#endif
857706f2543Smrg    DMX_WRAP(DestroyPicture, dmxDestroyPicture, dmxScreen, ps);
858706f2543Smrg}
859706f2543Smrg
860706f2543Smrg/** Change the picture's list of clip rectangles. */
861706f2543Smrgint dmxChangePictureClip(PicturePtr pPicture, int clipType,
862706f2543Smrg			 pointer value, int n)
863706f2543Smrg{
864706f2543Smrg    ScreenPtr         pScreen   = pPicture->pDrawable->pScreen;
865706f2543Smrg    DMXScreenInfo    *dmxScreen = &dmxScreens[pScreen->myNum];
866706f2543Smrg    PictureScreenPtr  ps        = GetPictureScreen(pScreen);
867706f2543Smrg    dmxPictPrivPtr    pPictPriv = DMX_GET_PICT_PRIV(pPicture);
868706f2543Smrg
869706f2543Smrg    DMX_UNWRAP(ChangePictureClip, dmxScreen, ps);
870706f2543Smrg#if 1
871706f2543Smrg    if (ps->ChangePictureClip)
872706f2543Smrg	ps->ChangePictureClip(pPicture, clipType, value, n);
873706f2543Smrg#endif
874706f2543Smrg
875706f2543Smrg    /* Change picture clip rects on back-end server */
876706f2543Smrg    if (pPictPriv->pict) {
877706f2543Smrg	/* The clip has already been changed into a region by the mi
878706f2543Smrg	 * routine called above.
879706f2543Smrg	 */
880706f2543Smrg	if (clipType == CT_NONE) {
881706f2543Smrg	    /* Disable clipping, show all */
882706f2543Smrg	    XFixesSetPictureClipRegion(dmxScreen->beDisplay,
883706f2543Smrg				       pPictPriv->pict, 0, 0, None);
884706f2543Smrg	} else if (pPicture->clientClip) {
885706f2543Smrg	    RegionPtr   pClip = pPicture->clientClip;
886706f2543Smrg	    BoxPtr      pBox  = RegionRects(pClip);
887706f2543Smrg	    int         nBox  = RegionNumRects(pClip);
888706f2543Smrg	    XRectangle *pRects;
889706f2543Smrg	    XRectangle *pRect;
890706f2543Smrg	    int         nRects;
891706f2543Smrg
892706f2543Smrg	    nRects = nBox;
893706f2543Smrg	    pRects = pRect = malloc(nRects * sizeof(*pRect));
894706f2543Smrg
895706f2543Smrg	    while (nBox--) {
896706f2543Smrg		pRect->x      = pBox->x1;
897706f2543Smrg		pRect->y      = pBox->y1;
898706f2543Smrg		pRect->width  = pBox->x2 - pBox->x1;
899706f2543Smrg		pRect->height = pBox->y2 - pBox->y1;
900706f2543Smrg		pBox++;
901706f2543Smrg		pRect++;
902706f2543Smrg	    }
903706f2543Smrg
904706f2543Smrg	    XRenderSetPictureClipRectangles(dmxScreen->beDisplay,
905706f2543Smrg					    pPictPriv->pict,
906706f2543Smrg					    0, 0,
907706f2543Smrg					    pRects,
908706f2543Smrg					    nRects);
909706f2543Smrg	    free(pRects);
910706f2543Smrg	} else {
911706f2543Smrg	    XRenderSetPictureClipRectangles(dmxScreen->beDisplay,
912706f2543Smrg					    pPictPriv->pict,
913706f2543Smrg					    0, 0, NULL, 0);
914706f2543Smrg	}
915706f2543Smrg	dmxSync(dmxScreen, FALSE);
916706f2543Smrg    } else {
917706f2543Smrg	/* FIXME: Handle saving clip region when offscreen */
918706f2543Smrg    }
919706f2543Smrg
920706f2543Smrg    DMX_WRAP(ChangePictureClip, dmxChangePictureClip, dmxScreen, ps);
921706f2543Smrg
922706f2543Smrg    return Success;
923706f2543Smrg}
924706f2543Smrg
925706f2543Smrg/** Destroy the picture's list of clip rectangles. */
926706f2543Smrgvoid dmxDestroyPictureClip(PicturePtr pPicture)
927706f2543Smrg{
928706f2543Smrg    ScreenPtr         pScreen   = pPicture->pDrawable->pScreen;
929706f2543Smrg    DMXScreenInfo    *dmxScreen = &dmxScreens[pScreen->myNum];
930706f2543Smrg    PictureScreenPtr  ps        = GetPictureScreen(pScreen);
931706f2543Smrg    dmxPictPrivPtr    pPictPriv = DMX_GET_PICT_PRIV(pPicture);
932706f2543Smrg
933706f2543Smrg    DMX_UNWRAP(DestroyPictureClip, dmxScreen, ps);
934706f2543Smrg#if 1
935706f2543Smrg    if (ps->DestroyPictureClip)
936706f2543Smrg	ps->DestroyPictureClip(pPicture);
937706f2543Smrg#endif
938706f2543Smrg
939706f2543Smrg    /* Destroy picture clip rects on back-end server */
940706f2543Smrg    if (pPictPriv->pict) {
941706f2543Smrg	XRenderSetPictureClipRectangles(dmxScreen->beDisplay,
942706f2543Smrg					pPictPriv->pict,
943706f2543Smrg					0, 0, NULL, 0);
944706f2543Smrg	dmxSync(dmxScreen, FALSE);
945706f2543Smrg    } else {
946706f2543Smrg	/* FIXME: Handle destroying clip region when offscreen */
947706f2543Smrg    }
948706f2543Smrg
949706f2543Smrg    DMX_WRAP(DestroyPictureClip, dmxDestroyPictureClip, dmxScreen, ps);
950706f2543Smrg}
951706f2543Smrg
952706f2543Smrg/** Change the attributes of the pictures.  If the picture has not yet
953706f2543Smrg *  been created due to lazy window creation, save the mask so that it
954706f2543Smrg *  can be used to appropriately initialize the picture's attributes
955706f2543Smrg *  when it is created later. */
956706f2543Smrgvoid dmxChangePicture(PicturePtr pPicture, Mask mask)
957706f2543Smrg{
958706f2543Smrg    ScreenPtr         pScreen   = pPicture->pDrawable->pScreen;
959706f2543Smrg    DMXScreenInfo    *dmxScreen = &dmxScreens[pScreen->myNum];
960706f2543Smrg    PictureScreenPtr  ps        = GetPictureScreen(pScreen);
961706f2543Smrg    dmxPictPrivPtr    pPictPriv = DMX_GET_PICT_PRIV(pPicture);
962706f2543Smrg
963706f2543Smrg    DMX_UNWRAP(ChangePicture, dmxScreen, ps);
964706f2543Smrg#if 1
965706f2543Smrg    if (ps->ChangePicture)
966706f2543Smrg	ps->ChangePicture(pPicture, mask);
967706f2543Smrg#endif
968706f2543Smrg
969706f2543Smrg    /* Picture attribute changes are handled in ValidatePicture */
970706f2543Smrg    pPictPriv->savedMask |= mask;
971706f2543Smrg
972706f2543Smrg    DMX_WRAP(ChangePicture, dmxChangePicture, dmxScreen, ps);
973706f2543Smrg}
974706f2543Smrg
975706f2543Smrg/** Validate the picture's attributes before rendering to it.  Update
976706f2543Smrg *  any picture attributes that have been changed by one of the higher
977706f2543Smrg *  layers. */
978706f2543Smrgvoid dmxValidatePicture(PicturePtr pPicture, Mask mask)
979706f2543Smrg{
980706f2543Smrg    ScreenPtr         pScreen   = pPicture->pDrawable->pScreen;
981706f2543Smrg    DMXScreenInfo    *dmxScreen = &dmxScreens[pScreen->myNum];
982706f2543Smrg    PictureScreenPtr  ps        = GetPictureScreen(pScreen);
983706f2543Smrg    dmxPictPrivPtr    pPictPriv = DMX_GET_PICT_PRIV(pPicture);
984706f2543Smrg
985706f2543Smrg    DMX_UNWRAP(ValidatePicture, dmxScreen, ps);
986706f2543Smrg
987706f2543Smrg    /* Change picture attributes on back-end server */
988706f2543Smrg    if (pPictPriv->pict) {
989706f2543Smrg	XRenderPictureAttributes  attribs;
990706f2543Smrg
991706f2543Smrg	if (mask & CPRepeat) {
992706f2543Smrg	    attribs.repeat = pPicture->repeatType;
993706f2543Smrg	}
994706f2543Smrg	if (mask & CPAlphaMap) {
995706f2543Smrg	    if (pPicture->alphaMap) {
996706f2543Smrg		dmxPictPrivPtr  pAlphaPriv;
997706f2543Smrg		pAlphaPriv = DMX_GET_PICT_PRIV(pPicture->alphaMap);
998706f2543Smrg		if (pAlphaPriv->pict) {
999706f2543Smrg		    attribs.alpha_map = pAlphaPriv->pict;
1000706f2543Smrg		} else {
1001706f2543Smrg		    /* FIXME: alpha picture drawable has not been created?? */
1002706f2543Smrg		    return; /* or should this be: attribs.alpha_map = None; */
1003706f2543Smrg		}
1004706f2543Smrg	    } else {
1005706f2543Smrg		attribs.alpha_map = None;
1006706f2543Smrg	    }
1007706f2543Smrg	}
1008706f2543Smrg	if (mask & CPAlphaXOrigin)
1009706f2543Smrg	    attribs.alpha_x_origin = pPicture->alphaOrigin.x;
1010706f2543Smrg	if (mask & CPAlphaYOrigin)
1011706f2543Smrg	    attribs.alpha_y_origin = pPicture->alphaOrigin.y;
1012706f2543Smrg	if (mask & CPClipXOrigin)
1013706f2543Smrg	    attribs.clip_x_origin = pPicture->clipOrigin.x;
1014706f2543Smrg	if (mask & CPClipYOrigin)
1015706f2543Smrg	    attribs.clip_y_origin = pPicture->clipOrigin.y;
1016706f2543Smrg	if (mask & CPClipMask)
1017706f2543Smrg	    mask &= ~CPClipMask; /* Handled in ChangePictureClip */
1018706f2543Smrg	if (mask & CPGraphicsExposure)
1019706f2543Smrg	    attribs.graphics_exposures = pPicture->graphicsExposures;
1020706f2543Smrg	if (mask & CPSubwindowMode)
1021706f2543Smrg	    attribs.subwindow_mode = pPicture->subWindowMode;
1022706f2543Smrg	if (mask & CPPolyEdge)
1023706f2543Smrg	    attribs.poly_edge = pPicture->polyEdge;
1024706f2543Smrg	if (mask & CPPolyMode)
1025706f2543Smrg	    attribs.poly_mode = pPicture->polyMode;
1026706f2543Smrg	if (mask & CPComponentAlpha)
1027706f2543Smrg	    attribs.component_alpha = pPicture->componentAlpha;
1028706f2543Smrg
1029706f2543Smrg	XRenderChangePicture(dmxScreen->beDisplay, pPictPriv->pict,
1030706f2543Smrg			     mask, &attribs);
1031706f2543Smrg	dmxSync(dmxScreen, FALSE);
1032706f2543Smrg    } else {
1033706f2543Smrg	pPictPriv->savedMask |= mask;
1034706f2543Smrg    }
1035706f2543Smrg
1036706f2543Smrg#if 1
1037706f2543Smrg    if (ps->ValidatePicture)
1038706f2543Smrg	ps->ValidatePicture(pPicture, mask);
1039706f2543Smrg#endif
1040706f2543Smrg
1041706f2543Smrg    DMX_WRAP(ValidatePicture, dmxValidatePicture, dmxScreen, ps);
1042706f2543Smrg}
1043706f2543Smrg
1044706f2543Smrg/** Composite a picture on the appropriate screen by combining the
1045706f2543Smrg *  specified rectangle of the transformed src and mask operands with
1046706f2543Smrg *  the specified rectangle of the dst using op as the compositing
1047706f2543Smrg *  operator.  For a complete description see the protocol document of
1048706f2543Smrg *  the RENDER library. */
1049706f2543Smrgvoid dmxComposite(CARD8 op,
1050706f2543Smrg		  PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
1051706f2543Smrg		  INT16 xSrc, INT16 ySrc,
1052706f2543Smrg		  INT16 xMask, INT16 yMask,
1053706f2543Smrg		  INT16 xDst, INT16 yDst,
1054706f2543Smrg		  CARD16 width, CARD16 height)
1055706f2543Smrg{
1056706f2543Smrg    ScreenPtr         pScreen   = pDst->pDrawable->pScreen;
1057706f2543Smrg    DMXScreenInfo    *dmxScreen = &dmxScreens[pScreen->myNum];
1058706f2543Smrg    PictureScreenPtr  ps        = GetPictureScreen(pScreen);
1059706f2543Smrg    dmxPictPrivPtr    pSrcPriv  = DMX_GET_PICT_PRIV(pSrc);
1060706f2543Smrg    dmxPictPrivPtr    pMaskPriv = NULL;
1061706f2543Smrg    dmxPictPrivPtr    pDstPriv  = DMX_GET_PICT_PRIV(pDst);
1062706f2543Smrg
1063706f2543Smrg    if (pMask) pMaskPriv = DMX_GET_PICT_PRIV(pMask);
1064706f2543Smrg
1065706f2543Smrg    DMX_UNWRAP(Composite, dmxScreen, ps);
1066706f2543Smrg#if 0
1067706f2543Smrg    if (ps->Composite)
1068706f2543Smrg	ps->Composite(op, pSrc, pMask, pDst,
1069706f2543Smrg		      xSrc, ySrc, xMask, yMask, xDst, yDst,
1070706f2543Smrg		      width, height);
1071706f2543Smrg#endif
1072706f2543Smrg
1073706f2543Smrg    /* Composite on back-end server */
1074706f2543Smrg    if (pSrcPriv->pict && pDstPriv->pict &&
1075706f2543Smrg	((pMaskPriv && pMaskPriv->pict) || !pMaskPriv)) {
1076706f2543Smrg	XRenderComposite(dmxScreen->beDisplay,
1077706f2543Smrg			 op,
1078706f2543Smrg			 pSrcPriv->pict,
1079706f2543Smrg			 pMaskPriv ? pMaskPriv->pict : None,
1080706f2543Smrg			 pDstPriv->pict,
1081706f2543Smrg			 xSrc, ySrc,
1082706f2543Smrg			 xMask, yMask,
1083706f2543Smrg			 xDst, yDst,
1084706f2543Smrg			 width, height);
1085706f2543Smrg	dmxSync(dmxScreen, FALSE);
1086706f2543Smrg    }
1087706f2543Smrg
1088706f2543Smrg
1089706f2543Smrg    DMX_WRAP(Composite, dmxComposite, dmxScreen, ps);
1090706f2543Smrg}
1091706f2543Smrg
1092706f2543Smrg/** Null function to catch when/if RENDER calls lower level mi hooks.
1093706f2543Smrg *  Compositing glyphs is handled by dmxProcRenderCompositeGlyphs().
1094706f2543Smrg *  This function should never be called. */
1095706f2543Smrgvoid dmxGlyphs(CARD8 op,
1096706f2543Smrg	       PicturePtr pSrc, PicturePtr pDst,
1097706f2543Smrg	       PictFormatPtr maskFormat,
1098706f2543Smrg	       INT16 xSrc, INT16 ySrc,
1099706f2543Smrg	       int nlists, GlyphListPtr lists, GlyphPtr *glyphs)
1100706f2543Smrg{
1101706f2543Smrg    /* This won't work, so we need to wrap ProcRenderCompositeGlyphs */
1102706f2543Smrg}
1103706f2543Smrg
1104706f2543Smrg/** Fill a rectangle on the appropriate screen by combining the color
1105706f2543Smrg *  with the dest picture in the area specified by the list of
1106706f2543Smrg *  rectangles.  For a complete description see the protocol document of
1107706f2543Smrg *  the RENDER library. */
1108706f2543Smrgvoid dmxCompositeRects(CARD8 op,
1109706f2543Smrg		       PicturePtr pDst,
1110706f2543Smrg		       xRenderColor *color,
1111706f2543Smrg		       int nRect, xRectangle *rects)
1112706f2543Smrg{
1113706f2543Smrg    ScreenPtr         pScreen   = pDst->pDrawable->pScreen;
1114706f2543Smrg    DMXScreenInfo    *dmxScreen = &dmxScreens[pScreen->myNum];
1115706f2543Smrg    PictureScreenPtr  ps        = GetPictureScreen(pScreen);
1116706f2543Smrg    dmxPictPrivPtr    pPictPriv = DMX_GET_PICT_PRIV(pDst);
1117706f2543Smrg
1118706f2543Smrg    DMX_UNWRAP(CompositeRects, dmxScreen, ps);
1119706f2543Smrg#if 0
1120706f2543Smrg    if (ps->CompositeRects)
1121706f2543Smrg	ps->CompositeRects(op, pDst, color, nRect, rects);
1122706f2543Smrg#endif
1123706f2543Smrg
1124706f2543Smrg    /* CompositeRects on back-end server */
1125706f2543Smrg    if (pPictPriv->pict) {
1126706f2543Smrg	XRenderFillRectangles(dmxScreen->beDisplay,
1127706f2543Smrg			      op,
1128706f2543Smrg			      pPictPriv->pict,
1129706f2543Smrg			      (XRenderColor *)color,
1130706f2543Smrg			      (XRectangle *)rects,
1131706f2543Smrg			      nRect);
1132706f2543Smrg	dmxSync(dmxScreen, FALSE);
1133706f2543Smrg    }
1134706f2543Smrg
1135706f2543Smrg    DMX_WRAP(CompositeRects, dmxCompositeRects, dmxScreen, ps);
1136706f2543Smrg}
1137706f2543Smrg
1138706f2543Smrg/** Indexed color visuals are not yet supported. */
1139706f2543SmrgBool dmxInitIndexed(ScreenPtr pScreen, PictFormatPtr pFormat)
1140706f2543Smrg{
1141706f2543Smrg    return TRUE;
1142706f2543Smrg}
1143706f2543Smrg
1144706f2543Smrg/** Indexed color visuals are not yet supported. */
1145706f2543Smrgvoid dmxCloseIndexed(ScreenPtr pScreen, PictFormatPtr pFormat)
1146706f2543Smrg{
1147706f2543Smrg}
1148706f2543Smrg
1149706f2543Smrg/** Indexed color visuals are not yet supported. */
1150706f2543Smrgvoid dmxUpdateIndexed(ScreenPtr pScreen, PictFormatPtr pFormat,
1151706f2543Smrg		      int ndef, xColorItem *pdef)
1152706f2543Smrg{
1153706f2543Smrg}
1154706f2543Smrg
1155706f2543Smrg/** Composite a list of trapezoids on the appropriate screen.  For a
1156706f2543Smrg *  complete description see the protocol document of the RENDER
1157706f2543Smrg *  library. */
1158706f2543Smrgvoid dmxTrapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
1159706f2543Smrg		   PictFormatPtr maskFormat,
1160706f2543Smrg		   INT16 xSrc, INT16 ySrc,
1161706f2543Smrg		   int ntrap, xTrapezoid *traps)
1162706f2543Smrg{
1163706f2543Smrg    ScreenPtr         pScreen   = pDst->pDrawable->pScreen;
1164706f2543Smrg    DMXScreenInfo    *dmxScreen = &dmxScreens[pScreen->myNum];
1165706f2543Smrg    PictureScreenPtr  ps        = GetPictureScreen(pScreen);
1166706f2543Smrg    dmxPictPrivPtr    pSrcPriv  = DMX_GET_PICT_PRIV(pSrc);
1167706f2543Smrg    dmxPictPrivPtr    pDstPriv  = DMX_GET_PICT_PRIV(pDst);
1168706f2543Smrg
1169706f2543Smrg    DMX_UNWRAP(Trapezoids, dmxScreen, ps);
1170706f2543Smrg#if 0
1171706f2543Smrg    if (ps->Trapezoids)
1172706f2543Smrg	ps->Trapezoids(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntrap, *traps);
1173706f2543Smrg#endif
1174706f2543Smrg
1175706f2543Smrg    /* Draw trapezoids on back-end server */
1176706f2543Smrg    if (pDstPriv->pict) {
1177706f2543Smrg	XRenderPictFormat *pFormat;
1178706f2543Smrg
1179706f2543Smrg	pFormat = dmxFindFormat(dmxScreen, maskFormat);
1180706f2543Smrg	if (!pFormat) {
1181706f2543Smrg	    /* FIXME: Error! */
1182706f2543Smrg	}
1183706f2543Smrg
1184706f2543Smrg	XRenderCompositeTrapezoids(dmxScreen->beDisplay,
1185706f2543Smrg				   op,
1186706f2543Smrg				   pSrcPriv->pict,
1187706f2543Smrg				   pDstPriv->pict,
1188706f2543Smrg				   pFormat,
1189706f2543Smrg				   xSrc, ySrc,
1190706f2543Smrg				   (XTrapezoid *)traps,
1191706f2543Smrg				   ntrap);
1192706f2543Smrg	dmxSync(dmxScreen, FALSE);
1193706f2543Smrg    }
1194706f2543Smrg
1195706f2543Smrg    DMX_WRAP(Trapezoids, dmxTrapezoids, dmxScreen, ps);
1196706f2543Smrg}
1197706f2543Smrg
1198706f2543Smrg/** Composite a list of triangles on the appropriate screen.  For a
1199706f2543Smrg *  complete description see the protocol document of the RENDER
1200706f2543Smrg *  library. */
1201706f2543Smrgvoid dmxTriangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
1202706f2543Smrg		  PictFormatPtr maskFormat,
1203706f2543Smrg		  INT16 xSrc, INT16 ySrc,
1204706f2543Smrg		  int ntri, xTriangle *tris)
1205706f2543Smrg{
1206706f2543Smrg    ScreenPtr         pScreen   = pDst->pDrawable->pScreen;
1207706f2543Smrg    DMXScreenInfo    *dmxScreen = &dmxScreens[pScreen->myNum];
1208706f2543Smrg    PictureScreenPtr  ps        = GetPictureScreen(pScreen);
1209706f2543Smrg    dmxPictPrivPtr    pSrcPriv  = DMX_GET_PICT_PRIV(pSrc);
1210706f2543Smrg    dmxPictPrivPtr    pDstPriv  = DMX_GET_PICT_PRIV(pDst);
1211706f2543Smrg
1212706f2543Smrg    DMX_UNWRAP(Triangles, dmxScreen, ps);
1213706f2543Smrg#if 0
1214706f2543Smrg    if (ps->Triangles)
1215706f2543Smrg	ps->Triangles(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, *tris);
1216706f2543Smrg#endif
1217706f2543Smrg
1218706f2543Smrg    /* Draw trapezoids on back-end server */
1219706f2543Smrg    if (pDstPriv->pict) {
1220706f2543Smrg	XRenderPictFormat *pFormat;
1221706f2543Smrg
1222706f2543Smrg	pFormat = dmxFindFormat(dmxScreen, maskFormat);
1223706f2543Smrg	if (!pFormat) {
1224706f2543Smrg	    /* FIXME: Error! */
1225706f2543Smrg	}
1226706f2543Smrg
1227706f2543Smrg	XRenderCompositeTriangles(dmxScreen->beDisplay,
1228706f2543Smrg				  op,
1229706f2543Smrg				  pSrcPriv->pict,
1230706f2543Smrg				  pDstPriv->pict,
1231706f2543Smrg				  pFormat,
1232706f2543Smrg				  xSrc, ySrc,
1233706f2543Smrg				  (XTriangle *)tris,
1234706f2543Smrg				  ntri);
1235706f2543Smrg	dmxSync(dmxScreen, FALSE);
1236706f2543Smrg    }
1237706f2543Smrg
1238706f2543Smrg    DMX_WRAP(Triangles, dmxTriangles, dmxScreen, ps);
1239706f2543Smrg}
1240706f2543Smrg
1241706f2543Smrg/** Composite a triangle strip on the appropriate screen.  For a
1242706f2543Smrg *  complete description see the protocol document of the RENDER
1243706f2543Smrg *  library. */
1244706f2543Smrgvoid dmxTriStrip(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
1245706f2543Smrg		 PictFormatPtr maskFormat,
1246706f2543Smrg		 INT16 xSrc, INT16 ySrc,
1247706f2543Smrg		 int npoint, xPointFixed *points)
1248706f2543Smrg{
1249706f2543Smrg    ScreenPtr         pScreen   = pDst->pDrawable->pScreen;
1250706f2543Smrg    DMXScreenInfo    *dmxScreen = &dmxScreens[pScreen->myNum];
1251706f2543Smrg    PictureScreenPtr  ps        = GetPictureScreen(pScreen);
1252706f2543Smrg    dmxPictPrivPtr    pSrcPriv  = DMX_GET_PICT_PRIV(pSrc);
1253706f2543Smrg    dmxPictPrivPtr    pDstPriv  = DMX_GET_PICT_PRIV(pDst);
1254706f2543Smrg
1255706f2543Smrg    DMX_UNWRAP(TriStrip, dmxScreen, ps);
1256706f2543Smrg#if 0
1257706f2543Smrg    if (ps->TriStrip)
1258706f2543Smrg	ps->TriStrip(op, pSrc, pDst, maskFormat, xSrc, ySrc, npoint, *points);
1259706f2543Smrg#endif
1260706f2543Smrg
1261706f2543Smrg    /* Draw trapezoids on back-end server */
1262706f2543Smrg    if (pDstPriv->pict) {
1263706f2543Smrg	XRenderPictFormat *pFormat;
1264706f2543Smrg
1265706f2543Smrg	pFormat = dmxFindFormat(dmxScreen, maskFormat);
1266706f2543Smrg	if (!pFormat) {
1267706f2543Smrg	    /* FIXME: Error! */
1268706f2543Smrg	}
1269706f2543Smrg
1270706f2543Smrg	XRenderCompositeTriStrip(dmxScreen->beDisplay,
1271706f2543Smrg				 op,
1272706f2543Smrg				 pSrcPriv->pict,
1273706f2543Smrg				 pDstPriv->pict,
1274706f2543Smrg				 pFormat,
1275706f2543Smrg				 xSrc, ySrc,
1276706f2543Smrg				 (XPointFixed *)points,
1277706f2543Smrg				 npoint);
1278706f2543Smrg	dmxSync(dmxScreen, FALSE);
1279706f2543Smrg    }
1280706f2543Smrg
1281706f2543Smrg    DMX_WRAP(TriStrip, dmxTriStrip, dmxScreen, ps);
1282706f2543Smrg}
1283706f2543Smrg
1284706f2543Smrg/** Composite a triangle fan on the appropriate screen.  For a complete
1285706f2543Smrg *  description see the protocol document of the RENDER library. */
1286706f2543Smrgvoid dmxTriFan(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
1287706f2543Smrg	       PictFormatPtr maskFormat,
1288706f2543Smrg	       INT16 xSrc, INT16 ySrc,
1289706f2543Smrg	       int npoint, xPointFixed *points)
1290706f2543Smrg{
1291706f2543Smrg    ScreenPtr         pScreen   = pDst->pDrawable->pScreen;
1292706f2543Smrg    DMXScreenInfo    *dmxScreen = &dmxScreens[pScreen->myNum];
1293706f2543Smrg    PictureScreenPtr  ps        = GetPictureScreen(pScreen);
1294706f2543Smrg    dmxPictPrivPtr    pSrcPriv  = DMX_GET_PICT_PRIV(pSrc);
1295706f2543Smrg    dmxPictPrivPtr    pDstPriv  = DMX_GET_PICT_PRIV(pDst);
1296706f2543Smrg
1297706f2543Smrg    DMX_UNWRAP(TriFan, dmxScreen, ps);
1298706f2543Smrg#if 0
1299706f2543Smrg    if (ps->TriFan)
1300706f2543Smrg	ps->TriFan(op, pSrc, pDst, maskFormat, xSrc, ySrc, npoint, *points);
1301706f2543Smrg#endif
1302706f2543Smrg
1303706f2543Smrg    /* Draw trapezoids on back-end server */
1304706f2543Smrg    if (pDstPriv->pict) {
1305706f2543Smrg	XRenderPictFormat *pFormat;
1306706f2543Smrg
1307706f2543Smrg	pFormat = dmxFindFormat(dmxScreen, maskFormat);
1308706f2543Smrg	if (!pFormat) {
1309706f2543Smrg	    /* FIXME: Error! */
1310706f2543Smrg	}
1311706f2543Smrg
1312706f2543Smrg	XRenderCompositeTriFan(dmxScreen->beDisplay,
1313706f2543Smrg			       op,
1314706f2543Smrg			       pSrcPriv->pict,
1315706f2543Smrg			       pDstPriv->pict,
1316706f2543Smrg			       pFormat,
1317706f2543Smrg			       xSrc, ySrc,
1318706f2543Smrg			       (XPointFixed *)points,
1319706f2543Smrg			       npoint);
1320706f2543Smrg	dmxSync(dmxScreen, FALSE);
1321706f2543Smrg    }
1322706f2543Smrg
1323706f2543Smrg    DMX_WRAP(TriFan, dmxTriFan, dmxScreen, ps);
1324706f2543Smrg}
1325