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