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;
68948a68b89Smrg        if (nparams < 0)
69048a68b89Smrg            return BadLength;
691706f2543Smrg
692706f2543Smrg	XRenderSetPictureFilter(dmxScreen->beDisplay,
693706f2543Smrg				pPictPriv->pict,
694706f2543Smrg				filter,
695706f2543Smrg				params,
696706f2543Smrg				nparams);
697706f2543Smrg	dmxSync(dmxScreen, FALSE);
698706f2543Smrg    }
699706f2543Smrg
700706f2543Smrg    return dmxSaveRenderVector[stuff->renderReqType](client);
701706f2543Smrg}
702706f2543Smrg
703706f2543Smrg
704706f2543Smrg/** Create a picture on the appropriate screen.  This is the actual
705706f2543Smrg *  function that creates the picture.  However, if the associated
706706f2543Smrg *  window has not yet been created due to lazy window creation, then
707706f2543Smrg *  delay the picture creation until the window is mapped. */
708706f2543Smrgstatic Picture dmxDoCreatePicture(PicturePtr pPicture)
709706f2543Smrg{
710706f2543Smrg    DrawablePtr               pDraw     = pPicture->pDrawable;
711706f2543Smrg    ScreenPtr                 pScreen   = pDraw->pScreen;
712706f2543Smrg    DMXScreenInfo            *dmxScreen = &dmxScreens[pScreen->myNum];
713706f2543Smrg    XRenderPictFormat        *pFormat;
714706f2543Smrg    Drawable                  draw;
715706f2543Smrg
716706f2543Smrg    if (pPicture->pDrawable->type == DRAWABLE_WINDOW) {
717706f2543Smrg	dmxWinPrivPtr  pWinPriv = DMX_GET_WINDOW_PRIV((WindowPtr)(pDraw));
718706f2543Smrg
719706f2543Smrg	if (!(draw = pWinPriv->window)) {
720706f2543Smrg	    /* Window has not been created yet due to the window
721706f2543Smrg	     * optimization.  Delay picture creation until window is
722706f2543Smrg	     * mapped.
723706f2543Smrg	     */
724706f2543Smrg	    pWinPriv->hasPict = TRUE;
725706f2543Smrg	    return 0;
726706f2543Smrg	}
727706f2543Smrg    } else {
728706f2543Smrg	dmxPixPrivPtr  pPixPriv = DMX_GET_PIXMAP_PRIV((PixmapPtr)(pDraw));
729706f2543Smrg
730706f2543Smrg	if (!(draw = pPixPriv->pixmap)) {
731706f2543Smrg	    /* FIXME: Zero width/height pixmap?? */
732706f2543Smrg	    return 0;
733706f2543Smrg	}
734706f2543Smrg    }
735706f2543Smrg
736706f2543Smrg    /* This should not be reached if the back-end display has been
737706f2543Smrg     * detached because the pWinPriv->window or the pPixPriv->pixmap
738706f2543Smrg     * will be NULL; however, we add it here for completeness
739706f2543Smrg     */
740706f2543Smrg    if (!dmxScreen->beDisplay)
741706f2543Smrg	return 0;
742706f2543Smrg
743706f2543Smrg    pFormat = dmxFindFormat(dmxScreen, pPicture->pFormat);
744706f2543Smrg
745706f2543Smrg    return XRenderCreatePicture(dmxScreen->beDisplay, draw, pFormat, 0, 0);
746706f2543Smrg}
747706f2543Smrg
748706f2543Smrg/** Create a list of pictures.  This function is called by
749706f2543Smrg *  dmxCreateAndRealizeWindow() during the lazy window creation
750706f2543Smrg *  realization process.  It creates the entire list of pictures that
751706f2543Smrg *  are associated with the given window. */
752706f2543Smrgvoid dmxCreatePictureList(WindowPtr pWindow)
753706f2543Smrg{
754706f2543Smrg    PicturePtr  pPicture = GetPictureWindow(pWindow);
755706f2543Smrg
756706f2543Smrg    while (pPicture) {
757706f2543Smrg	dmxPictPrivPtr  pPictPriv = DMX_GET_PICT_PRIV(pPicture);
758706f2543Smrg
759706f2543Smrg	/* Create the picture for this window */
760706f2543Smrg	pPictPriv->pict = dmxDoCreatePicture(pPicture);
761706f2543Smrg
762706f2543Smrg	/* ValidatePicture takes care of the state changes */
763706f2543Smrg
764706f2543Smrg	pPicture = pPicture->pNext;
765706f2543Smrg    }
766706f2543Smrg}
767706f2543Smrg
768706f2543Smrg/** Create \a pPicture on the backend. */
769706f2543Smrgint dmxBECreatePicture(PicturePtr pPicture)
770706f2543Smrg{
771706f2543Smrg    dmxPictPrivPtr    pPictPriv = DMX_GET_PICT_PRIV(pPicture);
772706f2543Smrg
773706f2543Smrg    /* Create picutre on BE */
774706f2543Smrg    pPictPriv->pict = dmxDoCreatePicture(pPicture);
775706f2543Smrg
776706f2543Smrg    /* Flush changes to the backend server */
777706f2543Smrg    dmxValidatePicture(pPicture, (1 << (CPLastBit+1)) - 1);
778706f2543Smrg
779706f2543Smrg    return Success;
780706f2543Smrg}
781706f2543Smrg
782706f2543Smrg/** Create a picture.  This function handles the CreatePicture
783706f2543Smrg *  unwrapping/wrapping and calls dmxDoCreatePicture to actually create
784706f2543Smrg *  the picture on the appropriate screen.  */
785706f2543Smrgint dmxCreatePicture(PicturePtr pPicture)
786706f2543Smrg{
787706f2543Smrg    ScreenPtr         pScreen   = pPicture->pDrawable->pScreen;
788706f2543Smrg    DMXScreenInfo    *dmxScreen = &dmxScreens[pScreen->myNum];
789706f2543Smrg    PictureScreenPtr  ps        = GetPictureScreen(pScreen);
790706f2543Smrg    dmxPictPrivPtr    pPictPriv = DMX_GET_PICT_PRIV(pPicture);
791706f2543Smrg    int               ret       = Success;
792706f2543Smrg
793706f2543Smrg    DMX_UNWRAP(CreatePicture, dmxScreen, ps);
794706f2543Smrg#if 1
795706f2543Smrg    if (ps->CreatePicture)
796706f2543Smrg	ret = ps->CreatePicture(pPicture);
797706f2543Smrg#endif
798706f2543Smrg
799706f2543Smrg    /* Create picture on back-end server */
800706f2543Smrg    pPictPriv->pict      = dmxDoCreatePicture(pPicture);
801706f2543Smrg    pPictPriv->savedMask = 0;
802706f2543Smrg
803706f2543Smrg    DMX_WRAP(CreatePicture, dmxCreatePicture, dmxScreen, ps);
804706f2543Smrg
805706f2543Smrg    return ret;
806706f2543Smrg}
807706f2543Smrg
808706f2543Smrg/** Destroy \a pPicture on the back-end server. */
809706f2543SmrgBool dmxBEFreePicture(PicturePtr pPicture)
810706f2543Smrg{
811706f2543Smrg    ScreenPtr      pScreen   = pPicture->pDrawable->pScreen;
812706f2543Smrg    DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
813706f2543Smrg    dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
814706f2543Smrg
815706f2543Smrg    if (pPictPriv->pict) {
816706f2543Smrg	XRenderFreePicture(dmxScreen->beDisplay, pPictPriv->pict);
817706f2543Smrg	pPictPriv->pict = (Picture)0;
818706f2543Smrg	return TRUE;
819706f2543Smrg    }
820706f2543Smrg
821706f2543Smrg    return FALSE;
822706f2543Smrg}
823706f2543Smrg
824706f2543Smrg/** Destroy a list of pictures that are associated with the window that
825706f2543Smrg *  is being destroyed.  This function is called by #dmxDestroyWindow().
826706f2543Smrg *  */
827706f2543SmrgBool dmxDestroyPictureList(WindowPtr pWindow)
828706f2543Smrg{
829706f2543Smrg    PicturePtr  pPicture = GetPictureWindow(pWindow);
830706f2543Smrg    Bool        ret      = FALSE;
831706f2543Smrg
832706f2543Smrg    while (pPicture) {
833706f2543Smrg	ret |= dmxBEFreePicture(pPicture);
834706f2543Smrg	pPicture = pPicture->pNext;
835706f2543Smrg    }
836706f2543Smrg
837706f2543Smrg    return ret;
838706f2543Smrg}
839706f2543Smrg
840706f2543Smrg/** Destroy a picture.  This function calls the wrapped function that
841706f2543Smrg *  frees the resources in the DMX server associated with this
842706f2543Smrg *  picture. */
843706f2543Smrgvoid dmxDestroyPicture(PicturePtr pPicture)
844706f2543Smrg{
845706f2543Smrg    ScreenPtr         pScreen   = pPicture->pDrawable->pScreen;
846706f2543Smrg    DMXScreenInfo    *dmxScreen = &dmxScreens[pScreen->myNum];
847706f2543Smrg    PictureScreenPtr  ps        = GetPictureScreen(pScreen);
848706f2543Smrg
849706f2543Smrg    DMX_UNWRAP(DestroyPicture, dmxScreen, ps);
850706f2543Smrg
851706f2543Smrg    /* Destroy picture on back-end server */
852706f2543Smrg    if (dmxBEFreePicture(pPicture))
853706f2543Smrg	dmxSync(dmxScreen, FALSE);
854706f2543Smrg
855706f2543Smrg#if 1
856706f2543Smrg    if (ps->DestroyPicture)
857706f2543Smrg	ps->DestroyPicture(pPicture);
858706f2543Smrg#endif
859706f2543Smrg    DMX_WRAP(DestroyPicture, dmxDestroyPicture, dmxScreen, ps);
860706f2543Smrg}
861706f2543Smrg
862706f2543Smrg/** Change the picture's list of clip rectangles. */
863706f2543Smrgint dmxChangePictureClip(PicturePtr pPicture, int clipType,
864706f2543Smrg			 pointer value, int n)
865706f2543Smrg{
866706f2543Smrg    ScreenPtr         pScreen   = pPicture->pDrawable->pScreen;
867706f2543Smrg    DMXScreenInfo    *dmxScreen = &dmxScreens[pScreen->myNum];
868706f2543Smrg    PictureScreenPtr  ps        = GetPictureScreen(pScreen);
869706f2543Smrg    dmxPictPrivPtr    pPictPriv = DMX_GET_PICT_PRIV(pPicture);
870706f2543Smrg
871706f2543Smrg    DMX_UNWRAP(ChangePictureClip, dmxScreen, ps);
872706f2543Smrg#if 1
873706f2543Smrg    if (ps->ChangePictureClip)
874706f2543Smrg	ps->ChangePictureClip(pPicture, clipType, value, n);
875706f2543Smrg#endif
876706f2543Smrg
877706f2543Smrg    /* Change picture clip rects on back-end server */
878706f2543Smrg    if (pPictPriv->pict) {
879706f2543Smrg	/* The clip has already been changed into a region by the mi
880706f2543Smrg	 * routine called above.
881706f2543Smrg	 */
882706f2543Smrg	if (clipType == CT_NONE) {
883706f2543Smrg	    /* Disable clipping, show all */
884706f2543Smrg	    XFixesSetPictureClipRegion(dmxScreen->beDisplay,
885706f2543Smrg				       pPictPriv->pict, 0, 0, None);
886706f2543Smrg	} else if (pPicture->clientClip) {
887706f2543Smrg	    RegionPtr   pClip = pPicture->clientClip;
888706f2543Smrg	    BoxPtr      pBox  = RegionRects(pClip);
889706f2543Smrg	    int         nBox  = RegionNumRects(pClip);
890706f2543Smrg	    XRectangle *pRects;
891706f2543Smrg	    XRectangle *pRect;
892706f2543Smrg	    int         nRects;
893706f2543Smrg
894706f2543Smrg	    nRects = nBox;
895706f2543Smrg	    pRects = pRect = malloc(nRects * sizeof(*pRect));
896706f2543Smrg
897706f2543Smrg	    while (nBox--) {
898706f2543Smrg		pRect->x      = pBox->x1;
899706f2543Smrg		pRect->y      = pBox->y1;
900706f2543Smrg		pRect->width  = pBox->x2 - pBox->x1;
901706f2543Smrg		pRect->height = pBox->y2 - pBox->y1;
902706f2543Smrg		pBox++;
903706f2543Smrg		pRect++;
904706f2543Smrg	    }
905706f2543Smrg
906706f2543Smrg	    XRenderSetPictureClipRectangles(dmxScreen->beDisplay,
907706f2543Smrg					    pPictPriv->pict,
908706f2543Smrg					    0, 0,
909706f2543Smrg					    pRects,
910706f2543Smrg					    nRects);
911706f2543Smrg	    free(pRects);
912706f2543Smrg	} else {
913706f2543Smrg	    XRenderSetPictureClipRectangles(dmxScreen->beDisplay,
914706f2543Smrg					    pPictPriv->pict,
915706f2543Smrg					    0, 0, NULL, 0);
916706f2543Smrg	}
917706f2543Smrg	dmxSync(dmxScreen, FALSE);
918706f2543Smrg    } else {
919706f2543Smrg	/* FIXME: Handle saving clip region when offscreen */
920706f2543Smrg    }
921706f2543Smrg
922706f2543Smrg    DMX_WRAP(ChangePictureClip, dmxChangePictureClip, dmxScreen, ps);
923706f2543Smrg
924706f2543Smrg    return Success;
925706f2543Smrg}
926706f2543Smrg
927706f2543Smrg/** Destroy the picture's list of clip rectangles. */
928706f2543Smrgvoid dmxDestroyPictureClip(PicturePtr pPicture)
929706f2543Smrg{
930706f2543Smrg    ScreenPtr         pScreen   = pPicture->pDrawable->pScreen;
931706f2543Smrg    DMXScreenInfo    *dmxScreen = &dmxScreens[pScreen->myNum];
932706f2543Smrg    PictureScreenPtr  ps        = GetPictureScreen(pScreen);
933706f2543Smrg    dmxPictPrivPtr    pPictPriv = DMX_GET_PICT_PRIV(pPicture);
934706f2543Smrg
935706f2543Smrg    DMX_UNWRAP(DestroyPictureClip, dmxScreen, ps);
936706f2543Smrg#if 1
937706f2543Smrg    if (ps->DestroyPictureClip)
938706f2543Smrg	ps->DestroyPictureClip(pPicture);
939706f2543Smrg#endif
940706f2543Smrg
941706f2543Smrg    /* Destroy picture clip rects on back-end server */
942706f2543Smrg    if (pPictPriv->pict) {
943706f2543Smrg	XRenderSetPictureClipRectangles(dmxScreen->beDisplay,
944706f2543Smrg					pPictPriv->pict,
945706f2543Smrg					0, 0, NULL, 0);
946706f2543Smrg	dmxSync(dmxScreen, FALSE);
947706f2543Smrg    } else {
948706f2543Smrg	/* FIXME: Handle destroying clip region when offscreen */
949706f2543Smrg    }
950706f2543Smrg
951706f2543Smrg    DMX_WRAP(DestroyPictureClip, dmxDestroyPictureClip, dmxScreen, ps);
952706f2543Smrg}
953706f2543Smrg
954706f2543Smrg/** Change the attributes of the pictures.  If the picture has not yet
955706f2543Smrg *  been created due to lazy window creation, save the mask so that it
956706f2543Smrg *  can be used to appropriately initialize the picture's attributes
957706f2543Smrg *  when it is created later. */
958706f2543Smrgvoid dmxChangePicture(PicturePtr pPicture, Mask mask)
959706f2543Smrg{
960706f2543Smrg    ScreenPtr         pScreen   = pPicture->pDrawable->pScreen;
961706f2543Smrg    DMXScreenInfo    *dmxScreen = &dmxScreens[pScreen->myNum];
962706f2543Smrg    PictureScreenPtr  ps        = GetPictureScreen(pScreen);
963706f2543Smrg    dmxPictPrivPtr    pPictPriv = DMX_GET_PICT_PRIV(pPicture);
964706f2543Smrg
965706f2543Smrg    DMX_UNWRAP(ChangePicture, dmxScreen, ps);
966706f2543Smrg#if 1
967706f2543Smrg    if (ps->ChangePicture)
968706f2543Smrg	ps->ChangePicture(pPicture, mask);
969706f2543Smrg#endif
970706f2543Smrg
971706f2543Smrg    /* Picture attribute changes are handled in ValidatePicture */
972706f2543Smrg    pPictPriv->savedMask |= mask;
973706f2543Smrg
974706f2543Smrg    DMX_WRAP(ChangePicture, dmxChangePicture, dmxScreen, ps);
975706f2543Smrg}
976706f2543Smrg
977706f2543Smrg/** Validate the picture's attributes before rendering to it.  Update
978706f2543Smrg *  any picture attributes that have been changed by one of the higher
979706f2543Smrg *  layers. */
980706f2543Smrgvoid dmxValidatePicture(PicturePtr pPicture, Mask mask)
981706f2543Smrg{
982706f2543Smrg    ScreenPtr         pScreen   = pPicture->pDrawable->pScreen;
983706f2543Smrg    DMXScreenInfo    *dmxScreen = &dmxScreens[pScreen->myNum];
984706f2543Smrg    PictureScreenPtr  ps        = GetPictureScreen(pScreen);
985706f2543Smrg    dmxPictPrivPtr    pPictPriv = DMX_GET_PICT_PRIV(pPicture);
986706f2543Smrg
987706f2543Smrg    DMX_UNWRAP(ValidatePicture, dmxScreen, ps);
988706f2543Smrg
989706f2543Smrg    /* Change picture attributes on back-end server */
990706f2543Smrg    if (pPictPriv->pict) {
991706f2543Smrg	XRenderPictureAttributes  attribs;
992706f2543Smrg
993706f2543Smrg	if (mask & CPRepeat) {
994706f2543Smrg	    attribs.repeat = pPicture->repeatType;
995706f2543Smrg	}
996706f2543Smrg	if (mask & CPAlphaMap) {
997706f2543Smrg	    if (pPicture->alphaMap) {
998706f2543Smrg		dmxPictPrivPtr  pAlphaPriv;
999706f2543Smrg		pAlphaPriv = DMX_GET_PICT_PRIV(pPicture->alphaMap);
1000706f2543Smrg		if (pAlphaPriv->pict) {
1001706f2543Smrg		    attribs.alpha_map = pAlphaPriv->pict;
1002706f2543Smrg		} else {
1003706f2543Smrg		    /* FIXME: alpha picture drawable has not been created?? */
1004706f2543Smrg		    return; /* or should this be: attribs.alpha_map = None; */
1005706f2543Smrg		}
1006706f2543Smrg	    } else {
1007706f2543Smrg		attribs.alpha_map = None;
1008706f2543Smrg	    }
1009706f2543Smrg	}
1010706f2543Smrg	if (mask & CPAlphaXOrigin)
1011706f2543Smrg	    attribs.alpha_x_origin = pPicture->alphaOrigin.x;
1012706f2543Smrg	if (mask & CPAlphaYOrigin)
1013706f2543Smrg	    attribs.alpha_y_origin = pPicture->alphaOrigin.y;
1014706f2543Smrg	if (mask & CPClipXOrigin)
1015706f2543Smrg	    attribs.clip_x_origin = pPicture->clipOrigin.x;
1016706f2543Smrg	if (mask & CPClipYOrigin)
1017706f2543Smrg	    attribs.clip_y_origin = pPicture->clipOrigin.y;
1018706f2543Smrg	if (mask & CPClipMask)
1019706f2543Smrg	    mask &= ~CPClipMask; /* Handled in ChangePictureClip */
1020706f2543Smrg	if (mask & CPGraphicsExposure)
1021706f2543Smrg	    attribs.graphics_exposures = pPicture->graphicsExposures;
1022706f2543Smrg	if (mask & CPSubwindowMode)
1023706f2543Smrg	    attribs.subwindow_mode = pPicture->subWindowMode;
1024706f2543Smrg	if (mask & CPPolyEdge)
1025706f2543Smrg	    attribs.poly_edge = pPicture->polyEdge;
1026706f2543Smrg	if (mask & CPPolyMode)
1027706f2543Smrg	    attribs.poly_mode = pPicture->polyMode;
1028706f2543Smrg	if (mask & CPComponentAlpha)
1029706f2543Smrg	    attribs.component_alpha = pPicture->componentAlpha;
1030706f2543Smrg
1031706f2543Smrg	XRenderChangePicture(dmxScreen->beDisplay, pPictPriv->pict,
1032706f2543Smrg			     mask, &attribs);
1033706f2543Smrg	dmxSync(dmxScreen, FALSE);
1034706f2543Smrg    } else {
1035706f2543Smrg	pPictPriv->savedMask |= mask;
1036706f2543Smrg    }
1037706f2543Smrg
1038706f2543Smrg#if 1
1039706f2543Smrg    if (ps->ValidatePicture)
1040706f2543Smrg	ps->ValidatePicture(pPicture, mask);
1041706f2543Smrg#endif
1042706f2543Smrg
1043706f2543Smrg    DMX_WRAP(ValidatePicture, dmxValidatePicture, dmxScreen, ps);
1044706f2543Smrg}
1045706f2543Smrg
1046706f2543Smrg/** Composite a picture on the appropriate screen by combining the
1047706f2543Smrg *  specified rectangle of the transformed src and mask operands with
1048706f2543Smrg *  the specified rectangle of the dst using op as the compositing
1049706f2543Smrg *  operator.  For a complete description see the protocol document of
1050706f2543Smrg *  the RENDER library. */
1051706f2543Smrgvoid dmxComposite(CARD8 op,
1052706f2543Smrg		  PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
1053706f2543Smrg		  INT16 xSrc, INT16 ySrc,
1054706f2543Smrg		  INT16 xMask, INT16 yMask,
1055706f2543Smrg		  INT16 xDst, INT16 yDst,
1056706f2543Smrg		  CARD16 width, CARD16 height)
1057706f2543Smrg{
1058706f2543Smrg    ScreenPtr         pScreen   = pDst->pDrawable->pScreen;
1059706f2543Smrg    DMXScreenInfo    *dmxScreen = &dmxScreens[pScreen->myNum];
1060706f2543Smrg    PictureScreenPtr  ps        = GetPictureScreen(pScreen);
1061706f2543Smrg    dmxPictPrivPtr    pSrcPriv  = DMX_GET_PICT_PRIV(pSrc);
1062706f2543Smrg    dmxPictPrivPtr    pMaskPriv = NULL;
1063706f2543Smrg    dmxPictPrivPtr    pDstPriv  = DMX_GET_PICT_PRIV(pDst);
1064706f2543Smrg
1065706f2543Smrg    if (pMask) pMaskPriv = DMX_GET_PICT_PRIV(pMask);
1066706f2543Smrg
1067706f2543Smrg    DMX_UNWRAP(Composite, dmxScreen, ps);
1068706f2543Smrg#if 0
1069706f2543Smrg    if (ps->Composite)
1070706f2543Smrg	ps->Composite(op, pSrc, pMask, pDst,
1071706f2543Smrg		      xSrc, ySrc, xMask, yMask, xDst, yDst,
1072706f2543Smrg		      width, height);
1073706f2543Smrg#endif
1074706f2543Smrg
1075706f2543Smrg    /* Composite on back-end server */
1076706f2543Smrg    if (pSrcPriv->pict && pDstPriv->pict &&
1077706f2543Smrg	((pMaskPriv && pMaskPriv->pict) || !pMaskPriv)) {
1078706f2543Smrg	XRenderComposite(dmxScreen->beDisplay,
1079706f2543Smrg			 op,
1080706f2543Smrg			 pSrcPriv->pict,
1081706f2543Smrg			 pMaskPriv ? pMaskPriv->pict : None,
1082706f2543Smrg			 pDstPriv->pict,
1083706f2543Smrg			 xSrc, ySrc,
1084706f2543Smrg			 xMask, yMask,
1085706f2543Smrg			 xDst, yDst,
1086706f2543Smrg			 width, height);
1087706f2543Smrg	dmxSync(dmxScreen, FALSE);
1088706f2543Smrg    }
1089706f2543Smrg
1090706f2543Smrg
1091706f2543Smrg    DMX_WRAP(Composite, dmxComposite, dmxScreen, ps);
1092706f2543Smrg}
1093706f2543Smrg
1094706f2543Smrg/** Null function to catch when/if RENDER calls lower level mi hooks.
1095706f2543Smrg *  Compositing glyphs is handled by dmxProcRenderCompositeGlyphs().
1096706f2543Smrg *  This function should never be called. */
1097706f2543Smrgvoid dmxGlyphs(CARD8 op,
1098706f2543Smrg	       PicturePtr pSrc, PicturePtr pDst,
1099706f2543Smrg	       PictFormatPtr maskFormat,
1100706f2543Smrg	       INT16 xSrc, INT16 ySrc,
1101706f2543Smrg	       int nlists, GlyphListPtr lists, GlyphPtr *glyphs)
1102706f2543Smrg{
1103706f2543Smrg    /* This won't work, so we need to wrap ProcRenderCompositeGlyphs */
1104706f2543Smrg}
1105706f2543Smrg
1106706f2543Smrg/** Fill a rectangle on the appropriate screen by combining the color
1107706f2543Smrg *  with the dest picture in the area specified by the list of
1108706f2543Smrg *  rectangles.  For a complete description see the protocol document of
1109706f2543Smrg *  the RENDER library. */
1110706f2543Smrgvoid dmxCompositeRects(CARD8 op,
1111706f2543Smrg		       PicturePtr pDst,
1112706f2543Smrg		       xRenderColor *color,
1113706f2543Smrg		       int nRect, xRectangle *rects)
1114706f2543Smrg{
1115706f2543Smrg    ScreenPtr         pScreen   = pDst->pDrawable->pScreen;
1116706f2543Smrg    DMXScreenInfo    *dmxScreen = &dmxScreens[pScreen->myNum];
1117706f2543Smrg    PictureScreenPtr  ps        = GetPictureScreen(pScreen);
1118706f2543Smrg    dmxPictPrivPtr    pPictPriv = DMX_GET_PICT_PRIV(pDst);
1119706f2543Smrg
1120706f2543Smrg    DMX_UNWRAP(CompositeRects, dmxScreen, ps);
1121706f2543Smrg#if 0
1122706f2543Smrg    if (ps->CompositeRects)
1123706f2543Smrg	ps->CompositeRects(op, pDst, color, nRect, rects);
1124706f2543Smrg#endif
1125706f2543Smrg
1126706f2543Smrg    /* CompositeRects on back-end server */
1127706f2543Smrg    if (pPictPriv->pict) {
1128706f2543Smrg	XRenderFillRectangles(dmxScreen->beDisplay,
1129706f2543Smrg			      op,
1130706f2543Smrg			      pPictPriv->pict,
1131706f2543Smrg			      (XRenderColor *)color,
1132706f2543Smrg			      (XRectangle *)rects,
1133706f2543Smrg			      nRect);
1134706f2543Smrg	dmxSync(dmxScreen, FALSE);
1135706f2543Smrg    }
1136706f2543Smrg
1137706f2543Smrg    DMX_WRAP(CompositeRects, dmxCompositeRects, dmxScreen, ps);
1138706f2543Smrg}
1139706f2543Smrg
1140706f2543Smrg/** Indexed color visuals are not yet supported. */
1141706f2543SmrgBool dmxInitIndexed(ScreenPtr pScreen, PictFormatPtr pFormat)
1142706f2543Smrg{
1143706f2543Smrg    return TRUE;
1144706f2543Smrg}
1145706f2543Smrg
1146706f2543Smrg/** Indexed color visuals are not yet supported. */
1147706f2543Smrgvoid dmxCloseIndexed(ScreenPtr pScreen, PictFormatPtr pFormat)
1148706f2543Smrg{
1149706f2543Smrg}
1150706f2543Smrg
1151706f2543Smrg/** Indexed color visuals are not yet supported. */
1152706f2543Smrgvoid dmxUpdateIndexed(ScreenPtr pScreen, PictFormatPtr pFormat,
1153706f2543Smrg		      int ndef, xColorItem *pdef)
1154706f2543Smrg{
1155706f2543Smrg}
1156706f2543Smrg
1157706f2543Smrg/** Composite a list of trapezoids on the appropriate screen.  For a
1158706f2543Smrg *  complete description see the protocol document of the RENDER
1159706f2543Smrg *  library. */
1160706f2543Smrgvoid dmxTrapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
1161706f2543Smrg		   PictFormatPtr maskFormat,
1162706f2543Smrg		   INT16 xSrc, INT16 ySrc,
1163706f2543Smrg		   int ntrap, xTrapezoid *traps)
1164706f2543Smrg{
1165706f2543Smrg    ScreenPtr         pScreen   = pDst->pDrawable->pScreen;
1166706f2543Smrg    DMXScreenInfo    *dmxScreen = &dmxScreens[pScreen->myNum];
1167706f2543Smrg    PictureScreenPtr  ps        = GetPictureScreen(pScreen);
1168706f2543Smrg    dmxPictPrivPtr    pSrcPriv  = DMX_GET_PICT_PRIV(pSrc);
1169706f2543Smrg    dmxPictPrivPtr    pDstPriv  = DMX_GET_PICT_PRIV(pDst);
1170706f2543Smrg
1171706f2543Smrg    DMX_UNWRAP(Trapezoids, dmxScreen, ps);
1172706f2543Smrg#if 0
1173706f2543Smrg    if (ps->Trapezoids)
1174706f2543Smrg	ps->Trapezoids(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntrap, *traps);
1175706f2543Smrg#endif
1176706f2543Smrg
1177706f2543Smrg    /* Draw trapezoids on back-end server */
1178706f2543Smrg    if (pDstPriv->pict) {
1179706f2543Smrg	XRenderPictFormat *pFormat;
1180706f2543Smrg
1181706f2543Smrg	pFormat = dmxFindFormat(dmxScreen, maskFormat);
1182706f2543Smrg	if (!pFormat) {
1183706f2543Smrg	    /* FIXME: Error! */
1184706f2543Smrg	}
1185706f2543Smrg
1186706f2543Smrg	XRenderCompositeTrapezoids(dmxScreen->beDisplay,
1187706f2543Smrg				   op,
1188706f2543Smrg				   pSrcPriv->pict,
1189706f2543Smrg				   pDstPriv->pict,
1190706f2543Smrg				   pFormat,
1191706f2543Smrg				   xSrc, ySrc,
1192706f2543Smrg				   (XTrapezoid *)traps,
1193706f2543Smrg				   ntrap);
1194706f2543Smrg	dmxSync(dmxScreen, FALSE);
1195706f2543Smrg    }
1196706f2543Smrg
1197706f2543Smrg    DMX_WRAP(Trapezoids, dmxTrapezoids, dmxScreen, ps);
1198706f2543Smrg}
1199706f2543Smrg
1200706f2543Smrg/** Composite a list of triangles on the appropriate screen.  For a
1201706f2543Smrg *  complete description see the protocol document of the RENDER
1202706f2543Smrg *  library. */
1203706f2543Smrgvoid dmxTriangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
1204706f2543Smrg		  PictFormatPtr maskFormat,
1205706f2543Smrg		  INT16 xSrc, INT16 ySrc,
1206706f2543Smrg		  int ntri, xTriangle *tris)
1207706f2543Smrg{
1208706f2543Smrg    ScreenPtr         pScreen   = pDst->pDrawable->pScreen;
1209706f2543Smrg    DMXScreenInfo    *dmxScreen = &dmxScreens[pScreen->myNum];
1210706f2543Smrg    PictureScreenPtr  ps        = GetPictureScreen(pScreen);
1211706f2543Smrg    dmxPictPrivPtr    pSrcPriv  = DMX_GET_PICT_PRIV(pSrc);
1212706f2543Smrg    dmxPictPrivPtr    pDstPriv  = DMX_GET_PICT_PRIV(pDst);
1213706f2543Smrg
1214706f2543Smrg    DMX_UNWRAP(Triangles, dmxScreen, ps);
1215706f2543Smrg#if 0
1216706f2543Smrg    if (ps->Triangles)
1217706f2543Smrg	ps->Triangles(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, *tris);
1218706f2543Smrg#endif
1219706f2543Smrg
1220706f2543Smrg    /* Draw trapezoids on back-end server */
1221706f2543Smrg    if (pDstPriv->pict) {
1222706f2543Smrg	XRenderPictFormat *pFormat;
1223706f2543Smrg
1224706f2543Smrg	pFormat = dmxFindFormat(dmxScreen, maskFormat);
1225706f2543Smrg	if (!pFormat) {
1226706f2543Smrg	    /* FIXME: Error! */
1227706f2543Smrg	}
1228706f2543Smrg
1229706f2543Smrg	XRenderCompositeTriangles(dmxScreen->beDisplay,
1230706f2543Smrg				  op,
1231706f2543Smrg				  pSrcPriv->pict,
1232706f2543Smrg				  pDstPriv->pict,
1233706f2543Smrg				  pFormat,
1234706f2543Smrg				  xSrc, ySrc,
1235706f2543Smrg				  (XTriangle *)tris,
1236706f2543Smrg				  ntri);
1237706f2543Smrg	dmxSync(dmxScreen, FALSE);
1238706f2543Smrg    }
1239706f2543Smrg
1240706f2543Smrg    DMX_WRAP(Triangles, dmxTriangles, dmxScreen, ps);
1241706f2543Smrg}
1242706f2543Smrg
1243706f2543Smrg/** Composite a triangle strip on the appropriate screen.  For a
1244706f2543Smrg *  complete description see the protocol document of the RENDER
1245706f2543Smrg *  library. */
1246706f2543Smrgvoid dmxTriStrip(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
1247706f2543Smrg		 PictFormatPtr maskFormat,
1248706f2543Smrg		 INT16 xSrc, INT16 ySrc,
1249706f2543Smrg		 int npoint, xPointFixed *points)
1250706f2543Smrg{
1251706f2543Smrg    ScreenPtr         pScreen   = pDst->pDrawable->pScreen;
1252706f2543Smrg    DMXScreenInfo    *dmxScreen = &dmxScreens[pScreen->myNum];
1253706f2543Smrg    PictureScreenPtr  ps        = GetPictureScreen(pScreen);
1254706f2543Smrg    dmxPictPrivPtr    pSrcPriv  = DMX_GET_PICT_PRIV(pSrc);
1255706f2543Smrg    dmxPictPrivPtr    pDstPriv  = DMX_GET_PICT_PRIV(pDst);
1256706f2543Smrg
1257706f2543Smrg    DMX_UNWRAP(TriStrip, dmxScreen, ps);
1258706f2543Smrg#if 0
1259706f2543Smrg    if (ps->TriStrip)
1260706f2543Smrg	ps->TriStrip(op, pSrc, pDst, maskFormat, xSrc, ySrc, npoint, *points);
1261706f2543Smrg#endif
1262706f2543Smrg
1263706f2543Smrg    /* Draw trapezoids on back-end server */
1264706f2543Smrg    if (pDstPriv->pict) {
1265706f2543Smrg	XRenderPictFormat *pFormat;
1266706f2543Smrg
1267706f2543Smrg	pFormat = dmxFindFormat(dmxScreen, maskFormat);
1268706f2543Smrg	if (!pFormat) {
1269706f2543Smrg	    /* FIXME: Error! */
1270706f2543Smrg	}
1271706f2543Smrg
1272706f2543Smrg	XRenderCompositeTriStrip(dmxScreen->beDisplay,
1273706f2543Smrg				 op,
1274706f2543Smrg				 pSrcPriv->pict,
1275706f2543Smrg				 pDstPriv->pict,
1276706f2543Smrg				 pFormat,
1277706f2543Smrg				 xSrc, ySrc,
1278706f2543Smrg				 (XPointFixed *)points,
1279706f2543Smrg				 npoint);
1280706f2543Smrg	dmxSync(dmxScreen, FALSE);
1281706f2543Smrg    }
1282706f2543Smrg
1283706f2543Smrg    DMX_WRAP(TriStrip, dmxTriStrip, dmxScreen, ps);
1284706f2543Smrg}
1285706f2543Smrg
1286706f2543Smrg/** Composite a triangle fan on the appropriate screen.  For a complete
1287706f2543Smrg *  description see the protocol document of the RENDER library. */
1288706f2543Smrgvoid dmxTriFan(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
1289706f2543Smrg	       PictFormatPtr maskFormat,
1290706f2543Smrg	       INT16 xSrc, INT16 ySrc,
1291706f2543Smrg	       int npoint, xPointFixed *points)
1292706f2543Smrg{
1293706f2543Smrg    ScreenPtr         pScreen   = pDst->pDrawable->pScreen;
1294706f2543Smrg    DMXScreenInfo    *dmxScreen = &dmxScreens[pScreen->myNum];
1295706f2543Smrg    PictureScreenPtr  ps        = GetPictureScreen(pScreen);
1296706f2543Smrg    dmxPictPrivPtr    pSrcPriv  = DMX_GET_PICT_PRIV(pSrc);
1297706f2543Smrg    dmxPictPrivPtr    pDstPriv  = DMX_GET_PICT_PRIV(pDst);
1298706f2543Smrg
1299706f2543Smrg    DMX_UNWRAP(TriFan, dmxScreen, ps);
1300706f2543Smrg#if 0
1301706f2543Smrg    if (ps->TriFan)
1302706f2543Smrg	ps->TriFan(op, pSrc, pDst, maskFormat, xSrc, ySrc, npoint, *points);
1303706f2543Smrg#endif
1304706f2543Smrg
1305706f2543Smrg    /* Draw trapezoids on back-end server */
1306706f2543Smrg    if (pDstPriv->pict) {
1307706f2543Smrg	XRenderPictFormat *pFormat;
1308706f2543Smrg
1309706f2543Smrg	pFormat = dmxFindFormat(dmxScreen, maskFormat);
1310706f2543Smrg	if (!pFormat) {
1311706f2543Smrg	    /* FIXME: Error! */
1312706f2543Smrg	}
1313706f2543Smrg
1314706f2543Smrg	XRenderCompositeTriFan(dmxScreen->beDisplay,
1315706f2543Smrg			       op,
1316706f2543Smrg			       pSrcPriv->pict,
1317706f2543Smrg			       pDstPriv->pict,
1318706f2543Smrg			       pFormat,
1319706f2543Smrg			       xSrc, ySrc,
1320706f2543Smrg			       (XPointFixed *)points,
1321706f2543Smrg			       npoint);
1322706f2543Smrg	dmxSync(dmxScreen, FALSE);
1323706f2543Smrg    }
1324706f2543Smrg
1325706f2543Smrg    DMX_WRAP(TriFan, dmxTriFan, dmxScreen, ps);
1326706f2543Smrg}
1327