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((pointer
*) &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((pointer
*) &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((pointer
*) &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((pointer
*) &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((pointer
*) &pSrc
,
502 stuff
->src
, PictureType
, client
, DixReadAccess
);
504 pSrcPriv
= DMX_GET_PICT_PRIV(pSrc
);
508 dixLookupResourceByType((pointer
*) &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((pointer
*) &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((pointer
*) &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((pointer
*) &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
, pointer 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
);