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 /* The shadow framebuffer only relies on FB to be initialized */
146 return fbPictureInit(pScreen, formats, nformats);
148 if (!miPictureInit(pScreen, formats, nformats))
151 if (!dixRegisterPrivateKey
152 (&dmxPictPrivateKeyRec, PRIVATE_PICTURE, sizeof(dmxPictPrivRec)))
155 ps = GetPictureScreen(pScreen);
157 DMX_WRAP(CreatePicture, dmxCreatePicture, dmxScreen, ps);
158 DMX_WRAP(DestroyPicture, dmxDestroyPicture, dmxScreen, ps);
160 DMX_WRAP(ChangePictureClip, dmxChangePictureClip, dmxScreen, ps);
161 DMX_WRAP(DestroyPictureClip, dmxDestroyPictureClip, dmxScreen, ps);
163 DMX_WRAP(ChangePicture, dmxChangePicture, dmxScreen, ps);
164 DMX_WRAP(ValidatePicture, dmxValidatePicture, dmxScreen, ps);
166 DMX_WRAP(Composite, dmxComposite, dmxScreen, ps);
167 DMX_WRAP(Glyphs, dmxGlyphs, dmxScreen, ps);
168 DMX_WRAP(CompositeRects, dmxCompositeRects, dmxScreen, ps);
170 DMX_WRAP(Trapezoids, dmxTrapezoids, dmxScreen, ps);
171 DMX_WRAP(Triangles, dmxTriangles, dmxScreen, ps);
176 /** Find the appropriate format on the requested screen given the
177 * internal format requested. The list of formats is searched
178 * sequentially as the XRenderFindFormat() function does not always
179 * find the appropriate format when a specific format is requested. */
180 static XRenderPictFormat *
181 dmxFindFormat(DMXScreenInfo * dmxScreen, PictFormatPtr pFmt)
183 XRenderPictFormat *pFormat = NULL;
186 if (!pFmt || !dmxScreen->beDisplay)
190 pFormat = XRenderFindFormat(dmxScreen->beDisplay, 0, 0, i++);
194 if (pFormat->type != pFmt->type)
196 if (pFormat->depth != pFmt->depth)
198 if (pFormat->direct.red != pFmt->direct.red)
200 if (pFormat->direct.redMask != pFmt->direct.redMask)
202 if (pFormat->direct.green != pFmt->direct.green)
204 if (pFormat->direct.greenMask != pFmt->direct.greenMask)
206 if (pFormat->direct.blue != pFmt->direct.blue)
208 if (pFormat->direct.blueMask != pFmt->direct.blueMask)
210 if (pFormat->direct.alpha != pFmt->direct.alpha)
212 if (pFormat->direct.alphaMask != pFmt->direct.alphaMask)
215 /* We have a match! */
222 /** Free \a glyphSet on back-end screen number \a idx. */
224 dmxBEFreeGlyphSet(ScreenPtr pScreen, GlyphSetPtr glyphSet)
226 dmxGlyphPrivPtr glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
227 int idx = pScreen->myNum;
228 DMXScreenInfo *dmxScreen = &dmxScreens[idx];
230 if (glyphPriv->glyphSets[idx]) {
231 XRenderFreeGlyphSet(dmxScreen->beDisplay, glyphPriv->glyphSets[idx]);
232 glyphPriv->glyphSets[idx] = (GlyphSet) 0;
239 /** Create \a glyphSet on the backend screen number \a idx. */
241 dmxBECreateGlyphSet(int idx, GlyphSetPtr glyphSet)
243 XRenderPictFormat *pFormat;
244 DMXScreenInfo *dmxScreen = &dmxScreens[idx];
245 dmxGlyphPrivPtr glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
246 PictFormatPtr pFmt = glyphSet->format;
247 int (*oldErrorHandler) (Display *, XErrorEvent *);
249 pFormat = dmxFindFormat(dmxScreen, pFmt);
254 dmxGlyphLastError = 0;
255 oldErrorHandler = XSetErrorHandler(dmxGlyphErrorHandler);
257 /* Catch when this fails */
258 glyphPriv->glyphSets[idx]
259 = XRenderCreateGlyphSet(dmxScreen->beDisplay, pFormat);
261 XSetErrorHandler(oldErrorHandler);
263 if (dmxGlyphLastError) {
264 return dmxGlyphLastError;
270 /** Create a Glyph Set on each screen. Save the glyphset ID from each
271 * screen in the Glyph Set's private structure. Fail if the format
272 * requested is not available or if the Glyph Set cannot be created on
275 dmxProcRenderCreateGlyphSet(ClientPtr client)
279 REQUEST(xRenderCreateGlyphSetReq);
281 ret = dmxSaveRenderVector[stuff->renderReqType] (client);
283 if (ret == Success) {
284 GlyphSetPtr glyphSet;
285 dmxGlyphPrivPtr glyphPriv;
288 /* Look up glyphSet that was just created ???? */
289 /* Store glyphsets from backends in glyphSet->devPrivate ????? */
290 /* Make sure we handle all errors here!! */
292 dixLookupResourceByType((pointer *) &glyphSet,
293 stuff->gsid, GlyphSetType,
294 client, DixDestroyAccess);
296 glyphPriv = malloc(sizeof(dmxGlyphPrivRec));
299 glyphPriv->glyphSets = NULL;
300 MAXSCREENSALLOC_RETURN(glyphPriv->glyphSets, BadAlloc);
301 DMX_SET_GLYPH_PRIV(glyphSet, glyphPriv);
303 for (i = 0; i < dmxNumScreens; i++) {
304 DMXScreenInfo *dmxScreen = &dmxScreens[i];
307 if (!dmxScreen->beDisplay) {
308 glyphPriv->glyphSets[i] = 0;
312 if ((beret = dmxBECreateGlyphSet(i, glyphSet)) != Success) {
315 /* Free the glyph sets we've allocated thus far */
316 for (j = 0; j < i; j++)
317 dmxBEFreeGlyphSet(screenInfo.screens[j], glyphSet);
319 /* Free the resource created by render */
320 FreeResource(stuff->gsid, RT_NONE);
330 /** Free the previously allocated Glyph Sets for each screen. */
332 dmxProcRenderFreeGlyphSet(ClientPtr client)
334 GlyphSetPtr glyphSet;
336 REQUEST(xRenderFreeGlyphSetReq);
338 REQUEST_SIZE_MATCH(xRenderFreeGlyphSetReq);
339 dixLookupResourceByType((pointer *) &glyphSet,
340 stuff->glyphset, GlyphSetType,
341 client, DixDestroyAccess);
343 if (glyphSet && glyphSet->refcnt == 1) {
344 dmxGlyphPrivPtr glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
347 for (i = 0; i < dmxNumScreens; i++) {
348 DMXScreenInfo *dmxScreen = &dmxScreens[i];
350 if (dmxScreen->beDisplay) {
351 if (dmxBEFreeGlyphSet(screenInfo.screens[i], glyphSet))
352 dmxSync(dmxScreen, FALSE);
356 MAXSCREENSFREE(glyphPriv->glyphSets);
358 DMX_SET_GLYPH_PRIV(glyphSet, NULL);
361 return dmxSaveRenderVector[stuff->renderReqType] (client);
364 /** Add glyphs to the Glyph Set on each screen. */
366 dmxProcRenderAddGlyphs(ClientPtr client)
370 REQUEST(xRenderAddGlyphsReq);
372 ret = dmxSaveRenderVector[stuff->renderReqType] (client);
374 if (ret == Success) {
375 GlyphSetPtr glyphSet;
376 dmxGlyphPrivPtr glyphPriv;
385 dixLookupResourceByType((pointer *) &glyphSet,
386 stuff->glyphset, GlyphSetType,
387 client, DixReadAccess);
388 glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
390 nglyphs = stuff->nglyphs;
391 gids = (CARD32 *) (stuff + 1);
392 gi = (xGlyphInfo *) (gids + nglyphs);
393 bits = (CARD8 *) (gi + nglyphs);
394 nbytes = ((stuff->length << 2) -
395 sizeof(xRenderAddGlyphsReq) -
396 (sizeof(CARD32) + sizeof(xGlyphInfo)) * nglyphs);
398 gidsCopy = malloc(sizeof(*gidsCopy) * nglyphs);
399 for (i = 0; i < nglyphs; i++)
400 gidsCopy[i] = gids[i];
402 /* FIXME: Will this ever fail? */
403 for (i = 0; i < dmxNumScreens; i++) {
404 DMXScreenInfo *dmxScreen = &dmxScreens[i];
406 if (dmxScreen->beDisplay) {
407 XRenderAddGlyphs(dmxScreen->beDisplay,
408 glyphPriv->glyphSets[i],
411 nglyphs, (char *) bits, nbytes);
412 dmxSync(dmxScreen, FALSE);
421 /** Free glyphs from the Glyph Set for each screen. */
423 dmxProcRenderFreeGlyphs(ClientPtr client)
425 GlyphSetPtr glyphSet;
427 REQUEST(xRenderFreeGlyphsReq);
429 REQUEST_AT_LEAST_SIZE(xRenderFreeGlyphsReq);
430 dixLookupResourceByType((pointer *) &glyphSet,
431 stuff->glyphset, GlyphSetType,
432 client, DixWriteAccess);
435 dmxGlyphPrivPtr glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
440 nglyphs = ((client->req_len << 2) - sizeof(xRenderFreeGlyphsReq)) >> 2;
442 gids = malloc(sizeof(*gids) * nglyphs);
443 for (i = 0; i < nglyphs; i++)
444 gids[i] = ((CARD32 *) (stuff + 1))[i];
446 for (i = 0; i < dmxNumScreens; i++) {
447 DMXScreenInfo *dmxScreen = &dmxScreens[i];
449 if (dmxScreen->beDisplay) {
450 XRenderFreeGlyphs(dmxScreen->beDisplay,
451 glyphPriv->glyphSets[i], gids, nglyphs);
452 dmxSync(dmxScreen, FALSE);
459 return dmxSaveRenderVector[stuff->renderReqType] (client);
462 /** Composite glyphs on each screen into the requested picture. If
463 * either the src or dest picture has not been allocated due to lazy
464 * window creation, this request will gracefully return. */
466 dmxProcRenderCompositeGlyphs(ClientPtr client)
470 REQUEST(xRenderCompositeGlyphsReq);
472 ret = dmxSaveRenderVector[stuff->renderReqType] (client);
474 /* For the following to work with PanoramiX, it assumes that Render
475 * wraps the ProcRenderVector after dmxRenderInit has been called.
477 if (ret == Success) {
479 dmxPictPrivPtr pSrcPriv;
481 dmxPictPrivPtr pDstPriv;
483 XRenderPictFormat *pFormat;
487 DMXScreenInfo *dmxScreen;
502 GlyphSetPtr glyphSet;
503 dmxGlyphPrivPtr glyphPriv;
505 dixLookupResourceByType((pointer *) &pSrc,
506 stuff->src, PictureType, client, DixReadAccess);
508 pSrcPriv = DMX_GET_PICT_PRIV(pSrc);
512 dixLookupResourceByType((pointer *) &pDst,
513 stuff->dst, PictureType,
514 client, DixWriteAccess);
516 pDstPriv = DMX_GET_PICT_PRIV(pDst);
520 scrnNum = pDst->pDrawable->pScreen->myNum;
521 dmxScreen = &dmxScreens[scrnNum];
523 /* Note: If the back-end display has been detached, then it
524 * should not be possible to reach here since the pSrcPriv->pict
525 * and pDstPriv->pict will have already been set to 0.
527 if (!dmxScreen->beDisplay)
530 if (stuff->maskFormat)
531 dixLookupResourceByType((pointer *) &pFmt,
532 stuff->maskFormat, PictFormatType,
533 client, DixReadAccess);
537 pFormat = dmxFindFormat(dmxScreen, pFmt);
539 switch (stuff->renderReqType) {
540 case X_RenderCompositeGlyphs8:
541 size = sizeof(CARD8);
543 case X_RenderCompositeGlyphs16:
544 size = sizeof(CARD16);
546 case X_RenderCompositeGlyphs32:
547 size = sizeof(CARD32);
550 return BadPictOp; /* Can't happen */
553 buffer = (CARD8 *) (stuff + 1);
554 end = (CARD8 *) stuff + (stuff->length << 2);
557 while (buffer + sizeof(xGlyphElt) < end) {
558 elt = (xGlyphElt *) buffer;
559 buffer += sizeof(xGlyphElt);
561 if (elt->len == 0xff) {
567 space = size * elt->len;
569 space += 4 - (space & 3);
574 /* The following only works for Render version > 0.2 */
576 /* All of the XGlyphElt* structure sizes are identical */
577 elts = malloc(nelt * sizeof(XGlyphElt8));
581 glyphs = malloc(nglyph * size);
587 buffer = (CARD8 *) (stuff + 1);
588 end = (CARD8 *) stuff + (stuff->length << 2);
592 dixLookupResourceByType((pointer *) &glyphSet,
593 stuff->glyphset, GlyphSetType,
594 client, DixReadAccess);
595 glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
597 while (buffer + sizeof(xGlyphElt) < end) {
598 elt = (xGlyphElt *) buffer;
599 buffer += sizeof(xGlyphElt);
601 if (elt->len == 0xff) {
602 dixLookupResourceByType((pointer *) &glyphSet,
603 *((CARD32 *) buffer),
604 GlyphSetType, client, DixReadAccess);
605 glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
609 curElt->glyphset = glyphPriv->glyphSets[scrnNum];
610 curElt->xOff = elt->deltax;
611 curElt->yOff = elt->deltay;
612 curElt->nchars = elt->len;
613 curElt->chars = curGlyph;
615 memcpy(curGlyph, buffer, size * elt->len);
616 curGlyph += size * elt->len;
620 space = size * elt->len;
622 space += 4 - (space & 3);
627 switch (stuff->renderReqType) {
628 case X_RenderCompositeGlyphs8:
629 XRenderCompositeText8(dmxScreen->beDisplay, stuff->op,
630 pSrcPriv->pict, pDstPriv->pict,
632 stuff->xSrc, stuff->ySrc, 0, 0, elts, nelt);
634 case X_RenderCompositeGlyphs16:
635 XRenderCompositeText16(dmxScreen->beDisplay, stuff->op,
636 pSrcPriv->pict, pDstPriv->pict,
638 stuff->xSrc, stuff->ySrc,
639 0, 0, (XGlyphElt16 *) elts, nelt);
641 case X_RenderCompositeGlyphs32:
642 XRenderCompositeText32(dmxScreen->beDisplay, stuff->op,
643 pSrcPriv->pict, pDstPriv->pict,
645 stuff->xSrc, stuff->ySrc,
646 0, 0, (XGlyphElt32 *) elts, nelt);
650 dmxSync(dmxScreen, FALSE);
659 /** Set the picture transform on each screen. */
661 dmxProcRenderSetPictureTransform(ClientPtr client)
663 DMXScreenInfo *dmxScreen;
665 dmxPictPrivPtr pPictPriv;
668 REQUEST(xRenderSetPictureTransformReq);
670 REQUEST_SIZE_MATCH(xRenderSetPictureTransformReq);
671 VERIFY_PICTURE(pPicture, stuff->picture, client, DixWriteAccess);
673 /* For the following to work with PanoramiX, it assumes that Render
674 * wraps the ProcRenderVector after dmxRenderInit has been called.
676 dmxScreen = &dmxScreens[pPicture->pDrawable->pScreen->myNum];
677 pPictPriv = DMX_GET_PICT_PRIV(pPicture);
679 if (pPictPriv->pict) {
680 xform.matrix[0][0] = stuff->transform.matrix11;
681 xform.matrix[0][1] = stuff->transform.matrix12;
682 xform.matrix[0][2] = stuff->transform.matrix13;
683 xform.matrix[1][0] = stuff->transform.matrix21;
684 xform.matrix[1][1] = stuff->transform.matrix22;
685 xform.matrix[1][2] = stuff->transform.matrix23;
686 xform.matrix[2][0] = stuff->transform.matrix31;
687 xform.matrix[2][1] = stuff->transform.matrix32;
688 xform.matrix[2][2] = stuff->transform.matrix33;
690 XRenderSetPictureTransform(dmxScreen->beDisplay,
691 pPictPriv->pict, &xform);
692 dmxSync(dmxScreen, FALSE);
695 return dmxSaveRenderVector[stuff->renderReqType] (client);
698 /** Set the picture filter on each screen. */
700 dmxProcRenderSetPictureFilter(ClientPtr client)
702 DMXScreenInfo *dmxScreen;
704 dmxPictPrivPtr pPictPriv;
709 REQUEST(xRenderSetPictureFilterReq);
711 REQUEST_AT_LEAST_SIZE(xRenderSetPictureFilterReq);
712 VERIFY_PICTURE(pPicture, stuff->picture, client, DixWriteAccess);
714 /* For the following to work with PanoramiX, it assumes that Render
715 * wraps the ProcRenderVector after dmxRenderInit has been called.
717 dmxScreen = &dmxScreens[pPicture->pDrawable->pScreen->myNum];
718 pPictPriv = DMX_GET_PICT_PRIV(pPicture);
720 if (pPictPriv->pict) {
721 filter = (char *) (stuff + 1);
722 params = (XFixed *) (filter + ((stuff->nbytes + 3) & ~3));
723 nparams = ((XFixed *) stuff + client->req_len) - params;
725 XRenderSetPictureFilter(dmxScreen->beDisplay,
726 pPictPriv->pict, filter, params, nparams);
727 dmxSync(dmxScreen, FALSE);
730 return dmxSaveRenderVector[stuff->renderReqType] (client);
733 /** Create a picture on the appropriate screen. This is the actual
734 * function that creates the picture. However, if the associated
735 * window has not yet been created due to lazy window creation, then
736 * delay the picture creation until the window is mapped. */
738 dmxDoCreatePicture(PicturePtr pPicture)
740 DrawablePtr pDraw = pPicture->pDrawable;
741 ScreenPtr pScreen = pDraw->pScreen;
742 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
743 XRenderPictFormat *pFormat;
746 if (pPicture->pDrawable->type == DRAWABLE_WINDOW) {
747 dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV((WindowPtr) (pDraw));
749 if (!(draw = pWinPriv->window)) {
750 /* Window has not been created yet due to the window
751 * optimization. Delay picture creation until window is
754 pWinPriv->hasPict = TRUE;
759 dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV((PixmapPtr) (pDraw));
761 if (!(draw = pPixPriv->pixmap)) {
762 /* FIXME: Zero width/height pixmap?? */
767 /* This should not be reached if the back-end display has been
768 * detached because the pWinPriv->window or the pPixPriv->pixmap
769 * will be NULL; however, we add it here for completeness
771 if (!dmxScreen->beDisplay)
774 pFormat = dmxFindFormat(dmxScreen, pPicture->pFormat);
776 return XRenderCreatePicture(dmxScreen->beDisplay, draw, pFormat, 0, 0);
779 /** Create a list of pictures. This function is called by
780 * dmxCreateAndRealizeWindow() during the lazy window creation
781 * realization process. It creates the entire list of pictures that
782 * are associated with the given window. */
784 dmxCreatePictureList(WindowPtr pWindow)
786 PicturePtr pPicture = GetPictureWindow(pWindow);
789 dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
791 /* Create the picture for this window */
792 pPictPriv->pict = dmxDoCreatePicture(pPicture);
794 /* ValidatePicture takes care of the state changes */
796 pPicture = pPicture->pNext;
800 /** Create \a pPicture on the backend. */
802 dmxBECreatePicture(PicturePtr pPicture)
804 dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
806 /* Create picutre on BE */
807 pPictPriv->pict = dmxDoCreatePicture(pPicture);
809 /* Flush changes to the backend server */
810 dmxValidatePicture(pPicture, (1 << (CPLastBit + 1)) - 1);
815 /** Create a picture. This function handles the CreatePicture
816 * unwrapping/wrapping and calls dmxDoCreatePicture to actually create
817 * the picture on the appropriate screen. */
819 dmxCreatePicture(PicturePtr pPicture)
821 ScreenPtr pScreen = pPicture->pDrawable->pScreen;
822 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
823 PictureScreenPtr ps = GetPictureScreen(pScreen);
824 dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
827 DMX_UNWRAP(CreatePicture, dmxScreen, ps);
829 if (ps->CreatePicture)
830 ret = ps->CreatePicture(pPicture);
833 /* Create picture on back-end server */
834 pPictPriv->pict = dmxDoCreatePicture(pPicture);
835 pPictPriv->savedMask = 0;
837 DMX_WRAP(CreatePicture, dmxCreatePicture, dmxScreen, ps);
842 /** Destroy \a pPicture on the back-end server. */
844 dmxBEFreePicture(PicturePtr pPicture)
846 ScreenPtr pScreen = pPicture->pDrawable->pScreen;
847 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
848 dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
850 if (pPictPriv->pict) {
851 XRenderFreePicture(dmxScreen->beDisplay, pPictPriv->pict);
852 pPictPriv->pict = (Picture) 0;
859 /** Destroy a list of pictures that are associated with the window that
860 * is being destroyed. This function is called by #dmxDestroyWindow().
863 dmxDestroyPictureList(WindowPtr pWindow)
865 PicturePtr pPicture = GetPictureWindow(pWindow);
869 ret |= dmxBEFreePicture(pPicture);
870 pPicture = pPicture->pNext;
876 /** Destroy a picture. This function calls the wrapped function that
877 * frees the resources in the DMX server associated with this
880 dmxDestroyPicture(PicturePtr pPicture)
882 ScreenPtr pScreen = pPicture->pDrawable->pScreen;
883 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
884 PictureScreenPtr ps = GetPictureScreen(pScreen);
886 DMX_UNWRAP(DestroyPicture, dmxScreen, ps);
888 /* Destroy picture on back-end server */
889 if (dmxBEFreePicture(pPicture))
890 dmxSync(dmxScreen, FALSE);
893 if (ps->DestroyPicture)
894 ps->DestroyPicture(pPicture);
896 DMX_WRAP(DestroyPicture, dmxDestroyPicture, dmxScreen, ps);
899 /** Change the picture's list of clip rectangles. */
901 dmxChangePictureClip(PicturePtr pPicture, int clipType, pointer value, int n)
903 ScreenPtr pScreen = pPicture->pDrawable->pScreen;
904 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
905 PictureScreenPtr ps = GetPictureScreen(pScreen);
906 dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
908 DMX_UNWRAP(ChangePictureClip, dmxScreen, ps);
910 if (ps->ChangePictureClip)
911 ps->ChangePictureClip(pPicture, clipType, value, n);
914 /* Change picture clip rects on back-end server */
915 if (pPictPriv->pict) {
916 /* The clip has already been changed into a region by the mi
917 * routine called above.
919 if (clipType == CT_NONE) {
920 /* Disable clipping, show all */
921 XFixesSetPictureClipRegion(dmxScreen->beDisplay,
922 pPictPriv->pict, 0, 0, None);
924 else if (pPicture->clientClip) {
925 RegionPtr pClip = pPicture->clientClip;
926 BoxPtr pBox = RegionRects(pClip);
927 int nBox = RegionNumRects(pClip);
933 pRects = pRect = malloc(nRects * sizeof(*pRect));
938 pRect->width = pBox->x2 - pBox->x1;
939 pRect->height = pBox->y2 - pBox->y1;
944 XRenderSetPictureClipRectangles(dmxScreen->beDisplay,
946 0, 0, pRects, nRects);
950 XRenderSetPictureClipRectangles(dmxScreen->beDisplay,
951 pPictPriv->pict, 0, 0, NULL, 0);
953 dmxSync(dmxScreen, FALSE);
956 /* FIXME: Handle saving clip region when offscreen */
959 DMX_WRAP(ChangePictureClip, dmxChangePictureClip, dmxScreen, ps);
964 /** Destroy the picture's list of clip rectangles. */
966 dmxDestroyPictureClip(PicturePtr pPicture)
968 ScreenPtr pScreen = pPicture->pDrawable->pScreen;
969 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
970 PictureScreenPtr ps = GetPictureScreen(pScreen);
971 dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
973 DMX_UNWRAP(DestroyPictureClip, dmxScreen, ps);
975 if (ps->DestroyPictureClip)
976 ps->DestroyPictureClip(pPicture);
979 /* Destroy picture clip rects on back-end server */
980 if (pPictPriv->pict) {
981 XRenderSetPictureClipRectangles(dmxScreen->beDisplay,
982 pPictPriv->pict, 0, 0, NULL, 0);
983 dmxSync(dmxScreen, FALSE);
986 /* FIXME: Handle destroying clip region when offscreen */
989 DMX_WRAP(DestroyPictureClip, dmxDestroyPictureClip, dmxScreen, ps);
992 /** Change the attributes of the pictures. If the picture has not yet
993 * been created due to lazy window creation, save the mask so that it
994 * can be used to appropriately initialize the picture's attributes
995 * when it is created later. */
997 dmxChangePicture(PicturePtr pPicture, Mask mask)
999 ScreenPtr pScreen = pPicture->pDrawable->pScreen;
1000 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
1001 PictureScreenPtr ps = GetPictureScreen(pScreen);
1002 dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
1004 DMX_UNWRAP(ChangePicture, dmxScreen, ps);
1006 if (ps->ChangePicture)
1007 ps->ChangePicture(pPicture, mask);
1010 /* Picture attribute changes are handled in ValidatePicture */
1011 pPictPriv->savedMask |= mask;
1013 DMX_WRAP(ChangePicture, dmxChangePicture, dmxScreen, ps);
1016 /** Validate the picture's attributes before rendering to it. Update
1017 * any picture attributes that have been changed by one of the higher
1020 dmxValidatePicture(PicturePtr pPicture, Mask mask)
1022 ScreenPtr pScreen = pPicture->pDrawable->pScreen;
1023 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
1024 PictureScreenPtr ps = GetPictureScreen(pScreen);
1025 dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
1027 DMX_UNWRAP(ValidatePicture, dmxScreen, ps);
1029 /* Change picture attributes on back-end server */
1030 if (pPictPriv->pict) {
1031 XRenderPictureAttributes attribs;
1033 if (mask & CPRepeat) {
1034 attribs.repeat = pPicture->repeatType;
1036 if (mask & CPAlphaMap) {
1037 if (pPicture->alphaMap) {
1038 dmxPictPrivPtr pAlphaPriv;
1040 pAlphaPriv = DMX_GET_PICT_PRIV(pPicture->alphaMap);
1041 if (pAlphaPriv->pict) {
1042 attribs.alpha_map = pAlphaPriv->pict;
1045 /* FIXME: alpha picture drawable has not been created?? */
1046 return; /* or should this be: attribs.alpha_map = None; */
1050 attribs.alpha_map = None;
1053 if (mask & CPAlphaXOrigin)
1054 attribs.alpha_x_origin = pPicture->alphaOrigin.x;
1055 if (mask & CPAlphaYOrigin)
1056 attribs.alpha_y_origin = pPicture->alphaOrigin.y;
1057 if (mask & CPClipXOrigin)
1058 attribs.clip_x_origin = pPicture->clipOrigin.x;
1059 if (mask & CPClipYOrigin)
1060 attribs.clip_y_origin = pPicture->clipOrigin.y;
1061 if (mask & CPClipMask)
1062 mask &= ~CPClipMask; /* Handled in ChangePictureClip */
1063 if (mask & CPGraphicsExposure)
1064 attribs.graphics_exposures = pPicture->graphicsExposures;
1065 if (mask & CPSubwindowMode)
1066 attribs.subwindow_mode = pPicture->subWindowMode;
1067 if (mask & CPPolyEdge)
1068 attribs.poly_edge = pPicture->polyEdge;
1069 if (mask & CPPolyMode)
1070 attribs.poly_mode = pPicture->polyMode;
1071 if (mask & CPComponentAlpha)
1072 attribs.component_alpha = pPicture->componentAlpha;
1074 XRenderChangePicture(dmxScreen->beDisplay, pPictPriv->pict,
1076 dmxSync(dmxScreen, FALSE);
1079 pPictPriv->savedMask |= mask;
1083 if (ps->ValidatePicture)
1084 ps->ValidatePicture(pPicture, mask);
1087 DMX_WRAP(ValidatePicture, dmxValidatePicture, dmxScreen, ps);
1090 /** Composite a picture on the appropriate screen by combining the
1091 * specified rectangle of the transformed src and mask operands with
1092 * the specified rectangle of the dst using op as the compositing
1093 * operator. For a complete description see the protocol document of
1094 * the RENDER library. */
1096 dmxComposite(CARD8 op,
1097 PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
1098 INT16 xSrc, INT16 ySrc,
1099 INT16 xMask, INT16 yMask,
1100 INT16 xDst, INT16 yDst, CARD16 width, CARD16 height)
1102 ScreenPtr pScreen = pDst->pDrawable->pScreen;
1103 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
1104 PictureScreenPtr ps = GetPictureScreen(pScreen);
1105 dmxPictPrivPtr pSrcPriv = DMX_GET_PICT_PRIV(pSrc);
1106 dmxPictPrivPtr pMaskPriv = NULL;
1107 dmxPictPrivPtr pDstPriv = DMX_GET_PICT_PRIV(pDst);
1110 pMaskPriv = DMX_GET_PICT_PRIV(pMask);
1112 DMX_UNWRAP(Composite, dmxScreen, ps);
1115 ps->Composite(op, pSrc, pMask, pDst,
1116 xSrc, ySrc, xMask, yMask, xDst, yDst, width, height);
1119 /* Composite on back-end server */
1120 if (pSrcPriv->pict && pDstPriv->pict &&
1121 ((pMaskPriv && pMaskPriv->pict) || !pMaskPriv)) {
1122 XRenderComposite(dmxScreen->beDisplay,
1125 pMaskPriv ? pMaskPriv->pict : None,
1127 xSrc, ySrc, xMask, yMask, xDst, yDst, width, height);
1128 dmxSync(dmxScreen, FALSE);
1131 DMX_WRAP(Composite, dmxComposite, dmxScreen, ps);
1134 /** Null function to catch when/if RENDER calls lower level mi hooks.
1135 * Compositing glyphs is handled by dmxProcRenderCompositeGlyphs().
1136 * This function should never be called. */
1139 PicturePtr pSrc, PicturePtr pDst,
1140 PictFormatPtr maskFormat,
1141 INT16 xSrc, INT16 ySrc,
1142 int nlists, GlyphListPtr lists, GlyphPtr * glyphs)
1144 /* This won't work, so we need to wrap ProcRenderCompositeGlyphs */
1147 /** Fill a rectangle on the appropriate screen by combining the color
1148 * with the dest picture in the area specified by the list of
1149 * rectangles. For a complete description see the protocol document of
1150 * the RENDER library. */
1152 dmxCompositeRects(CARD8 op,
1154 xRenderColor * color, int nRect, xRectangle *rects)
1156 ScreenPtr pScreen = pDst->pDrawable->pScreen;
1157 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
1158 PictureScreenPtr ps = GetPictureScreen(pScreen);
1159 dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pDst);
1161 DMX_UNWRAP(CompositeRects, dmxScreen, ps);
1163 if (ps->CompositeRects)
1164 ps->CompositeRects(op, pDst, color, nRect, rects);
1167 /* CompositeRects on back-end server */
1168 if (pPictPriv->pict) {
1169 XRenderFillRectangles(dmxScreen->beDisplay,
1172 (XRenderColor *) color,
1173 (XRectangle *) rects, nRect);
1174 dmxSync(dmxScreen, FALSE);
1177 DMX_WRAP(CompositeRects, dmxCompositeRects, dmxScreen, ps);
1180 /** Indexed color visuals are not yet supported. */
1182 dmxInitIndexed(ScreenPtr pScreen, PictFormatPtr pFormat)
1187 /** Indexed color visuals are not yet supported. */
1189 dmxCloseIndexed(ScreenPtr pScreen, PictFormatPtr pFormat)
1193 /** Indexed color visuals are not yet supported. */
1195 dmxUpdateIndexed(ScreenPtr pScreen, PictFormatPtr pFormat,
1196 int ndef, xColorItem * pdef)
1200 /** Composite a list of trapezoids on the appropriate screen. For a
1201 * complete description see the protocol document of the RENDER
1204 dmxTrapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
1205 PictFormatPtr maskFormat,
1206 INT16 xSrc, INT16 ySrc, int ntrap, xTrapezoid * traps)
1208 ScreenPtr pScreen = pDst->pDrawable->pScreen;
1209 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
1210 PictureScreenPtr ps = GetPictureScreen(pScreen);
1211 dmxPictPrivPtr pSrcPriv = DMX_GET_PICT_PRIV(pSrc);
1212 dmxPictPrivPtr pDstPriv = DMX_GET_PICT_PRIV(pDst);
1214 DMX_UNWRAP(Trapezoids, dmxScreen, ps);
1217 ps->Trapezoids(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntrap, *traps);
1220 /* Draw trapezoids on back-end server */
1221 if (pDstPriv->pict) {
1222 XRenderPictFormat *pFormat;
1224 pFormat = dmxFindFormat(dmxScreen, maskFormat);
1229 XRenderCompositeTrapezoids(dmxScreen->beDisplay,
1234 xSrc, ySrc, (XTrapezoid *) traps, ntrap);
1235 dmxSync(dmxScreen, FALSE);
1238 DMX_WRAP(Trapezoids, dmxTrapezoids, dmxScreen, ps);
1241 /** Composite a list of triangles on the appropriate screen. For a
1242 * complete description see the protocol document of the RENDER
1245 dmxTriangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
1246 PictFormatPtr maskFormat,
1247 INT16 xSrc, INT16 ySrc, int ntri, xTriangle * tris)
1249 ScreenPtr pScreen = pDst->pDrawable->pScreen;
1250 DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
1251 PictureScreenPtr ps = GetPictureScreen(pScreen);
1252 dmxPictPrivPtr pSrcPriv = DMX_GET_PICT_PRIV(pSrc);
1253 dmxPictPrivPtr pDstPriv = DMX_GET_PICT_PRIV(pDst);
1255 DMX_UNWRAP(Triangles, dmxScreen, ps);
1258 ps->Triangles(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, *tris);
1261 /* Draw trapezoids on back-end server */
1262 if (pDstPriv->pict) {
1263 XRenderPictFormat *pFormat;
1265 pFormat = dmxFindFormat(dmxScreen, maskFormat);
1270 XRenderCompositeTriangles(dmxScreen->beDisplay,
1275 xSrc, ySrc, (XTriangle *) tris, ntri);
1276 dmxSync(dmxScreen, FALSE);
1279 DMX_WRAP(Triangles, dmxTriangles, dmxScreen, ps);