From 49c7992dfc9c6b8a60baf1afbede4616e0265e7f Mon Sep 17 00:00:00 2001 From: marha Date: Sun, 9 May 2010 21:09:18 +0000 Subject: xserver git update 9/5/2010 --- xorg-server/hw/dmx/dmxpict.c | 2630 +++++++++++++++++++++--------------------- 1 file changed, 1314 insertions(+), 1316 deletions(-) (limited to 'xorg-server/hw/dmx') 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 - * - */ - -/** \file - * Provide support for the RENDER extension (version 0.8). - */ - -#ifdef HAVE_DMX_CONFIG_H -#include -#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 -#include -#include -#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 + * + */ + +/** \file + * Provide support for the RENDER extension (version 0.8). + */ + +#ifdef HAVE_DMX_CONFIG_H +#include +#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 +#include +#include +#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); +} -- cgit v1.2.3