2 * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina.
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:
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.
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
30 * Kevin E. Martin <kem@redhat.com>
35 * Provide support for the RENDER extension (version 0.8).
38 #ifdef HAVE_DMX_CONFIG_H
39 #include <dmx-config.h>
45 #include "dmxwindow.h"
46 #include "dmxpixmap.h"
49 #include "pixmapstr.h"
50 #include "dixstruct.h"
52 #include <X11/extensions/render.h>
53 #include <X11/extensions/renderproto.h>
54 #include <X11/extensions/Xfixes.h>
56 #include "picturestr.h"
60 extern int RenderErrBase;
61 extern int (*ProcRenderVector[RenderNumberRequests]) (ClientPtr);
63 static int (*dmxSaveRenderVector[RenderNumberRequests]) (ClientPtr);
65 static int dmxProcRenderCreateGlyphSet(ClientPtr client);
66 static int dmxProcRenderFreeGlyphSet(ClientPtr client);
67 static int dmxProcRenderAddGlyphs(ClientPtr client);
68 static int dmxProcRenderFreeGlyphs(ClientPtr client);
69 static int dmxProcRenderCompositeGlyphs(ClientPtr client);
70 static int dmxProcRenderSetPictureTransform(ClientPtr client);
71 static int dmxProcRenderSetPictureFilter(ClientPtr client);
74 /* FIXME: Not (yet) supported */
75 static int dmxProcRenderCreateCursor(ClientPtr client);
76 static int dmxProcRenderCreateAnimCursor(ClientPtr client);
79 /** Catch errors that might occur when allocating Glyph Sets. Errors
80 * are saved in dmxGlyphLastError for later handling. */
81 static int dmxGlyphLastError;
83 dmxGlyphErrorHandler(Display * dpy, XErrorEvent * ev)
85 dmxGlyphLastError = ev->error_code;
89 /** Initialize the Proc Vector for the RENDER extension. The functions
90 * here cannot be handled by the mi layer RENDER hooks either because
91 * the required information is no longer available when it reaches the
92 * mi layer or no mi layer hooks exist. This function is called from
93 * InitOutput() since it should be initialized only once per server
100 for (i = 0; i < RenderNumberRequests; i++)
101 dmxSaveRenderVector[i] = ProcRenderVector[i];
103 ProcRenderVector[X_RenderCreateGlyphSet]
104 = dmxProcRenderCreateGlyphSet;
105 ProcRenderVector[X_RenderFreeGlyphSet]
106 = dmxProcRenderFreeGlyphSet;
107 ProcRenderVector[X_RenderAddGlyphs]
108 = dmxProcRenderAddGlyphs;
109 ProcRenderVector[X_RenderFreeGlyphs]
110 = dmxProcRenderFreeGlyphs;
111 ProcRenderVector[X_RenderCompositeGlyphs8]
112 = dmxProcRenderCompositeGlyphs;
113 ProcRenderVector[X_RenderCompositeGlyphs16]
114 = dmxProcRenderCompositeGlyphs;
115 ProcRenderVector[X_RenderCompositeGlyphs32]
116 = dmxProcRenderCompositeGlyphs;
117 ProcRenderVector[X_RenderSetPictureTransform]
118 = dmxProcRenderSetPictureTransform;
119 ProcRenderVector[X_RenderSetPictureFilter]
120 = dmxProcRenderSetPictureFilter;
123 /** Reset the Proc Vector for the RENDER extension back to the original
124 * functions. This function is called from dmxCloseScreen() during the
125 * server reset (only for screen #0). */
131 for (i = 0; i < RenderNumberRequests; i++)
132 ProcRenderVector[i] = dmxSaveRenderVector[i];
135 /** Initialize the RENDER extension, allocate the picture privates and
136 * wrap mi function hooks. If the shadow frame buffer is used, then
137 * call the appropriate fb initialization function. */
139 dmxPictureInit(ScreenPtr pScreen, PictFormatPtr formats, int nformats)
141 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
144 if (!miPictureInit(pScreen, formats, nformats))
147 if (!dixRegisterPrivateKey
148 (&dmxPictPrivateKeyRec, PRIVATE_PICTURE, sizeof(dmxPictPrivRec)))
151 ps = GetPictureScreen(pScreen);
153 DMX_WRAP(CreatePicture, dmxCreatePicture, dmxScreen, ps);
154 DMX_WRAP(DestroyPicture, dmxDestroyPicture, dmxScreen, ps);
156 DMX_WRAP(ChangePictureClip, dmxChangePictureClip, dmxScreen, ps);
157 DMX_WRAP(DestroyPictureClip, dmxDestroyPictureClip, dmxScreen, ps);
159 DMX_WRAP(ChangePicture, dmxChangePicture, dmxScreen, ps);
160 DMX_WRAP(ValidatePicture, dmxValidatePicture, dmxScreen, ps);
162 DMX_WRAP(Composite, dmxComposite, dmxScreen, ps);
163 DMX_WRAP(Glyphs, dmxGlyphs, dmxScreen, ps);
164 DMX_WRAP(CompositeRects, dmxCompositeRects, dmxScreen, ps);
166 DMX_WRAP(Trapezoids, dmxTrapezoids, dmxScreen, ps);
167 DMX_WRAP(Triangles, dmxTriangles, dmxScreen, ps);
172 /** Find the appropriate format on the requested screen given the
173 * internal format requested. The list of formats is searched
174 * sequentially as the XRenderFindFormat() function does not always
175 * find the appropriate format when a specific format is requested. */
176 static XRenderPictFormat *
177 dmxFindFormat(DMXScreenInfo * dmxScreen, PictFormatPtr pFmt)
179 XRenderPictFormat *pFormat = NULL;
182 if (!pFmt || !dmxScreen->beDisplay)
186 pFormat = XRenderFindFormat(dmxScreen->beDisplay, 0, 0, i++);
190 if (pFormat->type != pFmt->type)
192 if (pFormat->depth != pFmt->depth)
194 if (pFormat->direct.red != pFmt->direct.red)
196 if (pFormat->direct.redMask != pFmt->direct.redMask)
198 if (pFormat->direct.green != pFmt->direct.green)
200 if (pFormat->direct.greenMask != pFmt->direct.greenMask)
202 if (pFormat->direct.blue != pFmt->direct.blue)
204 if (pFormat->direct.blueMask != pFmt->direct.blueMask)
206 if (pFormat->direct.alpha != pFmt->direct.alpha)
208 if (pFormat->direct.alphaMask != pFmt->direct.alphaMask)
211 /* We have a match! */
218 /** Free \a glyphSet on back-end screen number \a idx. */
220 dmxBEFreeGlyphSet(ScreenPtr pScreen, GlyphSetPtr glyphSet)
222 dmxGlyphPrivPtr glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
223 int idx = pScreen->myNum;
224 DMXScreenInfo *dmxScreen = &dmxScreens[idx];
226 if (glyphPriv->glyphSets[idx]) {
227 XRenderFreeGlyphSet(dmxScreen->beDisplay, glyphPriv->glyphSets[idx]);
228 glyphPriv->glyphSets[idx] = (GlyphSet) 0;
235 /** Create \a glyphSet on the backend screen number \a idx. */
237 dmxBECreateGlyphSet(int idx, GlyphSetPtr glyphSet)
239 XRenderPictFormat *pFormat;
240 DMXScreenInfo *dmxScreen = &dmxScreens[idx];
241 dmxGlyphPrivPtr glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
242 PictFormatPtr pFmt = glyphSet->format;
243 int (*oldErrorHandler) (Display *, XErrorEvent *);
245 pFormat = dmxFindFormat(dmxScreen, pFmt);
250 dmxGlyphLastError = 0;
251 oldErrorHandler = XSetErrorHandler(dmxGlyphErrorHandler);
253 /* Catch when this fails */
254 glyphPriv->glyphSets[idx]
255 = XRenderCreateGlyphSet(dmxScreen->beDisplay, pFormat);
257 XSetErrorHandler(oldErrorHandler);
259 if (dmxGlyphLastError) {
260 return dmxGlyphLastError;
266 /** Create a Glyph Set on each screen. Save the glyphset ID from each
267 * screen in the Glyph Set's private structure. Fail if the format
268 * requested is not available or if the Glyph Set cannot be created on
271 dmxProcRenderCreateGlyphSet(ClientPtr client)
275 REQUEST(xRenderCreateGlyphSetReq);
277 ret = dmxSaveRenderVector[stuff->renderReqType] (client);
279 if (ret == Success) {
280 GlyphSetPtr glyphSet;
281 dmxGlyphPrivPtr glyphPriv;
284 /* Look up glyphSet that was just created ???? */
285 /* Store glyphsets from backends in glyphSet->devPrivate ????? */
286 /* Make sure we handle all errors here!! */
288 dixLookupResourceByType((void **) &glyphSet,
289 stuff->gsid, GlyphSetType,
290 client, DixDestroyAccess);
292 glyphPriv = malloc(sizeof(dmxGlyphPrivRec));
295 glyphPriv->glyphSets = NULL;
296 MAXSCREENSALLOC_RETURN(glyphPriv->glyphSets, BadAlloc);
297 DMX_SET_GLYPH_PRIV(glyphSet, glyphPriv);
299 for (i = 0; i < dmxNumScreens; i++) {
300 DMXScreenInfo *dmxScreen = &dmxScreens[i];
303 if (!dmxScreen->beDisplay) {
304 glyphPriv->glyphSets[i] = 0;
308 if ((beret = dmxBECreateGlyphSet(i, glyphSet)) != Success) {
311 /* Free the glyph sets we've allocated thus far */
312 for (j = 0; j < i; j++)
313 dmxBEFreeGlyphSet(screenInfo.screens[j], glyphSet);
315 /* Free the resource created by render */
316 FreeResource(stuff->gsid, RT_NONE);
326 /** Free the previously allocated Glyph Sets for each screen. */
328 dmxProcRenderFreeGlyphSet(ClientPtr client)
330 GlyphSetPtr glyphSet;
332 REQUEST(xRenderFreeGlyphSetReq);
334 REQUEST_SIZE_MATCH(xRenderFreeGlyphSetReq);
335 dixLookupResourceByType((void **) &glyphSet,
336 stuff->glyphset, GlyphSetType,
337 client, DixDestroyAccess);
339 if (glyphSet && glyphSet->refcnt == 1) {
340 dmxGlyphPrivPtr glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
343 for (i = 0; i < dmxNumScreens; i++) {
344 DMXScreenInfo *dmxScreen = &dmxScreens[i];
346 if (dmxScreen->beDisplay) {
347 if (dmxBEFreeGlyphSet(screenInfo.screens[i], glyphSet))
348 dmxSync(dmxScreen, FALSE);
352 MAXSCREENSFREE(glyphPriv->glyphSets);
354 DMX_SET_GLYPH_PRIV(glyphSet, NULL);
357 return dmxSaveRenderVector[stuff->renderReqType] (client);
360 /** Add glyphs to the Glyph Set on each screen. */
362 dmxProcRenderAddGlyphs(ClientPtr client)
366 REQUEST(xRenderAddGlyphsReq);
368 ret = dmxSaveRenderVector[stuff->renderReqType] (client);
370 if (ret == Success) {
371 GlyphSetPtr glyphSet;
372 dmxGlyphPrivPtr glyphPriv;
381 dixLookupResourceByType((void **) &glyphSet,
382 stuff->glyphset, GlyphSetType,
383 client, DixReadAccess);
384 glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
386 nglyphs = stuff->nglyphs;
387 gids = (CARD32 *) (stuff + 1);
388 gi = (xGlyphInfo *) (gids + nglyphs);
389 bits = (CARD8 *) (gi + nglyphs);
390 nbytes = ((stuff->length << 2) -
391 sizeof(xRenderAddGlyphsReq) -
392 (sizeof(CARD32) + sizeof(xGlyphInfo)) * nglyphs);
394 gidsCopy = malloc(sizeof(*gidsCopy) * nglyphs);
395 for (i = 0; i < nglyphs; i++)
396 gidsCopy[i] = gids[i];
398 /* FIXME: Will this ever fail? */
399 for (i = 0; i < dmxNumScreens; i++) {
400 DMXScreenInfo *dmxScreen = &dmxScreens[i];
402 if (dmxScreen->beDisplay) {
403 XRenderAddGlyphs(dmxScreen->beDisplay,
404 glyphPriv->glyphSets[i],
407 nglyphs, (char *) bits, nbytes);
408 dmxSync(dmxScreen, FALSE);
417 /** Free glyphs from the Glyph Set for each screen. */
419 dmxProcRenderFreeGlyphs(ClientPtr client)
421 GlyphSetPtr glyphSet;
423 REQUEST(xRenderFreeGlyphsReq);
425 REQUEST_AT_LEAST_SIZE(xRenderFreeGlyphsReq);
426 dixLookupResourceByType((void **) &glyphSet,
427 stuff->glyphset, GlyphSetType,
428 client, DixWriteAccess);
431 dmxGlyphPrivPtr glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
436 nglyphs = ((client->req_len << 2) - sizeof(xRenderFreeGlyphsReq)) >> 2;
438 gids = malloc(sizeof(*gids) * nglyphs);
439 for (i = 0; i < nglyphs; i++)
440 gids[i] = ((CARD32 *) (stuff + 1))[i];
442 for (i = 0; i < dmxNumScreens; i++) {
443 DMXScreenInfo *dmxScreen = &dmxScreens[i];
445 if (dmxScreen->beDisplay) {
446 XRenderFreeGlyphs(dmxScreen->beDisplay,
447 glyphPriv->glyphSets[i], gids, nglyphs);
448 dmxSync(dmxScreen, FALSE);
455 return dmxSaveRenderVector[stuff->renderReqType] (client);
458 /** Composite glyphs on each screen into the requested picture. If
459 * either the src or dest picture has not been allocated due to lazy
460 * window creation, this request will gracefully return. */
462 dmxProcRenderCompositeGlyphs(ClientPtr client)
466 REQUEST(xRenderCompositeGlyphsReq);
468 ret = dmxSaveRenderVector[stuff->renderReqType] (client);
470 /* For the following to work with PanoramiX, it assumes that Render
471 * wraps the ProcRenderVector after dmxRenderInit has been called.
473 if (ret == Success) {
475 dmxPictPrivPtr pSrcPriv;
477 dmxPictPrivPtr pDstPriv;
479 XRenderPictFormat *pFormat;
483 DMXScreenInfo *dmxScreen;
498 GlyphSetPtr glyphSet;
499 dmxGlyphPrivPtr glyphPriv;
501 dixLookupResourceByType((void **) &pSrc,
502 stuff->src, PictureType, client, DixReadAccess);
504 pSrcPriv = DMX_GET_PICT_PRIV(pSrc);
508 dixLookupResourceByType((void **) &pDst,
509 stuff->dst, PictureType,
510 client, DixWriteAccess);
512 pDstPriv = DMX_GET_PICT_PRIV(pDst);
516 scrnNum = pDst->pDrawable->pScreen->myNum;
517 dmxScreen = &dmxScreens[scrnNum];
519 /* Note: If the back-end display has been detached, then it
520 * should not be possible to reach here since the pSrcPriv->pict
521 * and pDstPriv->pict will have already been set to 0.
523 if (!dmxScreen->beDisplay)
526 if (stuff->maskFormat)
527 dixLookupResourceByType((void **) &pFmt,
528 stuff->maskFormat, PictFormatType,
529 client, DixReadAccess);
533 pFormat = dmxFindFormat(dmxScreen, pFmt);
535 switch (stuff->renderReqType) {
536 case X_RenderCompositeGlyphs8:
537 size = sizeof(CARD8);
539 case X_RenderCompositeGlyphs16:
540 size = sizeof(CARD16);
542 case X_RenderCompositeGlyphs32:
543 size = sizeof(CARD32);
546 return BadPictOp; /* Can't happen */
549 buffer = (CARD8 *) (stuff + 1);
550 end = (CARD8 *) stuff + (stuff->length << 2);
553 while (buffer + sizeof(xGlyphElt) < end) {
554 elt = (xGlyphElt *) buffer;
555 buffer += sizeof(xGlyphElt);
557 if (elt->len == 0xff) {
563 space = size * elt->len;
565 space += 4 - (space & 3);
570 /* The following only works for Render version > 0.2 */
572 /* All of the XGlyphElt* structure sizes are identical */
573 elts = malloc(nelt * sizeof(XGlyphElt8));
577 glyphs = malloc(nglyph * size);
583 buffer = (CARD8 *) (stuff + 1);
584 end = (CARD8 *) stuff + (stuff->length << 2);
588 dixLookupResourceByType((void **) &glyphSet,
589 stuff->glyphset, GlyphSetType,
590 client, DixReadAccess);
591 glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
593 while (buffer + sizeof(xGlyphElt) < end) {
594 elt = (xGlyphElt *) buffer;
595 buffer += sizeof(xGlyphElt);
597 if (elt->len == 0xff) {
598 dixLookupResourceByType((void **) &glyphSet,
599 *((CARD32 *) buffer),
600 GlyphSetType, client, DixReadAccess);
601 glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
605 curElt->glyphset = glyphPriv->glyphSets[scrnNum];
606 curElt->xOff = elt->deltax;
607 curElt->yOff = elt->deltay;
608 curElt->nchars = elt->len;
609 curElt->chars = curGlyph;
611 memcpy(curGlyph, buffer, size * elt->len);
612 curGlyph += size * elt->len;
616 space = size * elt->len;
618 space += 4 - (space & 3);
623 switch (stuff->renderReqType) {
624 case X_RenderCompositeGlyphs8:
625 XRenderCompositeText8(dmxScreen->beDisplay, stuff->op,
626 pSrcPriv->pict, pDstPriv->pict,
628 stuff->xSrc, stuff->ySrc, 0, 0, elts, nelt);
630 case X_RenderCompositeGlyphs16:
631 XRenderCompositeText16(dmxScreen->beDisplay, stuff->op,
632 pSrcPriv->pict, pDstPriv->pict,
634 stuff->xSrc, stuff->ySrc,
635 0, 0, (XGlyphElt16 *) elts, nelt);
637 case X_RenderCompositeGlyphs32:
638 XRenderCompositeText32(dmxScreen->beDisplay, stuff->op,
639 pSrcPriv->pict, pDstPriv->pict,
641 stuff->xSrc, stuff->ySrc,
642 0, 0, (XGlyphElt32 *) elts, nelt);
646 dmxSync(dmxScreen, FALSE);
655 /** Set the picture transform on each screen. */
657 dmxProcRenderSetPictureTransform(ClientPtr client)
659 DMXScreenInfo *dmxScreen;
661 dmxPictPrivPtr pPictPriv;
664 REQUEST(xRenderSetPictureTransformReq);
666 REQUEST_SIZE_MATCH(xRenderSetPictureTransformReq);
667 VERIFY_PICTURE(pPicture, stuff->picture, client, DixWriteAccess);
669 /* For the following to work with PanoramiX, it assumes that Render
670 * wraps the ProcRenderVector after dmxRenderInit has been called.
672 dmxScreen = &dmxScreens[pPicture->pDrawable->pScreen->myNum];
673 pPictPriv = DMX_GET_PICT_PRIV(pPicture);
675 if (pPictPriv->pict) {
676 xform.matrix[0][0] = stuff->transform.matrix11;
677 xform.matrix[0][1] = stuff->transform.matrix12;
678 xform.matrix[0][2] = stuff->transform.matrix13;
679 xform.matrix[1][0] = stuff->transform.matrix21;
680 xform.matrix[1][1] = stuff->transform.matrix22;
681 xform.matrix[1][2] = stuff->transform.matrix23;
682 xform.matrix[2][0] = stuff->transform.matrix31;
683 xform.matrix[2][1] = stuff->transform.matrix32;
684 xform.matrix[2][2] = stuff->transform.matrix33;
686 XRenderSetPictureTransform(dmxScreen->beDisplay,
687 pPictPriv->pict, &xform);
688 dmxSync(dmxScreen, FALSE);
691 return dmxSaveRenderVector[stuff->renderReqType] (client);
694 /** Set the picture filter on each screen. */
696 dmxProcRenderSetPictureFilter(ClientPtr client)
698 DMXScreenInfo *dmxScreen;
700 dmxPictPrivPtr pPictPriv;
705 REQUEST(xRenderSetPictureFilterReq);
707 REQUEST_AT_LEAST_SIZE(xRenderSetPictureFilterReq);
708 VERIFY_PICTURE(pPicture, stuff->picture, client, DixWriteAccess);
710 /* For the following to work with PanoramiX, it assumes that Render
711 * wraps the ProcRenderVector after dmxRenderInit has been called.
713 dmxScreen = &dmxScreens[pPicture->pDrawable->pScreen->myNum];
714 pPictPriv = DMX_GET_PICT_PRIV(pPicture);
716 if (pPictPriv->pict) {
717 filter = (char *) (stuff + 1);
718 params = (XFixed *) (filter + ((stuff->nbytes + 3) & ~3));
719 nparams = ((XFixed *) stuff + client->req_len) - params;
721 XRenderSetPictureFilter(dmxScreen->beDisplay,
722 pPictPriv->pict, filter, params, nparams);
723 dmxSync(dmxScreen, FALSE);
726 return dmxSaveRenderVector[stuff->renderReqType] (client);
729 /** Create a picture on the appropriate screen. This is the actual
730 * function that creates the picture. However, if the associated
731 * window has not yet been created due to lazy window creation, then
732 * delay the picture creation until the window is mapped. */
734 dmxDoCreatePicture(PicturePtr pPicture)
736 DrawablePtr pDraw = pPicture->pDrawable;
737 ScreenPtr pScreen = pDraw->pScreen;
738 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
739 XRenderPictFormat *pFormat;
742 if (pPicture->pDrawable->type == DRAWABLE_WINDOW) {
743 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV((WindowPtr) (pDraw));
745 if (!(draw = pWinPriv->window)) {
746 /* Window has not been created yet due to the window
747 * optimization. Delay picture creation until window is
750 pWinPriv->hasPict = TRUE;
755 dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV((PixmapPtr) (pDraw));
757 if (!(draw = pPixPriv->pixmap)) {
758 /* FIXME: Zero width/height pixmap?? */
763 /* This should not be reached if the back-end display has been
764 * detached because the pWinPriv->window or the pPixPriv->pixmap
765 * will be NULL; however, we add it here for completeness
767 if (!dmxScreen->beDisplay)
770 pFormat = dmxFindFormat(dmxScreen, pPicture->pFormat);
772 return XRenderCreatePicture(dmxScreen->beDisplay, draw, pFormat, 0, 0);
775 /** Create a list of pictures. This function is called by
776 * dmxCreateAndRealizeWindow() during the lazy window creation
777 * realization process. It creates the entire list of pictures that
778 * are associated with the given window. */
780 dmxCreatePictureList(WindowPtr pWindow)
782 PicturePtr pPicture = GetPictureWindow(pWindow);
785 dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
787 /* Create the picture for this window */
788 pPictPriv->pict = dmxDoCreatePicture(pPicture);
790 /* ValidatePicture takes care of the state changes */
792 pPicture = pPicture->pNext;
796 /** Create \a pPicture on the backend. */
798 dmxBECreatePicture(PicturePtr pPicture)
800 dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
802 /* Create picutre on BE */
803 pPictPriv->pict = dmxDoCreatePicture(pPicture);
805 /* Flush changes to the backend server */
806 dmxValidatePicture(pPicture, (1 << (CPLastBit + 1)) - 1);
811 /** Create a picture. This function handles the CreatePicture
812 * unwrapping/wrapping and calls dmxDoCreatePicture to actually create
813 * the picture on the appropriate screen. */
815 dmxCreatePicture(PicturePtr pPicture)
817 ScreenPtr pScreen = pPicture->pDrawable->pScreen;
818 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
819 PictureScreenPtr ps = GetPictureScreen(pScreen);
820 dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
823 DMX_UNWRAP(CreatePicture, dmxScreen, ps);
825 if (ps->CreatePicture)
826 ret = ps->CreatePicture(pPicture);
829 /* Create picture on back-end server */
830 pPictPriv->pict = dmxDoCreatePicture(pPicture);
831 pPictPriv->savedMask = 0;
833 DMX_WRAP(CreatePicture, dmxCreatePicture, dmxScreen, ps);
838 /** Destroy \a pPicture on the back-end server. */
840 dmxBEFreePicture(PicturePtr pPicture)
842 ScreenPtr pScreen = pPicture->pDrawable->pScreen;
843 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
844 dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
846 if (pPictPriv->pict) {
847 XRenderFreePicture(dmxScreen->beDisplay, pPictPriv->pict);
848 pPictPriv->pict = (Picture) 0;
855 /** Destroy a list of pictures that are associated with the window that
856 * is being destroyed. This function is called by #dmxDestroyWindow().
859 dmxDestroyPictureList(WindowPtr pWindow)
861 PicturePtr pPicture = GetPictureWindow(pWindow);
865 ret |= dmxBEFreePicture(pPicture);
866 pPicture = pPicture->pNext;
872 /** Destroy a picture. This function calls the wrapped function that
873 * frees the resources in the DMX server associated with this
876 dmxDestroyPicture(PicturePtr pPicture)
878 ScreenPtr pScreen = pPicture->pDrawable->pScreen;
879 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
880 PictureScreenPtr ps = GetPictureScreen(pScreen);
882 DMX_UNWRAP(DestroyPicture, dmxScreen, ps);
884 /* Destroy picture on back-end server */
885 if (dmxBEFreePicture(pPicture))
886 dmxSync(dmxScreen, FALSE);
889 if (ps->DestroyPicture)
890 ps->DestroyPicture(pPicture);
892 DMX_WRAP(DestroyPicture, dmxDestroyPicture, dmxScreen, ps);
895 /** Change the picture's list of clip rectangles. */
897 dmxChangePictureClip(PicturePtr pPicture, int clipType, void *value, int n)
899 ScreenPtr pScreen = pPicture->pDrawable->pScreen;
900 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
901 PictureScreenPtr ps = GetPictureScreen(pScreen);
902 dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
904 DMX_UNWRAP(ChangePictureClip, dmxScreen, ps);
906 if (ps->ChangePictureClip)
907 ps->ChangePictureClip(pPicture, clipType, value, n);
910 /* Change picture clip rects on back-end server */
911 if (pPictPriv->pict) {
912 /* The clip has already been changed into a region by the mi
913 * routine called above.
915 if (clipType == CT_NONE) {
916 /* Disable clipping, show all */
917 XFixesSetPictureClipRegion(dmxScreen->beDisplay,
918 pPictPriv->pict, 0, 0, None);
920 else if (pPicture->clientClip) {
921 RegionPtr pClip = pPicture->clientClip;
922 BoxPtr pBox = RegionRects(pClip);
923 int nBox = RegionNumRects(pClip);
929 pRects = pRect = malloc(nRects * sizeof(*pRect));
934 pRect->width = pBox->x2 - pBox->x1;
935 pRect->height = pBox->y2 - pBox->y1;
940 XRenderSetPictureClipRectangles(dmxScreen->beDisplay,
942 0, 0, pRects, nRects);
946 XRenderSetPictureClipRectangles(dmxScreen->beDisplay,
947 pPictPriv->pict, 0, 0, NULL, 0);
949 dmxSync(dmxScreen, FALSE);
952 /* FIXME: Handle saving clip region when offscreen */
955 DMX_WRAP(ChangePictureClip, dmxChangePictureClip, dmxScreen, ps);
960 /** Destroy the picture's list of clip rectangles. */
962 dmxDestroyPictureClip(PicturePtr pPicture)
964 ScreenPtr pScreen = pPicture->pDrawable->pScreen;
965 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
966 PictureScreenPtr ps = GetPictureScreen(pScreen);
967 dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
969 DMX_UNWRAP(DestroyPictureClip, dmxScreen, ps);
971 if (ps->DestroyPictureClip)
972 ps->DestroyPictureClip(pPicture);
975 /* Destroy picture clip rects on back-end server */
976 if (pPictPriv->pict) {
977 XRenderSetPictureClipRectangles(dmxScreen->beDisplay,
978 pPictPriv->pict, 0, 0, NULL, 0);
979 dmxSync(dmxScreen, FALSE);
982 /* FIXME: Handle destroying clip region when offscreen */
985 DMX_WRAP(DestroyPictureClip, dmxDestroyPictureClip, dmxScreen, ps);
988 /** Change the attributes of the pictures. If the picture has not yet
989 * been created due to lazy window creation, save the mask so that it
990 * can be used to appropriately initialize the picture's attributes
991 * when it is created later. */
993 dmxChangePicture(PicturePtr pPicture, Mask mask)
995 ScreenPtr pScreen = pPicture->pDrawable->pScreen;
996 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
997 PictureScreenPtr ps = GetPictureScreen(pScreen);
998 dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
1000 DMX_UNWRAP(ChangePicture, dmxScreen, ps);
1002 if (ps->ChangePicture)
1003 ps->ChangePicture(pPicture, mask);
1006 /* Picture attribute changes are handled in ValidatePicture */
1007 pPictPriv->savedMask |= mask;
1009 DMX_WRAP(ChangePicture, dmxChangePicture, dmxScreen, ps);
1012 /** Validate the picture's attributes before rendering to it. Update
1013 * any picture attributes that have been changed by one of the higher
1016 dmxValidatePicture(PicturePtr pPicture, Mask mask)
1018 ScreenPtr pScreen = pPicture->pDrawable->pScreen;
1019 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
1020 PictureScreenPtr ps = GetPictureScreen(pScreen);
1021 dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
1023 DMX_UNWRAP(ValidatePicture, dmxScreen, ps);
1025 /* Change picture attributes on back-end server */
1026 if (pPictPriv->pict) {
1027 XRenderPictureAttributes attribs;
1029 if (mask & CPRepeat) {
1030 attribs.repeat = pPicture->repeatType;
1032 if (mask & CPAlphaMap) {
1033 if (pPicture->alphaMap) {
1034 dmxPictPrivPtr pAlphaPriv;
1036 pAlphaPriv = DMX_GET_PICT_PRIV(pPicture->alphaMap);
1037 if (pAlphaPriv->pict) {
1038 attribs.alpha_map = pAlphaPriv->pict;
1041 /* FIXME: alpha picture drawable has not been created?? */
1042 return; /* or should this be: attribs.alpha_map = None; */
1046 attribs.alpha_map = None;
1049 if (mask & CPAlphaXOrigin)
1050 attribs.alpha_x_origin = pPicture->alphaOrigin.x;
1051 if (mask & CPAlphaYOrigin)
1052 attribs.alpha_y_origin = pPicture->alphaOrigin.y;
1053 if (mask & CPClipXOrigin)
1054 attribs.clip_x_origin = pPicture->clipOrigin.x;
1055 if (mask & CPClipYOrigin)
1056 attribs.clip_y_origin = pPicture->clipOrigin.y;
1057 if (mask & CPClipMask)
1058 mask &= ~CPClipMask; /* Handled in ChangePictureClip */
1059 if (mask & CPGraphicsExposure)
1060 attribs.graphics_exposures = pPicture->graphicsExposures;
1061 if (mask & CPSubwindowMode)
1062 attribs.subwindow_mode = pPicture->subWindowMode;
1063 if (mask & CPPolyEdge)
1064 attribs.poly_edge = pPicture->polyEdge;
1065 if (mask & CPPolyMode)
1066 attribs.poly_mode = pPicture->polyMode;
1067 if (mask & CPComponentAlpha)
1068 attribs.component_alpha = pPicture->componentAlpha;
1070 XRenderChangePicture(dmxScreen->beDisplay, pPictPriv->pict,
1072 dmxSync(dmxScreen, FALSE);
1075 pPictPriv->savedMask |= mask;
1079 if (ps->ValidatePicture)
1080 ps->ValidatePicture(pPicture, mask);
1083 DMX_WRAP(ValidatePicture, dmxValidatePicture, dmxScreen, ps);
1086 /** Composite a picture on the appropriate screen by combining the
1087 * specified rectangle of the transformed src and mask operands with
1088 * the specified rectangle of the dst using op as the compositing
1089 * operator. For a complete description see the protocol document of
1090 * the RENDER library. */
1092 dmxComposite(CARD8 op,
1093 PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
1094 INT16 xSrc, INT16 ySrc,
1095 INT16 xMask, INT16 yMask,
1096 INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
1098 ScreenPtr pScreen = pDst->pDrawable->pScreen;
1099 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
1100 PictureScreenPtr ps = GetPictureScreen(pScreen);
1101 dmxPictPrivPtr pSrcPriv = DMX_GET_PICT_PRIV(pSrc);
1102 dmxPictPrivPtr pMaskPriv = NULL;
1103 dmxPictPrivPtr pDstPriv = DMX_GET_PICT_PRIV(pDst);
1106 pMaskPriv = DMX_GET_PICT_PRIV(pMask);
1108 DMX_UNWRAP(Composite, dmxScreen, ps);
1111 ps->Composite(op, pSrc, pMask, pDst,
1112 xSrc, ySrc, xMask, yMask, xDst, yDst, width, height);
1115 /* Composite on back-end server */
1116 if (pSrcPriv->pict && pDstPriv->pict &&
1117 ((pMaskPriv && pMaskPriv->pict) || !pMaskPriv)) {
1118 XRenderComposite(dmxScreen->beDisplay,
1121 pMaskPriv ? pMaskPriv->pict : None,
1123 xSrc, ySrc, xMask, yMask, xDst, yDst, width, height);
1124 dmxSync(dmxScreen, FALSE);
1127 DMX_WRAP(Composite, dmxComposite, dmxScreen, ps);
1130 /** Null function to catch when/if RENDER calls lower level mi hooks.
1131 * Compositing glyphs is handled by dmxProcRenderCompositeGlyphs().
1132 * This function should never be called. */
1135 PicturePtr pSrc, PicturePtr pDst,
1136 PictFormatPtr maskFormat,
1137 INT16 xSrc, INT16 ySrc,
1138 int nlists, GlyphListPtr lists, GlyphPtr * glyphs)
1140 /* This won't work, so we need to wrap ProcRenderCompositeGlyphs */
1143 /** Fill a rectangle on the appropriate screen by combining the color
1144 * with the dest picture in the area specified by the list of
1145 * rectangles. For a complete description see the protocol document of
1146 * the RENDER library. */
1148 dmxCompositeRects(CARD8 op,
1150 xRenderColor * color, int nRect, xRectangle *rects)
1152 ScreenPtr pScreen = pDst->pDrawable->pScreen;
1153 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
1154 PictureScreenPtr ps = GetPictureScreen(pScreen);
1155 dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pDst);
1157 DMX_UNWRAP(CompositeRects, dmxScreen, ps);
1159 if (ps->CompositeRects)
1160 ps->CompositeRects(op, pDst, color, nRect, rects);
1163 /* CompositeRects on back-end server */
1164 if (pPictPriv->pict) {
1165 XRenderFillRectangles(dmxScreen->beDisplay,
1168 (XRenderColor *) color,
1169 (XRectangle *) rects, nRect);
1170 dmxSync(dmxScreen, FALSE);
1173 DMX_WRAP(CompositeRects, dmxCompositeRects, dmxScreen, ps);
1176 /** Indexed color visuals are not yet supported. */
1178 dmxInitIndexed(ScreenPtr pScreen, PictFormatPtr pFormat)
1183 /** Indexed color visuals are not yet supported. */
1185 dmxCloseIndexed(ScreenPtr pScreen, PictFormatPtr pFormat)
1189 /** Indexed color visuals are not yet supported. */
1191 dmxUpdateIndexed(ScreenPtr pScreen, PictFormatPtr pFormat,
1192 int ndef, xColorItem * pdef)
1196 /** Composite a list of trapezoids on the appropriate screen. For a
1197 * complete description see the protocol document of the RENDER
1200 dmxTrapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
1201 PictFormatPtr maskFormat,
1202 INT16 xSrc, INT16 ySrc, int ntrap, xTrapezoid * traps)
1204 ScreenPtr pScreen = pDst->pDrawable->pScreen;
1205 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
1206 PictureScreenPtr ps = GetPictureScreen(pScreen);
1207 dmxPictPrivPtr pSrcPriv = DMX_GET_PICT_PRIV(pSrc);
1208 dmxPictPrivPtr pDstPriv = DMX_GET_PICT_PRIV(pDst);
1210 DMX_UNWRAP(Trapezoids, dmxScreen, ps);
1213 ps->Trapezoids(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntrap, *traps);
1216 /* Draw trapezoids on back-end server */
1217 if (pDstPriv->pict) {
1218 XRenderPictFormat *pFormat;
1220 pFormat = dmxFindFormat(dmxScreen, maskFormat);
1225 XRenderCompositeTrapezoids(dmxScreen->beDisplay,
1230 xSrc, ySrc, (XTrapezoid *) traps, ntrap);
1231 dmxSync(dmxScreen, FALSE);
1234 DMX_WRAP(Trapezoids, dmxTrapezoids, dmxScreen, ps);
1237 /** Composite a list of triangles on the appropriate screen. For a
1238 * complete description see the protocol document of the RENDER
1241 dmxTriangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
1242 PictFormatPtr maskFormat,
1243 INT16 xSrc, INT16 ySrc, int ntri, xTriangle * tris)
1245 ScreenPtr pScreen = pDst->pDrawable->pScreen;
1246 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
1247 PictureScreenPtr ps = GetPictureScreen(pScreen);
1248 dmxPictPrivPtr pSrcPriv = DMX_GET_PICT_PRIV(pSrc);
1249 dmxPictPrivPtr pDstPriv = DMX_GET_PICT_PRIV(pDst);
1251 DMX_UNWRAP(Triangles, dmxScreen, ps);
1254 ps->Triangles(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, *tris);
1257 /* Draw trapezoids on back-end server */
1258 if (pDstPriv->pict) {
1259 XRenderPictFormat *pFormat;
1261 pFormat = dmxFindFormat(dmxScreen, maskFormat);
1266 XRenderCompositeTriangles(dmxScreen->beDisplay,
1271 xSrc, ySrc, (XTriangle *) tris, ntri);
1272 dmxSync(dmxScreen, FALSE);
1275 DMX_WRAP(Triangles, dmxTriangles, dmxScreen, ps);