/* * * Copyright © 2000 SuSE, Inc. * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of SuSE not be used in advertising or * publicity pertaining to distribution of the software without specific, * written prior permission. SuSE makes no representations about the * suitability of this software for any purpose. It is provided "as is" * without express or implied warranty. * * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Author: Keith Packard, SuSE, Inc. */ #ifdef HAVE_DIX_CONFIG_H #include <dix-config.h> #endif #include <X11/X.h> #include <X11/Xproto.h> #include "misc.h" #include "os.h" #include "dixstruct.h" #include "resource.h" #include "scrnintstr.h" #include "windowstr.h" #include "pixmapstr.h" #include "colormapst.h" #include "extnsionst.h" #include "servermd.h" #include <X11/extensions/render.h> #include <X11/extensions/renderproto.h> #include "picturestr.h" #include "glyphstr.h" #include <X11/Xfuncproto.h> #include "cursorstr.h" #include "xace.h" #include "protocol-versions.h" #ifdef PANORAMIX #include "panoramiX.h" #include "panoramiXsrv.h" #endif #include <stdint.h> static int ProcRenderQueryVersion (ClientPtr pClient); static int ProcRenderQueryPictFormats (ClientPtr pClient); static int ProcRenderQueryPictIndexValues (ClientPtr pClient); static int ProcRenderQueryDithers (ClientPtr pClient); static int ProcRenderCreatePicture (ClientPtr pClient); static int ProcRenderChangePicture (ClientPtr pClient); static int ProcRenderSetPictureClipRectangles (ClientPtr pClient); static int ProcRenderFreePicture (ClientPtr pClient); static int ProcRenderComposite (ClientPtr pClient); static int ProcRenderScale (ClientPtr pClient); static int ProcRenderTrapezoids (ClientPtr pClient); static int ProcRenderTriangles (ClientPtr pClient); static int ProcRenderTriStrip (ClientPtr pClient); static int ProcRenderTriFan (ClientPtr pClient); static int ProcRenderColorTrapezoids (ClientPtr pClient); static int ProcRenderColorTriangles (ClientPtr pClient); static int ProcRenderTransform (ClientPtr pClient); static int ProcRenderCreateGlyphSet (ClientPtr pClient); static int ProcRenderReferenceGlyphSet (ClientPtr pClient); static int ProcRenderFreeGlyphSet (ClientPtr pClient); static int ProcRenderAddGlyphs (ClientPtr pClient); static int ProcRenderAddGlyphsFromPicture (ClientPtr pClient); static int ProcRenderFreeGlyphs (ClientPtr pClient); static int ProcRenderCompositeGlyphs (ClientPtr pClient); static int ProcRenderFillRectangles (ClientPtr pClient); static int ProcRenderCreateCursor (ClientPtr pClient); static int ProcRenderSetPictureTransform (ClientPtr pClient); static int ProcRenderQueryFilters (ClientPtr pClient); static int ProcRenderSetPictureFilter (ClientPtr pClient); static int ProcRenderCreateAnimCursor (ClientPtr pClient); static int ProcRenderAddTraps (ClientPtr pClient); static int ProcRenderCreateSolidFill (ClientPtr pClient); static int ProcRenderCreateLinearGradient (ClientPtr pClient); static int ProcRenderCreateRadialGradient (ClientPtr pClient); static int ProcRenderCreateConicalGradient (ClientPtr pClient); static int ProcRenderDispatch (ClientPtr pClient); static int SProcRenderQueryVersion (ClientPtr pClient); static int SProcRenderQueryPictFormats (ClientPtr pClient); static int SProcRenderQueryPictIndexValues (ClientPtr pClient); static int SProcRenderQueryDithers (ClientPtr pClient); static int SProcRenderCreatePicture (ClientPtr pClient); static int SProcRenderChangePicture (ClientPtr pClient); static int SProcRenderSetPictureClipRectangles (ClientPtr pClient); static int SProcRenderFreePicture (ClientPtr pClient); static int SProcRenderComposite (ClientPtr pClient); static int SProcRenderScale (ClientPtr pClient); static int SProcRenderTrapezoids (ClientPtr pClient); static int SProcRenderTriangles (ClientPtr pClient); static int SProcRenderTriStrip (ClientPtr pClient); static int SProcRenderTriFan (ClientPtr pClient); static int SProcRenderColorTrapezoids (ClientPtr pClient); static int SProcRenderColorTriangles (ClientPtr pClient); static int SProcRenderTransform (ClientPtr pClient); static int SProcRenderCreateGlyphSet (ClientPtr pClient); static int SProcRenderReferenceGlyphSet (ClientPtr pClient); static int SProcRenderFreeGlyphSet (ClientPtr pClient); static int SProcRenderAddGlyphs (ClientPtr pClient); static int SProcRenderAddGlyphsFromPicture (ClientPtr pClient); static int SProcRenderFreeGlyphs (ClientPtr pClient); static int SProcRenderCompositeGlyphs (ClientPtr pClient); static int SProcRenderFillRectangles (ClientPtr pClient); static int SProcRenderCreateCursor (ClientPtr pClient); static int SProcRenderSetPictureTransform (ClientPtr pClient); static int SProcRenderQueryFilters (ClientPtr pClient); static int SProcRenderSetPictureFilter (ClientPtr pClient); static int SProcRenderCreateAnimCursor (ClientPtr pClient); static int SProcRenderAddTraps (ClientPtr pClient); static int SProcRenderCreateSolidFill (ClientPtr pClient); static int SProcRenderCreateLinearGradient (ClientPtr pClient); static int SProcRenderCreateRadialGradient (ClientPtr pClient); static int SProcRenderCreateConicalGradient (ClientPtr pClient); static int SProcRenderDispatch (ClientPtr pClient); int (*ProcRenderVector[RenderNumberRequests])(ClientPtr) = { ProcRenderQueryVersion, ProcRenderQueryPictFormats, ProcRenderQueryPictIndexValues, ProcRenderQueryDithers, ProcRenderCreatePicture, ProcRenderChangePicture, ProcRenderSetPictureClipRectangles, ProcRenderFreePicture, ProcRenderComposite, ProcRenderScale, ProcRenderTrapezoids, ProcRenderTriangles, ProcRenderTriStrip, ProcRenderTriFan, ProcRenderColorTrapezoids, ProcRenderColorTriangles, ProcRenderTransform, ProcRenderCreateGlyphSet, ProcRenderReferenceGlyphSet, ProcRenderFreeGlyphSet, ProcRenderAddGlyphs, ProcRenderAddGlyphsFromPicture, ProcRenderFreeGlyphs, ProcRenderCompositeGlyphs, ProcRenderCompositeGlyphs, ProcRenderCompositeGlyphs, ProcRenderFillRectangles, ProcRenderCreateCursor, ProcRenderSetPictureTransform, ProcRenderQueryFilters, ProcRenderSetPictureFilter, ProcRenderCreateAnimCursor, ProcRenderAddTraps, ProcRenderCreateSolidFill, ProcRenderCreateLinearGradient, ProcRenderCreateRadialGradient, ProcRenderCreateConicalGradient }; int (*SProcRenderVector[RenderNumberRequests])(ClientPtr) = { SProcRenderQueryVersion, SProcRenderQueryPictFormats, SProcRenderQueryPictIndexValues, SProcRenderQueryDithers, SProcRenderCreatePicture, SProcRenderChangePicture, SProcRenderSetPictureClipRectangles, SProcRenderFreePicture, SProcRenderComposite, SProcRenderScale, SProcRenderTrapezoids, SProcRenderTriangles, SProcRenderTriStrip, SProcRenderTriFan, SProcRenderColorTrapezoids, SProcRenderColorTriangles, SProcRenderTransform, SProcRenderCreateGlyphSet, SProcRenderReferenceGlyphSet, SProcRenderFreeGlyphSet, SProcRenderAddGlyphs, SProcRenderAddGlyphsFromPicture, SProcRenderFreeGlyphs, SProcRenderCompositeGlyphs, SProcRenderCompositeGlyphs, SProcRenderCompositeGlyphs, SProcRenderFillRectangles, SProcRenderCreateCursor, SProcRenderSetPictureTransform, SProcRenderQueryFilters, SProcRenderSetPictureFilter, SProcRenderCreateAnimCursor, SProcRenderAddTraps, SProcRenderCreateSolidFill, SProcRenderCreateLinearGradient, SProcRenderCreateRadialGradient, SProcRenderCreateConicalGradient }; int RenderErrBase; static DevPrivateKeyRec RenderClientPrivateKeyRec; #define RenderClientPrivateKey (&RenderClientPrivateKeyRec ) typedef struct _RenderClient { int major_version; int minor_version; } RenderClientRec, *RenderClientPtr; #define GetRenderClient(pClient) ((RenderClientPtr)dixLookupPrivate(&(pClient)->devPrivates, RenderClientPrivateKey)) static void RenderClientCallback (CallbackListPtr *list, pointer closure, pointer data) { NewClientInfoRec *clientinfo = (NewClientInfoRec *) data; ClientPtr pClient = clientinfo->client; RenderClientPtr pRenderClient = GetRenderClient (pClient); pRenderClient->major_version = 0; pRenderClient->minor_version = 0; } #ifdef PANORAMIX RESTYPE XRT_PICTURE; #endif void RenderExtensionInit (void) { ExtensionEntry *extEntry; if (!PictureType) return; if (!PictureFinishInit ()) return; if (!dixRegisterPrivateKey(&RenderClientPrivateKeyRec, PRIVATE_CLIENT, sizeof(RenderClientRec))) return; if (!AddCallback (&ClientStateCallback, RenderClientCallback, 0)) return; extEntry = AddExtension (RENDER_NAME, 0, RenderNumberErrors, ProcRenderDispatch, SProcRenderDispatch, NULL, StandardMinorOpcode); if (!extEntry) return; RenderErrBase = extEntry->errorBase; #ifdef PANORAMIX if (XRT_PICTURE) SetResourceTypeErrorValue(XRT_PICTURE, RenderErrBase + BadPicture); #endif SetResourceTypeErrorValue(PictureType, RenderErrBase + BadPicture); SetResourceTypeErrorValue(PictFormatType, RenderErrBase + BadPictFormat); SetResourceTypeErrorValue(GlyphSetType, RenderErrBase + BadGlyphSet); } static int ProcRenderQueryVersion (ClientPtr client) { RenderClientPtr pRenderClient = GetRenderClient (client); xRenderQueryVersionReply rep; REQUEST(xRenderQueryVersionReq); pRenderClient->major_version = stuff->majorVersion; pRenderClient->minor_version = stuff->minorVersion; REQUEST_SIZE_MATCH(xRenderQueryVersionReq); memset(&rep, 0, sizeof(xRenderQueryVersionReply)); rep.type = X_Reply; rep.length = 0; rep.sequenceNumber = client->sequence; if ((stuff->majorVersion * 1000 + stuff->minorVersion) < (SERVER_RENDER_MAJOR_VERSION * 1000 + SERVER_RENDER_MINOR_VERSION)) { rep.majorVersion = stuff->majorVersion; rep.minorVersion = stuff->minorVersion; } else { rep.majorVersion = SERVER_RENDER_MAJOR_VERSION; rep.minorVersion = SERVER_RENDER_MINOR_VERSION; } if (client->swapped) { swaps(&rep.sequenceNumber); swapl(&rep.length); swapl(&rep.majorVersion); swapl(&rep.minorVersion); } WriteToClient(client, sizeof(xRenderQueryVersionReply), (char *)&rep); return Success; } static VisualPtr findVisual (ScreenPtr pScreen, VisualID vid) { VisualPtr pVisual; int v; for (v = 0; v < pScreen->numVisuals; v++) { pVisual = pScreen->visuals + v; if (pVisual->vid == vid) return pVisual; } return 0; } static int ProcRenderQueryPictFormats (ClientPtr client) { RenderClientPtr pRenderClient = GetRenderClient (client); xRenderQueryPictFormatsReply *reply; xPictScreen *pictScreen; xPictDepth *pictDepth; xPictVisual *pictVisual; xPictFormInfo *pictForm; CARD32 *pictSubpixel; ScreenPtr pScreen; VisualPtr pVisual; DepthPtr pDepth; int v, d; PictureScreenPtr ps; PictFormatPtr pFormat; int nformat; int ndepth; int nvisual; int rlength; int s; int numScreens; int numSubpixel; /* REQUEST(xRenderQueryPictFormatsReq); */ REQUEST_SIZE_MATCH(xRenderQueryPictFormatsReq); #ifdef PANORAMIX if (noPanoramiXExtension) numScreens = screenInfo.numScreens; else numScreens = ((xConnSetup *)ConnectionInfo)->numRoots; #else numScreens = screenInfo.numScreens; #endif ndepth = nformat = nvisual = 0; for (s = 0; s < numScreens; s++) { pScreen = screenInfo.screens[s]; for (d = 0; d < pScreen->numDepths; d++) { pDepth = pScreen->allowedDepths + d; ++ndepth; for (v = 0; v < pDepth->numVids; v++) { pVisual = findVisual (pScreen, pDepth->vids[v]); if (pVisual && PictureMatchVisual (pScreen, pDepth->depth, pVisual)) ++nvisual; } } ps = GetPictureScreenIfSet(pScreen); if (ps) nformat += ps->nformats; } if (pRenderClient->major_version == 0 && pRenderClient->minor_version < 6) numSubpixel = 0; else numSubpixel = numScreens; rlength = (sizeof (xRenderQueryPictFormatsReply) + nformat * sizeof (xPictFormInfo) + numScreens * sizeof (xPictScreen) + ndepth * sizeof (xPictDepth) + nvisual * sizeof (xPictVisual) + numSubpixel * sizeof (CARD32)); reply = (xRenderQueryPictFormatsReply *) calloc(1, rlength); if (!reply) return BadAlloc; reply->type = X_Reply; reply->sequenceNumber = client->sequence; reply->length = bytes_to_int32(rlength - sizeof(xGenericReply)); reply->numFormats = nformat; reply->numScreens = numScreens; reply->numDepths = ndepth; reply->numVisuals = nvisual; reply->numSubpixel = numSubpixel; pictForm = (xPictFormInfo *) (reply + 1); for (s = 0; s < numScreens; s++) { pScreen = screenInfo.screens[s]; ps = GetPictureScreenIfSet(pScreen); if (ps) { for (nformat = 0, pFormat = ps->formats; nformat < ps->nformats; nformat++, pFormat++) { pictForm->id = pFormat->id; pictForm->type = pFormat->type; pictForm->depth = pFormat->depth; pictForm->direct.red = pFormat->direct.red; pictForm->direct.redMask = pFormat->direct.redMask; pictForm->direct.green = pFormat->direct.green; pictForm->direct.greenMask = pFormat->direct.greenMask; pictForm->direct.blue = pFormat->direct.blue; pictForm->direct.blueMask = pFormat->direct.blueMask; pictForm->direct.alpha = pFormat->direct.alpha; pictForm->direct.alphaMask = pFormat->direct.alphaMask; if (pFormat->type == PictTypeIndexed && pFormat->index.pColormap) pictForm->colormap = pFormat->index.pColormap->mid; else pictForm->colormap = None; if (client->swapped) { swapl(&pictForm->id); swaps(&pictForm->direct.red); swaps(&pictForm->direct.redMask); swaps(&pictForm->direct.green); swaps(&pictForm->direct.greenMask); swaps(&pictForm->direct.blue); swaps(&pictForm->direct.blueMask); swaps(&pictForm->direct.alpha); swaps(&pictForm->direct.alphaMask); swapl(&pictForm->colormap); } pictForm++; } } } pictScreen = (xPictScreen *) pictForm; for (s = 0; s < numScreens; s++) { pScreen = screenInfo.screens[s]; pictDepth = (xPictDepth *) (pictScreen + 1); ndepth = 0; for (d = 0; d < pScreen->numDepths; d++) { pictVisual = (xPictVisual *) (pictDepth + 1); pDepth = pScreen->allowedDepths + d; nvisual = 0; for (v = 0; v < pDepth->numVids; v++) { pVisual = findVisual (pScreen, pDepth->vids[v]); if (pVisual && (pFormat = PictureMatchVisual (pScreen, pDepth->depth, pVisual))) { pictVisual->visual = pVisual->vid; pictVisual->format = pFormat->id; if (client->swapped) { swapl(&pictVisual->visual); swapl(&pictVisual->format); } pictVisual++; nvisual++; } } pictDepth->depth = pDepth->depth; pictDepth->nPictVisuals = nvisual; if (client->swapped) { swaps(&pictDepth->nPictVisuals); } ndepth++; pictDepth = (xPictDepth *) pictVisual; } pictScreen->nDepth = ndepth; ps = GetPictureScreenIfSet(pScreen); if (ps) pictScreen->fallback = ps->fallback->id; else pictScreen->fallback = 0; if (client->swapped) { swapl(&pictScreen->nDepth); swapl(&pictScreen->fallback); } pictScreen = (xPictScreen *) pictDepth; } pictSubpixel = (CARD32 *) pictScreen; for (s = 0; s < numSubpixel; s++) { pScreen = screenInfo.screens[s]; ps = GetPictureScreenIfSet(pScreen); if (ps) *pictSubpixel = ps->subpixel; else *pictSubpixel = SubPixelUnknown; if (client->swapped) { swapl(pictSubpixel); } ++pictSubpixel; } if (client->swapped) { swaps(&reply->sequenceNumber); swapl(&reply->length); swapl(&reply->numFormats); swapl(&reply->numScreens); swapl(&reply->numDepths); swapl(&reply->numVisuals); swapl(&reply->numSubpixel); } WriteToClient(client, rlength, (char *) reply); free(reply); return Success; } static int ProcRenderQueryPictIndexValues (ClientPtr client) { PictFormatPtr pFormat; int rc, num; int rlength; int i; REQUEST(xRenderQueryPictIndexValuesReq); xRenderQueryPictIndexValuesReply *reply; xIndexValue *values; REQUEST_AT_LEAST_SIZE(xRenderQueryPictIndexValuesReq); rc = dixLookupResourceByType((pointer *)&pFormat, stuff->format, PictFormatType, client, DixReadAccess); if (rc != Success) return rc; if (pFormat->type != PictTypeIndexed) { client->errorValue = stuff->format; return BadMatch; } num = pFormat->index.nvalues; rlength = (sizeof (xRenderQueryPictIndexValuesReply) + num * sizeof(xIndexValue)); reply = (xRenderQueryPictIndexValuesReply *) malloc(rlength); if (!reply) return BadAlloc; reply->type = X_Reply; reply->sequenceNumber = client->sequence; reply->length = bytes_to_int32(rlength - sizeof(xGenericReply)); reply->numIndexValues = num; values = (xIndexValue *) (reply + 1); memcpy (reply + 1, pFormat->index.pValues, num * sizeof (xIndexValue)); if (client->swapped) { for (i = 0; i < num; i++) { swapl(&values[i].pixel); swaps(&values[i].red); swaps(&values[i].green); swaps(&values[i].blue); swaps(&values[i].alpha); } swaps(&reply->sequenceNumber); swapl(&reply->length); swapl(&reply->numIndexValues); } WriteToClient(client, rlength, (char *) reply); free(reply); return Success; } static int ProcRenderQueryDithers (ClientPtr client) { return BadImplementation; } static int ProcRenderCreatePicture (ClientPtr client) { PicturePtr pPicture; DrawablePtr pDrawable; PictFormatPtr pFormat; int len, error, rc; REQUEST(xRenderCreatePictureReq); REQUEST_AT_LEAST_SIZE(xRenderCreatePictureReq); LEGAL_NEW_RESOURCE(stuff->pid, client); rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, DixReadAccess|DixAddAccess); if (rc != Success) return rc; rc = dixLookupResourceByType((pointer *)&pFormat, stuff->format, PictFormatType, client, DixReadAccess); if (rc != Success) return rc; if (pFormat->depth != pDrawable->depth) return BadMatch; len = client->req_len - bytes_to_int32(sizeof(xRenderCreatePictureReq)); if (Ones(stuff->mask) != len) return BadLength; pPicture = CreatePicture (stuff->pid, pDrawable, pFormat, stuff->mask, (XID *) (stuff + 1), client, &error); if (!pPicture) return error; if (!AddResource (stuff->pid, PictureType, (pointer)pPicture)) return BadAlloc; return Success; } static int ProcRenderChangePicture (ClientPtr client) { PicturePtr pPicture; REQUEST(xRenderChangePictureReq); int len; REQUEST_AT_LEAST_SIZE(xRenderChangePictureReq); VERIFY_PICTURE (pPicture, stuff->picture, client, DixSetAttrAccess); len = client->req_len - bytes_to_int32(sizeof(xRenderChangePictureReq)); if (Ones(stuff->mask) != len) return BadLength; return ChangePicture (pPicture, stuff->mask, (XID *) (stuff + 1), (DevUnion *) 0, client); } static int ProcRenderSetPictureClipRectangles (ClientPtr client) { REQUEST(xRenderSetPictureClipRectanglesReq); PicturePtr pPicture; int nr; REQUEST_AT_LEAST_SIZE(xRenderSetPictureClipRectanglesReq); VERIFY_PICTURE (pPicture, stuff->picture, client, DixSetAttrAccess); if (!pPicture->pDrawable) return BadDrawable; nr = (client->req_len << 2) - sizeof(xRenderSetPictureClipRectanglesReq); if (nr & 4) return BadLength; nr >>= 3; return SetPictureClipRects (pPicture, stuff->xOrigin, stuff->yOrigin, nr, (xRectangle *) &stuff[1]); } static int ProcRenderFreePicture (ClientPtr client) { PicturePtr pPicture; REQUEST(xRenderFreePictureReq); REQUEST_SIZE_MATCH(xRenderFreePictureReq); VERIFY_PICTURE (pPicture, stuff->picture, client, DixDestroyAccess); FreeResource (stuff->picture, RT_NONE); return Success; } static Bool PictOpValid (CARD8 op) { if (/*PictOpMinimum <= op && */ op <= PictOpMaximum) return TRUE; if (PictOpDisjointMinimum <= op && op <= PictOpDisjointMaximum) return TRUE; if (PictOpConjointMinimum <= op && op <= PictOpConjointMaximum) return TRUE; if (PictOpBlendMinimum <= op && op <= PictOpBlendMaximum) return TRUE; return FALSE; } static int ProcRenderComposite (ClientPtr client) { PicturePtr pSrc, pMask, pDst; REQUEST(xRenderCompositeReq); REQUEST_SIZE_MATCH(xRenderCompositeReq); if (!PictOpValid (stuff->op)) { client->errorValue = stuff->op; return BadValue; } VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess); if (!pDst->pDrawable) return BadDrawable; VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess); VERIFY_ALPHA (pMask, stuff->mask, client, DixReadAccess); if ((pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) || (pMask && pMask->pDrawable && pDst->pDrawable->pScreen != pMask->pDrawable->pScreen)) return BadMatch; CompositePicture (stuff->op, pSrc, pMask, pDst, stuff->xSrc, stuff->ySrc, stuff->xMask, stuff->yMask, stuff->xDst, stuff->yDst, stuff->width, stuff->height); return Success; } static int ProcRenderScale (ClientPtr client) { return BadImplementation; } static int ProcRenderTrapezoids (ClientPtr client) { int rc, ntraps; PicturePtr pSrc, pDst; PictFormatPtr pFormat; REQUEST(xRenderTrapezoidsReq); REQUEST_AT_LEAST_SIZE(xRenderTrapezoidsReq); if (!PictOpValid (stuff->op)) { client->errorValue = stuff->op; return BadValue; } VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess); VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess); if (!pDst->pDrawable) return BadDrawable; if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) return BadMatch; if (stuff->maskFormat) { rc = dixLookupResourceByType((pointer *)&pFormat, stuff->maskFormat, PictFormatType, client, DixReadAccess); if (rc != Success) return rc; } else pFormat = 0; ntraps = (client->req_len << 2) - sizeof (xRenderTrapezoidsReq); if (ntraps % sizeof (xTrapezoid)) return BadLength; ntraps /= sizeof (xTrapezoid); if (ntraps) CompositeTrapezoids (stuff->op, pSrc, pDst, pFormat, stuff->xSrc, stuff->ySrc, ntraps, (xTrapezoid *) &stuff[1]); return Success; } static int ProcRenderTriangles (ClientPtr client) { int rc, ntris; PicturePtr pSrc, pDst; PictFormatPtr pFormat; REQUEST(xRenderTrianglesReq); REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq); if (!PictOpValid (stuff->op)) { client->errorValue = stuff->op; return BadValue; } VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess); VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess); if (!pDst->pDrawable) return BadDrawable; if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) return BadMatch; if (stuff->maskFormat) { rc = dixLookupResourceByType((pointer *)&pFormat, stuff->maskFormat, PictFormatType, client, DixReadAccess); if (rc != Success) return rc; } else pFormat = 0; ntris = (client->req_len << 2) - sizeof (xRenderTrianglesReq); if (ntris % sizeof (xTriangle)) return BadLength; ntris /= sizeof (xTriangle); if (ntris) CompositeTriangles (stuff->op, pSrc, pDst, pFormat, stuff->xSrc, stuff->ySrc, ntris, (xTriangle *) &stuff[1]); return Success; } static int ProcRenderTriStrip (ClientPtr client) { int rc, npoints; PicturePtr pSrc, pDst; PictFormatPtr pFormat; REQUEST(xRenderTrianglesReq); REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq); if (!PictOpValid (stuff->op)) { client->errorValue = stuff->op; return BadValue; } VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess); VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess); if (!pDst->pDrawable) return BadDrawable; if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) return BadMatch; if (stuff->maskFormat) { rc = dixLookupResourceByType((pointer *)&pFormat, stuff->maskFormat, PictFormatType, client, DixReadAccess); if (rc != Success) return rc; } else pFormat = 0; npoints = ((client->req_len << 2) - sizeof (xRenderTriStripReq)); if (npoints & 4) return BadLength; npoints >>= 3; if (npoints >= 3) CompositeTriStrip (stuff->op, pSrc, pDst, pFormat, stuff->xSrc, stuff->ySrc, npoints, (xPointFixed *) &stuff[1]); return Success; } static int ProcRenderTriFan (ClientPtr client) { int rc, npoints; PicturePtr pSrc, pDst; PictFormatPtr pFormat; REQUEST(xRenderTrianglesReq); REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq); if (!PictOpValid (stuff->op)) { client->errorValue = stuff->op; return BadValue; } VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess); VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess); if (!pDst->pDrawable) return BadDrawable; if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) return BadMatch; if (stuff->maskFormat) { rc = dixLookupResourceByType((pointer *)&pFormat, stuff->maskFormat, PictFormatType, client, DixReadAccess); if (rc != Success) return rc; } else pFormat = 0; npoints = ((client->req_len << 2) - sizeof (xRenderTriStripReq)); if (npoints & 4) return BadLength; npoints >>= 3; if (npoints >= 3) CompositeTriFan (stuff->op, pSrc, pDst, pFormat, stuff->xSrc, stuff->ySrc, npoints, (xPointFixed *) &stuff[1]); return Success; } static int ProcRenderColorTrapezoids (ClientPtr client) { return BadImplementation; } static int ProcRenderColorTriangles (ClientPtr client) { return BadImplementation; } static int ProcRenderTransform (ClientPtr client) { return BadImplementation; } static int ProcRenderCreateGlyphSet (ClientPtr client) { GlyphSetPtr glyphSet; PictFormatPtr format; int rc, f; REQUEST(xRenderCreateGlyphSetReq); REQUEST_SIZE_MATCH(xRenderCreateGlyphSetReq); LEGAL_NEW_RESOURCE(stuff->gsid, client); rc = dixLookupResourceByType((pointer *)&format, stuff->format, PictFormatType, client, DixReadAccess); if (rc != Success) return rc; switch (format->depth) { case 1: f = GlyphFormat1; break; case 4: f = GlyphFormat4; break; case 8: f = GlyphFormat8; break; case 16: f = GlyphFormat16; break; case 32: f = GlyphFormat32; break; default: return BadMatch; } if (format->type != PictTypeDirect) return BadMatch; glyphSet = AllocateGlyphSet (f, format); if (!glyphSet) return BadAlloc; /* security creation/labeling check */ rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->gsid, GlyphSetType, glyphSet, RT_NONE, NULL, DixCreateAccess); if (rc != Success) return rc; if (!AddResource (stuff->gsid, GlyphSetType, (pointer)glyphSet)) return BadAlloc; return Success; } static int ProcRenderReferenceGlyphSet (ClientPtr client) { GlyphSetPtr glyphSet; int rc; REQUEST(xRenderReferenceGlyphSetReq); REQUEST_SIZE_MATCH(xRenderReferenceGlyphSetReq); LEGAL_NEW_RESOURCE(stuff->gsid, client); rc = dixLookupResourceByType((pointer *)&glyphSet, stuff->existing, GlyphSetType, client, DixGetAttrAccess); if (rc != Success) { client->errorValue = stuff->existing; return rc; } glyphSet->refcnt++; if (!AddResource (stuff->gsid, GlyphSetType, (pointer)glyphSet)) return BadAlloc; return Success; } #define NLOCALDELTA 64 #define NLOCALGLYPH 256 static int ProcRenderFreeGlyphSet (ClientPtr client) { GlyphSetPtr glyphSet; int rc; REQUEST(xRenderFreeGlyphSetReq); REQUEST_SIZE_MATCH(xRenderFreeGlyphSetReq); rc = dixLookupResourceByType((pointer *)&glyphSet, stuff->glyphset, GlyphSetType, client, DixDestroyAccess); if (rc != Success) { client->errorValue = stuff->glyphset; return rc; } FreeResource (stuff->glyphset, RT_NONE); return Success; } typedef struct _GlyphNew { Glyph id; GlyphPtr glyph; Bool found; unsigned char sha1[20]; } GlyphNewRec, *GlyphNewPtr; #define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0) static int ProcRenderAddGlyphs (ClientPtr client) { GlyphSetPtr glyphSet; REQUEST(xRenderAddGlyphsReq); GlyphNewRec glyphsLocal[NLOCALGLYPH]; GlyphNewPtr glyphsBase, glyphs, glyph_new; int remain, nglyphs; CARD32 *gids; xGlyphInfo *gi; CARD8 *bits; unsigned int size; int err; int i, screen; PicturePtr pSrc = NULL, pDst = NULL; PixmapPtr pSrcPix = NULL, pDstPix = NULL; CARD32 component_alpha; REQUEST_AT_LEAST_SIZE(xRenderAddGlyphsReq); err = dixLookupResourceByType((pointer *)&glyphSet, stuff->glyphset, GlyphSetType, client, DixAddAccess); if (err != Success) { client->errorValue = stuff->glyphset; return err; } err = BadAlloc; nglyphs = stuff->nglyphs; if (nglyphs > UINT32_MAX / sizeof(GlyphNewRec)) return BadAlloc; component_alpha = NeedsComponent (glyphSet->format->format); if (nglyphs <= NLOCALGLYPH) { memset (glyphsLocal, 0, sizeof (glyphsLocal)); glyphsBase = glyphsLocal; } else { glyphsBase = (GlyphNewPtr)calloc(nglyphs, sizeof (GlyphNewRec)); if (!glyphsBase) return BadAlloc; } remain = (client->req_len << 2) - sizeof (xRenderAddGlyphsReq); glyphs = glyphsBase; gids = (CARD32 *) (stuff + 1); gi = (xGlyphInfo *) (gids + nglyphs); bits = (CARD8 *) (gi + nglyphs); remain -= (sizeof (CARD32) + sizeof (xGlyphInfo)) * nglyphs; /* protect against bad nglyphs */ if (gi < ((xGlyphInfo *)stuff) || gi > ((xGlyphInfo *)((CARD32 *)stuff + client->req_len)) || bits < ((CARD8 *)stuff) || bits > ((CARD8 *)((CARD32 *)stuff + client->req_len))) { err = BadLength; goto bail; } for (i = 0; i < nglyphs; i++) { size_t padded_width; glyph_new = &glyphs[i]; padded_width = PixmapBytePad (gi[i].width, glyphSet->format->depth); if (gi[i].height && padded_width > (UINT32_MAX - sizeof(GlyphRec))/gi[i].height) break; size = gi[i].height * padded_width; if (remain < size) break; err = HashGlyph (&gi[i], bits, size, glyph_new->sha1); if (err) goto bail; glyph_new->glyph = FindGlyphByHash (glyph_new->sha1, glyphSet->fdepth); if (glyph_new->glyph && glyph_new->glyph != DeletedGlyph) { glyph_new->found = TRUE; } else { GlyphPtr glyph; glyph_new->found = FALSE; glyph_new->glyph = glyph = AllocateGlyph (&gi[i], glyphSet->fdepth); if (! glyph) { err = BadAlloc; goto bail; } for (screen = 0; screen < screenInfo.numScreens; screen++) { int width = gi[i].width; int height = gi[i].height; int depth = glyphSet->format->depth; ScreenPtr pScreen; int error; /* Skip work if it's invisibly small anyway */ if (!width || !height) break; pScreen = screenInfo.screens[screen]; pSrcPix = GetScratchPixmapHeader (pScreen, width, height, depth, depth, -1, bits); if (! pSrcPix) { err = BadAlloc; goto bail; } pSrc = CreatePicture (0, &pSrcPix->drawable, glyphSet->format, 0, NULL, serverClient, &error); if (! pSrc) { err = BadAlloc; goto bail; } pDstPix = (pScreen->CreatePixmap) (pScreen, width, height, depth, CREATE_PIXMAP_USAGE_GLYPH_PICTURE); if (!pDstPix) { err = BadAlloc; goto bail; } GlyphPicture (glyph)[screen] = pDst = CreatePicture (0, &pDstPix->drawable, glyphSet->format, CPComponentAlpha, &component_alpha, serverClient, &error); /* The picture takes a reference to the pixmap, so we drop ours. */ (pScreen->DestroyPixmap) (pDstPix); pDstPix = NULL; if (! pDst) { err = BadAlloc; goto bail; } CompositePicture (PictOpSrc, pSrc, None, pDst, 0, 0, 0, 0, 0, 0, width, height); FreePicture ((pointer) pSrc, 0); pSrc = NULL; FreeScratchPixmapHeader (pSrcPix); pSrcPix = NULL; } memcpy (glyph_new->glyph->sha1, glyph_new->sha1, 20); } glyph_new->id = gids[i]; if (size & 3) size += 4 - (size & 3); bits += size; remain -= size; } if (remain || i < nglyphs) { err = BadLength; goto bail; } if (!ResizeGlyphSet (glyphSet, nglyphs)) { err = BadAlloc; goto bail; } for (i = 0; i < nglyphs; i++) AddGlyph (glyphSet, glyphs[i].glyph, glyphs[i].id); if (glyphsBase != glyphsLocal) free(glyphsBase); return Success; bail: if (pSrc) FreePicture ((pointer) pSrc, 0); if (pSrcPix) FreeScratchPixmapHeader (pSrcPix); for (i = 0; i < nglyphs; i++) if (glyphs[i].glyph && ! glyphs[i].found) free(glyphs[i].glyph); if (glyphsBase != glyphsLocal) free(glyphsBase); return err; } static int ProcRenderAddGlyphsFromPicture (ClientPtr client) { return BadImplementation; } static int ProcRenderFreeGlyphs (ClientPtr client) { REQUEST(xRenderFreeGlyphsReq); GlyphSetPtr glyphSet; int rc, nglyph; CARD32 *gids; CARD32 glyph; REQUEST_AT_LEAST_SIZE(xRenderFreeGlyphsReq); rc = dixLookupResourceByType((pointer *)&glyphSet, stuff->glyphset, GlyphSetType, client, DixRemoveAccess); if (rc != Success) { client->errorValue = stuff->glyphset; return rc; } nglyph = bytes_to_int32((client->req_len << 2) - sizeof (xRenderFreeGlyphsReq)); gids = (CARD32 *) (stuff + 1); while (nglyph-- > 0) { glyph = *gids++; if (!DeleteGlyph (glyphSet, glyph)) { client->errorValue = glyph; return RenderErrBase + BadGlyph; } } return Success; } static int ProcRenderCompositeGlyphs (ClientPtr client) { GlyphSetPtr glyphSet; GlyphSet gs; PicturePtr pSrc, pDst; PictFormatPtr pFormat; GlyphListRec listsLocal[NLOCALDELTA]; GlyphListPtr lists, listsBase; GlyphPtr glyphsLocal[NLOCALGLYPH]; Glyph glyph; GlyphPtr *glyphs, *glyphsBase; xGlyphElt *elt; CARD8 *buffer, *end; int nglyph; int nlist; int space; int size; int rc, n; REQUEST(xRenderCompositeGlyphsReq); REQUEST_AT_LEAST_SIZE(xRenderCompositeGlyphsReq); switch (stuff->renderReqType) { default: size = 1; break; case X_RenderCompositeGlyphs16: size = 2; break; case X_RenderCompositeGlyphs32: size = 4; break; } if (!PictOpValid (stuff->op)) { client->errorValue = stuff->op; return BadValue; } VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess); VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess); if (!pDst->pDrawable) return BadDrawable; if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) return BadMatch; if (stuff->maskFormat) { rc = dixLookupResourceByType((pointer *)&pFormat, stuff->maskFormat, PictFormatType, client, DixReadAccess); if (rc != Success) return rc; } else pFormat = 0; rc = dixLookupResourceByType((pointer *)&glyphSet, stuff->glyphset, GlyphSetType, client, DixUseAccess); if (rc != Success) return rc; buffer = (CARD8 *) (stuff + 1); end = (CARD8 *) stuff + (client->req_len << 2); nglyph = 0; nlist = 0; while (buffer + sizeof (xGlyphElt) < end) { elt = (xGlyphElt *) buffer; buffer += sizeof (xGlyphElt); if (elt->len == 0xff) { buffer += 4; } else { nlist++; nglyph += elt->len; space = size * elt->len; if (space & 3) space += 4 - (space & 3); buffer += space; } } if (nglyph <= NLOCALGLYPH) glyphsBase = glyphsLocal; else { glyphsBase = (GlyphPtr *) malloc(nglyph * sizeof (GlyphPtr)); if (!glyphsBase) return BadAlloc; } if (nlist <= NLOCALDELTA) listsBase = listsLocal; else { listsBase = (GlyphListPtr) malloc(nlist * sizeof (GlyphListRec)); if (!listsBase) { rc = BadAlloc; goto bail; } } buffer = (CARD8 *) (stuff + 1); glyphs = glyphsBase; lists = listsBase; while (buffer + sizeof (xGlyphElt) < end) { elt = (xGlyphElt *) buffer; buffer += sizeof (xGlyphElt); if (elt->len == 0xff) { if (buffer + sizeof (GlyphSet) < end) { memcpy(&gs, buffer, sizeof(GlyphSet)); rc = dixLookupResourceByType((pointer *)&glyphSet, gs, GlyphSetType, client, DixUseAccess); if (rc != Success) goto bail; } buffer += 4; } else { lists->xOff = elt->deltax; lists->yOff = elt->deltay; lists->format = glyphSet->format; lists->len = 0; n = elt->len; while (n--) { if (buffer + size <= end) { switch (size) { case 1: glyph = *((CARD8 *)buffer); break; case 2: glyph = *((CARD16 *)buffer); break; case 4: default: glyph = *((CARD32 *)buffer); break; } if ((*glyphs = FindGlyph (glyphSet, glyph))) { lists->len++; glyphs++; } } buffer += size; } space = size * elt->len; if (space & 3) buffer += 4 - (space & 3); lists++; } } if (buffer > end) { rc = BadLength; goto bail; } CompositeGlyphs (stuff->op, pSrc, pDst, pFormat, stuff->xSrc, stuff->ySrc, nlist, listsBase, glyphsBase); rc = Success; bail: if (glyphsBase != glyphsLocal) free(glyphsBase); if (listsBase != listsLocal) free(listsBase); return rc; } static int ProcRenderFillRectangles (ClientPtr client) { PicturePtr pDst; int things; REQUEST(xRenderFillRectanglesReq); REQUEST_AT_LEAST_SIZE (xRenderFillRectanglesReq); if (!PictOpValid (stuff->op)) { client->errorValue = stuff->op; return BadValue; } VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess); if (!pDst->pDrawable) return BadDrawable; things = (client->req_len << 2) - sizeof(xRenderFillRectanglesReq); if (things & 4) return BadLength; things >>= 3; CompositeRects (stuff->op, pDst, &stuff->color, things, (xRectangle *) &stuff[1]); return Success; } static void RenderSetBit (unsigned char *line, int x, int bit) { unsigned char mask; if (screenInfo.bitmapBitOrder == LSBFirst) mask = (1 << (x & 7)); else mask = (0x80 >> (x & 7)); /* XXX assumes byte order is host byte order */ line += (x >> 3); if (bit) *line |= mask; else *line &= ~mask; } #define DITHER_DIM 2 static CARD32 orderedDither[DITHER_DIM][DITHER_DIM] = { { 1, 3, }, { 4, 2, }, }; #define DITHER_SIZE ((sizeof orderedDither / sizeof orderedDither[0][0]) + 1) static int ProcRenderCreateCursor (ClientPtr client) { REQUEST(xRenderCreateCursorReq); PicturePtr pSrc; ScreenPtr pScreen; unsigned short width, height; CARD32 *argbbits, *argb; unsigned char *srcbits, *srcline; unsigned char *mskbits, *mskline; int stride; int x, y; int nbytes_mono; CursorMetricRec cm; CursorPtr pCursor; CARD32 twocolor[3]; int rc, ncolor; REQUEST_SIZE_MATCH (xRenderCreateCursorReq); LEGAL_NEW_RESOURCE(stuff->cid, client); VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess); if (!pSrc->pDrawable) return BadDrawable; pScreen = pSrc->pDrawable->pScreen; width = pSrc->pDrawable->width; height = pSrc->pDrawable->height; if (height && width > UINT32_MAX/(height*sizeof(CARD32))) return BadAlloc; if ( stuff->x > width || stuff->y > height ) return BadMatch; argbbits = malloc(width * height * sizeof (CARD32)); if (!argbbits) return BadAlloc; stride = BitmapBytePad(width); nbytes_mono = stride*height; srcbits = calloc(1, nbytes_mono); if (!srcbits) { free(argbbits); return BadAlloc; } mskbits = calloc(1, nbytes_mono); if (!mskbits) { free(argbbits); free(srcbits); return BadAlloc; } if (pSrc->format == PICT_a8r8g8b8) { (*pScreen->GetImage) (pSrc->pDrawable, 0, 0, width, height, ZPixmap, 0xffffffff, (pointer) argbbits); } else { PixmapPtr pPixmap; PicturePtr pPicture; PictFormatPtr pFormat; int error; pFormat = PictureMatchFormat (pScreen, 32, PICT_a8r8g8b8); if (!pFormat) { free(argbbits); free(srcbits); free(mskbits); return BadImplementation; } pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, 32, CREATE_PIXMAP_USAGE_SCRATCH); if (!pPixmap) { free(argbbits); free(srcbits); free(mskbits); return BadAlloc; } pPicture = CreatePicture (0, &pPixmap->drawable, pFormat, 0, 0, client, &error); if (!pPicture) { free(argbbits); free(srcbits); free(mskbits); return error; } (*pScreen->DestroyPixmap) (pPixmap); CompositePicture (PictOpSrc, pSrc, 0, pPicture, 0, 0, 0, 0, 0, 0, width, height); (*pScreen->GetImage) (pPicture->pDrawable, 0, 0, width, height, ZPixmap, 0xffffffff, (pointer) argbbits); FreePicture (pPicture, 0); } /* * Check whether the cursor can be directly supported by * the core cursor code */ ncolor = 0; argb = argbbits; for (y = 0; ncolor <= 2 && y < height; y++) { for (x = 0; ncolor <= 2 && x < width; x++) { CARD32 p = *argb++; CARD32 a = (p >> 24); if (a == 0) /* transparent */ continue; if (a == 0xff) /* opaque */ { int n; for (n = 0; n < ncolor; n++) if (p == twocolor[n]) break; if (n == ncolor) twocolor[ncolor++] = p; } else ncolor = 3; } } /* * Convert argb image to two plane cursor */ srcline = srcbits; mskline = mskbits; argb = argbbits; for (y = 0; y < height; y++) { for (x = 0; x < width; x++) { CARD32 p = *argb++; if (ncolor <= 2) { CARD32 a = ((p >> 24)); RenderSetBit (mskline, x, a != 0); RenderSetBit (srcline, x, a != 0 && p == twocolor[0]); } else { CARD32 a = ((p >> 24) * DITHER_SIZE + 127) / 255; CARD32 i = ((CvtR8G8B8toY15(p) >> 7) * DITHER_SIZE + 127) / 255; CARD32 d = orderedDither[y&(DITHER_DIM-1)][x&(DITHER_DIM-1)]; /* Set mask from dithered alpha value */ RenderSetBit(mskline, x, a > d); /* Set src from dithered intensity value */ RenderSetBit(srcline, x, a > d && i <= d); } } srcline += stride; mskline += stride; } /* * Dither to white and black if the cursor has more than two colors */ if (ncolor > 2) { twocolor[0] = 0xff000000; twocolor[1] = 0xffffffff; } else { free(argbbits); argbbits = 0; } #define GetByte(p,s) (((p) >> (s)) & 0xff) #define GetColor(p,s) (GetByte(p,s) | (GetByte(p,s) << 8)) cm.width = width; cm.height = height; cm.xhot = stuff->x; cm.yhot = stuff->y; rc = AllocARGBCursor(srcbits, mskbits, argbbits, &cm, GetColor(twocolor[0], 16), GetColor(twocolor[0], 8), GetColor(twocolor[0], 0), GetColor(twocolor[1], 16), GetColor(twocolor[1], 8), GetColor(twocolor[1], 0), &pCursor, client, stuff->cid); if (rc != Success) goto bail; if (!AddResource(stuff->cid, RT_CURSOR, (pointer)pCursor)) { rc = BadAlloc; goto bail; } return Success; bail: free(srcbits); free(mskbits); return rc; } static int ProcRenderSetPictureTransform (ClientPtr client) { REQUEST(xRenderSetPictureTransformReq); PicturePtr pPicture; REQUEST_SIZE_MATCH(xRenderSetPictureTransformReq); VERIFY_PICTURE (pPicture, stuff->picture, client, DixSetAttrAccess); return SetPictureTransform (pPicture, (PictTransform *) &stuff->transform); } static int ProcRenderQueryFilters (ClientPtr client) { REQUEST (xRenderQueryFiltersReq); DrawablePtr pDrawable; xRenderQueryFiltersReply *reply; int nbytesName; int nnames; ScreenPtr pScreen; PictureScreenPtr ps; int i, j, len, total_bytes, rc; INT16 *aliases; char *names; REQUEST_SIZE_MATCH(xRenderQueryFiltersReq); rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0, DixGetAttrAccess); if (rc != Success) return rc; pScreen = pDrawable->pScreen; nbytesName = 0; nnames = 0; ps = GetPictureScreenIfSet(pScreen); if (ps) { for (i = 0; i < ps->nfilters; i++) nbytesName += 1 + strlen (ps->filters[i].name); for (i = 0; i < ps->nfilterAliases; i++) nbytesName += 1 + strlen (ps->filterAliases[i].alias); nnames = ps->nfilters + ps->nfilterAliases; } len = ((nnames + 1) >> 1) + bytes_to_int32(nbytesName); total_bytes = sizeof (xRenderQueryFiltersReply) + (len << 2); reply = (xRenderQueryFiltersReply *) malloc(total_bytes); if (!reply) return BadAlloc; aliases = (INT16 *) (reply + 1); names = (char *) (aliases + ((nnames + 1) & ~1)); reply->type = X_Reply; reply->sequenceNumber = client->sequence; reply->length = len; reply->numAliases = nnames; reply->numFilters = nnames; if (ps) { /* fill in alias values */ for (i = 0; i < ps->nfilters; i++) aliases[i] = FilterAliasNone; for (i = 0; i < ps->nfilterAliases; i++) { for (j = 0; j < ps->nfilters; j++) if (ps->filterAliases[i].filter_id == ps->filters[j].id) break; if (j == ps->nfilters) { for (j = 0; j < ps->nfilterAliases; j++) if (ps->filterAliases[i].filter_id == ps->filterAliases[j].alias_id) { break; } if (j == ps->nfilterAliases) j = FilterAliasNone; else j = j + ps->nfilters; } aliases[i + ps->nfilters] = j; } /* fill in filter names */ for (i = 0; i < ps->nfilters; i++) { j = strlen (ps->filters[i].name); *names++ = j; memcpy (names, ps->filters[i].name, j); names += j; } /* fill in filter alias names */ for (i = 0; i < ps->nfilterAliases; i++) { j = strlen (ps->filterAliases[i].alias); *names++ = j; memcpy (names, ps->filterAliases[i].alias, j); names += j; } } if (client->swapped) { for (i = 0; i < reply->numAliases; i++) { swaps(&aliases[i]); } swaps(&reply->sequenceNumber); swapl(&reply->length); swapl(&reply->numAliases); swapl(&reply->numFilters); } WriteToClient(client, total_bytes, (char *) reply); free(reply); return Success; } static int ProcRenderSetPictureFilter (ClientPtr client) { REQUEST (xRenderSetPictureFilterReq); PicturePtr pPicture; int result; xFixed *params; int nparams; char *name; REQUEST_AT_LEAST_SIZE (xRenderSetPictureFilterReq); VERIFY_PICTURE (pPicture, stuff->picture, client, DixSetAttrAccess); name = (char *) (stuff + 1); params = (xFixed *) (name + pad_to_int32(stuff->nbytes)); nparams = ((xFixed *) stuff + client->req_len) - params; result = SetPictureFilter (pPicture, name, stuff->nbytes, params, nparams); return result; } static int ProcRenderCreateAnimCursor (ClientPtr client) { REQUEST(xRenderCreateAnimCursorReq); CursorPtr *cursors; CARD32 *deltas; CursorPtr pCursor; int ncursor; xAnimCursorElt *elt; int i; int ret; REQUEST_AT_LEAST_SIZE(xRenderCreateAnimCursorReq); LEGAL_NEW_RESOURCE(stuff->cid, client); if (client->req_len & 1) return BadLength; ncursor = (client->req_len - (bytes_to_int32(sizeof(xRenderCreateAnimCursorReq)))) >> 1; cursors = malloc(ncursor * (sizeof (CursorPtr) + sizeof (CARD32))); if (!cursors) return BadAlloc; deltas = (CARD32 *) (cursors + ncursor); elt = (xAnimCursorElt *) (stuff + 1); for (i = 0; i < ncursor; i++) { ret = dixLookupResourceByType((pointer *)(cursors + i), elt->cursor, RT_CURSOR, client, DixReadAccess); if (ret != Success) { free(cursors); return ret; } deltas[i] = elt->delay; elt++; } ret = AnimCursorCreate (cursors, deltas, ncursor, &pCursor, client, stuff->cid); free(cursors); if (ret != Success) return ret; if (AddResource (stuff->cid, RT_CURSOR, (pointer)pCursor)) return Success; return BadAlloc; } static int ProcRenderAddTraps (ClientPtr client) { int ntraps; PicturePtr pPicture; REQUEST(xRenderAddTrapsReq); REQUEST_AT_LEAST_SIZE(xRenderAddTrapsReq); VERIFY_PICTURE (pPicture, stuff->picture, client, DixWriteAccess); if (!pPicture->pDrawable) return BadDrawable; ntraps = (client->req_len << 2) - sizeof (xRenderAddTrapsReq); if (ntraps % sizeof (xTrap)) return BadLength; ntraps /= sizeof (xTrap); if (ntraps) AddTraps (pPicture, stuff->xOff, stuff->yOff, ntraps, (xTrap *) &stuff[1]); return Success; } static int ProcRenderCreateSolidFill(ClientPtr client) { PicturePtr pPicture; int error = 0; REQUEST(xRenderCreateSolidFillReq); REQUEST_AT_LEAST_SIZE(xRenderCreateSolidFillReq); LEGAL_NEW_RESOURCE(stuff->pid, client); pPicture = CreateSolidPicture(stuff->pid, &stuff->color, &error); if (!pPicture) return error; /* security creation/labeling check */ error = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, PictureType, pPicture, RT_NONE, NULL, DixCreateAccess); if (error != Success) return error; if (!AddResource (stuff->pid, PictureType, (pointer)pPicture)) return BadAlloc; return Success; } static int ProcRenderCreateLinearGradient (ClientPtr client) { PicturePtr pPicture; int len; int error = 0; xFixed *stops; xRenderColor *colors; REQUEST(xRenderCreateLinearGradientReq); REQUEST_AT_LEAST_SIZE(xRenderCreateLinearGradientReq); LEGAL_NEW_RESOURCE(stuff->pid, client); len = (client->req_len << 2) - sizeof(xRenderCreateLinearGradientReq); if (stuff->nStops > UINT32_MAX/(sizeof(xFixed) + sizeof(xRenderColor))) return BadLength; if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor))) return BadLength; stops = (xFixed *)(stuff + 1); colors = (xRenderColor *)(stops + stuff->nStops); pPicture = CreateLinearGradientPicture (stuff->pid, &stuff->p1, &stuff->p2, stuff->nStops, stops, colors, &error); if (!pPicture) return error; /* security creation/labeling check */ error = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, PictureType, pPicture, RT_NONE, NULL, DixCreateAccess); if (error != Success) return error; if (!AddResource (stuff->pid, PictureType, (pointer)pPicture)) return BadAlloc; return Success; } static int ProcRenderCreateRadialGradient (ClientPtr client) { PicturePtr pPicture; int len; int error = 0; xFixed *stops; xRenderColor *colors; REQUEST(xRenderCreateRadialGradientReq); REQUEST_AT_LEAST_SIZE(xRenderCreateRadialGradientReq); LEGAL_NEW_RESOURCE(stuff->pid, client); len = (client->req_len << 2) - sizeof(xRenderCreateRadialGradientReq); if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor))) return BadLength; stops = (xFixed *)(stuff + 1); colors = (xRenderColor *)(stops + stuff->nStops); pPicture = CreateRadialGradientPicture (stuff->pid, &stuff->inner, &stuff->outer, stuff->inner_radius, stuff->outer_radius, stuff->nStops, stops, colors, &error); if (!pPicture) return error; /* security creation/labeling check */ error = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, PictureType, pPicture, RT_NONE, NULL, DixCreateAccess); if (error != Success) return error; if (!AddResource (stuff->pid, PictureType, (pointer)pPicture)) return BadAlloc; return Success; } static int ProcRenderCreateConicalGradient (ClientPtr client) { PicturePtr pPicture; int len; int error = 0; xFixed *stops; xRenderColor *colors; REQUEST(xRenderCreateConicalGradientReq); REQUEST_AT_LEAST_SIZE(xRenderCreateConicalGradientReq); LEGAL_NEW_RESOURCE(stuff->pid, client); len = (client->req_len << 2) - sizeof(xRenderCreateConicalGradientReq); if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor))) return BadLength; stops = (xFixed *)(stuff + 1); colors = (xRenderColor *)(stops + stuff->nStops); pPicture = CreateConicalGradientPicture (stuff->pid, &stuff->center, stuff->angle, stuff->nStops, stops, colors, &error); if (!pPicture) return error; /* security creation/labeling check */ error = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, PictureType, pPicture, RT_NONE, NULL, DixCreateAccess); if (error != Success) return error; if (!AddResource (stuff->pid, PictureType, (pointer)pPicture)) return BadAlloc; return Success; } static int ProcRenderDispatch (ClientPtr client) { REQUEST(xReq); if (stuff->data < RenderNumberRequests) return (*ProcRenderVector[stuff->data]) (client); else return BadRequest; } static int SProcRenderQueryVersion (ClientPtr client) { REQUEST(xRenderQueryVersionReq); swaps(&stuff->length); swapl(&stuff->majorVersion); swapl(&stuff->minorVersion); return (*ProcRenderVector[stuff->renderReqType])(client); } static int SProcRenderQueryPictFormats (ClientPtr client) { REQUEST(xRenderQueryPictFormatsReq); swaps(&stuff->length); return (*ProcRenderVector[stuff->renderReqType]) (client); } static int SProcRenderQueryPictIndexValues (ClientPtr client) { REQUEST(xRenderQueryPictIndexValuesReq); swaps(&stuff->length); swapl(&stuff->format); return (*ProcRenderVector[stuff->renderReqType]) (client); } static int SProcRenderQueryDithers (ClientPtr client) { return BadImplementation; } static int SProcRenderCreatePicture (ClientPtr client) { REQUEST(xRenderCreatePictureReq); swaps(&stuff->length); swapl(&stuff->pid); swapl(&stuff->drawable); swapl(&stuff->format); swapl(&stuff->mask); SwapRestL(stuff); return (*ProcRenderVector[stuff->renderReqType]) (client); } static int SProcRenderChangePicture (ClientPtr client) { REQUEST(xRenderChangePictureReq); swaps(&stuff->length); swapl(&stuff->picture); swapl(&stuff->mask); SwapRestL(stuff); return (*ProcRenderVector[stuff->renderReqType]) (client); } static int SProcRenderSetPictureClipRectangles (ClientPtr client) { REQUEST(xRenderSetPictureClipRectanglesReq); swaps(&stuff->length); swapl(&stuff->picture); swaps(&stuff->xOrigin); swaps(&stuff->yOrigin); SwapRestS(stuff); return (*ProcRenderVector[stuff->renderReqType]) (client); } static int SProcRenderFreePicture (ClientPtr client) { REQUEST(xRenderFreePictureReq); swaps(&stuff->length); swapl(&stuff->picture); return (*ProcRenderVector[stuff->renderReqType]) (client); } static int SProcRenderComposite (ClientPtr client) { REQUEST(xRenderCompositeReq); swaps(&stuff->length); swapl(&stuff->src); swapl(&stuff->mask); swapl(&stuff->dst); swaps(&stuff->xSrc); swaps(&stuff->ySrc); swaps(&stuff->xMask); swaps(&stuff->yMask); swaps(&stuff->xDst); swaps(&stuff->yDst); swaps(&stuff->width); swaps(&stuff->height); return (*ProcRenderVector[stuff->renderReqType]) (client); } static int SProcRenderScale (ClientPtr client) { REQUEST(xRenderScaleReq); swaps(&stuff->length); swapl(&stuff->src); swapl(&stuff->dst); swapl(&stuff->colorScale); swapl(&stuff->alphaScale); swaps(&stuff->xSrc); swaps(&stuff->ySrc); swaps(&stuff->xDst); swaps(&stuff->yDst); swaps(&stuff->width); swaps(&stuff->height); return (*ProcRenderVector[stuff->renderReqType]) (client); } static int SProcRenderTrapezoids (ClientPtr client) { REQUEST(xRenderTrapezoidsReq); REQUEST_AT_LEAST_SIZE(xRenderTrapezoidsReq); swaps(&stuff->length); swapl(&stuff->src); swapl(&stuff->dst); swapl(&stuff->maskFormat); swaps(&stuff->xSrc); swaps(&stuff->ySrc); SwapRestL(stuff); return (*ProcRenderVector[stuff->renderReqType]) (client); } static int SProcRenderTriangles (ClientPtr client) { REQUEST(xRenderTrianglesReq); REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq); swaps(&stuff->length); swapl(&stuff->src); swapl(&stuff->dst); swapl(&stuff->maskFormat); swaps(&stuff->xSrc); swaps(&stuff->ySrc); SwapRestL(stuff); return (*ProcRenderVector[stuff->renderReqType]) (client); } static int SProcRenderTriStrip (ClientPtr client) { REQUEST(xRenderTriStripReq); REQUEST_AT_LEAST_SIZE(xRenderTriStripReq); swaps(&stuff->length); swapl(&stuff->src); swapl(&stuff->dst); swapl(&stuff->maskFormat); swaps(&stuff->xSrc); swaps(&stuff->ySrc); SwapRestL(stuff); return (*ProcRenderVector[stuff->renderReqType]) (client); } static int SProcRenderTriFan (ClientPtr client) { REQUEST(xRenderTriFanReq); REQUEST_AT_LEAST_SIZE(xRenderTriFanReq); swaps(&stuff->length); swapl(&stuff->src); swapl(&stuff->dst); swapl(&stuff->maskFormat); swaps(&stuff->xSrc); swaps(&stuff->ySrc); SwapRestL(stuff); return (*ProcRenderVector[stuff->renderReqType]) (client); } static int SProcRenderColorTrapezoids (ClientPtr client) { return BadImplementation; } static int SProcRenderColorTriangles (ClientPtr client) { return BadImplementation; } static int SProcRenderTransform (ClientPtr client) { return BadImplementation; } static int SProcRenderCreateGlyphSet (ClientPtr client) { REQUEST(xRenderCreateGlyphSetReq); swaps(&stuff->length); swapl(&stuff->gsid); swapl(&stuff->format); return (*ProcRenderVector[stuff->renderReqType]) (client); } static int SProcRenderReferenceGlyphSet (ClientPtr client) { REQUEST(xRenderReferenceGlyphSetReq); swaps(&stuff->length); swapl(&stuff->gsid); swapl(&stuff->existing); return (*ProcRenderVector[stuff->renderReqType]) (client); } static int SProcRenderFreeGlyphSet (ClientPtr client) { REQUEST(xRenderFreeGlyphSetReq); swaps(&stuff->length); swapl(&stuff->glyphset); return (*ProcRenderVector[stuff->renderReqType]) (client); } static int SProcRenderAddGlyphs (ClientPtr client) { register int i; CARD32 *gids; void *end; xGlyphInfo *gi; REQUEST(xRenderAddGlyphsReq); swaps(&stuff->length); swapl(&stuff->glyphset); swapl(&stuff->nglyphs); if (stuff->nglyphs & 0xe0000000) return BadLength; end = (CARD8 *) stuff + (client->req_len << 2); gids = (CARD32 *) (stuff + 1); gi = (xGlyphInfo *) (gids + stuff->nglyphs); if ((char *) end - (char *) (gids + stuff->nglyphs) < 0) return BadLength; if ((char *) end - (char *) (gi + stuff->nglyphs) < 0) return BadLength; for (i = 0; i < stuff->nglyphs; i++) { swapl(&gids[i]); swaps(&gi[i].width); swaps(&gi[i].height); swaps(&gi[i].x); swaps(&gi[i].y); swaps(&gi[i].xOff); swaps(&gi[i].yOff); } return (*ProcRenderVector[stuff->renderReqType]) (client); } static int SProcRenderAddGlyphsFromPicture (ClientPtr client) { return BadImplementation; } static int SProcRenderFreeGlyphs (ClientPtr client) { REQUEST(xRenderFreeGlyphsReq); swaps(&stuff->length); swapl(&stuff->glyphset); SwapRestL(stuff); return (*ProcRenderVector[stuff->renderReqType]) (client); } static int SProcRenderCompositeGlyphs (ClientPtr client) { xGlyphElt *elt; CARD8 *buffer; CARD8 *end; int space; int i; int size; REQUEST(xRenderCompositeGlyphsReq); switch (stuff->renderReqType) { default: size = 1; break; case X_RenderCompositeGlyphs16: size = 2; break; case X_RenderCompositeGlyphs32: size = 4; break; } swaps(&stuff->length); swapl(&stuff->src); swapl(&stuff->dst); swapl(&stuff->maskFormat); swapl(&stuff->glyphset); swaps(&stuff->xSrc); swaps(&stuff->ySrc); buffer = (CARD8 *) (stuff + 1); end = (CARD8 *) stuff + (client->req_len << 2); while (buffer + sizeof (xGlyphElt) < end) { elt = (xGlyphElt *) buffer; buffer += sizeof (xGlyphElt); swaps(&elt->deltax); swaps(&elt->deltay); i = elt->len; if (i == 0xff) { swapl((int *)buffer); buffer += 4; } else { space = size * i; switch (size) { case 1: buffer += i; break; case 2: while (i--) { swaps((short *)buffer); buffer += 2; } break; case 4: while (i--) { swapl((int *)buffer); buffer += 4; } break; } if (space & 3) buffer += 4 - (space & 3); } } return (*ProcRenderVector[stuff->renderReqType]) (client); } static int SProcRenderFillRectangles (ClientPtr client) { REQUEST(xRenderFillRectanglesReq); REQUEST_AT_LEAST_SIZE (xRenderFillRectanglesReq); swaps(&stuff->length); swapl(&stuff->dst); swaps(&stuff->color.red); swaps(&stuff->color.green); swaps(&stuff->color.blue); swaps(&stuff->color.alpha); SwapRestS(stuff); return (*ProcRenderVector[stuff->renderReqType]) (client); } static int SProcRenderCreateCursor (ClientPtr client) { REQUEST(xRenderCreateCursorReq); REQUEST_SIZE_MATCH (xRenderCreateCursorReq); swaps(&stuff->length); swapl(&stuff->cid); swapl(&stuff->src); swaps(&stuff->x); swaps(&stuff->y); return (*ProcRenderVector[stuff->renderReqType]) (client); } static int SProcRenderSetPictureTransform (ClientPtr client) { REQUEST(xRenderSetPictureTransformReq); REQUEST_SIZE_MATCH(xRenderSetPictureTransformReq); swaps(&stuff->length); swapl(&stuff->picture); swapl(&stuff->transform.matrix11); swapl(&stuff->transform.matrix12); swapl(&stuff->transform.matrix13); swapl(&stuff->transform.matrix21); swapl(&stuff->transform.matrix22); swapl(&stuff->transform.matrix23); swapl(&stuff->transform.matrix31); swapl(&stuff->transform.matrix32); swapl(&stuff->transform.matrix33); return (*ProcRenderVector[stuff->renderReqType]) (client); } static int SProcRenderQueryFilters (ClientPtr client) { REQUEST (xRenderQueryFiltersReq); REQUEST_SIZE_MATCH (xRenderQueryFiltersReq); swaps(&stuff->length); swapl(&stuff->drawable); return (*ProcRenderVector[stuff->renderReqType]) (client); } static int SProcRenderSetPictureFilter (ClientPtr client) { REQUEST (xRenderSetPictureFilterReq); REQUEST_AT_LEAST_SIZE (xRenderSetPictureFilterReq); swaps(&stuff->length); swapl(&stuff->picture); swaps(&stuff->nbytes); return (*ProcRenderVector[stuff->renderReqType]) (client); } static int SProcRenderCreateAnimCursor (ClientPtr client) { REQUEST (xRenderCreateAnimCursorReq); REQUEST_AT_LEAST_SIZE (xRenderCreateAnimCursorReq); swaps(&stuff->length); swapl(&stuff->cid); SwapRestL(stuff); return (*ProcRenderVector[stuff->renderReqType]) (client); } static int SProcRenderAddTraps (ClientPtr client) { REQUEST (xRenderAddTrapsReq); REQUEST_AT_LEAST_SIZE (xRenderAddTrapsReq); swaps(&stuff->length); swapl(&stuff->picture); swaps(&stuff->xOff); swaps(&stuff->yOff); SwapRestL(stuff); return (*ProcRenderVector[stuff->renderReqType]) (client); } static int SProcRenderCreateSolidFill(ClientPtr client) { REQUEST (xRenderCreateSolidFillReq); REQUEST_AT_LEAST_SIZE (xRenderCreateSolidFillReq); swaps(&stuff->length); swapl(&stuff->pid); swaps(&stuff->color.alpha); swaps(&stuff->color.red); swaps(&stuff->color.green); swaps(&stuff->color.blue); return (*ProcRenderVector[stuff->renderReqType]) (client); } static void swapStops(void *stuff, int num) { int i; CARD32 *stops; CARD16 *colors; stops = (CARD32 *)(stuff); for (i = 0; i < num; ++i) { swapl(stops); ++stops; } colors = (CARD16 *)(stops); for (i = 0; i < 4*num; ++i) { swaps(colors); ++colors; } } static int SProcRenderCreateLinearGradient (ClientPtr client) { int len; REQUEST (xRenderCreateLinearGradientReq); REQUEST_AT_LEAST_SIZE (xRenderCreateLinearGradientReq); swaps(&stuff->length); swapl(&stuff->pid); swapl(&stuff->p1.x); swapl(&stuff->p1.y); swapl(&stuff->p2.x); swapl(&stuff->p2.y); swapl(&stuff->nStops); len = (client->req_len << 2) - sizeof(xRenderCreateLinearGradientReq); if (stuff->nStops > UINT32_MAX/(sizeof(xFixed) + sizeof(xRenderColor))) return BadLength; if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor))) return BadLength; swapStops(stuff+1, stuff->nStops); return (*ProcRenderVector[stuff->renderReqType]) (client); } static int SProcRenderCreateRadialGradient (ClientPtr client) { int len; REQUEST (xRenderCreateRadialGradientReq); REQUEST_AT_LEAST_SIZE (xRenderCreateRadialGradientReq); swaps(&stuff->length); swapl(&stuff->pid); swapl(&stuff->inner.x); swapl(&stuff->inner.y); swapl(&stuff->outer.x); swapl(&stuff->outer.y); swapl(&stuff->inner_radius); swapl(&stuff->outer_radius); swapl(&stuff->nStops); len = (client->req_len << 2) - sizeof(xRenderCreateRadialGradientReq); if (stuff->nStops > UINT32_MAX/(sizeof(xFixed) + sizeof(xRenderColor))) return BadLength; if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor))) return BadLength; swapStops(stuff+1, stuff->nStops); return (*ProcRenderVector[stuff->renderReqType]) (client); } static int SProcRenderCreateConicalGradient (ClientPtr client) { int len; REQUEST (xRenderCreateConicalGradientReq); REQUEST_AT_LEAST_SIZE (xRenderCreateConicalGradientReq); swaps(&stuff->length); swapl(&stuff->pid); swapl(&stuff->center.x); swapl(&stuff->center.y); swapl(&stuff->angle); swapl(&stuff->nStops); len = (client->req_len << 2) - sizeof(xRenderCreateConicalGradientReq); if (stuff->nStops > UINT32_MAX/(sizeof(xFixed) + sizeof(xRenderColor))) return BadLength; if (len != stuff->nStops*(sizeof(xFixed) + sizeof(xRenderColor))) return BadLength; swapStops(stuff+1, stuff->nStops); return (*ProcRenderVector[stuff->renderReqType]) (client); } static int SProcRenderDispatch (ClientPtr client) { REQUEST(xReq); if (stuff->data < RenderNumberRequests) return (*SProcRenderVector[stuff->data]) (client); else return BadRequest; } #ifdef PANORAMIX #define VERIFY_XIN_PICTURE(pPicture, pid, client, mode) {\ int rc = dixLookupResourceByType((pointer *)&(pPicture), pid,\ XRT_PICTURE, client, mode);\ if (rc != Success)\ return rc;\ } #define VERIFY_XIN_ALPHA(pPicture, pid, client, mode) {\ if (pid == None) \ pPicture = 0; \ else { \ VERIFY_XIN_PICTURE(pPicture, pid, client, mode); \ } \ } \ int (*PanoramiXSaveRenderVector[RenderNumberRequests])(ClientPtr); static int PanoramiXRenderCreatePicture (ClientPtr client) { REQUEST(xRenderCreatePictureReq); PanoramiXRes *refDraw, *newPict; int result, j; REQUEST_AT_LEAST_SIZE(xRenderCreatePictureReq); result = dixLookupResourceByClass((pointer *)&refDraw, stuff->drawable, XRC_DRAWABLE, client, DixWriteAccess); if (result != Success) return (result == BadValue) ? BadDrawable : result; if(!(newPict = (PanoramiXRes *) malloc(sizeof(PanoramiXRes)))) return BadAlloc; newPict->type = XRT_PICTURE; panoramix_setup_ids(newPict, client, stuff->pid); if (refDraw->type == XRT_WINDOW && stuff->drawable == screenInfo.screens[0]->root->drawable.id) { newPict->u.pict.root = TRUE; } else newPict->u.pict.root = FALSE; FOR_NSCREENS_BACKWARD(j) { stuff->pid = newPict->info[j].id; stuff->drawable = refDraw->info[j].id; result = (*PanoramiXSaveRenderVector[X_RenderCreatePicture]) (client); if(result != Success) break; } if (result == Success) AddResource(newPict->info[0].id, XRT_PICTURE, newPict); else free(newPict); return result; } static int PanoramiXRenderChangePicture (ClientPtr client) { PanoramiXRes *pict; int result = Success, j; REQUEST(xRenderChangePictureReq); REQUEST_AT_LEAST_SIZE(xRenderChangePictureReq); VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixWriteAccess); FOR_NSCREENS_BACKWARD(j) { stuff->picture = pict->info[j].id; result = (*PanoramiXSaveRenderVector[X_RenderChangePicture]) (client); if(result != Success) break; } return result; } static int PanoramiXRenderSetPictureClipRectangles (ClientPtr client) { REQUEST(xRenderSetPictureClipRectanglesReq); int result = Success, j; PanoramiXRes *pict; REQUEST_AT_LEAST_SIZE(xRenderSetPictureClipRectanglesReq); VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixWriteAccess); FOR_NSCREENS_BACKWARD(j) { stuff->picture = pict->info[j].id; result = (*PanoramiXSaveRenderVector[X_RenderSetPictureClipRectangles]) (client); if(result != Success) break; } return result; } static int PanoramiXRenderSetPictureTransform (ClientPtr client) { REQUEST(xRenderSetPictureTransformReq); int result = Success, j; PanoramiXRes *pict; REQUEST_AT_LEAST_SIZE(xRenderSetPictureTransformReq); VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixWriteAccess); FOR_NSCREENS_BACKWARD(j) { stuff->picture = pict->info[j].id; result = (*PanoramiXSaveRenderVector[X_RenderSetPictureTransform]) (client); if(result != Success) break; } return result; } static int PanoramiXRenderSetPictureFilter (ClientPtr client) { REQUEST(xRenderSetPictureFilterReq); int result = Success, j; PanoramiXRes *pict; REQUEST_AT_LEAST_SIZE(xRenderSetPictureFilterReq); VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixWriteAccess); FOR_NSCREENS_BACKWARD(j) { stuff->picture = pict->info[j].id; result = (*PanoramiXSaveRenderVector[X_RenderSetPictureFilter]) (client); if(result != Success) break; } return result; } static int PanoramiXRenderFreePicture (ClientPtr client) { PanoramiXRes *pict; int result = Success, j; REQUEST(xRenderFreePictureReq); REQUEST_SIZE_MATCH(xRenderFreePictureReq); client->errorValue = stuff->picture; VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixDestroyAccess); FOR_NSCREENS_BACKWARD(j) { stuff->picture = pict->info[j].id; result = (*PanoramiXSaveRenderVector[X_RenderFreePicture]) (client); if(result != Success) break; } /* Since ProcRenderFreePicture is using FreeResource, it will free our resource for us on the last pass through the loop above */ return result; } static int PanoramiXRenderComposite (ClientPtr client) { PanoramiXRes *src, *msk, *dst; int result = Success, j; xRenderCompositeReq orig; REQUEST(xRenderCompositeReq); REQUEST_SIZE_MATCH(xRenderCompositeReq); VERIFY_XIN_PICTURE (src, stuff->src, client, DixReadAccess); VERIFY_XIN_ALPHA (msk, stuff->mask, client, DixReadAccess); VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess); orig = *stuff; FOR_NSCREENS_FORWARD(j) { stuff->src = src->info[j].id; if (src->u.pict.root) { stuff->xSrc = orig.xSrc - screenInfo.screens[j]->x; stuff->ySrc = orig.ySrc - screenInfo.screens[j]->y; } stuff->dst = dst->info[j].id; if (dst->u.pict.root) { stuff->xDst = orig.xDst - screenInfo.screens[j]->x; stuff->yDst = orig.yDst - screenInfo.screens[j]->y; } if (msk) { stuff->mask = msk->info[j].id; if (msk->u.pict.root) { stuff->xMask = orig.xMask - screenInfo.screens[j]->x; stuff->yMask = orig.yMask - screenInfo.screens[j]->y; } } result = (*PanoramiXSaveRenderVector[X_RenderComposite]) (client); if(result != Success) break; } return result; } static int PanoramiXRenderCompositeGlyphs (ClientPtr client) { PanoramiXRes *src, *dst; int result = Success, j; REQUEST(xRenderCompositeGlyphsReq); xGlyphElt origElt, *elt; INT16 xSrc, ySrc; REQUEST_AT_LEAST_SIZE(xRenderCompositeGlyphsReq); VERIFY_XIN_PICTURE (src, stuff->src, client, DixReadAccess); VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess); if (client->req_len << 2 >= (sizeof (xRenderCompositeGlyphsReq) + sizeof (xGlyphElt))) { elt = (xGlyphElt *) (stuff + 1); origElt = *elt; xSrc = stuff->xSrc; ySrc = stuff->ySrc; FOR_NSCREENS_FORWARD(j) { stuff->src = src->info[j].id; if (src->u.pict.root) { stuff->xSrc = xSrc - screenInfo.screens[j]->x; stuff->ySrc = ySrc - screenInfo.screens[j]->y; } stuff->dst = dst->info[j].id; if (dst->u.pict.root) { elt->deltax = origElt.deltax - screenInfo.screens[j]->x; elt->deltay = origElt.deltay - screenInfo.screens[j]->y; } result = (*PanoramiXSaveRenderVector[stuff->renderReqType]) (client); if(result != Success) break; } } return result; } static int PanoramiXRenderFillRectangles (ClientPtr client) { PanoramiXRes *dst; int result = Success, j; REQUEST(xRenderFillRectanglesReq); char *extra; int extra_len; REQUEST_AT_LEAST_SIZE (xRenderFillRectanglesReq); VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess); extra_len = (client->req_len << 2) - sizeof (xRenderFillRectanglesReq); if (extra_len && (extra = (char *) malloc(extra_len))) { memcpy (extra, stuff + 1, extra_len); FOR_NSCREENS_FORWARD(j) { if (j) memcpy (stuff + 1, extra, extra_len); if (dst->u.pict.root) { int x_off = screenInfo.screens[j]->x; int y_off = screenInfo.screens[j]->y; if(x_off || y_off) { xRectangle *rects = (xRectangle *) (stuff + 1); int i = extra_len / sizeof (xRectangle); while (i--) { rects->x -= x_off; rects->y -= y_off; rects++; } } } stuff->dst = dst->info[j].id; result = (*PanoramiXSaveRenderVector[X_RenderFillRectangles]) (client); if(result != Success) break; } free(extra); } return result; } static int PanoramiXRenderTrapezoids(ClientPtr client) { PanoramiXRes *src, *dst; int result = Success, j; REQUEST(xRenderTrapezoidsReq); char *extra; int extra_len; REQUEST_AT_LEAST_SIZE (xRenderTrapezoidsReq); VERIFY_XIN_PICTURE (src, stuff->src, client, DixReadAccess); VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess); extra_len = (client->req_len << 2) - sizeof (xRenderTrapezoidsReq); if (extra_len && (extra = (char *) malloc(extra_len))) { memcpy (extra, stuff + 1, extra_len); FOR_NSCREENS_FORWARD(j) { if (j) memcpy (stuff + 1, extra, extra_len); if (dst->u.pict.root) { int x_off = screenInfo.screens[j]->x; int y_off = screenInfo.screens[j]->y; if(x_off || y_off) { xTrapezoid *trap = (xTrapezoid *) (stuff + 1); int i = extra_len / sizeof (xTrapezoid); while (i--) { trap->top -= y_off; trap->bottom -= y_off; trap->left.p1.x -= x_off; trap->left.p1.y -= y_off; trap->left.p2.x -= x_off; trap->left.p2.y -= y_off; trap->right.p1.x -= x_off; trap->right.p1.y -= y_off; trap->right.p2.x -= x_off; trap->right.p2.y -= y_off; trap++; } } } stuff->src = src->info[j].id; stuff->dst = dst->info[j].id; result = (*PanoramiXSaveRenderVector[X_RenderTrapezoids]) (client); if(result != Success) break; } free(extra); } return result; } static int PanoramiXRenderTriangles(ClientPtr client) { PanoramiXRes *src, *dst; int result = Success, j; REQUEST(xRenderTrianglesReq); char *extra; int extra_len; REQUEST_AT_LEAST_SIZE (xRenderTrianglesReq); VERIFY_XIN_PICTURE (src, stuff->src, client, DixReadAccess); VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess); extra_len = (client->req_len << 2) - sizeof (xRenderTrianglesReq); if (extra_len && (extra = (char *) malloc(extra_len))) { memcpy (extra, stuff + 1, extra_len); FOR_NSCREENS_FORWARD(j) { if (j) memcpy (stuff + 1, extra, extra_len); if (dst->u.pict.root) { int x_off = screenInfo.screens[j]->x; int y_off = screenInfo.screens[j]->y; if(x_off || y_off) { xTriangle *tri = (xTriangle *) (stuff + 1); int i = extra_len / sizeof (xTriangle); while (i--) { tri->p1.x -= x_off; tri->p1.y -= y_off; tri->p2.x -= x_off; tri->p2.y -= y_off; tri->p3.x -= x_off; tri->p3.y -= y_off; tri++; } } } stuff->src = src->info[j].id; stuff->dst = dst->info[j].id; result = (*PanoramiXSaveRenderVector[X_RenderTriangles]) (client); if(result != Success) break; } free(extra); } return result; } static int PanoramiXRenderTriStrip(ClientPtr client) { PanoramiXRes *src, *dst; int result = Success, j; REQUEST(xRenderTriStripReq); char *extra; int extra_len; REQUEST_AT_LEAST_SIZE (xRenderTriStripReq); VERIFY_XIN_PICTURE (src, stuff->src, client, DixReadAccess); VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess); extra_len = (client->req_len << 2) - sizeof (xRenderTriStripReq); if (extra_len && (extra = (char *) malloc(extra_len))) { memcpy (extra, stuff + 1, extra_len); FOR_NSCREENS_FORWARD(j) { if (j) memcpy (stuff + 1, extra, extra_len); if (dst->u.pict.root) { int x_off = screenInfo.screens[j]->x; int y_off = screenInfo.screens[j]->y; if(x_off || y_off) { xPointFixed *fixed = (xPointFixed *) (stuff + 1); int i = extra_len / sizeof (xPointFixed); while (i--) { fixed->x -= x_off; fixed->y -= y_off; fixed++; } } } stuff->src = src->info[j].id; stuff->dst = dst->info[j].id; result = (*PanoramiXSaveRenderVector[X_RenderTriStrip]) (client); if(result != Success) break; } free(extra); } return result; } static int PanoramiXRenderTriFan(ClientPtr client) { PanoramiXRes *src, *dst; int result = Success, j; REQUEST(xRenderTriFanReq); char *extra; int extra_len; REQUEST_AT_LEAST_SIZE (xRenderTriFanReq); VERIFY_XIN_PICTURE (src, stuff->src, client, DixReadAccess); VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess); extra_len = (client->req_len << 2) - sizeof (xRenderTriFanReq); if (extra_len && (extra = (char *) malloc(extra_len))) { memcpy (extra, stuff + 1, extra_len); FOR_NSCREENS_FORWARD(j) { if (j) memcpy (stuff + 1, extra, extra_len); if (dst->u.pict.root) { int x_off = screenInfo.screens[j]->x; int y_off = screenInfo.screens[j]->y; if(x_off || y_off) { xPointFixed *fixed = (xPointFixed *) (stuff + 1); int i = extra_len / sizeof (xPointFixed); while (i--) { fixed->x -= x_off; fixed->y -= y_off; fixed++; } } } stuff->src = src->info[j].id; stuff->dst = dst->info[j].id; result = (*PanoramiXSaveRenderVector[X_RenderTriFan]) (client); if(result != Success) break; } free(extra); } return result; } static int PanoramiXRenderAddTraps (ClientPtr client) { PanoramiXRes *picture; int result = Success, j; REQUEST(xRenderAddTrapsReq); char *extra; int extra_len; INT16 x_off, y_off; REQUEST_AT_LEAST_SIZE (xRenderAddTrapsReq); VERIFY_XIN_PICTURE (picture, stuff->picture, client, DixWriteAccess); extra_len = (client->req_len << 2) - sizeof (xRenderAddTrapsReq); if (extra_len && (extra = (char *) malloc(extra_len))) { memcpy (extra, stuff + 1, extra_len); x_off = stuff->xOff; y_off = stuff->yOff; FOR_NSCREENS_FORWARD(j) { if (j) memcpy (stuff + 1, extra, extra_len); stuff->picture = picture->info[j].id; if (picture->u.pict.root) { stuff->xOff = x_off + screenInfo.screens[j]->x; stuff->yOff = y_off + screenInfo.screens[j]->y; } result = (*PanoramiXSaveRenderVector[X_RenderAddTraps]) (client); if(result != Success) break; } free(extra); } return result; } static int PanoramiXRenderCreateSolidFill (ClientPtr client) { REQUEST(xRenderCreateSolidFillReq); PanoramiXRes *newPict; int result = Success, j; REQUEST_AT_LEAST_SIZE(xRenderCreateSolidFillReq); if(!(newPict = (PanoramiXRes *) malloc(sizeof(PanoramiXRes)))) return BadAlloc; newPict->type = XRT_PICTURE; panoramix_setup_ids(newPict, client, stuff->pid); newPict->u.pict.root = FALSE; FOR_NSCREENS_BACKWARD(j) { stuff->pid = newPict->info[j].id; result = (*PanoramiXSaveRenderVector[X_RenderCreateSolidFill]) (client); if(result != Success) break; } if (result == Success) AddResource(newPict->info[0].id, XRT_PICTURE, newPict); else free(newPict); return result; } static int PanoramiXRenderCreateLinearGradient (ClientPtr client) { REQUEST(xRenderCreateLinearGradientReq); PanoramiXRes *newPict; int result = Success, j; REQUEST_AT_LEAST_SIZE(xRenderCreateLinearGradientReq); if(!(newPict = (PanoramiXRes *) malloc(sizeof(PanoramiXRes)))) return BadAlloc; newPict->type = XRT_PICTURE; panoramix_setup_ids(newPict, client, stuff->pid); newPict->u.pict.root = FALSE; FOR_NSCREENS_BACKWARD(j) { stuff->pid = newPict->info[j].id; result = (*PanoramiXSaveRenderVector[X_RenderCreateLinearGradient]) (client); if(result != Success) break; } if (result == Success) AddResource(newPict->info[0].id, XRT_PICTURE, newPict); else free(newPict); return result; } static int PanoramiXRenderCreateRadialGradient (ClientPtr client) { REQUEST(xRenderCreateRadialGradientReq); PanoramiXRes *newPict; int result = Success, j; REQUEST_AT_LEAST_SIZE(xRenderCreateRadialGradientReq); if(!(newPict = (PanoramiXRes *) malloc(sizeof(PanoramiXRes)))) return BadAlloc; newPict->type = XRT_PICTURE; panoramix_setup_ids(newPict, client, stuff->pid); newPict->u.pict.root = FALSE; FOR_NSCREENS_BACKWARD(j) { stuff->pid = newPict->info[j].id; result = (*PanoramiXSaveRenderVector[X_RenderCreateRadialGradient]) (client); if(result != Success) break; } if (result == Success) AddResource(newPict->info[0].id, XRT_PICTURE, newPict); else free(newPict); return result; } static int PanoramiXRenderCreateConicalGradient (ClientPtr client) { REQUEST(xRenderCreateConicalGradientReq); PanoramiXRes *newPict; int result = Success, j; REQUEST_AT_LEAST_SIZE(xRenderCreateConicalGradientReq); if(!(newPict = (PanoramiXRes *) malloc(sizeof(PanoramiXRes)))) return BadAlloc; newPict->type = XRT_PICTURE; panoramix_setup_ids(newPict, client, stuff->pid); newPict->u.pict.root = FALSE; FOR_NSCREENS_BACKWARD(j) { stuff->pid = newPict->info[j].id; result = (*PanoramiXSaveRenderVector[X_RenderCreateConicalGradient]) (client); if(result != Success) break; } if (result == Success) AddResource(newPict->info[0].id, XRT_PICTURE, newPict); else free(newPict); return result; } void PanoramiXRenderInit (void) { int i; XRT_PICTURE = CreateNewResourceType (XineramaDeleteResource, "XineramaPicture"); if (RenderErrBase) SetResourceTypeErrorValue(XRT_PICTURE, RenderErrBase + BadPicture); for (i = 0; i < RenderNumberRequests; i++) PanoramiXSaveRenderVector[i] = ProcRenderVector[i]; /* * Stuff in Xinerama aware request processing hooks */ ProcRenderVector[X_RenderCreatePicture] = PanoramiXRenderCreatePicture; ProcRenderVector[X_RenderChangePicture] = PanoramiXRenderChangePicture; ProcRenderVector[X_RenderSetPictureTransform] = PanoramiXRenderSetPictureTransform; ProcRenderVector[X_RenderSetPictureFilter] = PanoramiXRenderSetPictureFilter; ProcRenderVector[X_RenderSetPictureClipRectangles] = PanoramiXRenderSetPictureClipRectangles; ProcRenderVector[X_RenderFreePicture] = PanoramiXRenderFreePicture; ProcRenderVector[X_RenderComposite] = PanoramiXRenderComposite; ProcRenderVector[X_RenderCompositeGlyphs8] = PanoramiXRenderCompositeGlyphs; ProcRenderVector[X_RenderCompositeGlyphs16] = PanoramiXRenderCompositeGlyphs; ProcRenderVector[X_RenderCompositeGlyphs32] = PanoramiXRenderCompositeGlyphs; ProcRenderVector[X_RenderFillRectangles] = PanoramiXRenderFillRectangles; ProcRenderVector[X_RenderTrapezoids] = PanoramiXRenderTrapezoids; ProcRenderVector[X_RenderTriangles] = PanoramiXRenderTriangles; ProcRenderVector[X_RenderTriStrip] = PanoramiXRenderTriStrip; ProcRenderVector[X_RenderTriFan] = PanoramiXRenderTriFan; ProcRenderVector[X_RenderAddTraps] = PanoramiXRenderAddTraps; ProcRenderVector[X_RenderCreateSolidFill] = PanoramiXRenderCreateSolidFill; ProcRenderVector[X_RenderCreateLinearGradient] = PanoramiXRenderCreateLinearGradient; ProcRenderVector[X_RenderCreateRadialGradient] = PanoramiXRenderCreateRadialGradient; ProcRenderVector[X_RenderCreateConicalGradient] = PanoramiXRenderCreateConicalGradient; } void PanoramiXRenderReset (void) { int i; for (i = 0; i < RenderNumberRequests; i++) ProcRenderVector[i] = PanoramiXSaveRenderVector[i]; RenderErrBase = 0; } #endif /* PANORAMIX */