1 /*
2  * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina.
3  *
4  * All Rights Reserved.
5  *
6  * Permission is hereby granted, free of charge, to any person obtaining
7  * a copy of this software and associated documentation files (the
8  * "Software"), to deal in the Software without restriction, including
9  * without limitation on the rights to use, copy, modify, merge,
10  * publish, distribute, sublicense, and/or sell copies of the Software,
11  * and to permit persons to whom the Software is furnished to do so,
12  * subject to the following conditions:
13  *
14  * The above copyright notice and this permission notice (including the
15  * next paragraph) shall be included in all copies or substantial
16  * portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
19  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
21  * NON-INFRINGEMENT.  IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
22  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
23  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
24  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
25  * SOFTWARE.
26  */
27 
28 /*
29  * Authors:
30  *   Kevin E. Martin <kem@redhat.com>
31  *
32  */
33 
34 /** \file
35  *  Provide support for the RENDER extension (version 0.8).
36  */
37 
38 #ifdef HAVE_DMX_CONFIG_H
39 #include <dmx-config.h>
40 #endif
41 
42 #include "dmx.h"
43 #include "dmxsync.h"
44 #include "dmxpict.h"
45 #include "dmxwindow.h"
46 #include "dmxpixmap.h"
47 
48 #include "fb.h"
49 #include "pixmapstr.h"
50 #include "dixstruct.h"
51 
52 #include <X11/extensions/render.h>
53 #include <X11/extensions/renderproto.h>
54 #include <X11/extensions/Xfixes.h>
55 #include "picture.h"
56 #include "picturestr.h"
57 #include "mipict.h"
58 #include "fbpict.h"
59 
60 extern int (*ProcRenderVector[RenderNumberRequests]) (ClientPtr);
61 
62 static int (*dmxSaveRenderVector[RenderNumberRequests]) (ClientPtr);
63 
64 static int dmxProcRenderCreateGlyphSet(ClientPtr client);
65 static int dmxProcRenderFreeGlyphSet(ClientPtr client);
66 static int dmxProcRenderAddGlyphs(ClientPtr client);
67 static int dmxProcRenderFreeGlyphs(ClientPtr client);
68 static int dmxProcRenderCompositeGlyphs(ClientPtr client);
69 static int dmxProcRenderSetPictureTransform(ClientPtr client);
70 static int dmxProcRenderSetPictureFilter(ClientPtr client);
71 
72 #if 0
73 /* FIXME: Not (yet) supported */
74 static int dmxProcRenderCreateCursor(ClientPtr client);
75 static int dmxProcRenderCreateAnimCursor(ClientPtr client);
76 #endif
77 
78 /** Catch errors that might occur when allocating Glyph Sets.  Errors
79  *  are saved in dmxGlyphLastError for later handling. */
80 static int dmxGlyphLastError;
81 static int
dmxGlyphErrorHandler(Display * dpy,XErrorEvent * ev)82 dmxGlyphErrorHandler(Display * dpy, XErrorEvent * ev)
83 {
84     dmxGlyphLastError = ev->error_code;
85     return 0;
86 }
87 
88 /** Initialize the Proc Vector for the RENDER extension.  The functions
89  *  here cannot be handled by the mi layer RENDER hooks either because
90  *  the required information is no longer available when it reaches the
91  *  mi layer or no mi layer hooks exist.  This function is called from
92  *  InitOutput() since it should be initialized only once per server
93  *  generation. */
94 void
dmxInitRender(void)95 dmxInitRender(void)
96 {
97     int i;
98 
99     for (i = 0; i < RenderNumberRequests; i++)
100         dmxSaveRenderVector[i] = ProcRenderVector[i];
101 
102     ProcRenderVector[X_RenderCreateGlyphSet]
103         = dmxProcRenderCreateGlyphSet;
104     ProcRenderVector[X_RenderFreeGlyphSet]
105         = dmxProcRenderFreeGlyphSet;
106     ProcRenderVector[X_RenderAddGlyphs]
107         = dmxProcRenderAddGlyphs;
108     ProcRenderVector[X_RenderFreeGlyphs]
109         = dmxProcRenderFreeGlyphs;
110     ProcRenderVector[X_RenderCompositeGlyphs8]
111         = dmxProcRenderCompositeGlyphs;
112     ProcRenderVector[X_RenderCompositeGlyphs16]
113         = dmxProcRenderCompositeGlyphs;
114     ProcRenderVector[X_RenderCompositeGlyphs32]
115         = dmxProcRenderCompositeGlyphs;
116     ProcRenderVector[X_RenderSetPictureTransform]
117         = dmxProcRenderSetPictureTransform;
118     ProcRenderVector[X_RenderSetPictureFilter]
119         = dmxProcRenderSetPictureFilter;
120 }
121 
122 /** Reset the Proc Vector for the RENDER extension back to the original
123  *  functions.  This function is called from dmxCloseScreen() during the
124  *  server reset (only for screen #0). */
125 void
dmxResetRender(void)126 dmxResetRender(void)
127 {
128     int i;
129 
130     for (i = 0; i < RenderNumberRequests; i++)
131         ProcRenderVector[i] = dmxSaveRenderVector[i];
132 }
133 
134 /** Initialize the RENDER extension, allocate the picture privates and
135  *  wrap mi function hooks.  If the shadow frame buffer is used, then
136  *  call the appropriate fb initialization function. */
137 Bool
dmxPictureInit(ScreenPtr pScreen,PictFormatPtr formats,int nformats)138 dmxPictureInit(ScreenPtr pScreen, PictFormatPtr formats, int nformats)
139 {
140     DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
141     PictureScreenPtr ps;
142 
143     if (!miPictureInit(pScreen, formats, nformats))
144         return FALSE;
145 
146     if (!dixRegisterPrivateKey
147         (&dmxPictPrivateKeyRec, PRIVATE_PICTURE, sizeof(dmxPictPrivRec)))
148         return FALSE;
149 
150     ps = GetPictureScreen(pScreen);
151 
152     DMX_WRAP(CreatePicture, dmxCreatePicture, dmxScreen, ps);
153     DMX_WRAP(DestroyPicture, dmxDestroyPicture, dmxScreen, ps);
154 
155     DMX_WRAP(ChangePictureClip, dmxChangePictureClip, dmxScreen, ps);
156     DMX_WRAP(DestroyPictureClip, dmxDestroyPictureClip, dmxScreen, ps);
157 
158     DMX_WRAP(ChangePicture, dmxChangePicture, dmxScreen, ps);
159     DMX_WRAP(ValidatePicture, dmxValidatePicture, dmxScreen, ps);
160 
161     DMX_WRAP(Composite, dmxComposite, dmxScreen, ps);
162     DMX_WRAP(Glyphs, dmxGlyphs, dmxScreen, ps);
163     DMX_WRAP(CompositeRects, dmxCompositeRects, dmxScreen, ps);
164 
165     DMX_WRAP(Trapezoids, dmxTrapezoids, dmxScreen, ps);
166     DMX_WRAP(Triangles, dmxTriangles, dmxScreen, ps);
167 
168     return TRUE;
169 }
170 
171 /** Find the appropriate format on the requested screen given the
172  *  internal format requested.  The list of formats is searched
173  *  sequentially as the XRenderFindFormat() function does not always
174  *  find the appropriate format when a specific format is requested. */
175 static XRenderPictFormat *
dmxFindFormat(DMXScreenInfo * dmxScreen,PictFormatPtr pFmt)176 dmxFindFormat(DMXScreenInfo * dmxScreen, PictFormatPtr pFmt)
177 {
178     XRenderPictFormat *pFormat = NULL;
179     int i = 0;
180 
181     if (!pFmt || !dmxScreen->beDisplay)
182         return pFormat;
183 
184     while (1) {
185         pFormat = XRenderFindFormat(dmxScreen->beDisplay, 0, 0, i++);
186         if (!pFormat)
187             break;
188 
189         if (pFormat->type != pFmt->type)
190             continue;
191         if (pFormat->depth != pFmt->depth)
192             continue;
193         if (pFormat->direct.red != pFmt->direct.red)
194             continue;
195         if (pFormat->direct.redMask != pFmt->direct.redMask)
196             continue;
197         if (pFormat->direct.green != pFmt->direct.green)
198             continue;
199         if (pFormat->direct.greenMask != pFmt->direct.greenMask)
200             continue;
201         if (pFormat->direct.blue != pFmt->direct.blue)
202             continue;
203         if (pFormat->direct.blueMask != pFmt->direct.blueMask)
204             continue;
205         if (pFormat->direct.alpha != pFmt->direct.alpha)
206             continue;
207         if (pFormat->direct.alphaMask != pFmt->direct.alphaMask)
208             continue;
209 
210         /* We have a match! */
211         break;
212     }
213 
214     return pFormat;
215 }
216 
217 /** Free \a glyphSet on back-end screen number \a idx. */
218 Bool
dmxBEFreeGlyphSet(ScreenPtr pScreen,GlyphSetPtr glyphSet)219 dmxBEFreeGlyphSet(ScreenPtr pScreen, GlyphSetPtr glyphSet)
220 {
221     dmxGlyphPrivPtr glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
222     int idx = pScreen->myNum;
223     DMXScreenInfo *dmxScreen = &dmxScreens[idx];
224 
225     if (glyphPriv->glyphSets[idx]) {
226         XRenderFreeGlyphSet(dmxScreen->beDisplay, glyphPriv->glyphSets[idx]);
227         glyphPriv->glyphSets[idx] = (GlyphSet) 0;
228         return TRUE;
229     }
230 
231     return FALSE;
232 }
233 
234 /** Create \a glyphSet on the backend screen number \a idx. */
235 int
dmxBECreateGlyphSet(int idx,GlyphSetPtr glyphSet)236 dmxBECreateGlyphSet(int idx, GlyphSetPtr glyphSet)
237 {
238     XRenderPictFormat *pFormat;
239     DMXScreenInfo *dmxScreen = &dmxScreens[idx];
240     dmxGlyphPrivPtr glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
241     PictFormatPtr pFmt = glyphSet->format;
242     int (*oldErrorHandler) (Display *, XErrorEvent *);
243 
244     pFormat = dmxFindFormat(dmxScreen, pFmt);
245     if (!pFormat) {
246         return BadMatch;
247     }
248 
249     dmxGlyphLastError = 0;
250     oldErrorHandler = XSetErrorHandler(dmxGlyphErrorHandler);
251 
252     /* Catch when this fails */
253     glyphPriv->glyphSets[idx]
254         = XRenderCreateGlyphSet(dmxScreen->beDisplay, pFormat);
255 
256     XSetErrorHandler(oldErrorHandler);
257 
258     if (dmxGlyphLastError) {
259         return dmxGlyphLastError;
260     }
261 
262     return Success;
263 }
264 
265 /** Create a Glyph Set on each screen.  Save the glyphset ID from each
266  *  screen in the Glyph Set's private structure.  Fail if the format
267  *  requested is not available or if the Glyph Set cannot be created on
268  *  the screen. */
269 static int
dmxProcRenderCreateGlyphSet(ClientPtr client)270 dmxProcRenderCreateGlyphSet(ClientPtr client)
271 {
272     int ret;
273 
274     REQUEST(xRenderCreateGlyphSetReq);
275 
276     ret = dmxSaveRenderVector[stuff->renderReqType] (client);
277 
278     if (ret == Success) {
279         GlyphSetPtr glyphSet;
280         dmxGlyphPrivPtr glyphPriv;
281         int i;
282 
283         /* Look up glyphSet that was just created ???? */
284         /* Store glyphsets from backends in glyphSet->devPrivate ????? */
285         /* Make sure we handle all errors here!! */
286 
287         dixLookupResourceByType((void **) &glyphSet,
288                                 stuff->gsid, GlyphSetType,
289                                 client, DixDestroyAccess);
290 
291         glyphPriv = malloc(sizeof(dmxGlyphPrivRec));
292         if (!glyphPriv)
293             return BadAlloc;
294         glyphPriv->glyphSets = NULL;
295         MAXSCREENSALLOC_RETURN(glyphPriv->glyphSets, BadAlloc);
296         DMX_SET_GLYPH_PRIV(glyphSet, glyphPriv);
297 
298         for (i = 0; i < dmxNumScreens; i++) {
299             DMXScreenInfo *dmxScreen = &dmxScreens[i];
300             int beret;
301 
302             if (!dmxScreen->beDisplay) {
303                 glyphPriv->glyphSets[i] = 0;
304                 continue;
305             }
306 
307             if ((beret = dmxBECreateGlyphSet(i, glyphSet)) != Success) {
308                 int j;
309 
310                 /* Free the glyph sets we've allocated thus far */
311                 for (j = 0; j < i; j++)
312                     dmxBEFreeGlyphSet(screenInfo.screens[j], glyphSet);
313 
314                 /* Free the resource created by render */
315                 FreeResource(stuff->gsid, RT_NONE);
316 
317                 return beret;
318             }
319         }
320     }
321 
322     return ret;
323 }
324 
325 /** Free the previously allocated Glyph Sets for each screen. */
326 static int
dmxProcRenderFreeGlyphSet(ClientPtr client)327 dmxProcRenderFreeGlyphSet(ClientPtr client)
328 {
329     GlyphSetPtr glyphSet;
330 
331     REQUEST(xRenderFreeGlyphSetReq);
332 
333     REQUEST_SIZE_MATCH(xRenderFreeGlyphSetReq);
334     dixLookupResourceByType((void **) &glyphSet,
335                             stuff->glyphset, GlyphSetType,
336                             client, DixDestroyAccess);
337 
338     if (glyphSet && glyphSet->refcnt == 1) {
339         dmxGlyphPrivPtr glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
340         int i;
341 
342         for (i = 0; i < dmxNumScreens; i++) {
343             DMXScreenInfo *dmxScreen = &dmxScreens[i];
344 
345             if (dmxScreen->beDisplay) {
346                 if (dmxBEFreeGlyphSet(screenInfo.screens[i], glyphSet))
347                     dmxSync(dmxScreen, FALSE);
348             }
349         }
350 
351         MAXSCREENSFREE(glyphPriv->glyphSets);
352         free(glyphPriv);
353         DMX_SET_GLYPH_PRIV(glyphSet, NULL);
354     }
355 
356     return dmxSaveRenderVector[stuff->renderReqType] (client);
357 }
358 
359 /** Add glyphs to the Glyph Set on each screen. */
360 static int
dmxProcRenderAddGlyphs(ClientPtr client)361 dmxProcRenderAddGlyphs(ClientPtr client)
362 {
363     int ret;
364 
365     REQUEST(xRenderAddGlyphsReq);
366 
367     ret = dmxSaveRenderVector[stuff->renderReqType] (client);
368 
369     if (ret == Success) {
370         GlyphSetPtr glyphSet;
371         dmxGlyphPrivPtr glyphPriv;
372         int i;
373         int nglyphs;
374         CARD32 *gids;
375         Glyph *gidsCopy;
376         xGlyphInfo *gi;
377         CARD8 *bits;
378         int nbytes;
379 
380         dixLookupResourceByType((void **) &glyphSet,
381                                 stuff->glyphset, GlyphSetType,
382                                 client, DixReadAccess);
383         glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
384 
385         nglyphs = stuff->nglyphs;
386         gids = (CARD32 *) (stuff + 1);
387         gi = (xGlyphInfo *) (gids + nglyphs);
388         bits = (CARD8 *) (gi + nglyphs);
389         nbytes = ((stuff->length << 2) -
390                   sizeof(xRenderAddGlyphsReq) -
391                   (sizeof(CARD32) + sizeof(xGlyphInfo)) * nglyphs);
392 
393         gidsCopy = xallocarray(nglyphs, sizeof(*gidsCopy));
394         for (i = 0; i < nglyphs; i++)
395             gidsCopy[i] = gids[i];
396 
397         /* FIXME: Will this ever fail? */
398         for (i = 0; i < dmxNumScreens; i++) {
399             DMXScreenInfo *dmxScreen = &dmxScreens[i];
400 
401             if (dmxScreen->beDisplay) {
402                 XRenderAddGlyphs(dmxScreen->beDisplay,
403                                  glyphPriv->glyphSets[i],
404                                  gidsCopy,
405                                  (XGlyphInfo *) gi,
406                                  nglyphs, (char *) bits, nbytes);
407                 dmxSync(dmxScreen, FALSE);
408             }
409         }
410         free(gidsCopy);
411     }
412 
413     return ret;
414 }
415 
416 /** Free glyphs from the Glyph Set for each screen. */
417 static int
dmxProcRenderFreeGlyphs(ClientPtr client)418 dmxProcRenderFreeGlyphs(ClientPtr client)
419 {
420     GlyphSetPtr glyphSet;
421 
422     REQUEST(xRenderFreeGlyphsReq);
423 
424     REQUEST_AT_LEAST_SIZE(xRenderFreeGlyphsReq);
425     dixLookupResourceByType((void **) &glyphSet,
426                             stuff->glyphset, GlyphSetType,
427                             client, DixWriteAccess);
428 
429     if (glyphSet) {
430         dmxGlyphPrivPtr glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
431         int i;
432         int nglyphs;
433         Glyph *gids;
434 
435         nglyphs = ((client->req_len << 2) - sizeof(xRenderFreeGlyphsReq)) >> 2;
436         if (nglyphs) {
437             gids = xallocarray(nglyphs, sizeof(*gids));
438             for (i = 0; i < nglyphs; i++)
439                 gids[i] = ((CARD32 *) (stuff + 1))[i];
440 
441             for (i = 0; i < dmxNumScreens; i++) {
442                 DMXScreenInfo *dmxScreen = &dmxScreens[i];
443 
444                 if (dmxScreen->beDisplay) {
445                     XRenderFreeGlyphs(dmxScreen->beDisplay,
446                                       glyphPriv->glyphSets[i], gids, nglyphs);
447                     dmxSync(dmxScreen, FALSE);
448                 }
449             }
450             free(gids);
451         }
452     }
453 
454     return dmxSaveRenderVector[stuff->renderReqType] (client);
455 }
456 
457 /** Composite glyphs on each screen into the requested picture.  If
458  *  either the src or dest picture has not been allocated due to lazy
459  *  window creation, this request will gracefully return. */
460 static int
dmxProcRenderCompositeGlyphs(ClientPtr client)461 dmxProcRenderCompositeGlyphs(ClientPtr client)
462 {
463     int ret;
464 
465     REQUEST(xRenderCompositeGlyphsReq);
466 
467     ret = dmxSaveRenderVector[stuff->renderReqType] (client);
468 
469     /* For the following to work with PanoramiX, it assumes that Render
470      * wraps the ProcRenderVector after dmxRenderInit has been called.
471      */
472     if (ret == Success) {
473         PicturePtr pSrc;
474         dmxPictPrivPtr pSrcPriv;
475         PicturePtr pDst;
476         dmxPictPrivPtr pDstPriv;
477         PictFormatPtr pFmt;
478         XRenderPictFormat *pFormat;
479         int size;
480 
481         int scrnNum;
482         DMXScreenInfo *dmxScreen;
483 
484         CARD8 *buffer;
485         CARD8 *end;
486         int space;
487 
488         int nglyph;
489         char *glyphs;
490         char *curGlyph;
491 
492         xGlyphElt *elt;
493         int nelt;
494         XGlyphElt8 *elts;
495         XGlyphElt8 *curElt;
496 
497         GlyphSetPtr glyphSet;
498         dmxGlyphPrivPtr glyphPriv;
499 
500         dixLookupResourceByType((void **) &pSrc,
501                                 stuff->src, PictureType, client, DixReadAccess);
502 
503         pSrcPriv = DMX_GET_PICT_PRIV(pSrc);
504         if (!pSrcPriv->pict)
505             return ret;
506 
507         dixLookupResourceByType((void **) &pDst,
508                                 stuff->dst, PictureType,
509                                 client, DixWriteAccess);
510 
511         pDstPriv = DMX_GET_PICT_PRIV(pDst);
512         if (!pDstPriv->pict)
513             return ret;
514 
515         scrnNum = pDst->pDrawable->pScreen->myNum;
516         dmxScreen = &dmxScreens[scrnNum];
517 
518         /* Note: If the back-end display has been detached, then it
519          * should not be possible to reach here since the pSrcPriv->pict
520          * and pDstPriv->pict will have already been set to 0.
521          */
522         if (!dmxScreen->beDisplay)
523             return ret;
524 
525         if (stuff->maskFormat)
526             dixLookupResourceByType((void **) &pFmt,
527                                     stuff->maskFormat, PictFormatType,
528                                     client, DixReadAccess);
529         else
530             pFmt = NULL;
531 
532         pFormat = dmxFindFormat(dmxScreen, pFmt);
533 
534         switch (stuff->renderReqType) {
535         case X_RenderCompositeGlyphs8:
536             size = sizeof(CARD8);
537             break;
538         case X_RenderCompositeGlyphs16:
539             size = sizeof(CARD16);
540             break;
541         case X_RenderCompositeGlyphs32:
542             size = sizeof(CARD32);
543             break;
544         default:
545             return BadPictOp;   /* Can't happen */
546         }
547 
548         buffer = (CARD8 *) (stuff + 1);
549         end = (CARD8 *) stuff + (stuff->length << 2);
550         nelt = 0;
551         nglyph = 0;
552         while (buffer + sizeof(xGlyphElt) < end) {
553             elt = (xGlyphElt *) buffer;
554             buffer += sizeof(xGlyphElt);
555 
556             if (elt->len == 0xff) {
557                 buffer += 4;
558             }
559             else {
560                 nelt++;
561                 nglyph += elt->len;
562                 space = size * elt->len;
563                 if (space & 3)
564                     space += 4 - (space & 3);
565                 buffer += space;
566             }
567         }
568 
569         /* The following only works for Render version > 0.2 */
570 
571         /* All of the XGlyphElt* structure sizes are identical */
572         elts = xallocarray(nelt, sizeof(XGlyphElt8));
573         if (!elts)
574             return BadAlloc;
575 
576         glyphs = xallocarray(nglyph, size);
577         if (!glyphs) {
578             free(elts);
579             return BadAlloc;
580         }
581 
582         buffer = (CARD8 *) (stuff + 1);
583         end = (CARD8 *) stuff + (stuff->length << 2);
584         curGlyph = glyphs;
585         curElt = elts;
586 
587         dixLookupResourceByType((void **) &glyphSet,
588                                 stuff->glyphset, GlyphSetType,
589                                 client, DixReadAccess);
590         glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
591 
592         while (buffer + sizeof(xGlyphElt) < end) {
593             elt = (xGlyphElt *) buffer;
594             buffer += sizeof(xGlyphElt);
595 
596             if (elt->len == 0xff) {
597                 dixLookupResourceByType((void **) &glyphSet,
598                                         *((CARD32 *) buffer),
599                                         GlyphSetType, client, DixReadAccess);
600                 glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
601                 buffer += 4;
602             }
603             else {
604                 curElt->glyphset = glyphPriv->glyphSets[scrnNum];
605                 curElt->xOff = elt->deltax;
606                 curElt->yOff = elt->deltay;
607                 curElt->nchars = elt->len;
608                 curElt->chars = curGlyph;
609 
610                 memcpy(curGlyph, buffer, size * elt->len);
611                 curGlyph += size * elt->len;
612 
613                 curElt++;
614 
615                 space = size * elt->len;
616                 if (space & 3)
617                     space += 4 - (space & 3);
618                 buffer += space;
619             }
620         }
621 
622         switch (stuff->renderReqType) {
623         case X_RenderCompositeGlyphs8:
624             XRenderCompositeText8(dmxScreen->beDisplay, stuff->op,
625                                   pSrcPriv->pict, pDstPriv->pict,
626                                   pFormat,
627                                   stuff->xSrc, stuff->ySrc, 0, 0, elts, nelt);
628             break;
629         case X_RenderCompositeGlyphs16:
630             XRenderCompositeText16(dmxScreen->beDisplay, stuff->op,
631                                    pSrcPriv->pict, pDstPriv->pict,
632                                    pFormat,
633                                    stuff->xSrc, stuff->ySrc,
634                                    0, 0, (XGlyphElt16 *) elts, nelt);
635             break;
636         case X_RenderCompositeGlyphs32:
637             XRenderCompositeText32(dmxScreen->beDisplay, stuff->op,
638                                    pSrcPriv->pict, pDstPriv->pict,
639                                    pFormat,
640                                    stuff->xSrc, stuff->ySrc,
641                                    0, 0, (XGlyphElt32 *) elts, nelt);
642             break;
643         }
644 
645         dmxSync(dmxScreen, FALSE);
646 
647         free(elts);
648         free(glyphs);
649     }
650 
651     return ret;
652 }
653 
654 /** Set the picture transform on each screen. */
655 static int
dmxProcRenderSetPictureTransform(ClientPtr client)656 dmxProcRenderSetPictureTransform(ClientPtr client)
657 {
658     DMXScreenInfo *dmxScreen;
659     PicturePtr pPicture;
660     dmxPictPrivPtr pPictPriv;
661     XTransform xform;
662 
663     REQUEST(xRenderSetPictureTransformReq);
664 
665     REQUEST_SIZE_MATCH(xRenderSetPictureTransformReq);
666     VERIFY_PICTURE(pPicture, stuff->picture, client, DixWriteAccess);
667 
668     /* For the following to work with PanoramiX, it assumes that Render
669      * wraps the ProcRenderVector after dmxRenderInit has been called.
670      */
671     dmxScreen = &dmxScreens[pPicture->pDrawable->pScreen->myNum];
672     pPictPriv = DMX_GET_PICT_PRIV(pPicture);
673 
674     if (pPictPriv->pict) {
675         xform.matrix[0][0] = stuff->transform.matrix11;
676         xform.matrix[0][1] = stuff->transform.matrix12;
677         xform.matrix[0][2] = stuff->transform.matrix13;
678         xform.matrix[1][0] = stuff->transform.matrix21;
679         xform.matrix[1][1] = stuff->transform.matrix22;
680         xform.matrix[1][2] = stuff->transform.matrix23;
681         xform.matrix[2][0] = stuff->transform.matrix31;
682         xform.matrix[2][1] = stuff->transform.matrix32;
683         xform.matrix[2][2] = stuff->transform.matrix33;
684 
685         XRenderSetPictureTransform(dmxScreen->beDisplay,
686                                    pPictPriv->pict, &xform);
687         dmxSync(dmxScreen, FALSE);
688     }
689 
690     return dmxSaveRenderVector[stuff->renderReqType] (client);
691 }
692 
693 /** Set the picture filter on each screen. */
694 static int
dmxProcRenderSetPictureFilter(ClientPtr client)695 dmxProcRenderSetPictureFilter(ClientPtr client)
696 {
697     DMXScreenInfo *dmxScreen;
698     PicturePtr pPicture;
699     dmxPictPrivPtr pPictPriv;
700     char *filter;
701     XFixed *params;
702     int nparams;
703 
704     REQUEST(xRenderSetPictureFilterReq);
705 
706     REQUEST_AT_LEAST_SIZE(xRenderSetPictureFilterReq);
707     VERIFY_PICTURE(pPicture, stuff->picture, client, DixWriteAccess);
708 
709     /* For the following to work with PanoramiX, it assumes that Render
710      * wraps the ProcRenderVector after dmxRenderInit has been called.
711      */
712     dmxScreen = &dmxScreens[pPicture->pDrawable->pScreen->myNum];
713     pPictPriv = DMX_GET_PICT_PRIV(pPicture);
714 
715     if (pPictPriv->pict) {
716         filter = (char *) (stuff + 1);
717         params = (XFixed *) (filter + ((stuff->nbytes + 3) & ~3));
718         nparams = ((XFixed *) stuff + client->req_len) - params;
719         if (nparams < 0)
720             return BadLength;
721 
722         XRenderSetPictureFilter(dmxScreen->beDisplay,
723                                 pPictPriv->pict, filter, params, nparams);
724         dmxSync(dmxScreen, FALSE);
725     }
726 
727     return dmxSaveRenderVector[stuff->renderReqType] (client);
728 }
729 
730 /** Create a picture on the appropriate screen.  This is the actual
731  *  function that creates the picture.  However, if the associated
732  *  window has not yet been created due to lazy window creation, then
733  *  delay the picture creation until the window is mapped. */
734 static Picture
dmxDoCreatePicture(PicturePtr pPicture)735 dmxDoCreatePicture(PicturePtr pPicture)
736 {
737     DrawablePtr pDraw = pPicture->pDrawable;
738     ScreenPtr pScreen = pDraw->pScreen;
739     DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
740     XRenderPictFormat *pFormat;
741     Drawable draw;
742 
743     if (pPicture->pDrawable->type == DRAWABLE_WINDOW) {
744         dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV((WindowPtr) (pDraw));
745 
746         if (!(draw = pWinPriv->window)) {
747             /* Window has not been created yet due to the window
748              * optimization.  Delay picture creation until window is
749              * mapped.
750              */
751             pWinPriv->hasPict = TRUE;
752             return 0;
753         }
754     }
755     else {
756         dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV((PixmapPtr) (pDraw));
757 
758         if (!(draw = pPixPriv->pixmap)) {
759             /* FIXME: Zero width/height pixmap?? */
760             return 0;
761         }
762     }
763 
764     /* This should not be reached if the back-end display has been
765      * detached because the pWinPriv->window or the pPixPriv->pixmap
766      * will be NULL; however, we add it here for completeness
767      */
768     if (!dmxScreen->beDisplay)
769         return 0;
770 
771     pFormat = dmxFindFormat(dmxScreen, pPicture->pFormat);
772 
773     return XRenderCreatePicture(dmxScreen->beDisplay, draw, pFormat, 0, 0);
774 }
775 
776 /** Create a list of pictures.  This function is called by
777  *  dmxCreateAndRealizeWindow() during the lazy window creation
778  *  realization process.  It creates the entire list of pictures that
779  *  are associated with the given window. */
780 void
dmxCreatePictureList(WindowPtr pWindow)781 dmxCreatePictureList(WindowPtr pWindow)
782 {
783     PicturePtr pPicture = GetPictureWindow(pWindow);
784 
785     while (pPicture) {
786         dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
787 
788         /* Create the picture for this window */
789         pPictPriv->pict = dmxDoCreatePicture(pPicture);
790 
791         /* ValidatePicture takes care of the state changes */
792 
793         pPicture = pPicture->pNext;
794     }
795 }
796 
797 /** Create \a pPicture on the backend. */
798 int
dmxBECreatePicture(PicturePtr pPicture)799 dmxBECreatePicture(PicturePtr pPicture)
800 {
801     dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
802 
803     /* Create picutre on BE */
804     pPictPriv->pict = dmxDoCreatePicture(pPicture);
805 
806     /* Flush changes to the backend server */
807     dmxValidatePicture(pPicture, (1 << (CPLastBit + 1)) - 1);
808 
809     return Success;
810 }
811 
812 /** Create a picture.  This function handles the CreatePicture
813  *  unwrapping/wrapping and calls dmxDoCreatePicture to actually create
814  *  the picture on the appropriate screen.  */
815 int
dmxCreatePicture(PicturePtr pPicture)816 dmxCreatePicture(PicturePtr pPicture)
817 {
818     ScreenPtr pScreen = pPicture->pDrawable->pScreen;
819     DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
820     PictureScreenPtr ps = GetPictureScreen(pScreen);
821     dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
822     int ret = Success;
823 
824     DMX_UNWRAP(CreatePicture, dmxScreen, ps);
825 #if 1
826     if (ps->CreatePicture)
827         ret = ps->CreatePicture(pPicture);
828 #endif
829 
830     /* Create picture on back-end server */
831     pPictPriv->pict = dmxDoCreatePicture(pPicture);
832     pPictPriv->savedMask = 0;
833 
834     DMX_WRAP(CreatePicture, dmxCreatePicture, dmxScreen, ps);
835 
836     return ret;
837 }
838 
839 /** Destroy \a pPicture on the back-end server. */
840 Bool
dmxBEFreePicture(PicturePtr pPicture)841 dmxBEFreePicture(PicturePtr pPicture)
842 {
843     ScreenPtr pScreen = pPicture->pDrawable->pScreen;
844     DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
845     dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
846 
847     if (pPictPriv->pict) {
848         XRenderFreePicture(dmxScreen->beDisplay, pPictPriv->pict);
849         pPictPriv->pict = (Picture) 0;
850         return TRUE;
851     }
852 
853     return FALSE;
854 }
855 
856 /** Destroy a list of pictures that are associated with the window that
857  *  is being destroyed.  This function is called by #dmxDestroyWindow().
858  *  */
859 Bool
dmxDestroyPictureList(WindowPtr pWindow)860 dmxDestroyPictureList(WindowPtr pWindow)
861 {
862     PicturePtr pPicture = GetPictureWindow(pWindow);
863     Bool ret = FALSE;
864 
865     while (pPicture) {
866         ret |= dmxBEFreePicture(pPicture);
867         pPicture = pPicture->pNext;
868     }
869 
870     return ret;
871 }
872 
873 /** Destroy a picture.  This function calls the wrapped function that
874  *  frees the resources in the DMX server associated with this
875  *  picture. */
876 void
dmxDestroyPicture(PicturePtr pPicture)877 dmxDestroyPicture(PicturePtr pPicture)
878 {
879     ScreenPtr pScreen = pPicture->pDrawable->pScreen;
880     DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
881     PictureScreenPtr ps = GetPictureScreen(pScreen);
882 
883     DMX_UNWRAP(DestroyPicture, dmxScreen, ps);
884 
885     /* Destroy picture on back-end server */
886     if (dmxBEFreePicture(pPicture))
887         dmxSync(dmxScreen, FALSE);
888 
889 #if 1
890     if (ps->DestroyPicture)
891         ps->DestroyPicture(pPicture);
892 #endif
893     DMX_WRAP(DestroyPicture, dmxDestroyPicture, dmxScreen, ps);
894 }
895 
896 /** Change the picture's list of clip rectangles. */
897 int
dmxChangePictureClip(PicturePtr pPicture,int clipType,void * value,int n)898 dmxChangePictureClip(PicturePtr pPicture, int clipType, void *value, int n)
899 {
900     ScreenPtr pScreen = pPicture->pDrawable->pScreen;
901     DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
902     PictureScreenPtr ps = GetPictureScreen(pScreen);
903     dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
904 
905     DMX_UNWRAP(ChangePictureClip, dmxScreen, ps);
906 #if 1
907     if (ps->ChangePictureClip)
908         ps->ChangePictureClip(pPicture, clipType, value, n);
909 #endif
910 
911     /* Change picture clip rects on back-end server */
912     if (pPictPriv->pict) {
913         /* The clip has already been changed into a region by the mi
914          * routine called above.
915          */
916         if (clipType == CT_NONE) {
917             /* Disable clipping, show all */
918             XFixesSetPictureClipRegion(dmxScreen->beDisplay,
919                                        pPictPriv->pict, 0, 0, None);
920         }
921         else if (pPicture->clientClip) {
922             RegionPtr pClip = pPicture->clientClip;
923             BoxPtr pBox = RegionRects(pClip);
924             int nBox = RegionNumRects(pClip);
925             XRectangle *pRects;
926             XRectangle *pRect;
927             int nRects;
928 
929             nRects = nBox;
930             pRects = pRect = xallocarray(nRects, sizeof(*pRect));
931 
932             while (nBox--) {
933                 pRect->x = pBox->x1;
934                 pRect->y = pBox->y1;
935                 pRect->width = pBox->x2 - pBox->x1;
936                 pRect->height = pBox->y2 - pBox->y1;
937                 pBox++;
938                 pRect++;
939             }
940 
941             XRenderSetPictureClipRectangles(dmxScreen->beDisplay,
942                                             pPictPriv->pict,
943                                             0, 0, pRects, nRects);
944             free(pRects);
945         }
946         else {
947             XRenderSetPictureClipRectangles(dmxScreen->beDisplay,
948                                             pPictPriv->pict, 0, 0, NULL, 0);
949         }
950         dmxSync(dmxScreen, FALSE);
951     }
952     else {
953         /* FIXME: Handle saving clip region when offscreen */
954     }
955 
956     DMX_WRAP(ChangePictureClip, dmxChangePictureClip, dmxScreen, ps);
957 
958     return Success;
959 }
960 
961 /** Destroy the picture's list of clip rectangles. */
962 void
dmxDestroyPictureClip(PicturePtr pPicture)963 dmxDestroyPictureClip(PicturePtr pPicture)
964 {
965     ScreenPtr pScreen = pPicture->pDrawable->pScreen;
966     DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
967     PictureScreenPtr ps = GetPictureScreen(pScreen);
968     dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
969 
970     DMX_UNWRAP(DestroyPictureClip, dmxScreen, ps);
971 #if 1
972     if (ps->DestroyPictureClip)
973         ps->DestroyPictureClip(pPicture);
974 #endif
975 
976     /* Destroy picture clip rects on back-end server */
977     if (pPictPriv->pict) {
978         XRenderSetPictureClipRectangles(dmxScreen->beDisplay,
979                                         pPictPriv->pict, 0, 0, NULL, 0);
980         dmxSync(dmxScreen, FALSE);
981     }
982     else {
983         /* FIXME: Handle destroying clip region when offscreen */
984     }
985 
986     DMX_WRAP(DestroyPictureClip, dmxDestroyPictureClip, dmxScreen, ps);
987 }
988 
989 /** Change the attributes of the pictures.  If the picture has not yet
990  *  been created due to lazy window creation, save the mask so that it
991  *  can be used to appropriately initialize the picture's attributes
992  *  when it is created later. */
993 void
dmxChangePicture(PicturePtr pPicture,Mask mask)994 dmxChangePicture(PicturePtr pPicture, Mask mask)
995 {
996     ScreenPtr pScreen = pPicture->pDrawable->pScreen;
997     DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
998     PictureScreenPtr ps = GetPictureScreen(pScreen);
999     dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
1000 
1001     DMX_UNWRAP(ChangePicture, dmxScreen, ps);
1002 #if 1
1003     if (ps->ChangePicture)
1004         ps->ChangePicture(pPicture, mask);
1005 #endif
1006 
1007     /* Picture attribute changes are handled in ValidatePicture */
1008     pPictPriv->savedMask |= mask;
1009 
1010     DMX_WRAP(ChangePicture, dmxChangePicture, dmxScreen, ps);
1011 }
1012 
1013 /** Validate the picture's attributes before rendering to it.  Update
1014  *  any picture attributes that have been changed by one of the higher
1015  *  layers. */
1016 void
dmxValidatePicture(PicturePtr pPicture,Mask mask)1017 dmxValidatePicture(PicturePtr pPicture, Mask mask)
1018 {
1019     ScreenPtr pScreen = pPicture->pDrawable->pScreen;
1020     DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
1021     PictureScreenPtr ps = GetPictureScreen(pScreen);
1022     dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
1023 
1024     DMX_UNWRAP(ValidatePicture, dmxScreen, ps);
1025 
1026     /* Change picture attributes on back-end server */
1027     if (pPictPriv->pict) {
1028         XRenderPictureAttributes attribs;
1029 
1030         if (mask & CPRepeat) {
1031             attribs.repeat = pPicture->repeatType;
1032         }
1033         if (mask & CPAlphaMap) {
1034             if (pPicture->alphaMap) {
1035                 dmxPictPrivPtr pAlphaPriv;
1036 
1037                 pAlphaPriv = DMX_GET_PICT_PRIV(pPicture->alphaMap);
1038                 if (pAlphaPriv->pict) {
1039                     attribs.alpha_map = pAlphaPriv->pict;
1040                 }
1041                 else {
1042                     /* FIXME: alpha picture drawable has not been created?? */
1043                     return;     /* or should this be: attribs.alpha_map = None; */
1044                 }
1045             }
1046             else {
1047                 attribs.alpha_map = None;
1048             }
1049         }
1050         if (mask & CPAlphaXOrigin)
1051             attribs.alpha_x_origin = pPicture->alphaOrigin.x;
1052         if (mask & CPAlphaYOrigin)
1053             attribs.alpha_y_origin = pPicture->alphaOrigin.y;
1054         if (mask & CPClipXOrigin)
1055             attribs.clip_x_origin = pPicture->clipOrigin.x;
1056         if (mask & CPClipYOrigin)
1057             attribs.clip_y_origin = pPicture->clipOrigin.y;
1058         if (mask & CPClipMask)
1059             mask &= ~CPClipMask;        /* Handled in ChangePictureClip */
1060         if (mask & CPGraphicsExposure)
1061             attribs.graphics_exposures = pPicture->graphicsExposures;
1062         if (mask & CPSubwindowMode)
1063             attribs.subwindow_mode = pPicture->subWindowMode;
1064         if (mask & CPPolyEdge)
1065             attribs.poly_edge = pPicture->polyEdge;
1066         if (mask & CPPolyMode)
1067             attribs.poly_mode = pPicture->polyMode;
1068         if (mask & CPComponentAlpha)
1069             attribs.component_alpha = pPicture->componentAlpha;
1070 
1071         XRenderChangePicture(dmxScreen->beDisplay, pPictPriv->pict,
1072                              mask, &attribs);
1073         dmxSync(dmxScreen, FALSE);
1074     }
1075     else {
1076         pPictPriv->savedMask |= mask;
1077     }
1078 
1079 #if 1
1080     if (ps->ValidatePicture)
1081         ps->ValidatePicture(pPicture, mask);
1082 #endif
1083 
1084     DMX_WRAP(ValidatePicture, dmxValidatePicture, dmxScreen, ps);
1085 }
1086 
1087 /** Composite a picture on the appropriate screen by combining the
1088  *  specified rectangle of the transformed src and mask operands with
1089  *  the specified rectangle of the dst using op as the compositing
1090  *  operator.  For a complete description see the protocol document of
1091  *  the RENDER library. */
1092 void
dmxComposite(CARD8 op,PicturePtr pSrc,PicturePtr pMask,PicturePtr pDst,INT16 xSrc,INT16 ySrc,INT16 xMask,INT16 yMask,INT16 xDst,INT16 yDst,CARD16 width,CARD16 height)1093 dmxComposite(CARD8 op,
1094              PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
1095              INT16 xSrc, INT16 ySrc,
1096              INT16 xMask, INT16 yMask,
1097              INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
1098 {
1099     ScreenPtr pScreen = pDst->pDrawable->pScreen;
1100     DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
1101     PictureScreenPtr ps = GetPictureScreen(pScreen);
1102     dmxPictPrivPtr pSrcPriv = DMX_GET_PICT_PRIV(pSrc);
1103     dmxPictPrivPtr pMaskPriv = NULL;
1104     dmxPictPrivPtr pDstPriv = DMX_GET_PICT_PRIV(pDst);
1105 
1106     if (pMask)
1107         pMaskPriv = DMX_GET_PICT_PRIV(pMask);
1108 
1109     DMX_UNWRAP(Composite, dmxScreen, ps);
1110 #if 0
1111     if (ps->Composite)
1112         ps->Composite(op, pSrc, pMask, pDst,
1113                       xSrc, ySrc, xMask, yMask, xDst, yDst, width, height);
1114 #endif
1115 
1116     /* Composite on back-end server */
1117     if (pSrcPriv->pict && pDstPriv->pict &&
1118         ((pMaskPriv && pMaskPriv->pict) || !pMaskPriv)) {
1119         XRenderComposite(dmxScreen->beDisplay,
1120                          op,
1121                          pSrcPriv->pict,
1122                          pMaskPriv ? pMaskPriv->pict : None,
1123                          pDstPriv->pict,
1124                          xSrc, ySrc, xMask, yMask, xDst, yDst, width, height);
1125         dmxSync(dmxScreen, FALSE);
1126     }
1127 
1128     DMX_WRAP(Composite, dmxComposite, dmxScreen, ps);
1129 }
1130 
1131 /** Null function to catch when/if RENDER calls lower level mi hooks.
1132  *  Compositing glyphs is handled by dmxProcRenderCompositeGlyphs().
1133  *  This function should never be called. */
1134 void
dmxGlyphs(CARD8 op,PicturePtr pSrc,PicturePtr pDst,PictFormatPtr maskFormat,INT16 xSrc,INT16 ySrc,int nlists,GlyphListPtr lists,GlyphPtr * glyphs)1135 dmxGlyphs(CARD8 op,
1136           PicturePtr pSrc, PicturePtr pDst,
1137           PictFormatPtr maskFormat,
1138           INT16 xSrc, INT16 ySrc,
1139           int nlists, GlyphListPtr lists, GlyphPtr * glyphs)
1140 {
1141     /* This won't work, so we need to wrap ProcRenderCompositeGlyphs */
1142 }
1143 
1144 /** Fill a rectangle on the appropriate screen by combining the color
1145  *  with the dest picture in the area specified by the list of
1146  *  rectangles.  For a complete description see the protocol document of
1147  *  the RENDER library. */
1148 void
dmxCompositeRects(CARD8 op,PicturePtr pDst,xRenderColor * color,int nRect,xRectangle * rects)1149 dmxCompositeRects(CARD8 op,
1150                   PicturePtr pDst,
1151                   xRenderColor * color, int nRect, xRectangle *rects)
1152 {
1153     ScreenPtr pScreen = pDst->pDrawable->pScreen;
1154     DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
1155     PictureScreenPtr ps = GetPictureScreen(pScreen);
1156     dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pDst);
1157 
1158     DMX_UNWRAP(CompositeRects, dmxScreen, ps);
1159 #if 0
1160     if (ps->CompositeRects)
1161         ps->CompositeRects(op, pDst, color, nRect, rects);
1162 #endif
1163 
1164     /* CompositeRects on back-end server */
1165     if (pPictPriv->pict) {
1166         XRenderFillRectangles(dmxScreen->beDisplay,
1167                               op,
1168                               pPictPriv->pict,
1169                               (XRenderColor *) color,
1170                               (XRectangle *) rects, nRect);
1171         dmxSync(dmxScreen, FALSE);
1172     }
1173 
1174     DMX_WRAP(CompositeRects, dmxCompositeRects, dmxScreen, ps);
1175 }
1176 
1177 /** Indexed color visuals are not yet supported. */
1178 Bool
dmxInitIndexed(ScreenPtr pScreen,PictFormatPtr pFormat)1179 dmxInitIndexed(ScreenPtr pScreen, PictFormatPtr pFormat)
1180 {
1181     return TRUE;
1182 }
1183 
1184 /** Indexed color visuals are not yet supported. */
1185 void
dmxCloseIndexed(ScreenPtr pScreen,PictFormatPtr pFormat)1186 dmxCloseIndexed(ScreenPtr pScreen, PictFormatPtr pFormat)
1187 {
1188 }
1189 
1190 /** Indexed color visuals are not yet supported. */
1191 void
dmxUpdateIndexed(ScreenPtr pScreen,PictFormatPtr pFormat,int ndef,xColorItem * pdef)1192 dmxUpdateIndexed(ScreenPtr pScreen, PictFormatPtr pFormat,
1193                  int ndef, xColorItem * pdef)
1194 {
1195 }
1196 
1197 /** Composite a list of trapezoids on the appropriate screen.  For a
1198  *  complete description see the protocol document of the RENDER
1199  *  library. */
1200 void
dmxTrapezoids(CARD8 op,PicturePtr pSrc,PicturePtr pDst,PictFormatPtr maskFormat,INT16 xSrc,INT16 ySrc,int ntrap,xTrapezoid * traps)1201 dmxTrapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
1202               PictFormatPtr maskFormat,
1203               INT16 xSrc, INT16 ySrc, int ntrap, xTrapezoid * traps)
1204 {
1205     ScreenPtr pScreen = pDst->pDrawable->pScreen;
1206     DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
1207     PictureScreenPtr ps = GetPictureScreen(pScreen);
1208     dmxPictPrivPtr pSrcPriv = DMX_GET_PICT_PRIV(pSrc);
1209     dmxPictPrivPtr pDstPriv = DMX_GET_PICT_PRIV(pDst);
1210 
1211     DMX_UNWRAP(Trapezoids, dmxScreen, ps);
1212 #if 0
1213     if (ps->Trapezoids)
1214         ps->Trapezoids(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntrap, *traps);
1215 #endif
1216 
1217     /* Draw trapezoids on back-end server */
1218     if (pDstPriv->pict) {
1219         XRenderPictFormat *pFormat;
1220 
1221         pFormat = dmxFindFormat(dmxScreen, maskFormat);
1222         if (!pFormat) {
1223             /* FIXME: Error! */
1224         }
1225 
1226         XRenderCompositeTrapezoids(dmxScreen->beDisplay,
1227                                    op,
1228                                    pSrcPriv->pict,
1229                                    pDstPriv->pict,
1230                                    pFormat,
1231                                    xSrc, ySrc, (XTrapezoid *) traps, ntrap);
1232         dmxSync(dmxScreen, FALSE);
1233     }
1234 
1235     DMX_WRAP(Trapezoids, dmxTrapezoids, dmxScreen, ps);
1236 }
1237 
1238 /** Composite a list of triangles on the appropriate screen.  For a
1239  *  complete description see the protocol document of the RENDER
1240  *  library. */
1241 void
dmxTriangles(CARD8 op,PicturePtr pSrc,PicturePtr pDst,PictFormatPtr maskFormat,INT16 xSrc,INT16 ySrc,int ntri,xTriangle * tris)1242 dmxTriangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
1243              PictFormatPtr maskFormat,
1244              INT16 xSrc, INT16 ySrc, int ntri, xTriangle * tris)
1245 {
1246     ScreenPtr pScreen = pDst->pDrawable->pScreen;
1247     DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
1248     PictureScreenPtr ps = GetPictureScreen(pScreen);
1249     dmxPictPrivPtr pSrcPriv = DMX_GET_PICT_PRIV(pSrc);
1250     dmxPictPrivPtr pDstPriv = DMX_GET_PICT_PRIV(pDst);
1251 
1252     DMX_UNWRAP(Triangles, dmxScreen, ps);
1253 #if 0
1254     if (ps->Triangles)
1255         ps->Triangles(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, *tris);
1256 #endif
1257 
1258     /* Draw trapezoids on back-end server */
1259     if (pDstPriv->pict) {
1260         XRenderPictFormat *pFormat;
1261 
1262         pFormat = dmxFindFormat(dmxScreen, maskFormat);
1263         if (!pFormat) {
1264             /* FIXME: Error! */
1265         }
1266 
1267         XRenderCompositeTriangles(dmxScreen->beDisplay,
1268                                   op,
1269                                   pSrcPriv->pict,
1270                                   pDstPriv->pict,
1271                                   pFormat,
1272                                   xSrc, ySrc, (XTriangle *) tris, ntri);
1273         dmxSync(dmxScreen, FALSE);
1274     }
1275 
1276     DMX_WRAP(Triangles, dmxTriangles, dmxScreen, ps);
1277 }
1278