diff options
Diffstat (limited to 'xorg-server/hw/dmx/dmxpict.c')
-rw-r--r-- | xorg-server/hw/dmx/dmxpict.c | 2630 |
1 files changed, 1314 insertions, 1316 deletions
diff --git a/xorg-server/hw/dmx/dmxpict.c b/xorg-server/hw/dmx/dmxpict.c index 072e3a61a..efb2e41c9 100644 --- a/xorg-server/hw/dmx/dmxpict.c +++ b/xorg-server/hw/dmx/dmxpict.c @@ -1,1316 +1,1314 @@ -/* - * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina. - * - * All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation on the rights to use, copy, modify, merge, - * publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, - * subject to the following conditions: - * - * The above copyright notice and this permission notice (including the - * next paragraph) shall be included in all copies or substantial - * portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/* - * Authors: - * Kevin E. Martin <kem@redhat.com> - * - */ - -/** \file - * Provide support for the RENDER extension (version 0.8). - */ - -#ifdef HAVE_DMX_CONFIG_H -#include <dmx-config.h> -#endif - -#include "dmx.h" -#include "dmxsync.h" -#include "dmxpict.h" -#include "dmxwindow.h" -#include "dmxpixmap.h" - -#include "fb.h" -#include "pixmapstr.h" -#include "dixstruct.h" - -#include <X11/extensions/render.h> -#include <X11/extensions/renderproto.h> -#include <X11/extensions/Xfixes.h> -#include "picture.h" -#include "picturestr.h" -#include "mipict.h" -#include "fbpict.h" - - -extern int RenderErrBase; -extern int (*ProcRenderVector[RenderNumberRequests])(ClientPtr); - -static int (*dmxSaveRenderVector[RenderNumberRequests])(ClientPtr); - - -static int dmxProcRenderCreateGlyphSet(ClientPtr client); -static int dmxProcRenderFreeGlyphSet(ClientPtr client); -static int dmxProcRenderAddGlyphs(ClientPtr client); -static int dmxProcRenderFreeGlyphs(ClientPtr client); -static int dmxProcRenderCompositeGlyphs(ClientPtr client); -static int dmxProcRenderSetPictureTransform(ClientPtr client); -static int dmxProcRenderSetPictureFilter(ClientPtr client); -#if 0 -/* FIXME: Not (yet) supported */ -static int dmxProcRenderCreateCursor(ClientPtr client); -static int dmxProcRenderCreateAnimCursor(ClientPtr client); -#endif - -/** Catch errors that might occur when allocating Glyph Sets. Errors - * are saved in dmxGlyphLastError for later handling. */ -static int dmxGlyphLastError; -static int dmxGlyphErrorHandler(Display *dpy, XErrorEvent *ev) -{ - dmxGlyphLastError = ev->error_code; - return 0; -} - - -/** Initialize the Proc Vector for the RENDER extension. The functions - * here cannot be handled by the mi layer RENDER hooks either because - * the required information is no longer available when it reaches the - * mi layer or no mi layer hooks exist. This function is called from - * InitOutput() since it should be initialized only once per server - * generation. */ -void dmxInitRender(void) -{ - int i; - - for (i = 0; i < RenderNumberRequests; i++) - dmxSaveRenderVector[i] = ProcRenderVector[i]; - - ProcRenderVector[X_RenderCreateGlyphSet] - = dmxProcRenderCreateGlyphSet; - ProcRenderVector[X_RenderFreeGlyphSet] - = dmxProcRenderFreeGlyphSet; - ProcRenderVector[X_RenderAddGlyphs] - = dmxProcRenderAddGlyphs; - ProcRenderVector[X_RenderFreeGlyphs] - = dmxProcRenderFreeGlyphs; - ProcRenderVector[X_RenderCompositeGlyphs8] - = dmxProcRenderCompositeGlyphs; - ProcRenderVector[X_RenderCompositeGlyphs16] - = dmxProcRenderCompositeGlyphs; - ProcRenderVector[X_RenderCompositeGlyphs32] - = dmxProcRenderCompositeGlyphs; - ProcRenderVector[X_RenderSetPictureTransform] - = dmxProcRenderSetPictureTransform; - ProcRenderVector[X_RenderSetPictureFilter] - = dmxProcRenderSetPictureFilter; -} - -/** Reset the Proc Vector for the RENDER extension back to the original - * functions. This function is called from dmxCloseScreen() during the - * server reset (only for screen #0). */ -void dmxResetRender(void) -{ - int i; - - for (i = 0; i < RenderNumberRequests; i++) - ProcRenderVector[i] = dmxSaveRenderVector[i]; -} - -/** Initialize the RENDER extension, allocate the picture privates and - * wrap mi function hooks. If the shadow frame buffer is used, then - * call the appropriate fb initialization function. */ -Bool dmxPictureInit(ScreenPtr pScreen, PictFormatPtr formats, int nformats) -{ - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - PictureScreenPtr ps; - - /* The shadow framebuffer only relies on FB to be initialized */ - if (dmxShadowFB) return fbPictureInit(pScreen, formats, nformats); - - if (!miPictureInit(pScreen, formats, nformats)) - return FALSE; - - if (!dixRequestPrivate(dmxPictPrivateKey, sizeof(dmxPictPrivRec))) - return FALSE; - - ps = GetPictureScreen(pScreen); - - DMX_WRAP(CreatePicture, dmxCreatePicture, dmxScreen, ps); - DMX_WRAP(DestroyPicture, dmxDestroyPicture, dmxScreen, ps); - - DMX_WRAP(ChangePictureClip, dmxChangePictureClip, dmxScreen, ps); - DMX_WRAP(DestroyPictureClip, dmxDestroyPictureClip, dmxScreen, ps); - - DMX_WRAP(ChangePicture, dmxChangePicture, dmxScreen, ps); - DMX_WRAP(ValidatePicture, dmxValidatePicture, dmxScreen, ps); - - DMX_WRAP(Composite, dmxComposite, dmxScreen, ps); - DMX_WRAP(Glyphs, dmxGlyphs, dmxScreen, ps); - DMX_WRAP(CompositeRects, dmxCompositeRects, dmxScreen, ps); - - DMX_WRAP(Trapezoids, dmxTrapezoids, dmxScreen, ps); - DMX_WRAP(Triangles, dmxTriangles, dmxScreen, ps); - DMX_WRAP(TriStrip, dmxTriStrip, dmxScreen, ps); - DMX_WRAP(TriFan, dmxTriFan, dmxScreen, ps); - - return TRUE; -} - - -/** Find the appropriate format on the requested screen given the - * internal format requested. The list of formats is searched - * sequentially as the XRenderFindFormat() function does not always - * find the appropriate format when a specific format is requested. */ -static XRenderPictFormat *dmxFindFormat(DMXScreenInfo *dmxScreen, - PictFormatPtr pFmt) -{ - XRenderPictFormat *pFormat = NULL; - int i = 0; - - if (!pFmt || !dmxScreen->beDisplay) return pFormat; - - while (1) { - pFormat = XRenderFindFormat(dmxScreen->beDisplay, 0, 0, i++); - if (!pFormat) break; - - if (pFormat->type != pFmt->type) continue; - if (pFormat->depth != pFmt->depth) continue; - if (pFormat->direct.red != pFmt->direct.red) continue; - if (pFormat->direct.redMask != pFmt->direct.redMask) continue; - if (pFormat->direct.green != pFmt->direct.green) continue; - if (pFormat->direct.greenMask != pFmt->direct.greenMask) continue; - if (pFormat->direct.blue != pFmt->direct.blue) continue; - if (pFormat->direct.blueMask != pFmt->direct.blueMask) continue; - if (pFormat->direct.alpha != pFmt->direct.alpha) continue; - if (pFormat->direct.alphaMask != pFmt->direct.alphaMask) continue; - - /* We have a match! */ - break; - } - - return pFormat; -} - -/** Free \a glyphSet on back-end screen number \a idx. */ -Bool dmxBEFreeGlyphSet(ScreenPtr pScreen, GlyphSetPtr glyphSet) -{ - dmxGlyphPrivPtr glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet); - int idx = pScreen->myNum; - DMXScreenInfo *dmxScreen = &dmxScreens[idx]; - - if (glyphPriv->glyphSets[idx]) { - XRenderFreeGlyphSet(dmxScreen->beDisplay, glyphPriv->glyphSets[idx]); - glyphPriv->glyphSets[idx] = (GlyphSet)0; - return TRUE; - } - - return FALSE; -} - -/** Create \a glyphSet on the backend screen number \a idx. */ -int dmxBECreateGlyphSet(int idx, GlyphSetPtr glyphSet) -{ - XRenderPictFormat *pFormat; - DMXScreenInfo *dmxScreen = &dmxScreens[idx]; - dmxGlyphPrivPtr glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet); - PictFormatPtr pFmt = glyphSet->format; - int (*oldErrorHandler)(Display *, XErrorEvent *); - - pFormat = dmxFindFormat(dmxScreen, pFmt); - if (!pFormat) { - return BadMatch; - } - - dmxGlyphLastError = 0; - oldErrorHandler = XSetErrorHandler(dmxGlyphErrorHandler); - - /* Catch when this fails */ - glyphPriv->glyphSets[idx] - = XRenderCreateGlyphSet(dmxScreen->beDisplay, pFormat); - - XSetErrorHandler(oldErrorHandler); - - if (dmxGlyphLastError) { - return dmxGlyphLastError; - } - - return Success; -} - -/** Create a Glyph Set on each screen. Save the glyphset ID from each - * screen in the Glyph Set's private structure. Fail if the format - * requested is not available or if the Glyph Set cannot be created on - * the screen. */ -static int dmxProcRenderCreateGlyphSet(ClientPtr client) -{ - int ret; - REQUEST(xRenderCreateGlyphSetReq); - - ret = dmxSaveRenderVector[stuff->renderReqType](client); - - if (ret == Success) { - GlyphSetPtr glyphSet; - dmxGlyphPrivPtr glyphPriv; - int i; - - /* Look up glyphSet that was just created ???? */ - /* Store glyphsets from backends in glyphSet->devPrivate ????? */ - /* Make sure we handle all errors here!! */ - - glyphSet = SecurityLookupIDByType(client, stuff->gsid, GlyphSetType, - DixDestroyAccess); - glyphPriv = xalloc(sizeof(dmxGlyphPrivRec)); - if (!glyphPriv) return BadAlloc; - glyphPriv->glyphSets = NULL; - MAXSCREENSALLOC_RETURN(glyphPriv->glyphSets, BadAlloc); - DMX_SET_GLYPH_PRIV(glyphSet, glyphPriv); - - for (i = 0; i < dmxNumScreens; i++) { - DMXScreenInfo *dmxScreen = &dmxScreens[i]; - int beret; - - if (!dmxScreen->beDisplay) { - glyphPriv->glyphSets[i] = 0; - continue; - } - - if ((beret = dmxBECreateGlyphSet(i, glyphSet)) != Success) { - int j; - - /* Free the glyph sets we've allocated thus far */ - for (j = 0; j < i; j++) - dmxBEFreeGlyphSet(screenInfo.screens[j], glyphSet); - - /* Free the resource created by render */ - FreeResource(stuff->gsid, RT_NONE); - - return beret; - } - } - } - - return ret; -} - -/** Free the previously allocated Glyph Sets for each screen. */ -static int dmxProcRenderFreeGlyphSet(ClientPtr client) -{ - GlyphSetPtr glyphSet; - REQUEST(xRenderFreeGlyphSetReq); - - REQUEST_SIZE_MATCH(xRenderFreeGlyphSetReq); - glyphSet = SecurityLookupIDByType(client, stuff->glyphset, GlyphSetType, - DixDestroyAccess); - - if (glyphSet && glyphSet->refcnt == 1) { - dmxGlyphPrivPtr glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet); - int i; - - for (i = 0; i < dmxNumScreens; i++) { - DMXScreenInfo *dmxScreen = &dmxScreens[i]; - - if (dmxScreen->beDisplay) { - if (dmxBEFreeGlyphSet(screenInfo.screens[i], glyphSet)) - dmxSync(dmxScreen, FALSE); - } - } - - MAXSCREENSFREE(glyphPriv->glyphSets); - xfree(glyphPriv); - DMX_SET_GLYPH_PRIV(glyphSet, NULL); - } - - return dmxSaveRenderVector[stuff->renderReqType](client); -} - -/** Add glyphs to the Glyph Set on each screen. */ -static int dmxProcRenderAddGlyphs(ClientPtr client) -{ - int ret; - REQUEST(xRenderAddGlyphsReq); - - ret = dmxSaveRenderVector[stuff->renderReqType](client); - - if (ret == Success) { - GlyphSetPtr glyphSet; - dmxGlyphPrivPtr glyphPriv; - int i; - int nglyphs; - CARD32 *gids; - Glyph *gidsCopy; - xGlyphInfo *gi; - CARD8 *bits; - int nbytes; - - glyphSet = SecurityLookupIDByType(client, stuff->glyphset, - GlyphSetType, DixReadAccess); - glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet); - - nglyphs = stuff->nglyphs; - gids = (CARD32 *)(stuff + 1); - gi = (xGlyphInfo *)(gids + nglyphs); - bits = (CARD8 *)(gi + nglyphs); - nbytes = ((stuff->length << 2) - - sizeof(xRenderAddGlyphsReq) - - (sizeof(CARD32) + sizeof(xGlyphInfo)) * nglyphs); - - gidsCopy = xalloc(sizeof(*gidsCopy) * nglyphs); - for (i = 0; i < nglyphs; i++) gidsCopy[i] = gids[i]; - - /* FIXME: Will this ever fail? */ - for (i = 0; i < dmxNumScreens; i++) { - DMXScreenInfo *dmxScreen = &dmxScreens[i]; - - if (dmxScreen->beDisplay) { - XRenderAddGlyphs(dmxScreen->beDisplay, - glyphPriv->glyphSets[i], - gidsCopy, - (XGlyphInfo *)gi, - nglyphs, - (char *)bits, - nbytes); - dmxSync(dmxScreen, FALSE); - } - } - xfree(gidsCopy); - } - - return ret; -} - -/** Free glyphs from the Glyph Set for each screen. */ -static int dmxProcRenderFreeGlyphs(ClientPtr client) -{ - GlyphSetPtr glyphSet; - REQUEST(xRenderFreeGlyphsReq); - - REQUEST_AT_LEAST_SIZE(xRenderFreeGlyphsReq); - glyphSet = SecurityLookupIDByType(client, stuff->glyphset, GlyphSetType, - DixWriteAccess); - - if (glyphSet) { - dmxGlyphPrivPtr glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet); - int i; - int nglyphs; - Glyph *gids; - - nglyphs = ((client->req_len << 2) - sizeof(xRenderFreeGlyphsReq)) >> 2; - if (nglyphs) { - gids = xalloc(sizeof(*gids) * nglyphs); - for (i = 0; i < nglyphs; i++) - gids[i] = ((CARD32 *)(stuff + 1))[i]; - - for (i = 0; i < dmxNumScreens; i++) { - DMXScreenInfo *dmxScreen = &dmxScreens[i]; - - if (dmxScreen->beDisplay) { - XRenderFreeGlyphs(dmxScreen->beDisplay, - glyphPriv->glyphSets[i], gids, nglyphs); - dmxSync(dmxScreen, FALSE); - } - } - xfree(gids); - } - } - - return dmxSaveRenderVector[stuff->renderReqType](client); -} - -/** Composite glyphs on each screen into the requested picture. If - * either the src or dest picture has not been allocated due to lazy - * window creation, this request will gracefully return. */ -static int dmxProcRenderCompositeGlyphs(ClientPtr client) -{ - int ret; - REQUEST(xRenderCompositeGlyphsReq); - - ret = dmxSaveRenderVector[stuff->renderReqType](client); - - /* For the following to work with PanoramiX, it assumes that Render - * wraps the ProcRenderVector after dmxRenderInit has been called. - */ - if (ret == Success) { - PicturePtr pSrc; - dmxPictPrivPtr pSrcPriv; - PicturePtr pDst; - dmxPictPrivPtr pDstPriv; - PictFormatPtr pFmt; - XRenderPictFormat *pFormat; - int size; - - int scrnNum; - DMXScreenInfo *dmxScreen; - - CARD8 *buffer; - CARD8 *end; - int space; - - int nglyph; - char *glyphs; - char *curGlyph; - - xGlyphElt *elt; - int nelt; - XGlyphElt8 *elts; - XGlyphElt8 *curElt; - - GlyphSetPtr glyphSet; - dmxGlyphPrivPtr glyphPriv; - - pSrc = SecurityLookupIDByType(client, stuff->src, PictureType, - DixReadAccess); - pSrcPriv = DMX_GET_PICT_PRIV(pSrc); - if (!pSrcPriv->pict) - return ret; - - pDst = SecurityLookupIDByType(client, stuff->dst, PictureType, - DixWriteAccess); - pDstPriv = DMX_GET_PICT_PRIV(pDst); - if (!pDstPriv->pict) - return ret; - - scrnNum = pDst->pDrawable->pScreen->myNum; - dmxScreen = &dmxScreens[scrnNum]; - - /* Note: If the back-end display has been detached, then it - * should not be possible to reach here since the pSrcPriv->pict - * and pDstPriv->pict will have already been set to 0. - */ - if (!dmxScreen->beDisplay) - return ret; - - if (stuff->maskFormat) - pFmt = SecurityLookupIDByType(client, stuff->maskFormat, - PictFormatType, DixReadAccess); - else - pFmt = NULL; - - pFormat = dmxFindFormat(dmxScreen, pFmt); - - switch (stuff->renderReqType) { - case X_RenderCompositeGlyphs8: size = sizeof(CARD8); break; - case X_RenderCompositeGlyphs16: size = sizeof(CARD16); break; - case X_RenderCompositeGlyphs32: size = sizeof(CARD32); break; - default: return BadPictOp; /* Can't happen */ - } - - buffer = (CARD8 *)(stuff + 1); - end = (CARD8 *)stuff + (stuff->length << 2); - nelt = 0; - nglyph = 0; - while (buffer + sizeof(xGlyphElt) < end) { - elt = (xGlyphElt *)buffer; - buffer += sizeof(xGlyphElt); - - if (elt->len == 0xff) { - buffer += 4; - } else { - nelt++; - nglyph += elt->len; - space = size * elt->len; - if (space & 3) space += 4 - (space & 3); - buffer += space; - } - } - - /* The following only works for Render version > 0.2 */ - - /* All of the XGlyphElt* structure sizes are identical */ - elts = xalloc(nelt * sizeof(XGlyphElt8)); - if (!elts) - return BadAlloc; - - glyphs = xalloc(nglyph * size); - if (!glyphs) { - xfree(elts); - return BadAlloc; - } - - buffer = (CARD8 *)(stuff + 1); - end = (CARD8 *)stuff + (stuff->length << 2); - curGlyph = glyphs; - curElt = elts; - - glyphSet = SecurityLookupIDByType(client, stuff->glyphset, - GlyphSetType, DixReadAccess); - glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet); - - while (buffer + sizeof(xGlyphElt) < end) { - elt = (xGlyphElt *)buffer; - buffer += sizeof(xGlyphElt); - - if (elt->len == 0xff) { - glyphSet = SecurityLookupIDByType(client, - *((CARD32 *)buffer), - GlyphSetType, - DixReadAccess); - glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet); - buffer += 4; - } else { - curElt->glyphset = glyphPriv->glyphSets[scrnNum]; - curElt->xOff = elt->deltax; - curElt->yOff = elt->deltay; - curElt->nchars = elt->len; - curElt->chars = curGlyph; - - memcpy(curGlyph, buffer, size*elt->len); - curGlyph += size * elt->len; - - curElt++; - - space = size * elt->len; - if (space & 3) space += 4 - (space & 3); - buffer += space; - } - } - - switch (stuff->renderReqType) { - case X_RenderCompositeGlyphs8: - XRenderCompositeText8(dmxScreen->beDisplay, stuff->op, - pSrcPriv->pict, pDstPriv->pict, - pFormat, - stuff->xSrc, stuff->ySrc, - 0, 0, elts, nelt); - break; - case X_RenderCompositeGlyphs16: - XRenderCompositeText16(dmxScreen->beDisplay, stuff->op, - pSrcPriv->pict, pDstPriv->pict, - pFormat, - stuff->xSrc, stuff->ySrc, - 0, 0, (XGlyphElt16 *)elts, nelt); - break; - case X_RenderCompositeGlyphs32: - XRenderCompositeText32(dmxScreen->beDisplay, stuff->op, - pSrcPriv->pict, pDstPriv->pict, - pFormat, - stuff->xSrc, stuff->ySrc, - 0, 0, (XGlyphElt32 *)elts, nelt); - break; - } - - dmxSync(dmxScreen, FALSE); - - xfree(elts); - xfree(glyphs); - } - - return ret; -} - -/** Set the picture transform on each screen. */ -static int dmxProcRenderSetPictureTransform(ClientPtr client) -{ - DMXScreenInfo *dmxScreen; - PicturePtr pPicture; - dmxPictPrivPtr pPictPriv; - XTransform xform; - REQUEST(xRenderSetPictureTransformReq); - - REQUEST_SIZE_MATCH(xRenderSetPictureTransformReq); - VERIFY_PICTURE(pPicture, stuff->picture, client, DixWriteAccess, - RenderErrBase + BadPicture); - - /* For the following to work with PanoramiX, it assumes that Render - * wraps the ProcRenderVector after dmxRenderInit has been called. - */ - dmxScreen = &dmxScreens[pPicture->pDrawable->pScreen->myNum]; - pPictPriv = DMX_GET_PICT_PRIV(pPicture); - - if (pPictPriv->pict) { - xform.matrix[0][0] = stuff->transform.matrix11; - xform.matrix[0][1] = stuff->transform.matrix12; - xform.matrix[0][2] = stuff->transform.matrix13; - xform.matrix[1][0] = stuff->transform.matrix21; - xform.matrix[1][1] = stuff->transform.matrix22; - xform.matrix[1][2] = stuff->transform.matrix23; - xform.matrix[2][0] = stuff->transform.matrix31; - xform.matrix[2][1] = stuff->transform.matrix32; - xform.matrix[2][2] = stuff->transform.matrix33; - - XRenderSetPictureTransform(dmxScreen->beDisplay, - pPictPriv->pict, - &xform); - dmxSync(dmxScreen, FALSE); - } - - return dmxSaveRenderVector[stuff->renderReqType](client); -} - -/** Set the picture filter on each screen. */ -static int dmxProcRenderSetPictureFilter(ClientPtr client) -{ - DMXScreenInfo *dmxScreen; - PicturePtr pPicture; - dmxPictPrivPtr pPictPriv; - char *filter; - XFixed *params; - int nparams; - REQUEST(xRenderSetPictureFilterReq); - - REQUEST_AT_LEAST_SIZE(xRenderSetPictureFilterReq); - VERIFY_PICTURE(pPicture, stuff->picture, client, DixWriteAccess, - RenderErrBase + BadPicture); - - /* For the following to work with PanoramiX, it assumes that Render - * wraps the ProcRenderVector after dmxRenderInit has been called. - */ - dmxScreen = &dmxScreens[pPicture->pDrawable->pScreen->myNum]; - pPictPriv = DMX_GET_PICT_PRIV(pPicture); - - if (pPictPriv->pict) { - filter = (char *)(stuff + 1); - params = (XFixed *)(filter + ((stuff->nbytes + 3) & ~3)); - nparams = ((XFixed *)stuff + client->req_len) - params; - - XRenderSetPictureFilter(dmxScreen->beDisplay, - pPictPriv->pict, - filter, - params, - nparams); - dmxSync(dmxScreen, FALSE); - } - - return dmxSaveRenderVector[stuff->renderReqType](client); -} - - -/** Create a picture on the appropriate screen. This is the actual - * function that creates the picture. However, if the associated - * window has not yet been created due to lazy window creation, then - * delay the picture creation until the window is mapped. */ -static Picture dmxDoCreatePicture(PicturePtr pPicture) -{ - DrawablePtr pDraw = pPicture->pDrawable; - ScreenPtr pScreen = pDraw->pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - XRenderPictFormat *pFormat; - Drawable draw; - - if (pPicture->pDrawable->type == DRAWABLE_WINDOW) { - dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV((WindowPtr)(pDraw)); - - if (!(draw = pWinPriv->window)) { - /* Window has not been created yet due to the window - * optimization. Delay picture creation until window is - * mapped. - */ - pWinPriv->hasPict = TRUE; - return 0; - } - } else { - dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV((PixmapPtr)(pDraw)); - - if (!(draw = pPixPriv->pixmap)) { - /* FIXME: Zero width/height pixmap?? */ - return 0; - } - } - - /* This should not be reached if the back-end display has been - * detached because the pWinPriv->window or the pPixPriv->pixmap - * will be NULL; however, we add it here for completeness - */ - if (!dmxScreen->beDisplay) - return 0; - - pFormat = dmxFindFormat(dmxScreen, pPicture->pFormat); - - return XRenderCreatePicture(dmxScreen->beDisplay, draw, pFormat, 0, 0); -} - -/** Create a list of pictures. This function is called by - * dmxCreateAndRealizeWindow() during the lazy window creation - * realization process. It creates the entire list of pictures that - * are associated with the given window. */ -void dmxCreatePictureList(WindowPtr pWindow) -{ - PicturePtr pPicture = GetPictureWindow(pWindow); - - while (pPicture) { - dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture); - - /* Create the picture for this window */ - pPictPriv->pict = dmxDoCreatePicture(pPicture); - - /* ValidatePicture takes care of the state changes */ - - pPicture = pPicture->pNext; - } -} - -/** Create \a pPicture on the backend. */ -int dmxBECreatePicture(PicturePtr pPicture) -{ - dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture); - - /* Create picutre on BE */ - pPictPriv->pict = dmxDoCreatePicture(pPicture); - - /* Flush changes to the backend server */ - dmxValidatePicture(pPicture, (1 << (CPLastBit+1)) - 1); - - return Success; -} - -/** Create a picture. This function handles the CreatePicture - * unwrapping/wrapping and calls dmxDoCreatePicture to actually create - * the picture on the appropriate screen. */ -int dmxCreatePicture(PicturePtr pPicture) -{ - ScreenPtr pScreen = pPicture->pDrawable->pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - PictureScreenPtr ps = GetPictureScreen(pScreen); - dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture); - int ret = Success; - - DMX_UNWRAP(CreatePicture, dmxScreen, ps); -#if 1 - if (ps->CreatePicture) - ret = ps->CreatePicture(pPicture); -#endif - - /* Create picture on back-end server */ - pPictPriv->pict = dmxDoCreatePicture(pPicture); - pPictPriv->savedMask = 0; - - DMX_WRAP(CreatePicture, dmxCreatePicture, dmxScreen, ps); - - return ret; -} - -/** Destroy \a pPicture on the back-end server. */ -Bool dmxBEFreePicture(PicturePtr pPicture) -{ - ScreenPtr pScreen = pPicture->pDrawable->pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture); - - if (pPictPriv->pict) { - XRenderFreePicture(dmxScreen->beDisplay, pPictPriv->pict); - pPictPriv->pict = (Picture)0; - return TRUE; - } - - return FALSE; -} - -/** Destroy a list of pictures that are associated with the window that - * is being destroyed. This function is called by #dmxDestroyWindow(). - * */ -Bool dmxDestroyPictureList(WindowPtr pWindow) -{ - PicturePtr pPicture = GetPictureWindow(pWindow); - Bool ret = FALSE; - - while (pPicture) { - ret |= dmxBEFreePicture(pPicture); - pPicture = pPicture->pNext; - } - - return ret; -} - -/** Destroy a picture. This function calls the wrapped function that - * frees the resources in the DMX server associated with this - * picture. */ -void dmxDestroyPicture(PicturePtr pPicture) -{ - ScreenPtr pScreen = pPicture->pDrawable->pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - PictureScreenPtr ps = GetPictureScreen(pScreen); - - DMX_UNWRAP(DestroyPicture, dmxScreen, ps); - - /* Destroy picture on back-end server */ - if (dmxBEFreePicture(pPicture)) - dmxSync(dmxScreen, FALSE); - -#if 1 - if (ps->DestroyPicture) - ps->DestroyPicture(pPicture); -#endif - DMX_WRAP(DestroyPicture, dmxDestroyPicture, dmxScreen, ps); -} - -/** Change the picture's list of clip rectangles. */ -int dmxChangePictureClip(PicturePtr pPicture, int clipType, - pointer value, int n) -{ - ScreenPtr pScreen = pPicture->pDrawable->pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - PictureScreenPtr ps = GetPictureScreen(pScreen); - dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture); - - DMX_UNWRAP(ChangePictureClip, dmxScreen, ps); -#if 1 - if (ps->ChangePictureClip) - ps->ChangePictureClip(pPicture, clipType, value, n); -#endif - - /* Change picture clip rects on back-end server */ - if (pPictPriv->pict) { - /* The clip has already been changed into a region by the mi - * routine called above. - */ - if (clipType == CT_NONE) { - /* Disable clipping, show all */ - XFixesSetPictureClipRegion(dmxScreen->beDisplay, - pPictPriv->pict, 0, 0, None); - } else if (pPicture->clientClip) { - RegionPtr pClip = pPicture->clientClip; - BoxPtr pBox = REGION_RECTS(pClip); - int nBox = REGION_NUM_RECTS(pClip); - XRectangle *pRects; - XRectangle *pRect; - int nRects; - - nRects = nBox; - pRects = pRect = xalloc(nRects * sizeof(*pRect)); - - while (nBox--) { - pRect->x = pBox->x1; - pRect->y = pBox->y1; - pRect->width = pBox->x2 - pBox->x1; - pRect->height = pBox->y2 - pBox->y1; - pBox++; - pRect++; - } - - XRenderSetPictureClipRectangles(dmxScreen->beDisplay, - pPictPriv->pict, - 0, 0, - pRects, - nRects); - xfree(pRects); - } else { - XRenderSetPictureClipRectangles(dmxScreen->beDisplay, - pPictPriv->pict, - 0, 0, NULL, 0); - } - dmxSync(dmxScreen, FALSE); - } else { - /* FIXME: Handle saving clip region when offscreen */ - } - - DMX_WRAP(ChangePictureClip, dmxChangePictureClip, dmxScreen, ps); - - return Success; -} - -/** Destroy the picture's list of clip rectangles. */ -void dmxDestroyPictureClip(PicturePtr pPicture) -{ - ScreenPtr pScreen = pPicture->pDrawable->pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - PictureScreenPtr ps = GetPictureScreen(pScreen); - dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture); - - DMX_UNWRAP(DestroyPictureClip, dmxScreen, ps); -#if 1 - if (ps->DestroyPictureClip) - ps->DestroyPictureClip(pPicture); -#endif - - /* Destroy picture clip rects on back-end server */ - if (pPictPriv->pict) { - XRenderSetPictureClipRectangles(dmxScreen->beDisplay, - pPictPriv->pict, - 0, 0, NULL, 0); - dmxSync(dmxScreen, FALSE); - } else { - /* FIXME: Handle destroying clip region when offscreen */ - } - - DMX_WRAP(DestroyPictureClip, dmxDestroyPictureClip, dmxScreen, ps); -} - -/** Change the attributes of the pictures. If the picture has not yet - * been created due to lazy window creation, save the mask so that it - * can be used to appropriately initialize the picture's attributes - * when it is created later. */ -void dmxChangePicture(PicturePtr pPicture, Mask mask) -{ - ScreenPtr pScreen = pPicture->pDrawable->pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - PictureScreenPtr ps = GetPictureScreen(pScreen); - dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture); - - DMX_UNWRAP(ChangePicture, dmxScreen, ps); -#if 1 - if (ps->ChangePicture) - ps->ChangePicture(pPicture, mask); -#endif - - /* Picture attribute changes are handled in ValidatePicture */ - pPictPriv->savedMask |= mask; - - DMX_WRAP(ChangePicture, dmxChangePicture, dmxScreen, ps); -} - -/** Validate the picture's attributes before rendering to it. Update - * any picture attributes that have been changed by one of the higher - * layers. */ -void dmxValidatePicture(PicturePtr pPicture, Mask mask) -{ - ScreenPtr pScreen = pPicture->pDrawable->pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - PictureScreenPtr ps = GetPictureScreen(pScreen); - dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture); - - DMX_UNWRAP(ValidatePicture, dmxScreen, ps); - - /* Change picture attributes on back-end server */ - if (pPictPriv->pict) { - XRenderPictureAttributes attribs; - - if (mask & CPRepeat) { - attribs.repeat = pPicture->repeatType; - } - if (mask & CPAlphaMap) { - if (pPicture->alphaMap) { - dmxPictPrivPtr pAlphaPriv; - pAlphaPriv = DMX_GET_PICT_PRIV(pPicture->alphaMap); - if (pAlphaPriv->pict) { - attribs.alpha_map = pAlphaPriv->pict; - } else { - /* FIXME: alpha picture drawable has not been created?? */ - return; /* or should this be: attribs.alpha_map = None; */ - } - } else { - attribs.alpha_map = None; - } - } - if (mask & CPAlphaXOrigin) - attribs.alpha_x_origin = pPicture->alphaOrigin.x; - if (mask & CPAlphaYOrigin) - attribs.alpha_y_origin = pPicture->alphaOrigin.y; - if (mask & CPClipXOrigin) - attribs.clip_x_origin = pPicture->clipOrigin.x; - if (mask & CPClipYOrigin) - attribs.clip_y_origin = pPicture->clipOrigin.y; - if (mask & CPClipMask) - mask &= ~CPClipMask; /* Handled in ChangePictureClip */ - if (mask & CPGraphicsExposure) - attribs.graphics_exposures = pPicture->graphicsExposures; - if (mask & CPSubwindowMode) - attribs.subwindow_mode = pPicture->subWindowMode; - if (mask & CPPolyEdge) - attribs.poly_edge = pPicture->polyEdge; - if (mask & CPPolyMode) - attribs.poly_mode = pPicture->polyMode; - if (mask & CPDither) - attribs.dither = pPicture->dither; - if (mask & CPComponentAlpha) - attribs.component_alpha = pPicture->componentAlpha; - - XRenderChangePicture(dmxScreen->beDisplay, pPictPriv->pict, - mask, &attribs); - dmxSync(dmxScreen, FALSE); - } else { - pPictPriv->savedMask |= mask; - } - -#if 1 - if (ps->ValidatePicture) - ps->ValidatePicture(pPicture, mask); -#endif - - DMX_WRAP(ValidatePicture, dmxValidatePicture, dmxScreen, ps); -} - -/** Composite a picture on the appropriate screen by combining the - * specified rectangle of the transformed src and mask operands with - * the specified rectangle of the dst using op as the compositing - * operator. For a complete description see the protocol document of - * the RENDER library. */ -void dmxComposite(CARD8 op, - PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, - INT16 xSrc, INT16 ySrc, - INT16 xMask, INT16 yMask, - INT16 xDst, INT16 yDst, - CARD16 width, CARD16 height) -{ - ScreenPtr pScreen = pDst->pDrawable->pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - PictureScreenPtr ps = GetPictureScreen(pScreen); - dmxPictPrivPtr pSrcPriv = DMX_GET_PICT_PRIV(pSrc); - dmxPictPrivPtr pMaskPriv = NULL; - dmxPictPrivPtr pDstPriv = DMX_GET_PICT_PRIV(pDst); - - if (pMask) pMaskPriv = DMX_GET_PICT_PRIV(pMask); - - DMX_UNWRAP(Composite, dmxScreen, ps); -#if 0 - if (ps->Composite) - ps->Composite(op, pSrc, pMask, pDst, - xSrc, ySrc, xMask, yMask, xDst, yDst, - width, height); -#endif - - /* Composite on back-end server */ - if (pSrcPriv->pict && pDstPriv->pict && - ((pMaskPriv && pMaskPriv->pict) || !pMaskPriv)) { - XRenderComposite(dmxScreen->beDisplay, - op, - pSrcPriv->pict, - pMaskPriv ? pMaskPriv->pict : None, - pDstPriv->pict, - xSrc, ySrc, - xMask, yMask, - xDst, yDst, - width, height); - dmxSync(dmxScreen, FALSE); - } - - - DMX_WRAP(Composite, dmxComposite, dmxScreen, ps); -} - -/** Null function to catch when/if RENDER calls lower level mi hooks. - * Compositing glyphs is handled by dmxProcRenderCompositeGlyphs(). - * This function should never be called. */ -void dmxGlyphs(CARD8 op, - PicturePtr pSrc, PicturePtr pDst, - PictFormatPtr maskFormat, - INT16 xSrc, INT16 ySrc, - int nlists, GlyphListPtr lists, GlyphPtr *glyphs) -{ - /* This won't work, so we need to wrap ProcRenderCompositeGlyphs */ -} - -/** Fill a rectangle on the appropriate screen by combining the color - * with the dest picture in the area specified by the list of - * rectangles. For a complete description see the protocol document of - * the RENDER library. */ -void dmxCompositeRects(CARD8 op, - PicturePtr pDst, - xRenderColor *color, - int nRect, xRectangle *rects) -{ - ScreenPtr pScreen = pDst->pDrawable->pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - PictureScreenPtr ps = GetPictureScreen(pScreen); - dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pDst); - - DMX_UNWRAP(CompositeRects, dmxScreen, ps); -#if 0 - if (ps->CompositeRects) - ps->CompositeRects(op, pDst, color, nRect, rects); -#endif - - /* CompositeRects on back-end server */ - if (pPictPriv->pict) { - XRenderFillRectangles(dmxScreen->beDisplay, - op, - pPictPriv->pict, - (XRenderColor *)color, - (XRectangle *)rects, - nRect); - dmxSync(dmxScreen, FALSE); - } - - DMX_WRAP(CompositeRects, dmxCompositeRects, dmxScreen, ps); -} - -/** Indexed color visuals are not yet supported. */ -Bool dmxInitIndexed(ScreenPtr pScreen, PictFormatPtr pFormat) -{ - return TRUE; -} - -/** Indexed color visuals are not yet supported. */ -void dmxCloseIndexed(ScreenPtr pScreen, PictFormatPtr pFormat) -{ -} - -/** Indexed color visuals are not yet supported. */ -void dmxUpdateIndexed(ScreenPtr pScreen, PictFormatPtr pFormat, - int ndef, xColorItem *pdef) -{ -} - -/** Composite a list of trapezoids on the appropriate screen. For a - * complete description see the protocol document of the RENDER - * library. */ -void dmxTrapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst, - PictFormatPtr maskFormat, - INT16 xSrc, INT16 ySrc, - int ntrap, xTrapezoid *traps) -{ - ScreenPtr pScreen = pDst->pDrawable->pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - PictureScreenPtr ps = GetPictureScreen(pScreen); - dmxPictPrivPtr pSrcPriv = DMX_GET_PICT_PRIV(pSrc); - dmxPictPrivPtr pDstPriv = DMX_GET_PICT_PRIV(pDst); - - DMX_UNWRAP(Trapezoids, dmxScreen, ps); -#if 0 - if (ps->Trapezoids) - ps->Trapezoids(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntrap, *traps); -#endif - - /* Draw trapezoids on back-end server */ - if (pDstPriv->pict) { - XRenderPictFormat *pFormat; - - pFormat = dmxFindFormat(dmxScreen, maskFormat); - if (!pFormat) { - /* FIXME: Error! */ - } - - XRenderCompositeTrapezoids(dmxScreen->beDisplay, - op, - pSrcPriv->pict, - pDstPriv->pict, - pFormat, - xSrc, ySrc, - (XTrapezoid *)traps, - ntrap); - dmxSync(dmxScreen, FALSE); - } - - DMX_WRAP(Trapezoids, dmxTrapezoids, dmxScreen, ps); -} - -/** Composite a list of triangles on the appropriate screen. For a - * complete description see the protocol document of the RENDER - * library. */ -void dmxTriangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst, - PictFormatPtr maskFormat, - INT16 xSrc, INT16 ySrc, - int ntri, xTriangle *tris) -{ - ScreenPtr pScreen = pDst->pDrawable->pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - PictureScreenPtr ps = GetPictureScreen(pScreen); - dmxPictPrivPtr pSrcPriv = DMX_GET_PICT_PRIV(pSrc); - dmxPictPrivPtr pDstPriv = DMX_GET_PICT_PRIV(pDst); - - DMX_UNWRAP(Triangles, dmxScreen, ps); -#if 0 - if (ps->Triangles) - ps->Triangles(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, *tris); -#endif - - /* Draw trapezoids on back-end server */ - if (pDstPriv->pict) { - XRenderPictFormat *pFormat; - - pFormat = dmxFindFormat(dmxScreen, maskFormat); - if (!pFormat) { - /* FIXME: Error! */ - } - - XRenderCompositeTriangles(dmxScreen->beDisplay, - op, - pSrcPriv->pict, - pDstPriv->pict, - pFormat, - xSrc, ySrc, - (XTriangle *)tris, - ntri); - dmxSync(dmxScreen, FALSE); - } - - DMX_WRAP(Triangles, dmxTriangles, dmxScreen, ps); -} - -/** Composite a triangle strip on the appropriate screen. For a - * complete description see the protocol document of the RENDER - * library. */ -void dmxTriStrip(CARD8 op, PicturePtr pSrc, PicturePtr pDst, - PictFormatPtr maskFormat, - INT16 xSrc, INT16 ySrc, - int npoint, xPointFixed *points) -{ - ScreenPtr pScreen = pDst->pDrawable->pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - PictureScreenPtr ps = GetPictureScreen(pScreen); - dmxPictPrivPtr pSrcPriv = DMX_GET_PICT_PRIV(pSrc); - dmxPictPrivPtr pDstPriv = DMX_GET_PICT_PRIV(pDst); - - DMX_UNWRAP(TriStrip, dmxScreen, ps); -#if 0 - if (ps->TriStrip) - ps->TriStrip(op, pSrc, pDst, maskFormat, xSrc, ySrc, npoint, *points); -#endif - - /* Draw trapezoids on back-end server */ - if (pDstPriv->pict) { - XRenderPictFormat *pFormat; - - pFormat = dmxFindFormat(dmxScreen, maskFormat); - if (!pFormat) { - /* FIXME: Error! */ - } - - XRenderCompositeTriStrip(dmxScreen->beDisplay, - op, - pSrcPriv->pict, - pDstPriv->pict, - pFormat, - xSrc, ySrc, - (XPointFixed *)points, - npoint); - dmxSync(dmxScreen, FALSE); - } - - DMX_WRAP(TriStrip, dmxTriStrip, dmxScreen, ps); -} - -/** Composite a triangle fan on the appropriate screen. For a complete - * description see the protocol document of the RENDER library. */ -void dmxTriFan(CARD8 op, PicturePtr pSrc, PicturePtr pDst, - PictFormatPtr maskFormat, - INT16 xSrc, INT16 ySrc, - int npoint, xPointFixed *points) -{ - ScreenPtr pScreen = pDst->pDrawable->pScreen; - DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum]; - PictureScreenPtr ps = GetPictureScreen(pScreen); - dmxPictPrivPtr pSrcPriv = DMX_GET_PICT_PRIV(pSrc); - dmxPictPrivPtr pDstPriv = DMX_GET_PICT_PRIV(pDst); - - DMX_UNWRAP(TriFan, dmxScreen, ps); -#if 0 - if (ps->TriFan) - ps->TriFan(op, pSrc, pDst, maskFormat, xSrc, ySrc, npoint, *points); -#endif - - /* Draw trapezoids on back-end server */ - if (pDstPriv->pict) { - XRenderPictFormat *pFormat; - - pFormat = dmxFindFormat(dmxScreen, maskFormat); - if (!pFormat) { - /* FIXME: Error! */ - } - - XRenderCompositeTriFan(dmxScreen->beDisplay, - op, - pSrcPriv->pict, - pDstPriv->pict, - pFormat, - xSrc, ySrc, - (XPointFixed *)points, - npoint); - dmxSync(dmxScreen, FALSE); - } - - DMX_WRAP(TriFan, dmxTriFan, dmxScreen, ps); -} +/*
+ * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina.
+ *
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining
+ * a copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation on the rights to use, copy, modify, merge,
+ * publish, distribute, sublicense, and/or sell copies of the Software,
+ * and to permit persons to whom the Software is furnished to do so,
+ * subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial
+ * portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
+ * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+/*
+ * Authors:
+ * Kevin E. Martin <kem@redhat.com>
+ *
+ */
+
+/** \file
+ * Provide support for the RENDER extension (version 0.8).
+ */
+
+#ifdef HAVE_DMX_CONFIG_H
+#include <dmx-config.h>
+#endif
+
+#include "dmx.h"
+#include "dmxsync.h"
+#include "dmxpict.h"
+#include "dmxwindow.h"
+#include "dmxpixmap.h"
+
+#include "fb.h"
+#include "pixmapstr.h"
+#include "dixstruct.h"
+
+#include <X11/extensions/render.h>
+#include <X11/extensions/renderproto.h>
+#include <X11/extensions/Xfixes.h>
+#include "picture.h"
+#include "picturestr.h"
+#include "mipict.h"
+#include "fbpict.h"
+
+
+extern int RenderErrBase;
+extern int (*ProcRenderVector[RenderNumberRequests])(ClientPtr);
+
+static int (*dmxSaveRenderVector[RenderNumberRequests])(ClientPtr);
+
+
+static int dmxProcRenderCreateGlyphSet(ClientPtr client);
+static int dmxProcRenderFreeGlyphSet(ClientPtr client);
+static int dmxProcRenderAddGlyphs(ClientPtr client);
+static int dmxProcRenderFreeGlyphs(ClientPtr client);
+static int dmxProcRenderCompositeGlyphs(ClientPtr client);
+static int dmxProcRenderSetPictureTransform(ClientPtr client);
+static int dmxProcRenderSetPictureFilter(ClientPtr client);
+#if 0
+/* FIXME: Not (yet) supported */
+static int dmxProcRenderCreateCursor(ClientPtr client);
+static int dmxProcRenderCreateAnimCursor(ClientPtr client);
+#endif
+
+/** Catch errors that might occur when allocating Glyph Sets. Errors
+ * are saved in dmxGlyphLastError for later handling. */
+static int dmxGlyphLastError;
+static int dmxGlyphErrorHandler(Display *dpy, XErrorEvent *ev)
+{
+ dmxGlyphLastError = ev->error_code;
+ return 0;
+}
+
+
+/** Initialize the Proc Vector for the RENDER extension. The functions
+ * here cannot be handled by the mi layer RENDER hooks either because
+ * the required information is no longer available when it reaches the
+ * mi layer or no mi layer hooks exist. This function is called from
+ * InitOutput() since it should be initialized only once per server
+ * generation. */
+void dmxInitRender(void)
+{
+ int i;
+
+ for (i = 0; i < RenderNumberRequests; i++)
+ dmxSaveRenderVector[i] = ProcRenderVector[i];
+
+ ProcRenderVector[X_RenderCreateGlyphSet]
+ = dmxProcRenderCreateGlyphSet;
+ ProcRenderVector[X_RenderFreeGlyphSet]
+ = dmxProcRenderFreeGlyphSet;
+ ProcRenderVector[X_RenderAddGlyphs]
+ = dmxProcRenderAddGlyphs;
+ ProcRenderVector[X_RenderFreeGlyphs]
+ = dmxProcRenderFreeGlyphs;
+ ProcRenderVector[X_RenderCompositeGlyphs8]
+ = dmxProcRenderCompositeGlyphs;
+ ProcRenderVector[X_RenderCompositeGlyphs16]
+ = dmxProcRenderCompositeGlyphs;
+ ProcRenderVector[X_RenderCompositeGlyphs32]
+ = dmxProcRenderCompositeGlyphs;
+ ProcRenderVector[X_RenderSetPictureTransform]
+ = dmxProcRenderSetPictureTransform;
+ ProcRenderVector[X_RenderSetPictureFilter]
+ = dmxProcRenderSetPictureFilter;
+}
+
+/** Reset the Proc Vector for the RENDER extension back to the original
+ * functions. This function is called from dmxCloseScreen() during the
+ * server reset (only for screen #0). */
+void dmxResetRender(void)
+{
+ int i;
+
+ for (i = 0; i < RenderNumberRequests; i++)
+ ProcRenderVector[i] = dmxSaveRenderVector[i];
+}
+
+/** Initialize the RENDER extension, allocate the picture privates and
+ * wrap mi function hooks. If the shadow frame buffer is used, then
+ * call the appropriate fb initialization function. */
+Bool dmxPictureInit(ScreenPtr pScreen, PictFormatPtr formats, int nformats)
+{
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ PictureScreenPtr ps;
+
+ /* The shadow framebuffer only relies on FB to be initialized */
+ if (dmxShadowFB) return fbPictureInit(pScreen, formats, nformats);
+
+ if (!miPictureInit(pScreen, formats, nformats))
+ return FALSE;
+
+ if (!dixRequestPrivate(dmxPictPrivateKey, sizeof(dmxPictPrivRec)))
+ return FALSE;
+
+ ps = GetPictureScreen(pScreen);
+
+ DMX_WRAP(CreatePicture, dmxCreatePicture, dmxScreen, ps);
+ DMX_WRAP(DestroyPicture, dmxDestroyPicture, dmxScreen, ps);
+
+ DMX_WRAP(ChangePictureClip, dmxChangePictureClip, dmxScreen, ps);
+ DMX_WRAP(DestroyPictureClip, dmxDestroyPictureClip, dmxScreen, ps);
+
+ DMX_WRAP(ChangePicture, dmxChangePicture, dmxScreen, ps);
+ DMX_WRAP(ValidatePicture, dmxValidatePicture, dmxScreen, ps);
+
+ DMX_WRAP(Composite, dmxComposite, dmxScreen, ps);
+ DMX_WRAP(Glyphs, dmxGlyphs, dmxScreen, ps);
+ DMX_WRAP(CompositeRects, dmxCompositeRects, dmxScreen, ps);
+
+ DMX_WRAP(Trapezoids, dmxTrapezoids, dmxScreen, ps);
+ DMX_WRAP(Triangles, dmxTriangles, dmxScreen, ps);
+ DMX_WRAP(TriStrip, dmxTriStrip, dmxScreen, ps);
+ DMX_WRAP(TriFan, dmxTriFan, dmxScreen, ps);
+
+ return TRUE;
+}
+
+
+/** Find the appropriate format on the requested screen given the
+ * internal format requested. The list of formats is searched
+ * sequentially as the XRenderFindFormat() function does not always
+ * find the appropriate format when a specific format is requested. */
+static XRenderPictFormat *dmxFindFormat(DMXScreenInfo *dmxScreen,
+ PictFormatPtr pFmt)
+{
+ XRenderPictFormat *pFormat = NULL;
+ int i = 0;
+
+ if (!pFmt || !dmxScreen->beDisplay) return pFormat;
+
+ while (1) {
+ pFormat = XRenderFindFormat(dmxScreen->beDisplay, 0, 0, i++);
+ if (!pFormat) break;
+
+ if (pFormat->type != pFmt->type) continue;
+ if (pFormat->depth != pFmt->depth) continue;
+ if (pFormat->direct.red != pFmt->direct.red) continue;
+ if (pFormat->direct.redMask != pFmt->direct.redMask) continue;
+ if (pFormat->direct.green != pFmt->direct.green) continue;
+ if (pFormat->direct.greenMask != pFmt->direct.greenMask) continue;
+ if (pFormat->direct.blue != pFmt->direct.blue) continue;
+ if (pFormat->direct.blueMask != pFmt->direct.blueMask) continue;
+ if (pFormat->direct.alpha != pFmt->direct.alpha) continue;
+ if (pFormat->direct.alphaMask != pFmt->direct.alphaMask) continue;
+
+ /* We have a match! */
+ break;
+ }
+
+ return pFormat;
+}
+
+/** Free \a glyphSet on back-end screen number \a idx. */
+Bool dmxBEFreeGlyphSet(ScreenPtr pScreen, GlyphSetPtr glyphSet)
+{
+ dmxGlyphPrivPtr glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
+ int idx = pScreen->myNum;
+ DMXScreenInfo *dmxScreen = &dmxScreens[idx];
+
+ if (glyphPriv->glyphSets[idx]) {
+ XRenderFreeGlyphSet(dmxScreen->beDisplay, glyphPriv->glyphSets[idx]);
+ glyphPriv->glyphSets[idx] = (GlyphSet)0;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/** Create \a glyphSet on the backend screen number \a idx. */
+int dmxBECreateGlyphSet(int idx, GlyphSetPtr glyphSet)
+{
+ XRenderPictFormat *pFormat;
+ DMXScreenInfo *dmxScreen = &dmxScreens[idx];
+ dmxGlyphPrivPtr glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
+ PictFormatPtr pFmt = glyphSet->format;
+ int (*oldErrorHandler)(Display *, XErrorEvent *);
+
+ pFormat = dmxFindFormat(dmxScreen, pFmt);
+ if (!pFormat) {
+ return BadMatch;
+ }
+
+ dmxGlyphLastError = 0;
+ oldErrorHandler = XSetErrorHandler(dmxGlyphErrorHandler);
+
+ /* Catch when this fails */
+ glyphPriv->glyphSets[idx]
+ = XRenderCreateGlyphSet(dmxScreen->beDisplay, pFormat);
+
+ XSetErrorHandler(oldErrorHandler);
+
+ if (dmxGlyphLastError) {
+ return dmxGlyphLastError;
+ }
+
+ return Success;
+}
+
+/** Create a Glyph Set on each screen. Save the glyphset ID from each
+ * screen in the Glyph Set's private structure. Fail if the format
+ * requested is not available or if the Glyph Set cannot be created on
+ * the screen. */
+static int dmxProcRenderCreateGlyphSet(ClientPtr client)
+{
+ int ret;
+ REQUEST(xRenderCreateGlyphSetReq);
+
+ ret = dmxSaveRenderVector[stuff->renderReqType](client);
+
+ if (ret == Success) {
+ GlyphSetPtr glyphSet;
+ dmxGlyphPrivPtr glyphPriv;
+ int i;
+
+ /* Look up glyphSet that was just created ???? */
+ /* Store glyphsets from backends in glyphSet->devPrivate ????? */
+ /* Make sure we handle all errors here!! */
+
+ glyphSet = SecurityLookupIDByType(client, stuff->gsid, GlyphSetType,
+ DixDestroyAccess);
+ glyphPriv = xalloc(sizeof(dmxGlyphPrivRec));
+ if (!glyphPriv) return BadAlloc;
+ glyphPriv->glyphSets = NULL;
+ MAXSCREENSALLOC_RETURN(glyphPriv->glyphSets, BadAlloc);
+ DMX_SET_GLYPH_PRIV(glyphSet, glyphPriv);
+
+ for (i = 0; i < dmxNumScreens; i++) {
+ DMXScreenInfo *dmxScreen = &dmxScreens[i];
+ int beret;
+
+ if (!dmxScreen->beDisplay) {
+ glyphPriv->glyphSets[i] = 0;
+ continue;
+ }
+
+ if ((beret = dmxBECreateGlyphSet(i, glyphSet)) != Success) {
+ int j;
+
+ /* Free the glyph sets we've allocated thus far */
+ for (j = 0; j < i; j++)
+ dmxBEFreeGlyphSet(screenInfo.screens[j], glyphSet);
+
+ /* Free the resource created by render */
+ FreeResource(stuff->gsid, RT_NONE);
+
+ return beret;
+ }
+ }
+ }
+
+ return ret;
+}
+
+/** Free the previously allocated Glyph Sets for each screen. */
+static int dmxProcRenderFreeGlyphSet(ClientPtr client)
+{
+ GlyphSetPtr glyphSet;
+ REQUEST(xRenderFreeGlyphSetReq);
+
+ REQUEST_SIZE_MATCH(xRenderFreeGlyphSetReq);
+ glyphSet = SecurityLookupIDByType(client, stuff->glyphset, GlyphSetType,
+ DixDestroyAccess);
+
+ if (glyphSet && glyphSet->refcnt == 1) {
+ dmxGlyphPrivPtr glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
+ int i;
+
+ for (i = 0; i < dmxNumScreens; i++) {
+ DMXScreenInfo *dmxScreen = &dmxScreens[i];
+
+ if (dmxScreen->beDisplay) {
+ if (dmxBEFreeGlyphSet(screenInfo.screens[i], glyphSet))
+ dmxSync(dmxScreen, FALSE);
+ }
+ }
+
+ MAXSCREENSFREE(glyphPriv->glyphSets);
+ xfree(glyphPriv);
+ DMX_SET_GLYPH_PRIV(glyphSet, NULL);
+ }
+
+ return dmxSaveRenderVector[stuff->renderReqType](client);
+}
+
+/** Add glyphs to the Glyph Set on each screen. */
+static int dmxProcRenderAddGlyphs(ClientPtr client)
+{
+ int ret;
+ REQUEST(xRenderAddGlyphsReq);
+
+ ret = dmxSaveRenderVector[stuff->renderReqType](client);
+
+ if (ret == Success) {
+ GlyphSetPtr glyphSet;
+ dmxGlyphPrivPtr glyphPriv;
+ int i;
+ int nglyphs;
+ CARD32 *gids;
+ Glyph *gidsCopy;
+ xGlyphInfo *gi;
+ CARD8 *bits;
+ int nbytes;
+
+ glyphSet = SecurityLookupIDByType(client, stuff->glyphset,
+ GlyphSetType, DixReadAccess);
+ glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
+
+ nglyphs = stuff->nglyphs;
+ gids = (CARD32 *)(stuff + 1);
+ gi = (xGlyphInfo *)(gids + nglyphs);
+ bits = (CARD8 *)(gi + nglyphs);
+ nbytes = ((stuff->length << 2) -
+ sizeof(xRenderAddGlyphsReq) -
+ (sizeof(CARD32) + sizeof(xGlyphInfo)) * nglyphs);
+
+ gidsCopy = xalloc(sizeof(*gidsCopy) * nglyphs);
+ for (i = 0; i < nglyphs; i++) gidsCopy[i] = gids[i];
+
+ /* FIXME: Will this ever fail? */
+ for (i = 0; i < dmxNumScreens; i++) {
+ DMXScreenInfo *dmxScreen = &dmxScreens[i];
+
+ if (dmxScreen->beDisplay) {
+ XRenderAddGlyphs(dmxScreen->beDisplay,
+ glyphPriv->glyphSets[i],
+ gidsCopy,
+ (XGlyphInfo *)gi,
+ nglyphs,
+ (char *)bits,
+ nbytes);
+ dmxSync(dmxScreen, FALSE);
+ }
+ }
+ xfree(gidsCopy);
+ }
+
+ return ret;
+}
+
+/** Free glyphs from the Glyph Set for each screen. */
+static int dmxProcRenderFreeGlyphs(ClientPtr client)
+{
+ GlyphSetPtr glyphSet;
+ REQUEST(xRenderFreeGlyphsReq);
+
+ REQUEST_AT_LEAST_SIZE(xRenderFreeGlyphsReq);
+ glyphSet = SecurityLookupIDByType(client, stuff->glyphset, GlyphSetType,
+ DixWriteAccess);
+
+ if (glyphSet) {
+ dmxGlyphPrivPtr glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
+ int i;
+ int nglyphs;
+ Glyph *gids;
+
+ nglyphs = ((client->req_len << 2) - sizeof(xRenderFreeGlyphsReq)) >> 2;
+ if (nglyphs) {
+ gids = xalloc(sizeof(*gids) * nglyphs);
+ for (i = 0; i < nglyphs; i++)
+ gids[i] = ((CARD32 *)(stuff + 1))[i];
+
+ for (i = 0; i < dmxNumScreens; i++) {
+ DMXScreenInfo *dmxScreen = &dmxScreens[i];
+
+ if (dmxScreen->beDisplay) {
+ XRenderFreeGlyphs(dmxScreen->beDisplay,
+ glyphPriv->glyphSets[i], gids, nglyphs);
+ dmxSync(dmxScreen, FALSE);
+ }
+ }
+ xfree(gids);
+ }
+ }
+
+ return dmxSaveRenderVector[stuff->renderReqType](client);
+}
+
+/** Composite glyphs on each screen into the requested picture. If
+ * either the src or dest picture has not been allocated due to lazy
+ * window creation, this request will gracefully return. */
+static int dmxProcRenderCompositeGlyphs(ClientPtr client)
+{
+ int ret;
+ REQUEST(xRenderCompositeGlyphsReq);
+
+ ret = dmxSaveRenderVector[stuff->renderReqType](client);
+
+ /* For the following to work with PanoramiX, it assumes that Render
+ * wraps the ProcRenderVector after dmxRenderInit has been called.
+ */
+ if (ret == Success) {
+ PicturePtr pSrc;
+ dmxPictPrivPtr pSrcPriv;
+ PicturePtr pDst;
+ dmxPictPrivPtr pDstPriv;
+ PictFormatPtr pFmt;
+ XRenderPictFormat *pFormat;
+ int size;
+
+ int scrnNum;
+ DMXScreenInfo *dmxScreen;
+
+ CARD8 *buffer;
+ CARD8 *end;
+ int space;
+
+ int nglyph;
+ char *glyphs;
+ char *curGlyph;
+
+ xGlyphElt *elt;
+ int nelt;
+ XGlyphElt8 *elts;
+ XGlyphElt8 *curElt;
+
+ GlyphSetPtr glyphSet;
+ dmxGlyphPrivPtr glyphPriv;
+
+ pSrc = SecurityLookupIDByType(client, stuff->src, PictureType,
+ DixReadAccess);
+ pSrcPriv = DMX_GET_PICT_PRIV(pSrc);
+ if (!pSrcPriv->pict)
+ return ret;
+
+ pDst = SecurityLookupIDByType(client, stuff->dst, PictureType,
+ DixWriteAccess);
+ pDstPriv = DMX_GET_PICT_PRIV(pDst);
+ if (!pDstPriv->pict)
+ return ret;
+
+ scrnNum = pDst->pDrawable->pScreen->myNum;
+ dmxScreen = &dmxScreens[scrnNum];
+
+ /* Note: If the back-end display has been detached, then it
+ * should not be possible to reach here since the pSrcPriv->pict
+ * and pDstPriv->pict will have already been set to 0.
+ */
+ if (!dmxScreen->beDisplay)
+ return ret;
+
+ if (stuff->maskFormat)
+ pFmt = SecurityLookupIDByType(client, stuff->maskFormat,
+ PictFormatType, DixReadAccess);
+ else
+ pFmt = NULL;
+
+ pFormat = dmxFindFormat(dmxScreen, pFmt);
+
+ switch (stuff->renderReqType) {
+ case X_RenderCompositeGlyphs8: size = sizeof(CARD8); break;
+ case X_RenderCompositeGlyphs16: size = sizeof(CARD16); break;
+ case X_RenderCompositeGlyphs32: size = sizeof(CARD32); break;
+ default: return BadPictOp; /* Can't happen */
+ }
+
+ buffer = (CARD8 *)(stuff + 1);
+ end = (CARD8 *)stuff + (stuff->length << 2);
+ nelt = 0;
+ nglyph = 0;
+ while (buffer + sizeof(xGlyphElt) < end) {
+ elt = (xGlyphElt *)buffer;
+ buffer += sizeof(xGlyphElt);
+
+ if (elt->len == 0xff) {
+ buffer += 4;
+ } else {
+ nelt++;
+ nglyph += elt->len;
+ space = size * elt->len;
+ if (space & 3) space += 4 - (space & 3);
+ buffer += space;
+ }
+ }
+
+ /* The following only works for Render version > 0.2 */
+
+ /* All of the XGlyphElt* structure sizes are identical */
+ elts = xalloc(nelt * sizeof(XGlyphElt8));
+ if (!elts)
+ return BadAlloc;
+
+ glyphs = xalloc(nglyph * size);
+ if (!glyphs) {
+ xfree(elts);
+ return BadAlloc;
+ }
+
+ buffer = (CARD8 *)(stuff + 1);
+ end = (CARD8 *)stuff + (stuff->length << 2);
+ curGlyph = glyphs;
+ curElt = elts;
+
+ glyphSet = SecurityLookupIDByType(client, stuff->glyphset,
+ GlyphSetType, DixReadAccess);
+ glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
+
+ while (buffer + sizeof(xGlyphElt) < end) {
+ elt = (xGlyphElt *)buffer;
+ buffer += sizeof(xGlyphElt);
+
+ if (elt->len == 0xff) {
+ glyphSet = SecurityLookupIDByType(client,
+ *((CARD32 *)buffer),
+ GlyphSetType,
+ DixReadAccess);
+ glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
+ buffer += 4;
+ } else {
+ curElt->glyphset = glyphPriv->glyphSets[scrnNum];
+ curElt->xOff = elt->deltax;
+ curElt->yOff = elt->deltay;
+ curElt->nchars = elt->len;
+ curElt->chars = curGlyph;
+
+ memcpy(curGlyph, buffer, size*elt->len);
+ curGlyph += size * elt->len;
+
+ curElt++;
+
+ space = size * elt->len;
+ if (space & 3) space += 4 - (space & 3);
+ buffer += space;
+ }
+ }
+
+ switch (stuff->renderReqType) {
+ case X_RenderCompositeGlyphs8:
+ XRenderCompositeText8(dmxScreen->beDisplay, stuff->op,
+ pSrcPriv->pict, pDstPriv->pict,
+ pFormat,
+ stuff->xSrc, stuff->ySrc,
+ 0, 0, elts, nelt);
+ break;
+ case X_RenderCompositeGlyphs16:
+ XRenderCompositeText16(dmxScreen->beDisplay, stuff->op,
+ pSrcPriv->pict, pDstPriv->pict,
+ pFormat,
+ stuff->xSrc, stuff->ySrc,
+ 0, 0, (XGlyphElt16 *)elts, nelt);
+ break;
+ case X_RenderCompositeGlyphs32:
+ XRenderCompositeText32(dmxScreen->beDisplay, stuff->op,
+ pSrcPriv->pict, pDstPriv->pict,
+ pFormat,
+ stuff->xSrc, stuff->ySrc,
+ 0, 0, (XGlyphElt32 *)elts, nelt);
+ break;
+ }
+
+ dmxSync(dmxScreen, FALSE);
+
+ xfree(elts);
+ xfree(glyphs);
+ }
+
+ return ret;
+}
+
+/** Set the picture transform on each screen. */
+static int dmxProcRenderSetPictureTransform(ClientPtr client)
+{
+ DMXScreenInfo *dmxScreen;
+ PicturePtr pPicture;
+ dmxPictPrivPtr pPictPriv;
+ XTransform xform;
+ REQUEST(xRenderSetPictureTransformReq);
+
+ REQUEST_SIZE_MATCH(xRenderSetPictureTransformReq);
+ VERIFY_PICTURE(pPicture, stuff->picture, client, DixWriteAccess);
+
+ /* For the following to work with PanoramiX, it assumes that Render
+ * wraps the ProcRenderVector after dmxRenderInit has been called.
+ */
+ dmxScreen = &dmxScreens[pPicture->pDrawable->pScreen->myNum];
+ pPictPriv = DMX_GET_PICT_PRIV(pPicture);
+
+ if (pPictPriv->pict) {
+ xform.matrix[0][0] = stuff->transform.matrix11;
+ xform.matrix[0][1] = stuff->transform.matrix12;
+ xform.matrix[0][2] = stuff->transform.matrix13;
+ xform.matrix[1][0] = stuff->transform.matrix21;
+ xform.matrix[1][1] = stuff->transform.matrix22;
+ xform.matrix[1][2] = stuff->transform.matrix23;
+ xform.matrix[2][0] = stuff->transform.matrix31;
+ xform.matrix[2][1] = stuff->transform.matrix32;
+ xform.matrix[2][2] = stuff->transform.matrix33;
+
+ XRenderSetPictureTransform(dmxScreen->beDisplay,
+ pPictPriv->pict,
+ &xform);
+ dmxSync(dmxScreen, FALSE);
+ }
+
+ return dmxSaveRenderVector[stuff->renderReqType](client);
+}
+
+/** Set the picture filter on each screen. */
+static int dmxProcRenderSetPictureFilter(ClientPtr client)
+{
+ DMXScreenInfo *dmxScreen;
+ PicturePtr pPicture;
+ dmxPictPrivPtr pPictPriv;
+ char *filter;
+ XFixed *params;
+ int nparams;
+ REQUEST(xRenderSetPictureFilterReq);
+
+ REQUEST_AT_LEAST_SIZE(xRenderSetPictureFilterReq);
+ VERIFY_PICTURE(pPicture, stuff->picture, client, DixWriteAccess);
+
+ /* For the following to work with PanoramiX, it assumes that Render
+ * wraps the ProcRenderVector after dmxRenderInit has been called.
+ */
+ dmxScreen = &dmxScreens[pPicture->pDrawable->pScreen->myNum];
+ pPictPriv = DMX_GET_PICT_PRIV(pPicture);
+
+ if (pPictPriv->pict) {
+ filter = (char *)(stuff + 1);
+ params = (XFixed *)(filter + ((stuff->nbytes + 3) & ~3));
+ nparams = ((XFixed *)stuff + client->req_len) - params;
+
+ XRenderSetPictureFilter(dmxScreen->beDisplay,
+ pPictPriv->pict,
+ filter,
+ params,
+ nparams);
+ dmxSync(dmxScreen, FALSE);
+ }
+
+ return dmxSaveRenderVector[stuff->renderReqType](client);
+}
+
+
+/** Create a picture on the appropriate screen. This is the actual
+ * function that creates the picture. However, if the associated
+ * window has not yet been created due to lazy window creation, then
+ * delay the picture creation until the window is mapped. */
+static Picture dmxDoCreatePicture(PicturePtr pPicture)
+{
+ DrawablePtr pDraw = pPicture->pDrawable;
+ ScreenPtr pScreen = pDraw->pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ XRenderPictFormat *pFormat;
+ Drawable draw;
+
+ if (pPicture->pDrawable->type == DRAWABLE_WINDOW) {
+ dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV((WindowPtr)(pDraw));
+
+ if (!(draw = pWinPriv->window)) {
+ /* Window has not been created yet due to the window
+ * optimization. Delay picture creation until window is
+ * mapped.
+ */
+ pWinPriv->hasPict = TRUE;
+ return 0;
+ }
+ } else {
+ dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV((PixmapPtr)(pDraw));
+
+ if (!(draw = pPixPriv->pixmap)) {
+ /* FIXME: Zero width/height pixmap?? */
+ return 0;
+ }
+ }
+
+ /* This should not be reached if the back-end display has been
+ * detached because the pWinPriv->window or the pPixPriv->pixmap
+ * will be NULL; however, we add it here for completeness
+ */
+ if (!dmxScreen->beDisplay)
+ return 0;
+
+ pFormat = dmxFindFormat(dmxScreen, pPicture->pFormat);
+
+ return XRenderCreatePicture(dmxScreen->beDisplay, draw, pFormat, 0, 0);
+}
+
+/** Create a list of pictures. This function is called by
+ * dmxCreateAndRealizeWindow() during the lazy window creation
+ * realization process. It creates the entire list of pictures that
+ * are associated with the given window. */
+void dmxCreatePictureList(WindowPtr pWindow)
+{
+ PicturePtr pPicture = GetPictureWindow(pWindow);
+
+ while (pPicture) {
+ dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
+
+ /* Create the picture for this window */
+ pPictPriv->pict = dmxDoCreatePicture(pPicture);
+
+ /* ValidatePicture takes care of the state changes */
+
+ pPicture = pPicture->pNext;
+ }
+}
+
+/** Create \a pPicture on the backend. */
+int dmxBECreatePicture(PicturePtr pPicture)
+{
+ dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
+
+ /* Create picutre on BE */
+ pPictPriv->pict = dmxDoCreatePicture(pPicture);
+
+ /* Flush changes to the backend server */
+ dmxValidatePicture(pPicture, (1 << (CPLastBit+1)) - 1);
+
+ return Success;
+}
+
+/** Create a picture. This function handles the CreatePicture
+ * unwrapping/wrapping and calls dmxDoCreatePicture to actually create
+ * the picture on the appropriate screen. */
+int dmxCreatePicture(PicturePtr pPicture)
+{
+ ScreenPtr pScreen = pPicture->pDrawable->pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+ dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
+ int ret = Success;
+
+ DMX_UNWRAP(CreatePicture, dmxScreen, ps);
+#if 1
+ if (ps->CreatePicture)
+ ret = ps->CreatePicture(pPicture);
+#endif
+
+ /* Create picture on back-end server */
+ pPictPriv->pict = dmxDoCreatePicture(pPicture);
+ pPictPriv->savedMask = 0;
+
+ DMX_WRAP(CreatePicture, dmxCreatePicture, dmxScreen, ps);
+
+ return ret;
+}
+
+/** Destroy \a pPicture on the back-end server. */
+Bool dmxBEFreePicture(PicturePtr pPicture)
+{
+ ScreenPtr pScreen = pPicture->pDrawable->pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
+
+ if (pPictPriv->pict) {
+ XRenderFreePicture(dmxScreen->beDisplay, pPictPriv->pict);
+ pPictPriv->pict = (Picture)0;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/** Destroy a list of pictures that are associated with the window that
+ * is being destroyed. This function is called by #dmxDestroyWindow().
+ * */
+Bool dmxDestroyPictureList(WindowPtr pWindow)
+{
+ PicturePtr pPicture = GetPictureWindow(pWindow);
+ Bool ret = FALSE;
+
+ while (pPicture) {
+ ret |= dmxBEFreePicture(pPicture);
+ pPicture = pPicture->pNext;
+ }
+
+ return ret;
+}
+
+/** Destroy a picture. This function calls the wrapped function that
+ * frees the resources in the DMX server associated with this
+ * picture. */
+void dmxDestroyPicture(PicturePtr pPicture)
+{
+ ScreenPtr pScreen = pPicture->pDrawable->pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+
+ DMX_UNWRAP(DestroyPicture, dmxScreen, ps);
+
+ /* Destroy picture on back-end server */
+ if (dmxBEFreePicture(pPicture))
+ dmxSync(dmxScreen, FALSE);
+
+#if 1
+ if (ps->DestroyPicture)
+ ps->DestroyPicture(pPicture);
+#endif
+ DMX_WRAP(DestroyPicture, dmxDestroyPicture, dmxScreen, ps);
+}
+
+/** Change the picture's list of clip rectangles. */
+int dmxChangePictureClip(PicturePtr pPicture, int clipType,
+ pointer value, int n)
+{
+ ScreenPtr pScreen = pPicture->pDrawable->pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+ dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
+
+ DMX_UNWRAP(ChangePictureClip, dmxScreen, ps);
+#if 1
+ if (ps->ChangePictureClip)
+ ps->ChangePictureClip(pPicture, clipType, value, n);
+#endif
+
+ /* Change picture clip rects on back-end server */
+ if (pPictPriv->pict) {
+ /* The clip has already been changed into a region by the mi
+ * routine called above.
+ */
+ if (clipType == CT_NONE) {
+ /* Disable clipping, show all */
+ XFixesSetPictureClipRegion(dmxScreen->beDisplay,
+ pPictPriv->pict, 0, 0, None);
+ } else if (pPicture->clientClip) {
+ RegionPtr pClip = pPicture->clientClip;
+ BoxPtr pBox = REGION_RECTS(pClip);
+ int nBox = REGION_NUM_RECTS(pClip);
+ XRectangle *pRects;
+ XRectangle *pRect;
+ int nRects;
+
+ nRects = nBox;
+ pRects = pRect = xalloc(nRects * sizeof(*pRect));
+
+ while (nBox--) {
+ pRect->x = pBox->x1;
+ pRect->y = pBox->y1;
+ pRect->width = pBox->x2 - pBox->x1;
+ pRect->height = pBox->y2 - pBox->y1;
+ pBox++;
+ pRect++;
+ }
+
+ XRenderSetPictureClipRectangles(dmxScreen->beDisplay,
+ pPictPriv->pict,
+ 0, 0,
+ pRects,
+ nRects);
+ xfree(pRects);
+ } else {
+ XRenderSetPictureClipRectangles(dmxScreen->beDisplay,
+ pPictPriv->pict,
+ 0, 0, NULL, 0);
+ }
+ dmxSync(dmxScreen, FALSE);
+ } else {
+ /* FIXME: Handle saving clip region when offscreen */
+ }
+
+ DMX_WRAP(ChangePictureClip, dmxChangePictureClip, dmxScreen, ps);
+
+ return Success;
+}
+
+/** Destroy the picture's list of clip rectangles. */
+void dmxDestroyPictureClip(PicturePtr pPicture)
+{
+ ScreenPtr pScreen = pPicture->pDrawable->pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+ dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
+
+ DMX_UNWRAP(DestroyPictureClip, dmxScreen, ps);
+#if 1
+ if (ps->DestroyPictureClip)
+ ps->DestroyPictureClip(pPicture);
+#endif
+
+ /* Destroy picture clip rects on back-end server */
+ if (pPictPriv->pict) {
+ XRenderSetPictureClipRectangles(dmxScreen->beDisplay,
+ pPictPriv->pict,
+ 0, 0, NULL, 0);
+ dmxSync(dmxScreen, FALSE);
+ } else {
+ /* FIXME: Handle destroying clip region when offscreen */
+ }
+
+ DMX_WRAP(DestroyPictureClip, dmxDestroyPictureClip, dmxScreen, ps);
+}
+
+/** Change the attributes of the pictures. If the picture has not yet
+ * been created due to lazy window creation, save the mask so that it
+ * can be used to appropriately initialize the picture's attributes
+ * when it is created later. */
+void dmxChangePicture(PicturePtr pPicture, Mask mask)
+{
+ ScreenPtr pScreen = pPicture->pDrawable->pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+ dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
+
+ DMX_UNWRAP(ChangePicture, dmxScreen, ps);
+#if 1
+ if (ps->ChangePicture)
+ ps->ChangePicture(pPicture, mask);
+#endif
+
+ /* Picture attribute changes are handled in ValidatePicture */
+ pPictPriv->savedMask |= mask;
+
+ DMX_WRAP(ChangePicture, dmxChangePicture, dmxScreen, ps);
+}
+
+/** Validate the picture's attributes before rendering to it. Update
+ * any picture attributes that have been changed by one of the higher
+ * layers. */
+void dmxValidatePicture(PicturePtr pPicture, Mask mask)
+{
+ ScreenPtr pScreen = pPicture->pDrawable->pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+ dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
+
+ DMX_UNWRAP(ValidatePicture, dmxScreen, ps);
+
+ /* Change picture attributes on back-end server */
+ if (pPictPriv->pict) {
+ XRenderPictureAttributes attribs;
+
+ if (mask & CPRepeat) {
+ attribs.repeat = pPicture->repeatType;
+ }
+ if (mask & CPAlphaMap) {
+ if (pPicture->alphaMap) {
+ dmxPictPrivPtr pAlphaPriv;
+ pAlphaPriv = DMX_GET_PICT_PRIV(pPicture->alphaMap);
+ if (pAlphaPriv->pict) {
+ attribs.alpha_map = pAlphaPriv->pict;
+ } else {
+ /* FIXME: alpha picture drawable has not been created?? */
+ return; /* or should this be: attribs.alpha_map = None; */
+ }
+ } else {
+ attribs.alpha_map = None;
+ }
+ }
+ if (mask & CPAlphaXOrigin)
+ attribs.alpha_x_origin = pPicture->alphaOrigin.x;
+ if (mask & CPAlphaYOrigin)
+ attribs.alpha_y_origin = pPicture->alphaOrigin.y;
+ if (mask & CPClipXOrigin)
+ attribs.clip_x_origin = pPicture->clipOrigin.x;
+ if (mask & CPClipYOrigin)
+ attribs.clip_y_origin = pPicture->clipOrigin.y;
+ if (mask & CPClipMask)
+ mask &= ~CPClipMask; /* Handled in ChangePictureClip */
+ if (mask & CPGraphicsExposure)
+ attribs.graphics_exposures = pPicture->graphicsExposures;
+ if (mask & CPSubwindowMode)
+ attribs.subwindow_mode = pPicture->subWindowMode;
+ if (mask & CPPolyEdge)
+ attribs.poly_edge = pPicture->polyEdge;
+ if (mask & CPPolyMode)
+ attribs.poly_mode = pPicture->polyMode;
+ if (mask & CPDither)
+ attribs.dither = pPicture->dither;
+ if (mask & CPComponentAlpha)
+ attribs.component_alpha = pPicture->componentAlpha;
+
+ XRenderChangePicture(dmxScreen->beDisplay, pPictPriv->pict,
+ mask, &attribs);
+ dmxSync(dmxScreen, FALSE);
+ } else {
+ pPictPriv->savedMask |= mask;
+ }
+
+#if 1
+ if (ps->ValidatePicture)
+ ps->ValidatePicture(pPicture, mask);
+#endif
+
+ DMX_WRAP(ValidatePicture, dmxValidatePicture, dmxScreen, ps);
+}
+
+/** Composite a picture on the appropriate screen by combining the
+ * specified rectangle of the transformed src and mask operands with
+ * the specified rectangle of the dst using op as the compositing
+ * operator. For a complete description see the protocol document of
+ * the RENDER library. */
+void dmxComposite(CARD8 op,
+ PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
+ INT16 xSrc, INT16 ySrc,
+ INT16 xMask, INT16 yMask,
+ INT16 xDst, INT16 yDst,
+ CARD16 width, CARD16 height)
+{
+ ScreenPtr pScreen = pDst->pDrawable->pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+ dmxPictPrivPtr pSrcPriv = DMX_GET_PICT_PRIV(pSrc);
+ dmxPictPrivPtr pMaskPriv = NULL;
+ dmxPictPrivPtr pDstPriv = DMX_GET_PICT_PRIV(pDst);
+
+ if (pMask) pMaskPriv = DMX_GET_PICT_PRIV(pMask);
+
+ DMX_UNWRAP(Composite, dmxScreen, ps);
+#if 0
+ if (ps->Composite)
+ ps->Composite(op, pSrc, pMask, pDst,
+ xSrc, ySrc, xMask, yMask, xDst, yDst,
+ width, height);
+#endif
+
+ /* Composite on back-end server */
+ if (pSrcPriv->pict && pDstPriv->pict &&
+ ((pMaskPriv && pMaskPriv->pict) || !pMaskPriv)) {
+ XRenderComposite(dmxScreen->beDisplay,
+ op,
+ pSrcPriv->pict,
+ pMaskPriv ? pMaskPriv->pict : None,
+ pDstPriv->pict,
+ xSrc, ySrc,
+ xMask, yMask,
+ xDst, yDst,
+ width, height);
+ dmxSync(dmxScreen, FALSE);
+ }
+
+
+ DMX_WRAP(Composite, dmxComposite, dmxScreen, ps);
+}
+
+/** Null function to catch when/if RENDER calls lower level mi hooks.
+ * Compositing glyphs is handled by dmxProcRenderCompositeGlyphs().
+ * This function should never be called. */
+void dmxGlyphs(CARD8 op,
+ PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat,
+ INT16 xSrc, INT16 ySrc,
+ int nlists, GlyphListPtr lists, GlyphPtr *glyphs)
+{
+ /* This won't work, so we need to wrap ProcRenderCompositeGlyphs */
+}
+
+/** Fill a rectangle on the appropriate screen by combining the color
+ * with the dest picture in the area specified by the list of
+ * rectangles. For a complete description see the protocol document of
+ * the RENDER library. */
+void dmxCompositeRects(CARD8 op,
+ PicturePtr pDst,
+ xRenderColor *color,
+ int nRect, xRectangle *rects)
+{
+ ScreenPtr pScreen = pDst->pDrawable->pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+ dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pDst);
+
+ DMX_UNWRAP(CompositeRects, dmxScreen, ps);
+#if 0
+ if (ps->CompositeRects)
+ ps->CompositeRects(op, pDst, color, nRect, rects);
+#endif
+
+ /* CompositeRects on back-end server */
+ if (pPictPriv->pict) {
+ XRenderFillRectangles(dmxScreen->beDisplay,
+ op,
+ pPictPriv->pict,
+ (XRenderColor *)color,
+ (XRectangle *)rects,
+ nRect);
+ dmxSync(dmxScreen, FALSE);
+ }
+
+ DMX_WRAP(CompositeRects, dmxCompositeRects, dmxScreen, ps);
+}
+
+/** Indexed color visuals are not yet supported. */
+Bool dmxInitIndexed(ScreenPtr pScreen, PictFormatPtr pFormat)
+{
+ return TRUE;
+}
+
+/** Indexed color visuals are not yet supported. */
+void dmxCloseIndexed(ScreenPtr pScreen, PictFormatPtr pFormat)
+{
+}
+
+/** Indexed color visuals are not yet supported. */
+void dmxUpdateIndexed(ScreenPtr pScreen, PictFormatPtr pFormat,
+ int ndef, xColorItem *pdef)
+{
+}
+
+/** Composite a list of trapezoids on the appropriate screen. For a
+ * complete description see the protocol document of the RENDER
+ * library. */
+void dmxTrapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat,
+ INT16 xSrc, INT16 ySrc,
+ int ntrap, xTrapezoid *traps)
+{
+ ScreenPtr pScreen = pDst->pDrawable->pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+ dmxPictPrivPtr pSrcPriv = DMX_GET_PICT_PRIV(pSrc);
+ dmxPictPrivPtr pDstPriv = DMX_GET_PICT_PRIV(pDst);
+
+ DMX_UNWRAP(Trapezoids, dmxScreen, ps);
+#if 0
+ if (ps->Trapezoids)
+ ps->Trapezoids(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntrap, *traps);
+#endif
+
+ /* Draw trapezoids on back-end server */
+ if (pDstPriv->pict) {
+ XRenderPictFormat *pFormat;
+
+ pFormat = dmxFindFormat(dmxScreen, maskFormat);
+ if (!pFormat) {
+ /* FIXME: Error! */
+ }
+
+ XRenderCompositeTrapezoids(dmxScreen->beDisplay,
+ op,
+ pSrcPriv->pict,
+ pDstPriv->pict,
+ pFormat,
+ xSrc, ySrc,
+ (XTrapezoid *)traps,
+ ntrap);
+ dmxSync(dmxScreen, FALSE);
+ }
+
+ DMX_WRAP(Trapezoids, dmxTrapezoids, dmxScreen, ps);
+}
+
+/** Composite a list of triangles on the appropriate screen. For a
+ * complete description see the protocol document of the RENDER
+ * library. */
+void dmxTriangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat,
+ INT16 xSrc, INT16 ySrc,
+ int ntri, xTriangle *tris)
+{
+ ScreenPtr pScreen = pDst->pDrawable->pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+ dmxPictPrivPtr pSrcPriv = DMX_GET_PICT_PRIV(pSrc);
+ dmxPictPrivPtr pDstPriv = DMX_GET_PICT_PRIV(pDst);
+
+ DMX_UNWRAP(Triangles, dmxScreen, ps);
+#if 0
+ if (ps->Triangles)
+ ps->Triangles(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, *tris);
+#endif
+
+ /* Draw trapezoids on back-end server */
+ if (pDstPriv->pict) {
+ XRenderPictFormat *pFormat;
+
+ pFormat = dmxFindFormat(dmxScreen, maskFormat);
+ if (!pFormat) {
+ /* FIXME: Error! */
+ }
+
+ XRenderCompositeTriangles(dmxScreen->beDisplay,
+ op,
+ pSrcPriv->pict,
+ pDstPriv->pict,
+ pFormat,
+ xSrc, ySrc,
+ (XTriangle *)tris,
+ ntri);
+ dmxSync(dmxScreen, FALSE);
+ }
+
+ DMX_WRAP(Triangles, dmxTriangles, dmxScreen, ps);
+}
+
+/** Composite a triangle strip on the appropriate screen. For a
+ * complete description see the protocol document of the RENDER
+ * library. */
+void dmxTriStrip(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat,
+ INT16 xSrc, INT16 ySrc,
+ int npoint, xPointFixed *points)
+{
+ ScreenPtr pScreen = pDst->pDrawable->pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+ dmxPictPrivPtr pSrcPriv = DMX_GET_PICT_PRIV(pSrc);
+ dmxPictPrivPtr pDstPriv = DMX_GET_PICT_PRIV(pDst);
+
+ DMX_UNWRAP(TriStrip, dmxScreen, ps);
+#if 0
+ if (ps->TriStrip)
+ ps->TriStrip(op, pSrc, pDst, maskFormat, xSrc, ySrc, npoint, *points);
+#endif
+
+ /* Draw trapezoids on back-end server */
+ if (pDstPriv->pict) {
+ XRenderPictFormat *pFormat;
+
+ pFormat = dmxFindFormat(dmxScreen, maskFormat);
+ if (!pFormat) {
+ /* FIXME: Error! */
+ }
+
+ XRenderCompositeTriStrip(dmxScreen->beDisplay,
+ op,
+ pSrcPriv->pict,
+ pDstPriv->pict,
+ pFormat,
+ xSrc, ySrc,
+ (XPointFixed *)points,
+ npoint);
+ dmxSync(dmxScreen, FALSE);
+ }
+
+ DMX_WRAP(TriStrip, dmxTriStrip, dmxScreen, ps);
+}
+
+/** Composite a triangle fan on the appropriate screen. For a complete
+ * description see the protocol document of the RENDER library. */
+void dmxTriFan(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat,
+ INT16 xSrc, INT16 ySrc,
+ int npoint, xPointFixed *points)
+{
+ ScreenPtr pScreen = pDst->pDrawable->pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+ dmxPictPrivPtr pSrcPriv = DMX_GET_PICT_PRIV(pSrc);
+ dmxPictPrivPtr pDstPriv = DMX_GET_PICT_PRIV(pDst);
+
+ DMX_UNWRAP(TriFan, dmxScreen, ps);
+#if 0
+ if (ps->TriFan)
+ ps->TriFan(op, pSrc, pDst, maskFormat, xSrc, ySrc, npoint, *points);
+#endif
+
+ /* Draw trapezoids on back-end server */
+ if (pDstPriv->pict) {
+ XRenderPictFormat *pFormat;
+
+ pFormat = dmxFindFormat(dmxScreen, maskFormat);
+ if (!pFormat) {
+ /* FIXME: Error! */
+ }
+
+ XRenderCompositeTriFan(dmxScreen->beDisplay,
+ op,
+ pSrcPriv->pict,
+ pDstPriv->pict,
+ pFormat,
+ xSrc, ySrc,
+ (XPointFixed *)points,
+ npoint);
+ dmxSync(dmxScreen, FALSE);
+ }
+
+ DMX_WRAP(TriFan, dmxTriFan, dmxScreen, ps);
+}
|