Files
xserver/render/render.c

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

3037 lines
90 KiB
C
Raw Normal View History

2003-11-14 16:48:57 +00:00
/*
*
* Copyright © 2000 SuSE, Inc.
2003-11-14 16:48:57 +00:00
*
* 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.
*/
#include <dix-config.h>
#include <stdint.h>
#include <X11/X.h>
#include <X11/Xproto.h>
#include <X11/extensions/render.h>
#include <X11/extensions/renderproto.h>
#include <X11/Xfuncproto.h>
#include "dix/colormap_priv.h"
#include "dix/cursor_priv.h"
#include "dix/dix_priv.h"
#include "dix/request_priv.h"
#include "dix/screenint_priv.h"
#include "dix/server_priv.h"
#include "miext/extinit_priv.h"
#include "os/osdep.h"
#include "Xext/panoramiX.h"
#include "Xext/panoramiXsrv.h"
#include "misc.h"
#include "os.h"
2003-11-14 16:48:57 +00:00
#include "dixstruct.h"
#include "resource.h"
#include "scrnintstr.h"
#include "windowstr.h"
#include "pixmapstr.h"
#include "extnsionst.h"
#include "servermd.h"
#include "picturestr_priv.h"
#include "glyphstr_priv.h"
2003-11-14 16:48:57 +00:00
#include "cursorstr.h"
#include "xace.h"
#include "protocol-versions.h"
2003-11-14 16:48:57 +00:00
Bool noRenderExtension = FALSE;
Bool usePanoramiX = FALSE;
2003-11-14 16:48:57 +00:00
static int ProcRenderQueryVersion(ClientPtr pClient);
static int ProcRenderQueryPictFormats(ClientPtr pClient);
static int ProcRenderQueryPictIndexValues(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 ProcRenderTrapezoids(ClientPtr pClient);
static int ProcRenderTriangles(ClientPtr pClient);
static int ProcRenderTriStrip(ClientPtr pClient);
static int ProcRenderTriFan(ClientPtr pClient);
static int ProcRenderCreateGlyphSet(ClientPtr pClient);
static int ProcRenderReferenceGlyphSet(ClientPtr pClient);
static int ProcRenderFreeGlyphSet(ClientPtr pClient);
static int ProcRenderAddGlyphs(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);
2003-11-14 16:48:57 +00:00
static int ProcRenderDispatch(ClientPtr pClient);
int RenderErrBase;
static DevPrivateKeyRec RenderClientPrivateKeyRec;
#define RenderClientPrivateKey (&RenderClientPrivateKeyRec )
2003-11-14 16:48:57 +00:00
typedef struct _RenderClient {
int major_version;
int minor_version;
} RenderClientRec, *RenderClientPtr;
#define GetRenderClient(pClient) ((RenderClientPtr)dixLookupPrivate(&(pClient)->devPrivates, RenderClientPrivateKey))
2003-11-14 16:48:57 +00:00
#ifdef XINERAMA
RESTYPE XRT_PICTURE;
#endif /* XINERAMA */
void
2003-11-14 16:48:57 +00:00
RenderExtensionInit(void)
{
ExtensionEntry *extEntry;
if (!PictureType)
return;
if (!PictureFinishInit())
return;
if (!dixRegisterPrivateKey
(&RenderClientPrivateKeyRec, PRIVATE_CLIENT, sizeof(RenderClientRec)))
2003-11-14 16:48:57 +00:00
return;
2003-11-14 16:48:57 +00:00
extEntry = AddExtension(RENDER_NAME, 0, RenderNumberErrors,
ProcRenderDispatch, ProcRenderDispatch,
NULL, StandardMinorOpcode);
2003-11-14 16:48:57 +00:00
if (!extEntry)
return;
RenderErrBase = extEntry->errorBase;
#ifdef XINERAMA
if (XRT_PICTURE)
SetResourceTypeErrorValue(XRT_PICTURE, RenderErrBase + BadPicture);
#endif /* XINERAMA */
SetResourceTypeErrorValue(PictureType, RenderErrBase + BadPicture);
SetResourceTypeErrorValue(PictFormatType, RenderErrBase + BadPictFormat);
SetResourceTypeErrorValue(GlyphSetType, RenderErrBase + BadGlyphSet);
2003-11-14 16:48:57 +00:00
}
static int
ProcRenderQueryVersion(ClientPtr client)
{
RenderClientPtr pRenderClient = GetRenderClient(client);
2003-11-14 16:48:57 +00:00
REQUEST(xRenderQueryVersionReq);
REQUEST_SIZE_MATCH(xRenderQueryVersionReq);
if (client->swapped) {
swapl(&stuff->majorVersion);
swapl(&stuff->minorVersion);
}
2003-11-14 16:48:57 +00:00
pRenderClient->major_version = stuff->majorVersion;
pRenderClient->minor_version = stuff->minorVersion;
xRenderQueryVersionReply reply = {
.majorVersion = SERVER_RENDER_MAJOR_VERSION,
.minorVersion = SERVER_RENDER_MINOR_VERSION
};
if ((stuff->majorVersion * 1000 + stuff->minorVersion) <
(SERVER_RENDER_MAJOR_VERSION * 1000 + SERVER_RENDER_MINOR_VERSION)) {
reply.majorVersion = stuff->majorVersion;
reply.minorVersion = stuff->minorVersion;
}
2003-11-14 16:48:57 +00:00
if (client->swapped) {
swapl(&reply.majorVersion);
swapl(&reply.minorVersion);
2003-11-14 16:48:57 +00:00
}
return X_SEND_REPLY_SIMPLE(client, reply);
2003-11-14 16:48:57 +00:00
}
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);
xPictScreen *pictScreen;
xPictDepth *pictDepth;
xPictVisual *pictVisual;
CARD32 *pictSubpixel;
VisualPtr pVisual;
DepthPtr pDepth;
int v, d;
int nformat;
int ndepth;
int nvisual;
int rlength;
int numScreens;
int numSubpixel;
2003-11-14 16:48:57 +00:00
/* REQUEST(xRenderQueryPictFormatsReq); */
REQUEST_SIZE_MATCH(xRenderQueryPictFormatsReq);
#ifdef XINERAMA
2003-11-14 16:48:57 +00:00
if (noPanoramiXExtension)
numScreens = screenInfo.numScreens;
else
numScreens = ((xConnSetup *) ConnectionInfo)->numRoots;
#else
numScreens = screenInfo.numScreens;
#endif /* XINERAMA */
2003-11-14 16:48:57 +00:00
ndepth = nformat = nvisual = 0;
for (unsigned int walkScreenIdx = 0; walkScreenIdx < numScreens; walkScreenIdx++) {
ScreenPtr walkScreen = screenInfo.screens[walkScreenIdx];
for (d = 0; d < walkScreen->numDepths; d++) {
pDepth = walkScreen->allowedDepths + d;
2003-11-14 16:48:57 +00:00
++ndepth;
2003-11-14 16:48:57 +00:00
for (v = 0; v < pDepth->numVids; v++) {
pVisual = findVisual(walkScreen, pDepth->vids[v]);
2003-11-14 16:48:57 +00:00
if (pVisual &&
PictureMatchVisual(walkScreen, pDepth->depth, pVisual))
2003-11-14 16:48:57 +00:00
++nvisual;
}
}
PictureScreenPtr ps = GetPictureScreenIfSet(walkScreen);
2003-11-14 16:48:57 +00:00
if (ps)
nformat += ps->nformats;
}
if (pRenderClient->major_version == 0 && pRenderClient->minor_version < 6)
numSubpixel = 0;
else
numSubpixel = numScreens;
rlength = (nformat * sizeof(xPictFormInfo) +
2003-11-14 16:48:57 +00:00
numScreens * sizeof(xPictScreen) +
ndepth * sizeof(xPictDepth) +
nvisual * sizeof(xPictVisual) + numSubpixel * sizeof(CARD32));
x_rpcbuf_t rpcbuf = { .swapped = client->swapped, .err_clear = TRUE };
xPictFormInfo *pictForm = x_rpcbuf_reserve(&rpcbuf, rlength);
if (!pictForm)
return BadAlloc;
for (unsigned int walkScreenIdx = 0; walkScreenIdx < numScreens; walkScreenIdx++) {
ScreenPtr walkScreen = screenInfo.screens[walkScreenIdx];
PictureScreenPtr ps = GetPictureScreenIfSet(walkScreen);
2003-11-14 16:48:57 +00:00
if (ps) {
size_t idx;
PictFormatPtr pFormat;
for (idx = 0, pFormat = ps->formats;
idx < ps->nformats; idx++, pFormat++) {
2003-11-14 16:48:57 +00:00
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);
2003-11-14 16:48:57 +00:00
}
pictForm++;
}
}
}
2003-11-14 16:48:57 +00:00
pictScreen = (xPictScreen *) pictForm;
for (unsigned int walkScreenIdx = 0; walkScreenIdx < numScreens; walkScreenIdx++) {
ScreenPtr walkScreen = screenInfo.screens[walkScreenIdx];
2003-11-14 16:48:57 +00:00
pictDepth = (xPictDepth *) (pictScreen + 1);
pictScreen->nDepth = 0; /* counting in here */
for (d = 0; d < walkScreen->numDepths; d++) {
2003-11-14 16:48:57 +00:00
pictVisual = (xPictVisual *) (pictDepth + 1);
pDepth = walkScreen->allowedDepths + d;
pictDepth->nPictVisuals = 0; /* counting in here */
2003-11-14 16:48:57 +00:00
for (v = 0; v < pDepth->numVids; v++) {
PictFormatPtr pFormat;
pVisual = findVisual(walkScreen, pDepth->vids[v]);
if (pVisual && (pFormat = PictureMatchVisual(walkScreen,
2003-11-14 16:48:57 +00:00
pDepth->depth,
pVisual))) {
pictVisual->visual = pVisual->vid;
pictVisual->format = pFormat->id;
if (client->swapped) {
swapl(&pictVisual->visual);
swapl(&pictVisual->format);
2003-11-14 16:48:57 +00:00
}
pictVisual++;
pictDepth->nPictVisuals++;
}
2003-11-14 16:48:57 +00:00
}
pictDepth->depth = pDepth->depth;
if (client->swapped) {
swaps(&pictDepth->nPictVisuals);
2003-11-14 16:48:57 +00:00
}
pictScreen->nDepth++;
2003-11-14 16:48:57 +00:00
pictDepth = (xPictDepth *) pictVisual;
}
PictureScreenPtr ps = GetPictureScreenIfSet(walkScreen);
2003-11-14 16:48:57 +00:00
if (ps)
pictScreen->fallback = ps->fallback->id;
else
pictScreen->fallback = 0;
if (client->swapped) {
swapl(&pictScreen->nDepth);
swapl(&pictScreen->fallback);
2003-11-14 16:48:57 +00:00
}
pictScreen = (xPictScreen *) pictDepth;
}
pictSubpixel = (CARD32 *) pictScreen;
for (unsigned int walkScreenIdx = 0; walkScreenIdx < numSubpixel; walkScreenIdx++) {
ScreenPtr walkScreen = screenInfo.screens[walkScreenIdx];
PictureScreenPtr ps = GetPictureScreenIfSet(walkScreen);
2003-11-14 16:48:57 +00:00
if (ps)
*pictSubpixel = ps->subpixel;
else
*pictSubpixel = SubPixelUnknown;
if (client->swapped) {
swapl(pictSubpixel);
2003-11-14 16:48:57 +00:00
}
++pictSubpixel;
}
xRenderQueryPictFormatsReply reply = {
.numFormats = nformat,
.numScreens = numScreens,
.numDepths = ndepth,
.numVisuals = nvisual,
.numSubpixel = numSubpixel,
};
2003-11-14 16:48:57 +00:00
if (client->swapped) {
swapl(&reply.numFormats);
swapl(&reply.numScreens);
swapl(&reply.numDepths);
swapl(&reply.numVisuals);
swapl(&reply.numSubpixel);
2003-11-14 16:48:57 +00:00
}
return X_SEND_REPLY_WITH_RPCBUF(client, reply, rpcbuf);
2003-11-14 16:48:57 +00:00
}
static int
ProcRenderQueryPictIndexValues(ClientPtr client)
{
PictFormatPtr pFormat;
int rc;
2003-11-14 16:48:57 +00:00
REQUEST(xRenderQueryPictIndexValuesReq);
REQUEST_AT_LEAST_SIZE(xRenderQueryPictIndexValuesReq);
if (client->swapped)
swapl(&stuff->format);
rc = dixLookupResourceByType((void **) &pFormat, stuff->format,
PictFormatType, client, DixReadAccess);
if (rc != Success)
return rc;
2003-11-14 16:48:57 +00:00
if (pFormat->type != PictTypeIndexed) {
client->errorValue = stuff->format;
return BadMatch;
}
x_rpcbuf_t rpcbuf = { .swapped = client->swapped, .err_clear = TRUE };
for (int i = 0; i < pFormat->index.nvalues; i++) {
/* write xIndexValue */
xIndexValue *iv = &(pFormat->index.pValues[i]);
x_rpcbuf_write_CARD32(&rpcbuf, iv->pixel);
x_rpcbuf_write_CARD16(&rpcbuf, iv->red);
x_rpcbuf_write_CARD16(&rpcbuf, iv->green);
x_rpcbuf_write_CARD16(&rpcbuf, iv->blue);
x_rpcbuf_write_CARD16(&rpcbuf, iv->alpha);
}
xRenderQueryPictIndexValuesReply reply = {
.numIndexValues = pFormat->index.nvalues
};
2003-11-14 16:48:57 +00:00
if (client->swapped) {
swapl(&reply.numIndexValues);
2003-11-14 16:48:57 +00:00
}
return X_SEND_REPLY_WITH_RPCBUF(client, reply, rpcbuf);
2003-11-14 16:48:57 +00:00
}
static int
SingleRenderCreatePicture(ClientPtr client, xRenderCreatePictureReq *stuff)
2003-11-14 16:48:57 +00:00
{
PicturePtr pPicture;
DrawablePtr pDrawable;
PictFormatPtr pFormat;
int len, error, rc;
2003-11-14 16:48:57 +00:00
LEGAL_NEW_RESOURCE(stuff->pid, client);
rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0,
DixReadAccess | DixAddAccess);
if (rc != Success)
return rc;
rc = dixLookupResourceByType((void **) &pFormat, stuff->format,
PictFormatType, client, DixReadAccess);
if (rc != Success)
return rc;
2003-11-14 16:48:57 +00:00
if (pFormat->depth != pDrawable->depth)
return BadMatch;
len = client->req_len - bytes_to_int32(sizeof(xRenderCreatePictureReq));
2003-11-14 16:48:57 +00:00
if (Ones(stuff->mask) != len)
return BadLength;
2003-11-14 16:48:57 +00:00
pPicture = CreatePicture(stuff->pid,
pDrawable,
pFormat,
stuff->mask, (XID *) (stuff + 1), client, &error);
if (!pPicture)
return error;
if (!AddResource(stuff->pid, PictureType, (void *) pPicture))
2003-11-14 16:48:57 +00:00
return BadAlloc;
return Success;
}
static int
SingleRenderChangePicture(ClientPtr client, xRenderChangePictureReq *stuff, Picture pictID)
2003-11-14 16:48:57 +00:00
{
PicturePtr pPicture;
2003-11-14 16:48:57 +00:00
int len;
VERIFY_PICTURE(pPicture, pictID, client, DixSetAttrAccess);
len = client->req_len - bytes_to_int32(sizeof(xRenderChangePictureReq));
2003-11-14 16:48:57 +00:00
if (Ones(stuff->mask) != len)
return BadLength;
2003-11-14 16:48:57 +00:00
return ChangePicture(pPicture, stuff->mask, (XID *) (stuff + 1),
(DevUnion *) 0, client);
}
static int
SingleRenderSetPictureClipRectangles(ClientPtr client,
xRenderSetPictureClipRectanglesReq *stuff,
Picture pictID)
2003-11-14 16:48:57 +00:00
{
PicturePtr pPicture;
int nr;
VERIFY_PICTURE(pPicture, pictID, client, DixSetAttrAccess);
if (!pPicture->pDrawable)
return RenderErrBase + BadPicture;
nr = (client->req_len << 2) - sizeof(xRenderSetPictureClipRectanglesReq);
2003-11-14 16:48:57 +00:00
if (nr & 4)
return BadLength;
nr >>= 3;
return SetPictureClipRects(pPicture,
2003-11-14 16:48:57 +00:00
stuff->xOrigin, stuff->yOrigin,
nr, (xRectangle *) &stuff[1]);
}
static int
SingleRenderFreePicture(ClientPtr client)
2003-11-14 16:48:57 +00:00
{
PicturePtr pPicture;
2003-11-14 16:48:57 +00:00
REQUEST(xRenderFreePictureReq);
VERIFY_PICTURE(pPicture, stuff->picture, client, DixDestroyAccess);
FreeResource(stuff->picture, X11_RESTYPE_NONE);
return Success;
2003-11-14 16:48:57 +00:00
}
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;
2003-11-14 16:48:57 +00:00
return FALSE;
}
static int
SingleRenderComposite(ClientPtr client, xRenderCompositeReq *stuff)
2003-11-14 16:48:57 +00:00
{
PicturePtr pSrc, pMask, pDst;
2003-11-14 16:48:57 +00:00
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))
2003-11-14 16:48:57 +00:00
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
SingleRenderTrapezoids(ClientPtr client, xRenderTrapezoidsReq *stuff)
2003-11-14 16:48:57 +00:00
{
int rc, ntraps;
2003-11-14 16:48:57 +00:00
PicturePtr pSrc, pDst;
PictFormatPtr pFormat;
2003-11-14 16:48:57 +00:00
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)
2003-11-14 16:48:57 +00:00
return BadMatch;
if (stuff->maskFormat) {
rc = dixLookupResourceByType((void **) &pFormat, stuff->maskFormat,
PictFormatType, client, DixReadAccess);
if (rc != Success)
return rc;
2003-11-14 16:48:57 +00:00
}
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;
2003-11-14 16:48:57 +00:00
}
static int
SingleRenderTriangles(ClientPtr client, xRenderTrianglesReq *stuff)
2003-11-14 16:48:57 +00:00
{
int rc, ntris;
2003-11-14 16:48:57 +00:00
PicturePtr pSrc, pDst;
PictFormatPtr pFormat;
2003-11-14 16:48:57 +00:00
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)
2003-11-14 16:48:57 +00:00
return BadMatch;
if (stuff->maskFormat) {
rc = dixLookupResourceByType((void **) &pFormat, stuff->maskFormat,
PictFormatType, client, DixReadAccess);
if (rc != Success)
return rc;
2003-11-14 16:48:57 +00:00
}
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;
2003-11-14 16:48:57 +00:00
}
static int
SingleRenderTriStrip(ClientPtr client, xRenderTriStripReq *stuff)
2003-11-14 16:48:57 +00:00
{
int rc, npoints;
2003-11-14 16:48:57 +00:00
PicturePtr pSrc, pDst;
PictFormatPtr pFormat;
2003-11-14 16:48:57 +00:00
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)
2003-11-14 16:48:57 +00:00
return BadMatch;
if (stuff->maskFormat) {
rc = dixLookupResourceByType((void **) &pFormat, stuff->maskFormat,
PictFormatType, client, DixReadAccess);
if (rc != Success)
return rc;
2003-11-14 16:48:57 +00:00
}
else
pFormat = 0;
npoints = ((client->req_len << 2) - sizeof(xRenderTriStripReq));
if (npoints & 4)
return BadLength;
2003-11-14 16:48:57 +00:00
npoints >>= 3;
if (npoints >= 3)
CompositeTriStrip(stuff->op, pSrc, pDst, pFormat,
stuff->xSrc, stuff->ySrc,
npoints, (xPointFixed *) &stuff[1]);
return Success;
2003-11-14 16:48:57 +00:00
}
static int
SingleRenderTriFan(ClientPtr client, xRenderTriFanReq *stuff)
2003-11-14 16:48:57 +00:00
{
int rc, npoints;
2003-11-14 16:48:57 +00:00
PicturePtr pSrc, pDst;
PictFormatPtr pFormat;
2003-11-14 16:48:57 +00:00
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)
2003-11-14 16:48:57 +00:00
return BadMatch;
if (stuff->maskFormat) {
rc = dixLookupResourceByType((void **) &pFormat, stuff->maskFormat,
PictFormatType, client, DixReadAccess);
if (rc != Success)
return rc;
2003-11-14 16:48:57 +00:00
}
else
pFormat = 0;
npoints = ((client->req_len << 2) - sizeof(xRenderTriStripReq));
if (npoints & 4)
return BadLength;
2003-11-14 16:48:57 +00:00
npoints >>= 3;
if (npoints >= 3)
CompositeTriFan(stuff->op, pSrc, pDst, pFormat,
stuff->xSrc, stuff->ySrc,
npoints, (xPointFixed *) &stuff[1]);
return Success;
2003-11-14 16:48:57 +00:00
}
static int
ProcRenderCreateGlyphSet(ClientPtr client)
{
GlyphSetPtr glyphSet;
PictFormatPtr format;
int rc, f;
2003-11-14 16:48:57 +00:00
REQUEST(xRenderCreateGlyphSetReq);
REQUEST_SIZE_MATCH(xRenderCreateGlyphSetReq);
if (client->swapped) {
swapl(&stuff->gsid);
swapl(&stuff->format);
}
2003-11-14 16:48:57 +00:00
LEGAL_NEW_RESOURCE(stuff->gsid, client);
rc = dixLookupResourceByType((void **) &format, stuff->format,
PictFormatType, client, DixReadAccess);
if (rc != Success)
return rc;
2003-11-14 16:48:57 +00:00
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 = XaceHookResourceAccess(client, stuff->gsid, GlyphSetType,
glyphSet, X11_RESTYPE_NONE, NULL, DixCreateAccess);
if (rc != Success)
return rc;
if (!AddResource(stuff->gsid, GlyphSetType, (void *) glyphSet))
2003-11-14 16:48:57 +00:00
return BadAlloc;
return Success;
}
static int
ProcRenderReferenceGlyphSet(ClientPtr client)
{
GlyphSetPtr glyphSet;
int rc;
2003-11-14 16:48:57 +00:00
REQUEST(xRenderReferenceGlyphSetReq);
REQUEST_SIZE_MATCH(xRenderReferenceGlyphSetReq);
if (client->swapped) {
swapl(&stuff->gsid);
swapl(&stuff->existing);
}
2003-11-14 16:48:57 +00:00
LEGAL_NEW_RESOURCE(stuff->gsid, client);
rc = dixLookupResourceByType((void **) &glyphSet, stuff->existing,
GlyphSetType, client, DixGetAttrAccess);
if (rc != Success) {
2003-11-14 16:48:57 +00:00
client->errorValue = stuff->existing;
return rc;
2003-11-14 16:48:57 +00:00
}
glyphSet->refcnt++;
if (!AddResource(stuff->gsid, GlyphSetType, (void *) glyphSet))
2003-11-14 16:48:57 +00:00
return BadAlloc;
return Success;
2003-11-14 16:48:57 +00:00
}
#define NLOCALDELTA 64
#define NLOCALGLYPH 256
static int
ProcRenderFreeGlyphSet(ClientPtr client)
{
GlyphSetPtr glyphSet;
int rc;
2003-11-14 16:48:57 +00:00
REQUEST(xRenderFreeGlyphSetReq);
REQUEST_SIZE_MATCH(xRenderFreeGlyphSetReq);
if (client->swapped)
swapl(&stuff->glyphset);
rc = dixLookupResourceByType((void **) &glyphSet, stuff->glyphset,
GlyphSetType, client, DixDestroyAccess);
if (rc != Success) {
2003-11-14 16:48:57 +00:00
client->errorValue = stuff->glyphset;
return rc;
2003-11-14 16:48:57 +00:00
}
FreeResource(stuff->glyphset, X11_RESTYPE_NONE);
return Success;
2003-11-14 16:48:57 +00:00
}
typedef struct _GlyphNew {
Glyph id;
GlyphPtr glyph;
Bool found;
unsigned char sha1[20];
2003-11-14 16:48:57 +00:00
} GlyphNewRec, *GlyphNewPtr;
#define NeedsComponent(f) (PIXMAN_FORMAT_A(f) != 0 && PIXMAN_FORMAT_RGB(f) != 0)
2003-11-14 16:48:57 +00:00
static int
ProcRenderAddGlyphs(ClientPtr client)
{
REQUEST(xRenderAddGlyphsReq);
REQUEST_AT_LEAST_SIZE(xRenderAddGlyphsReq);
if (client->swapped) {
swapl(&stuff->glyphset);
swapl(&stuff->nglyphs);
if (stuff->nglyphs & 0xe0000000)
return BadLength;
void *end = (CARD8 *) stuff + (client->req_len << 2);
CARD32 *gids = (CARD32 *) (stuff + 1);
xGlyphInfo *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 (int 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);
}
}
2003-11-14 16:48:57 +00:00
GlyphSetPtr glyphSet;
2003-11-14 16:48:57 +00:00
GlyphNewRec glyphsLocal[NLOCALGLYPH];
GlyphNewPtr glyphsBase, glyphs, glyph_new;
2003-11-14 16:48:57 +00:00
int remain, nglyphs;
CARD32 *gids;
xGlyphInfo *gi;
CARD8 *bits;
unsigned int size;
int err;
int i;
CARD32 component_alpha;
2003-11-14 16:48:57 +00:00
REQUEST_AT_LEAST_SIZE(xRenderAddGlyphsReq);
err =
dixLookupResourceByType((void **) &glyphSet, stuff->glyphset,
GlyphSetType, client, DixAddAccess);
if (err != Success) {
2003-11-14 16:48:57 +00:00
client->errorValue = stuff->glyphset;
return err;
2003-11-14 16:48:57 +00:00
}
err = BadAlloc;
2003-11-14 16:48:57 +00:00
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));
2003-11-14 16:48:57 +00:00
glyphsBase = glyphsLocal;
}
2003-11-14 16:48:57 +00:00
else {
glyphsBase = (GlyphNewPtr) calloc(nglyphs, sizeof(GlyphNewRec));
2003-11-14 16:48:57 +00:00
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;
2003-11-14 16:48:57 +00:00
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;
++glyph_new->glyph->refcnt;
}
else {
GlyphPtr glyph;
glyph_new->found = FALSE;
glyph_new->glyph = glyph = AllocateGlyph(&gi[i], glyphSet->fdepth);
if (!glyph) {
err = BadAlloc;
goto bail;
}
DIX_FOR_EACH_SCREEN({
int width = gi[i].width;
int height = gi[i].height;
int depth = glyphSet->format->depth;
int error;
/* Skip work if it's invisibly small anyway */
if (!width || !height)
break;
PixmapPtr pSrcPix = GetScratchPixmapHeader(walkScreen,
width, height,
depth, depth, -1, bits);
if (!pSrcPix) {
err = BadAlloc;
goto bail;
}
PicturePtr pSrc = CreatePicture(0, &pSrcPix->drawable,
glyphSet->format, 0, NULL,
serverClient, &error);
if (!pSrc) {
err = BadAlloc;
FreeScratchPixmapHeader(pSrcPix);
goto bail;
}
PixmapPtr pDstPix = walkScreen->CreatePixmap(walkScreen,
width, height, depth,
2007-11-15 12:16:36 -08:00
CREATE_PIXMAP_USAGE_GLYPH_PICTURE);
if (!pDstPix) {
err = BadAlloc;
FreeScratchPixmapHeader(pSrcPix);
FreePicture((void *) pSrc, 0);
goto bail;
}
PicturePtr pDst = CreatePicture(0, &pDstPix->drawable,
glyphSet->format,
CPComponentAlpha, &component_alpha,
serverClient, &error);
SetGlyphPicture(glyph, walkScreen, pDst);
2007-08-23 16:33:05 -07:00
/* The picture takes a reference to the pixmap, so we
drop ours. */
dixDestroyPixmap(pDstPix, 0);
pDstPix = NULL;
if (!pDst) {
err = BadAlloc;
FreePicture((void *) pSrc, 0);
FreeScratchPixmapHeader(pSrcPix);
goto bail;
}
CompositePicture(PictOpSrc,
pSrc,
None, pDst, 0, 0, 0, 0, 0, 0, width, height);
FreePicture((void *) pSrc, 0);
FreeScratchPixmapHeader(pSrcPix);
});
memcpy(glyph_new->glyph->sha1, glyph_new->sha1, 20);
}
glyph_new->id = gids[i];
2003-11-14 16:48:57 +00:00
if (size & 3)
size += 4 - (size & 3);
bits += size;
remain -= size;
}
if (remain || i < nglyphs) {
2003-11-14 16:48:57 +00:00
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);
FreeGlyph(glyphs[i].glyph, glyphSet->fdepth);
}
2003-11-14 16:48:57 +00:00
if (glyphsBase != glyphsLocal)
free(glyphsBase);
return Success;
2003-11-14 16:48:57 +00:00
bail:
for (i = 0; i < nglyphs; i++) {
if (glyphs[i].glyph) {
--glyphs[i].glyph->refcnt;
if (!glyphs[i].found)
free(glyphs[i].glyph);
}
}
2003-11-14 16:48:57 +00:00
if (glyphsBase != glyphsLocal)
free(glyphsBase);
2003-11-14 16:48:57 +00:00
return err;
}
static int
ProcRenderFreeGlyphs(ClientPtr client)
{
REQUEST(xRenderFreeGlyphsReq);
REQUEST_AT_LEAST_SIZE(xRenderFreeGlyphsReq);
if (client->swapped) {
swapl(&stuff->glyphset);
SwapRestL(stuff);
}
2003-11-14 16:48:57 +00:00
GlyphSetPtr glyphSet;
int rc, nglyph;
2003-11-14 16:48:57 +00:00
CARD32 *gids;
CARD32 glyph;
rc = dixLookupResourceByType((void **) &glyphSet, stuff->glyphset,
GlyphSetType, client, DixRemoveAccess);
if (rc != Success) {
2003-11-14 16:48:57 +00:00
client->errorValue = stuff->glyphset;
return rc;
2003-11-14 16:48:57 +00:00
}
nglyph =
bytes_to_int32((client->req_len << 2) - sizeof(xRenderFreeGlyphsReq));
2003-11-14 16:48:57 +00:00
gids = (CARD32 *) (stuff + 1);
while (nglyph-- > 0) {
glyph = *gids++;
if (!DeleteGlyph(glyphSet, glyph)) {
client->errorValue = glyph;
return RenderErrBase + BadGlyph;
}
}
return Success;
2003-11-14 16:48:57 +00:00
}
static int
SingleRenderCompositeGlyphs(ClientPtr client, xRenderCompositeGlyphsReq *stuff)
2003-11-14 16:48:57 +00:00
{
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;
2003-11-14 16:48:57 +00:00
switch (stuff->renderReqType) {
default:
size = 1;
break;
case X_RenderCompositeGlyphs16:
size = 2;
break;
case X_RenderCompositeGlyphs32:
size = 4;
break;
2003-11-14 16:48:57 +00:00
}
2003-11-14 16:48:57 +00:00
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)
2003-11-14 16:48:57 +00:00
return BadMatch;
if (stuff->maskFormat) {
rc = dixLookupResourceByType((void **) &pFormat, stuff->maskFormat,
PictFormatType, client, DixReadAccess);
if (rc != Success)
return rc;
2003-11-14 16:48:57 +00:00
}
else
pFormat = 0;
rc = dixLookupResourceByType((void **) &glyphSet, stuff->glyphset,
GlyphSetType, client, DixUseAccess);
if (rc != Success)
return rc;
2003-11-14 16:48:57 +00:00
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);
2003-11-14 16:48:57 +00:00
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 = calloc(nglyph, sizeof(GlyphPtr));
2003-11-14 16:48:57 +00:00
if (!glyphsBase)
return BadAlloc;
}
if (nlist <= NLOCALDELTA)
listsBase = listsLocal;
else {
listsBase = calloc(nlist, sizeof(GlyphListRec));
if (!listsBase) {
rc = BadAlloc;
goto bail;
}
2003-11-14 16:48:57 +00:00
}
buffer = (CARD8 *) (stuff + 1);
glyphs = glyphsBase;
lists = listsBase;
while (buffer + sizeof(xGlyphElt) < end) {
elt = (xGlyphElt *) buffer;
buffer += sizeof(xGlyphElt);
2003-11-14 16:48:57 +00:00
if (elt->len == 0xff) {
if (buffer + sizeof(GlyphSet) < end) {
memcpy(&gs, buffer, sizeof(GlyphSet));
rc = dixLookupResourceByType((void **) &glyphSet, gs,
GlyphSetType, client,
DixUseAccess);
if (rc != Success)
goto bail;
2003-11-14 16:48:57 +00:00
}
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;
}
2003-11-14 16:48:57 +00:00
CompositeGlyphs(stuff->op,
pSrc,
pDst,
pFormat,
stuff->xSrc, stuff->ySrc, nlist, listsBase, glyphsBase);
rc = Success;
2003-11-14 16:48:57 +00:00
bail:
2003-11-14 16:48:57 +00:00
if (glyphsBase != glyphsLocal)
free(glyphsBase);
2003-11-14 16:48:57 +00:00
if (listsBase != listsLocal)
free(listsBase);
return rc;
2003-11-14 16:48:57 +00:00
}
static int
SingleRenderFillRectangles(ClientPtr client, xRenderFillRectanglesReq *stuff)
2003-11-14 16:48:57 +00:00
{
PicturePtr pDst;
int things;
2003-11-14 16:48:57 +00:00
if (!PictOpValid(stuff->op)) {
client->errorValue = stuff->op;
return BadValue;
}
VERIFY_PICTURE(pDst, stuff->dst, client, DixWriteAccess);
if (!pDst->pDrawable)
return BadDrawable;
2003-11-14 16:48:57 +00:00
things = (client->req_len << 2) - sizeof(xRenderFillRectanglesReq);
if (things & 4)
return BadLength;
2003-11-14 16:48:57 +00:00
things >>= 3;
2003-11-14 16:48:57 +00:00
CompositeRects(stuff->op,
pDst, &stuff->color, things, (xRectangle *) &stuff[1]);
return Success;
2003-11-14 16:48:57 +00:00
}
static void
RenderSetBit(unsigned char *line, int x, int bit)
2003-11-14 16:48:57 +00:00
{
unsigned char mask;
2003-11-14 16:48:57 +00:00
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);
REQUEST_SIZE_MATCH(xRenderCreateCursorReq);
if (client->swapped) {
swapl(&stuff->cid);
swapl(&stuff->src);
swaps(&stuff->x);
swaps(&stuff->y);
}
2003-11-14 16:48:57 +00:00
PicturePtr pSrc;
ScreenPtr pScreen;
unsigned short width, height;
CARD32 *argb;
unsigned char *srcline;
unsigned char *mskline;
2003-11-14 16:48:57 +00:00
int stride;
int x, y;
int nbytes_mono;
CursorMetricRec cm;
CursorPtr pCursor;
CARD32 twocolor[3];
int rc, ncolor;
2003-11-14 16:48:57 +00:00
LEGAL_NEW_RESOURCE(stuff->cid, client);
VERIFY_PICTURE(pSrc, stuff->src, client, DixReadAccess);
if (!pSrc->pDrawable)
return BadDrawable;
2003-11-14 16:48:57 +00:00
pScreen = pSrc->pDrawable->pScreen;
width = pSrc->pDrawable->width;
height = pSrc->pDrawable->height;
if (height && width > UINT32_MAX / (height * sizeof(CARD32)))
return BadAlloc;
2003-11-14 16:48:57 +00:00
if (stuff->x > width || stuff->y > height)
return BadMatch;
CARD32 *argbbits = calloc(width * height, sizeof(CARD32));
2003-11-14 16:48:57 +00:00
if (!argbbits)
return BadAlloc;
2003-11-14 16:48:57 +00:00
stride = BitmapBytePad(width);
nbytes_mono = stride * height;
unsigned char *srcbits = calloc(1, nbytes_mono);
2003-11-14 16:48:57 +00:00
if (!srcbits) {
free(argbbits);
return BadAlloc;
2003-11-14 16:48:57 +00:00
}
unsigned char *mskbits = calloc(1, nbytes_mono);
2003-11-14 16:48:57 +00:00
if (!mskbits) {
free(argbbits);
free(srcbits);
return BadAlloc;
2003-11-14 16:48:57 +00:00
}
/* what kind of maniac creates a cursor from a window picture though */
if (pSrc->pDrawable->type == DRAWABLE_WINDOW)
pScreen->SourceValidate(pSrc->pDrawable, 0, 0, width, height,
IncludeInferiors);
if (pSrc->format == PIXMAN_a8r8g8b8) {
2003-11-14 16:48:57 +00:00
(*pScreen->GetImage) (pSrc->pDrawable,
0, 0, width, height, ZPixmap,
0xffffffff, (void *) argbbits);
2003-11-14 16:48:57 +00:00
}
else {
PixmapPtr pPixmap;
PicturePtr pPicture;
PictFormatPtr pFormat;
int error;
pFormat = PictureMatchFormat(pScreen, 32, PIXMAN_a8r8g8b8);
2003-11-14 16:48:57 +00:00
if (!pFormat) {
free(argbbits);
free(srcbits);
free(mskbits);
return BadImplementation;
2003-11-14 16:48:57 +00:00
}
pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, 32,
CREATE_PIXMAP_USAGE_SCRATCH);
2003-11-14 16:48:57 +00:00
if (!pPixmap) {
free(argbbits);
free(srcbits);
free(mskbits);
return BadAlloc;
2003-11-14 16:48:57 +00:00
}
pPicture = CreatePicture(0, &pPixmap->drawable, pFormat, 0, 0,
client, &error);
if (!pPicture) {
free(argbbits);
free(srcbits);
free(mskbits);
2003-11-14 16:48:57 +00:00
return error;
}
dixDestroyPixmap(pPixmap, 0);
2003-11-14 16:48:57 +00:00
CompositePicture(PictOpSrc,
pSrc, 0, pPicture, 0, 0, 0, 0, 0, 0, width, height);
(*pScreen->GetImage) (pPicture->pDrawable,
0, 0, width, height, ZPixmap,
0xffffffff, (void *) argbbits);
2003-11-14 16:48:57 +00:00
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);
2003-11-14 16:48:57 +00:00
if (a == 0) /* transparent */
continue;
if (a == 0xff) { /* opaque */
int n;
2003-11-14 16:48:57 +00:00
for (n = 0; n < ncolor; n++)
if (p == twocolor[n])
break;
if (n == ncolor)
twocolor[ncolor++] = p;
}
else
ncolor = 3;
}
}
2003-11-14 16:48:57 +00:00
/*
* 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++;
2003-11-14 16:48:57 +00:00
if (ncolor <= 2) {
CARD32 a = ((p >> 24));
RenderSetBit(mskline, x, a != 0);
RenderSetBit(srcline, x, a != 0 && p == twocolor[0]);
2003-11-14 16:48:57 +00:00
}
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);
2003-11-14 16:48:57 +00:00
/* Set src from dithered intensity value */
RenderSetBit(srcline, x, a > d && i <= d);
2003-11-14 16:48:57 +00:00
}
}
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);
2003-11-14 16:48:57 +00:00
argbbits = 0;
}
2003-11-14 16:48:57 +00:00
#define GetByte(p,s) (((p) >> (s)) & 0xff)
#define GetColor(p,s) (GetByte(p,s) | (GetByte(p,s) << 8))
2003-11-14 16:48:57 +00:00
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, X11_RESTYPE_CURSOR, (void *) pCursor)) {
rc = BadAlloc;
goto bail;
}
return Success;
bail:
free(srcbits);
free(mskbits);
return rc;
2003-11-14 16:48:57 +00:00
}
static int
SingleRenderSetPictureTransform(ClientPtr client,
xRenderSetPictureTransformReq *stuff)
2003-11-14 16:48:57 +00:00
{
PicturePtr pPicture;
VERIFY_PICTURE(pPicture, stuff->picture, client, DixSetAttrAccess);
return SetPictureTransform(pPicture, (PictTransform *) &stuff->transform);
2003-11-14 16:48:57 +00:00
}
static int
ProcRenderQueryFilters(ClientPtr client)
{
REQUEST(xRenderQueryFiltersReq);
REQUEST_SIZE_MATCH(xRenderQueryFiltersReq);
if (client->swapped)
swapl(&stuff->drawable);
2003-11-14 16:48:57 +00:00
DrawablePtr pDrawable;
int nbytesName;
int nnames;
ScreenPtr pScreen;
PictureScreenPtr ps;
int i, j, len, total_bytes, rc;
2003-11-14 16:48:57 +00:00
INT16 *aliases;
char *names;
rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0,
DixGetAttrAccess);
if (rc != Success)
return rc;
2003-11-14 16:48:57 +00:00
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 = (len << 2);
x_rpcbuf_t rpcbuf = { .swapped = client->swapped, .err_clear = TRUE };
aliases = (INT16 *) x_rpcbuf_reserve(&rpcbuf, total_bytes);
if (!aliases)
2003-11-14 16:48:57 +00:00
return BadAlloc;
2003-11-14 16:48:57 +00:00
names = (char *) (aliases + ((nnames + 1) & ~1));
2003-11-14 16:48:57 +00:00
if (ps) {
2003-11-14 16:48:57 +00:00
/* 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;
}
2003-11-14 16:48:57 +00:00
/* 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);
2003-11-14 16:48:57 +00:00
names += j;
}
2003-11-14 16:48:57 +00:00
/* 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);
2003-11-14 16:48:57 +00:00
names += j;
}
}
xRenderQueryFiltersReply reply = {
.numAliases = nnames,
.numFilters = nnames
};
2003-11-14 16:48:57 +00:00
if (client->swapped) {
for (i = 0; i < nnames; i++) {
swaps(&aliases[i]);
2003-11-14 16:48:57 +00:00
}
swapl(&reply.numAliases);
swapl(&reply.numFilters);
2003-11-14 16:48:57 +00:00
}
return X_SEND_REPLY_WITH_RPCBUF(client, reply, rpcbuf);
2003-11-14 16:48:57 +00:00
}
static int
SingleRenderSetPictureFilter(ClientPtr client, xRenderSetPictureFilterReq *stuff)
2003-11-14 16:48:57 +00:00
{
PicturePtr pPicture;
int result;
xFixed *params;
int nparams;
char *name;
VERIFY_PICTURE(pPicture, stuff->picture, client, DixSetAttrAccess);
2003-11-14 16:48:57 +00:00
name = (char *) (stuff + 1);
params = (xFixed *) (name + pad_to_int32(stuff->nbytes));
2003-11-14 16:48:57 +00:00
nparams = ((xFixed *) stuff + client->req_len) - params;
if (nparams < 0)
return BadLength;
2003-11-14 16:48:57 +00:00
result = SetPictureFilter(pPicture, name, stuff->nbytes, params, nparams);
return result;
}
static int
ProcRenderCreateAnimCursor(ClientPtr client)
{
REQUEST(xRenderCreateAnimCursorReq);
REQUEST_AT_LEAST_SIZE(xRenderCreateAnimCursorReq);
if (client->swapped) {
swapl(&stuff->cid);
SwapRestL(stuff);
}
2003-11-14 16:48:57 +00:00
CARD32 *deltas;
CursorPtr pCursor;
xAnimCursorElt *elt;
int i;
int ret;
LEGAL_NEW_RESOURCE(stuff->cid, client);
if (client->req_len & 1)
return BadLength;
int ncursor =
(client->req_len -
(bytes_to_int32(sizeof(xRenderCreateAnimCursorReq)))) >> 1;
if (ncursor <= 0)
return BadValue;
CursorPtr *cursors = calloc(ncursor, sizeof(CursorPtr) + sizeof(CARD32));
2003-11-14 16:48:57 +00:00
if (!cursors)
return BadAlloc;
deltas = (CARD32 *) (cursors + ncursor);
elt = (xAnimCursorElt *) (stuff + 1);
for (i = 0; i < ncursor; i++) {
ret = dixLookupResourceByType((void **) (cursors + i), elt->cursor,
X11_RESTYPE_CURSOR, client, DixReadAccess);
if (ret != Success) {
free(cursors);
return ret;
2003-11-14 16:48:57 +00:00
}
deltas[i] = elt->delay;
elt++;
}
ret = AnimCursorCreate(cursors, deltas, ncursor, &pCursor, client,
stuff->cid);
free(cursors);
2003-11-14 16:48:57 +00:00
if (ret != Success)
return ret;
if (AddResource(stuff->cid, X11_RESTYPE_CURSOR, (void *) pCursor))
return Success;
2003-11-14 16:48:57 +00:00
return BadAlloc;
}
static int
SingleRenderAddTraps(ClientPtr client, xRenderAddTrapsReq *stuff)
{
int ntraps;
PicturePtr pPicture;
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
SingleRenderCreateSolidFill(ClientPtr client, xRenderCreateSolidFillReq *stuff)
{
PicturePtr pPicture;
int error = 0;
LEGAL_NEW_RESOURCE(stuff->pid, client);
pPicture = CreateSolidPicture(stuff->pid, &stuff->color, &error);
if (!pPicture)
return error;
/* security creation/labeling check */
error = XaceHookResourceAccess(client, stuff->pid, PictureType,
pPicture, X11_RESTYPE_NONE, NULL, DixCreateAccess);
if (error != Success)
return error;
if (!AddResource(stuff->pid, PictureType, (void *) pPicture))
return BadAlloc;
return Success;
}
static int
SingleRenderCreateLinearGradient(ClientPtr client, xRenderCreateLinearGradientReq *stuff)
{
PicturePtr pPicture;
int len;
int error = 0;
xFixed *stops;
xRenderColor *colors;
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 = XaceHookResourceAccess(client, stuff->pid, PictureType,
pPicture, X11_RESTYPE_NONE, NULL, DixCreateAccess);
if (error != Success)
return error;
if (!AddResource(stuff->pid, PictureType, (void *) pPicture))
return BadAlloc;
return Success;
}
static int
SingleRenderCreateRadialGradient(ClientPtr client,
xRenderCreateRadialGradientReq *stuff)
{
PicturePtr pPicture;
int len;
int error = 0;
xFixed *stops;
xRenderColor *colors;
LEGAL_NEW_RESOURCE(stuff->pid, client);
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;
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 = XaceHookResourceAccess(client, stuff->pid, PictureType,
pPicture, X11_RESTYPE_NONE, NULL, DixCreateAccess);
if (error != Success)
return error;
if (!AddResource(stuff->pid, PictureType, (void *) pPicture))
return BadAlloc;
return Success;
}
static int
SingleRenderCreateConicalGradient(ClientPtr client,
xRenderCreateConicalGradientReq *stuff)
{
PicturePtr pPicture;
int len;
int error = 0;
xFixed *stops;
xRenderColor *colors;
LEGAL_NEW_RESOURCE(stuff->pid, client);
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;
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 = XaceHookResourceAccess(client, stuff->pid, PictureType,
pPicture, X11_RESTYPE_NONE, NULL, DixCreateAccess);
if (error != Success)
return error;
if (!AddResource(stuff->pid, PictureType, (void *) pPicture))
return BadAlloc;
return Success;
}
2003-11-14 16:48:57 +00:00
static int
ProcRenderDispatch(ClientPtr client)
{
REQUEST(xReq);
switch (stuff->data) {
case X_RenderQueryVersion: return ProcRenderQueryVersion(client);
case X_RenderQueryPictFormats: return ProcRenderQueryPictFormats(client);
/* 0.7 */
case X_RenderQueryPictIndexValues: return ProcRenderQueryPictIndexValues(client);
case X_RenderQueryDithers: return BadImplementation;
case X_RenderCreatePicture: return ProcRenderCreatePicture(client);
case X_RenderChangePicture: return ProcRenderChangePicture(client);
case X_RenderSetPictureClipRectangles: return ProcRenderSetPictureClipRectangles(client);
case X_RenderFreePicture: return ProcRenderFreePicture(client);
case X_RenderComposite: return ProcRenderComposite(client);
case X_RenderScale: return BadImplementation;
case X_RenderTrapezoids: return ProcRenderTrapezoids(client);
case X_RenderTriangles: return ProcRenderTriangles(client);
case X_RenderTriStrip: return ProcRenderTriStrip(client);
case X_RenderTriFan: return ProcRenderTriFan(client);
case X_RenderColorTrapezoids: return BadImplementation;
case X_RenderColorTriangles: return BadImplementation;
/* case X_RenderTransform: return BadImplementation; --> doesn't actually exist */
case X_RenderCreateGlyphSet: return ProcRenderCreateGlyphSet(client);
case X_RenderReferenceGlyphSet: return ProcRenderReferenceGlyphSet(client);
case X_RenderFreeGlyphSet: return ProcRenderFreeGlyphSet(client);
case X_RenderAddGlyphs: return ProcRenderAddGlyphs(client);
case X_RenderAddGlyphsFromPicture: return BadImplementation;
case X_RenderFreeGlyphs: return ProcRenderFreeGlyphs(client);
case X_RenderCompositeGlyphs8: return ProcRenderCompositeGlyphs(client);
case X_RenderCompositeGlyphs16: return ProcRenderCompositeGlyphs(client);
case X_RenderCompositeGlyphs32: return ProcRenderCompositeGlyphs(client);
case X_RenderFillRectangles: return ProcRenderFillRectangles(client);
/* 0.5 */
case X_RenderCreateCursor: return ProcRenderCreateCursor(client);
/* 0.6 */
case X_RenderSetPictureTransform: return ProcRenderSetPictureTransform(client);
case X_RenderQueryFilters: return ProcRenderQueryFilters(client);
case X_RenderSetPictureFilter: return ProcRenderSetPictureFilter(client);
/* 0.8 */
case X_RenderCreateAnimCursor: return ProcRenderCreateAnimCursor(client);
/* 0.9 */
case X_RenderAddTraps: return ProcRenderAddTraps(client);
/* 0.10 */
case X_RenderCreateSolidFill: return ProcRenderCreateSolidFill(client);
case X_RenderCreateLinearGradient: return ProcRenderCreateLinearGradient(client);
case X_RenderCreateRadialGradient: return ProcRenderCreateRadialGradient(client);
case X_RenderCreateConicalGradient: return ProcRenderCreateConicalGradient(client);
}
return BadRequest;
2003-11-14 16:48:57 +00:00
}
static void _X_COLD
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;
}
}
#ifdef XINERAMA
#define VERIFY_XIN_PICTURE(pPicture, pid, client, mode) {\
int rc = dixLookupResourceByType((void **)&(pPicture), pid,\
XRT_PICTURE, client, mode);\
if (rc != Success)\
return rc;\
2003-11-14 16:48:57 +00:00
}
#define VERIFY_XIN_ALPHA(pPicture, pid, client, mode) {\
2003-11-14 16:48:57 +00:00
if (pid == None) \
pPicture = 0; \
else { \
VERIFY_XIN_PICTURE(pPicture, pid, client, mode); \
2003-11-14 16:48:57 +00:00
} \
} \
static int
PanoramiXRenderCreatePicture(ClientPtr client, xRenderCreatePictureReq *stuff)
2003-11-14 16:48:57 +00:00
{
PanoramiXRes *refDraw, *newPict;
int result;
2003-11-14 16:48:57 +00:00
result = dixLookupResourceByClass((void **) &refDraw, stuff->drawable,
XRC_DRAWABLE, client, DixWriteAccess);
if (result != Success)
return (result == BadValue) ? BadDrawable : result;
if (!(newPict = calloc(1, sizeof(PanoramiXRes))))
2003-11-14 16:48:57 +00:00
return BadAlloc;
newPict->type = XRT_PICTURE;
panoramix_setup_ids(newPict, client, stuff->pid);
2003-11-14 16:48:57 +00:00
if (refDraw->type == XRT_WINDOW &&
treewide: rename dixGetFirstScreenPtr() to dixGetMasterScreen() for correct semantics In Xinerama/Panoramix configuration there's one screen that's having special meaning - it's used for simulating as the frontend for all client operations: the clients (should) only talk to that screen, while panoramix subsystem is proxying those operations to all the other screens (with certain changed applied, eg. coordinate transformations). Historically, this screen happens to be the first one in the system (some of it's proc's are hooked up in order to achieve desired behaviour). That's why it used to be accessed via screenInfo.screens[0] - that already had been encapsulated into a tiny helper `dixGetFirstScreen()`. a) the correct terminus technicus for a situation where one device (or SW entity) entirely controlling others is a master-slave-relationship: the controlling device/entity is `master`, the controlled ones are `slave` (to that specific master). b) the term "first screen" is inacurate and misleading here: what the caller's are actually interest in isn't the first entry in the screen array, but the screen that's controlling the others. With upcoming refactoring of the Xinerama/Panoramix subsystem, this might well be a different array index than 0. c) the term `default` also wouldn't match: `default` implies there's a real practical choice, and such value applies when no explicit choice has been made. But in this case, it practically doesn't make sense (except perhaps for debugging purpose) for a client to use any different screen. Therefore fixing the function name to the correct technical terminology. (for sake of patch readability, renaming corresponding variables is left to subsequent patches). Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
2025-09-11 16:50:43 +02:00
stuff->drawable == dixGetMasterScreen()->root->drawable.id) {
2003-11-14 16:48:57 +00:00
newPict->u.pict.root = TRUE;
}
else
newPict->u.pict.root = FALSE;
XINERAMA_FOR_EACH_SCREEN_BACKWARD({
stuff->pid = newPict->info[walkScreenIdx].id;
stuff->drawable = refDraw->info[walkScreenIdx].id;
result = SingleRenderCreatePicture(client, stuff);
2003-11-14 16:48:57 +00:00
if (result != Success)
break;
});
2003-11-14 16:48:57 +00:00
if (result == Success)
AddResource(newPict->info[0].id, XRT_PICTURE, newPict);
else
free(newPict);
2003-11-14 16:48:57 +00:00
return result;
2003-11-14 16:48:57 +00:00
}
static int
PanoramiXRenderChangePicture(ClientPtr client, xRenderChangePictureReq *stuff, Picture pictID)
2003-11-14 16:48:57 +00:00
{
PanoramiXRes *pict;
int result = Success;
VERIFY_XIN_PICTURE(pict, pictID, client, DixWriteAccess);
XINERAMA_FOR_EACH_SCREEN_BACKWARD({
result = SingleRenderChangePicture(client, stuff, pict->info[walkScreenIdx].id);
2003-11-14 16:48:57 +00:00
if (result != Success)
break;
});
2003-11-14 16:48:57 +00:00
return result;
2003-11-14 16:48:57 +00:00
}
static int
PanoramiXRenderSetPictureClipRectangles(ClientPtr client,
xRenderSetPictureClipRectanglesReq *stuff,
Picture pictID)
2003-11-14 16:48:57 +00:00
{
int result = Success;
2003-11-14 16:48:57 +00:00
PanoramiXRes *pict;
VERIFY_XIN_PICTURE(pict, pictID, client, DixWriteAccess);
XINERAMA_FOR_EACH_SCREEN_BACKWARD({
result = SingleRenderSetPictureClipRectangles(client, stuff, pict->info[walkScreenIdx].id);
2003-11-14 16:48:57 +00:00
if (result != Success)
break;
});
2003-11-14 16:48:57 +00:00
return result;
2003-11-14 16:48:57 +00:00
}
static int
PanoramiXRenderSetPictureTransform(ClientPtr client, xRenderSetPictureTransformReq *stuff)
{
int result = Success;
PanoramiXRes *pict;
VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixWriteAccess);
XINERAMA_FOR_EACH_SCREEN_BACKWARD({
stuff->picture = pict->info[walkScreenIdx].id;
result = SingleRenderSetPictureTransform(client, stuff);
if (result != Success)
break;
});
return result;
}
static int
PanoramiXRenderSetPictureFilter(ClientPtr client, xRenderSetPictureFilterReq *stuff)
{
int result = Success;
PanoramiXRes *pict;
VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixWriteAccess);
XINERAMA_FOR_EACH_SCREEN_BACKWARD({
stuff->picture = pict->info[walkScreenIdx].id;
result = SingleRenderSetPictureFilter(client, stuff);
if (result != Success)
break;
});
return result;
}
2003-11-14 16:48:57 +00:00
static int
PanoramiXRenderFreePicture(ClientPtr client)
{
PanoramiXRes *pict;
int result = Success;
2003-11-14 16:48:57 +00:00
REQUEST(xRenderFreePictureReq);
client->errorValue = stuff->picture;
VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixDestroyAccess);
2003-11-14 16:48:57 +00:00
XINERAMA_FOR_EACH_SCREEN_BACKWARD({
stuff->picture = pict->info[walkScreenIdx].id;
result = SingleRenderFreePicture(client);
2003-11-14 16:48:57 +00:00
if (result != Success)
break;
});
2003-11-14 16:48:57 +00:00
/* Since ProcRenderFreePicture is using FreeResource, it will free
our resource for us on the last pass through the loop above */
return result;
2003-11-14 16:48:57 +00:00
}
static int
PanoramiXRenderComposite(ClientPtr client, xRenderCompositeReq *orig_req)
2003-11-14 16:48:57 +00:00
{
PanoramiXRes *src, *msk, *dst;
int result = Success;
xRenderCompositeReq orig = *orig_req;
VERIFY_XIN_PICTURE(src, orig.src, client, DixReadAccess);
VERIFY_XIN_ALPHA(msk, orig.mask, client, DixReadAccess);
VERIFY_XIN_PICTURE(dst, orig.dst, client, DixWriteAccess);
xRenderCompositeReq sub_req = orig;
XINERAMA_FOR_EACH_SCREEN_FORWARD({
sub_req.src = src->info[walkScreenIdx].id;
2003-11-14 16:48:57 +00:00
if (src->u.pict.root) {
sub_req.xSrc = orig.xSrc - walkScreen->x;
sub_req.ySrc = orig.ySrc - walkScreen->y;
2003-11-14 16:48:57 +00:00
}
sub_req.dst = dst->info[walkScreenIdx].id;
2003-11-14 16:48:57 +00:00
if (dst->u.pict.root) {
sub_req.xDst = orig.xDst - walkScreen->x;
sub_req.yDst = orig.yDst - walkScreen->y;
2003-11-14 16:48:57 +00:00
}
if (msk) {
sub_req.mask = msk->info[walkScreenIdx].id;
2003-11-14 16:48:57 +00:00
if (msk->u.pict.root) {
sub_req.xMask = orig.xMask - walkScreen->x;
sub_req.yMask = orig.yMask - walkScreen->y;
}
2003-11-14 16:48:57 +00:00
}
result = SingleRenderComposite(client, &sub_req);
2003-11-14 16:48:57 +00:00
if (result != Success)
break;
});
2003-11-14 16:48:57 +00:00
return result;
}
static int
PanoramiXRenderCompositeGlyphs(ClientPtr client, xRenderCompositeGlyphsReq *stuff)
2003-11-14 16:48:57 +00:00
{
PanoramiXRes *src, *dst;
int result = Success;
2003-11-14 16:48:57 +00:00
xGlyphElt origElt, *elt;
INT16 xSrc, ySrc;
VERIFY_XIN_PICTURE(src, stuff->src, client, DixReadAccess);
VERIFY_XIN_PICTURE(dst, stuff->dst, client, DixWriteAccess);
2003-11-14 16:48:57 +00:00
if (client->req_len << 2 >= (sizeof(xRenderCompositeGlyphsReq) +
sizeof(xGlyphElt))) {
elt = (xGlyphElt *) (stuff + 1);
origElt = *elt;
xSrc = stuff->xSrc;
ySrc = stuff->ySrc;
XINERAMA_FOR_EACH_SCREEN_FORWARD({
stuff->src = src->info[walkScreenIdx].id;
2003-11-14 16:48:57 +00:00
if (src->u.pict.root) {
stuff->xSrc = xSrc - walkScreen->x;
stuff->ySrc = ySrc - walkScreen->y;
2003-11-14 16:48:57 +00:00
}
stuff->dst = dst->info[walkScreenIdx].id;
2003-11-14 16:48:57 +00:00
if (dst->u.pict.root) {
elt->deltax = origElt.deltax - walkScreen->x;
elt->deltay = origElt.deltay - walkScreen->y;
2003-11-14 16:48:57 +00:00
}
result = SingleRenderCompositeGlyphs(client, stuff);
2003-11-14 16:48:57 +00:00
if (result != Success)
break;
});
2003-11-14 16:48:57 +00:00
}
return result;
}
static int
PanoramiXRenderFillRectangles(ClientPtr client, xRenderFillRectanglesReq *stuff)
2003-11-14 16:48:57 +00:00
{
PanoramiXRes *dst;
int result = Success;
2003-11-14 16:48:57 +00:00
char *extra;
int extra_len;
VERIFY_XIN_PICTURE(dst, stuff->dst, client, DixWriteAccess);
2003-11-14 16:48:57 +00:00
extra_len = (client->req_len << 2) - sizeof(xRenderFillRectanglesReq);
if (extra_len && (extra = calloc(1, extra_len))) {
2003-11-14 16:48:57 +00:00
memcpy(extra, stuff + 1, extra_len);
XINERAMA_FOR_EACH_SCREEN_FORWARD({
if (walkScreenIdx) /* skip screen #0 */
2003-11-14 16:48:57 +00:00
memcpy(stuff + 1, extra, extra_len);
if (dst->u.pict.root) {
int x_off = walkScreen->x;
int y_off = walkScreen->y;
2003-11-14 16:48:57 +00:00
if (x_off || y_off) {
xRectangle *rects = (xRectangle *) (stuff + 1);
int i = extra_len / sizeof(xRectangle);
2003-11-14 16:48:57 +00:00
while (i--) {
rects->x -= x_off;
rects->y -= y_off;
rects++;
}
}
2003-11-14 16:48:57 +00:00
}
stuff->dst = dst->info[walkScreenIdx].id;
result = SingleRenderFillRectangles(client, stuff);
2003-11-14 16:48:57 +00:00
if (result != Success)
break;
});
free(extra);
2003-11-14 16:48:57 +00:00
}
return result;
}
static int
PanoramiXRenderTrapezoids(ClientPtr client, xRenderTrapezoidsReq *stuff)
{
PanoramiXRes *src, *dst;
int result = Success;
char *extra;
int extra_len;
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 = calloc(1, extra_len))) {
memcpy(extra, stuff + 1, extra_len);
XINERAMA_FOR_EACH_SCREEN_FORWARD({
if (walkScreenIdx) /* skip screen #0 */
memcpy(stuff + 1, extra, extra_len);
if (dst->u.pict.root) {
int x_off = walkScreen->x;
int y_off = walkScreen->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[walkScreenIdx].id;
stuff->dst = dst->info[walkScreenIdx].id;
result = SingleRenderTrapezoids(client, stuff);
if (result != Success)
break;
});
free(extra);
}
return result;
}
static int
PanoramiXRenderTriangles(ClientPtr client, xRenderTrianglesReq *stuff)
{
PanoramiXRes *src, *dst;
int result = Success;
char *extra;
int extra_len;
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 = calloc(1, extra_len))) {
memcpy(extra, stuff + 1, extra_len);
XINERAMA_FOR_EACH_SCREEN_FORWARD({
if (walkScreenIdx) /* skip screen #0 */
memcpy(stuff + 1, extra, extra_len);
if (dst->u.pict.root) {
int x_off = walkScreen->x;
int y_off = walkScreen->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[walkScreenIdx].id;
stuff->dst = dst->info[walkScreenIdx].id;
result = SingleRenderTriangles(client, stuff);
if (result != Success)
break;
});
free(extra);
}
return result;
}
static int
PanoramiXRenderTriStrip(ClientPtr client, xRenderTriStripReq *stuff)
{
PanoramiXRes *src, *dst;
int result = Success;
char *extra;
int extra_len;
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 = calloc(1, extra_len))) {
memcpy(extra, stuff + 1, extra_len);
XINERAMA_FOR_EACH_SCREEN_FORWARD({
if (walkScreenIdx) /* skip screen #0 */
memcpy(stuff + 1, extra, extra_len);
if (dst->u.pict.root) {
int x_off = walkScreen->x;
int y_off = walkScreen->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[walkScreenIdx].id;
stuff->dst = dst->info[walkScreenIdx].id;
result = SingleRenderTriStrip(client, stuff);
if (result != Success)
break;
});
free(extra);
}
return result;
}
static int
PanoramiXRenderTriFan(ClientPtr client, xRenderTriFanReq *stuff)
{
PanoramiXRes *src, *dst;
int result = Success;
char *extra;
int extra_len;
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 = calloc(1, extra_len))) {
memcpy(extra, stuff + 1, extra_len);
XINERAMA_FOR_EACH_SCREEN_FORWARD({
if (walkScreenIdx) /* skip screen #0 */
memcpy(stuff + 1, extra, extra_len);
if (dst->u.pict.root) {
int x_off = walkScreen->x;
int y_off = walkScreen->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[walkScreenIdx].id;
stuff->dst = dst->info[walkScreenIdx].id;
result = SingleRenderTriFan(client, stuff);
if (result != Success)
break;
});
free(extra);
}
return result;
}
static int
PanoramiXRenderAddTraps(ClientPtr client, xRenderAddTrapsReq *stuff)
{
PanoramiXRes *picture;
int result = Success;
char *extra;
int extra_len;
INT16 x_off, y_off;
VERIFY_XIN_PICTURE(picture, stuff->picture, client, DixWriteAccess);
extra_len = (client->req_len << 2) - sizeof(xRenderAddTrapsReq);
if (extra_len && (extra = calloc(1, extra_len))) {
memcpy(extra, stuff + 1, extra_len);
x_off = stuff->xOff;
y_off = stuff->yOff;
XINERAMA_FOR_EACH_SCREEN_FORWARD({
if (walkScreenIdx) /* skip screen #0 */
memcpy(stuff + 1, extra, extra_len);
stuff->picture = picture->info[walkScreenIdx].id;
if (picture->u.pict.root) {
stuff->xOff = x_off + walkScreen->x;
stuff->yOff = y_off + walkScreen->y;
}
result = SingleRenderAddTraps(client, stuff);
if (result != Success)
break;
});
free(extra);
}
return result;
}
static int
PanoramiXRenderCreateSolidFill(ClientPtr client, xRenderCreateSolidFillReq *stuff)
{
PanoramiXRes *newPict;
int result = Success;
if (!(newPict = calloc(1, sizeof(PanoramiXRes))))
return BadAlloc;
newPict->type = XRT_PICTURE;
panoramix_setup_ids(newPict, client, stuff->pid);
newPict->u.pict.root = FALSE;
XINERAMA_FOR_EACH_SCREEN_BACKWARD({
stuff->pid = newPict->info[walkScreenIdx].id;
result = SingleRenderCreateSolidFill(client, stuff);
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,
xRenderCreateLinearGradientReq *stuff)
{
PanoramiXRes *newPict;
int result = Success;
if (!(newPict = calloc(1, sizeof(PanoramiXRes))))
return BadAlloc;
newPict->type = XRT_PICTURE;
panoramix_setup_ids(newPict, client, stuff->pid);
newPict->u.pict.root = FALSE;
XINERAMA_FOR_EACH_SCREEN_BACKWARD({
stuff->pid = newPict->info[walkScreenIdx].id;
result = SingleRenderCreateLinearGradient(client, stuff);
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,
xRenderCreateRadialGradientReq *stuff)
{
PanoramiXRes *newPict;
int result = Success;
if (!(newPict = calloc(1, sizeof(PanoramiXRes))))
return BadAlloc;
newPict->type = XRT_PICTURE;
panoramix_setup_ids(newPict, client, stuff->pid);
newPict->u.pict.root = FALSE;
XINERAMA_FOR_EACH_SCREEN_BACKWARD({
stuff->pid = newPict->info[walkScreenIdx].id;
result = SingleRenderCreateRadialGradient(client, stuff);
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,
xRenderCreateConicalGradientReq *stuff)
{
PanoramiXRes *newPict;
int result = Success;
if (!(newPict = calloc(1, sizeof(PanoramiXRes))))
return BadAlloc;
newPict->type = XRT_PICTURE;
panoramix_setup_ids(newPict, client, stuff->pid);
newPict->u.pict.root = FALSE;
XINERAMA_FOR_EACH_SCREEN_BACKWARD({
stuff->pid = newPict->info[walkScreenIdx].id;
result = SingleRenderCreateConicalGradient(client, stuff);
if (result != Success)
break;
});
if (result == Success)
AddResource(newPict->info[0].id, XRT_PICTURE, newPict);
else
free(newPict);
return result;
}
void
2003-11-14 16:48:57 +00:00
PanoramiXRenderInit(void)
{
XRT_PICTURE = CreateNewResourceType(XineramaDeleteResource,
"XineramaPicture");
if (RenderErrBase)
SetResourceTypeErrorValue(XRT_PICTURE, RenderErrBase + BadPicture);
usePanoramiX = TRUE;
2003-11-14 16:48:57 +00:00
}
void
2003-11-14 16:48:57 +00:00
PanoramiXRenderReset(void)
{
RenderErrBase = 0;
usePanoramiX = FALSE;
2003-11-14 16:48:57 +00:00
}
#endif /* XINERAMA */
static int
ProcRenderCreatePicture(ClientPtr client)
{
REQUEST(xRenderCreatePictureReq);
REQUEST_AT_LEAST_SIZE(xRenderCreatePictureReq);
if (client->swapped) {
swapl(&stuff->pid);
swapl(&stuff->drawable);
swapl(&stuff->format);
swapl(&stuff->mask);
SwapRestL(stuff);
}
#ifdef XINERAMA
return (usePanoramiX ? PanoramiXRenderCreatePicture(client, stuff)
: SingleRenderCreatePicture(client, stuff));
#else
return SingleRenderCreatePicture(client, stuff);
#endif
}
static int
ProcRenderChangePicture(ClientPtr client)
{
REQUEST(xRenderChangePictureReq);
REQUEST_AT_LEAST_SIZE(xRenderChangePictureReq);
if (client->swapped) {
swapl(&stuff->picture);
swapl(&stuff->mask);
SwapRestL(stuff);
}
#ifdef XINERAMA
return (usePanoramiX ? PanoramiXRenderChangePicture(client, stuff, stuff->picture)
: SingleRenderChangePicture(client, stuff, stuff->picture));
#else
return SingleRenderChangePicture(client, stuff, stuff->picture);
#endif
}
static int
ProcRenderSetPictureClipRectangles(ClientPtr client)
{
REQUEST(xRenderSetPictureClipRectanglesReq);
REQUEST_AT_LEAST_SIZE(xRenderSetPictureClipRectanglesReq);
if (client->swapped) {
swapl(&stuff->picture);
swaps(&stuff->xOrigin);
swaps(&stuff->yOrigin);
SwapRestS(stuff);
}
#ifdef XINERAMA
return (usePanoramiX ? PanoramiXRenderSetPictureClipRectangles(client, stuff, stuff->picture)
: SingleRenderSetPictureClipRectangles(client, stuff, stuff->picture));
#else
return SingleRenderSetPictureClipRectangles(client, stuff, stuff->picture);
#endif
}
static int
ProcRenderFreePicture(ClientPtr client)
{
REQUEST(xRenderFreePictureReq);
REQUEST_SIZE_MATCH(xRenderFreePictureReq);
if (client->swapped)
swapl(&stuff->picture);
#ifdef XINERAMA
return (usePanoramiX ? PanoramiXRenderFreePicture(client)
: SingleRenderFreePicture(client));
#else
return SingleRenderFreePicture(client);
#endif
}
static int
ProcRenderComposite(ClientPtr client)
{
REQUEST(xRenderCompositeReq);
REQUEST_SIZE_MATCH(xRenderCompositeReq);
if (client->swapped) {
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);
}
#ifdef XINERAMA
return (usePanoramiX ? PanoramiXRenderComposite(client, stuff)
: SingleRenderComposite(client, stuff));
#else
return SingleRenderComposite(client, stuff);
#endif
}
static int
ProcRenderTrapezoids(ClientPtr client)
{
REQUEST(xRenderTrapezoidsReq);
REQUEST_AT_LEAST_SIZE(xRenderTrapezoidsReq);
if (client->swapped) {
swapl(&stuff->src);
swapl(&stuff->dst);
swapl(&stuff->maskFormat);
swaps(&stuff->xSrc);
swaps(&stuff->ySrc);
SwapRestL(stuff);
}
#ifdef XINERAMA
return (usePanoramiX ? PanoramiXRenderTrapezoids(client, stuff)
: SingleRenderTrapezoids(client, stuff));
#else
return SingleRenderTrapezoids(client, stuff);
#endif
}
static int
ProcRenderTriangles(ClientPtr client)
{
REQUEST(xRenderTrianglesReq);
REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq);
if (client->swapped) {
swapl(&stuff->src);
swapl(&stuff->dst);
swapl(&stuff->maskFormat);
swaps(&stuff->xSrc);
swaps(&stuff->ySrc);
SwapRestL(stuff);
}
#ifdef XINERAMA
return (usePanoramiX ? PanoramiXRenderTriangles(client, stuff)
: SingleRenderTriangles(client, stuff));
#else
return SingleRenderTriangles(client, stuff);
#endif
}
static int
ProcRenderTriStrip(ClientPtr client)
{
REQUEST(xRenderTriStripReq);
REQUEST_AT_LEAST_SIZE(xRenderTriStripReq);
if (client->swapped) {
swapl(&stuff->src);
swapl(&stuff->dst);
swapl(&stuff->maskFormat);
swaps(&stuff->xSrc);
swaps(&stuff->ySrc);
SwapRestL(stuff);
}
#ifdef XINERAMA
return (usePanoramiX ? PanoramiXRenderTriStrip(client, stuff)
: SingleRenderTriStrip(client, stuff));
#else
2025-11-02 21:17:07 +01:00
return SingleRenderTriStrip(client, stuff);
#endif
}
static int
ProcRenderTriFan(ClientPtr client)
{
REQUEST(xRenderTriFanReq);
REQUEST_AT_LEAST_SIZE(xRenderTriFanReq);
if (client->swapped) {
swapl(&stuff->src);
swapl(&stuff->dst);
swapl(&stuff->maskFormat);
swaps(&stuff->xSrc);
swaps(&stuff->ySrc);
SwapRestL(stuff);
}
#ifdef XINERAMA
return (usePanoramiX ? PanoramiXRenderTriFan(client, stuff)
: SingleRenderTriFan(client, stuff));
#else
return SingleRenderTriFan(client, stuff);
#endif
}
static int
ProcRenderCompositeGlyphs(ClientPtr client)
{
REQUEST(xRenderCompositeGlyphsReq);
REQUEST_AT_LEAST_SIZE(xRenderCompositeGlyphsReq);
if (client->swapped) {
int size = 0;
switch (stuff->renderReqType) {
default:
size = 1;
break;
case X_RenderCompositeGlyphs16:
size = 2;
break;
case X_RenderCompositeGlyphs32:
size = 4;
break;
}
swapl(&stuff->src);
swapl(&stuff->dst);
swapl(&stuff->maskFormat);
swapl(&stuff->glyphset);
swaps(&stuff->xSrc);
swaps(&stuff->ySrc);
CARD8 *buffer = (CARD8 *) (stuff + 1);
CARD8 *end = (CARD8 *) stuff + (client->req_len << 2);
while (buffer + sizeof(xGlyphElt) < end) {
xGlyphElt *elt = (xGlyphElt *) buffer;
buffer += sizeof(xGlyphElt);
swaps(&elt->deltax);
swaps(&elt->deltay);
int i = elt->len;
if (i == 0xff) {
if (buffer + 4 > end) {
return BadLength;
}
swapl((int *) buffer);
buffer += 4;
}
else {
int space = size * i;
switch (size) {
case 1:
buffer += i;
break;
case 2:
if (buffer + i * 2 > end) {
return BadLength;
}
while (i--) {
swaps((short *) buffer);
buffer += 2;
}
break;
case 4:
if (buffer + i * 4 > end) {
return BadLength;
}
while (i--) {
swapl((int *) buffer);
buffer += 4;
}
break;
}
if (space & 3)
buffer += 4 - (space & 3);
}
}
}
#ifdef XINERAMA
return (usePanoramiX ? PanoramiXRenderCompositeGlyphs(client, stuff)
: SingleRenderCompositeGlyphs(client, stuff));
#else
return SingleRenderCompositeGlyphs(client, stuff);
#endif
}
static int
ProcRenderFillRectangles(ClientPtr client)
{
REQUEST(xRenderFillRectanglesReq);
REQUEST_AT_LEAST_SIZE(xRenderFillRectanglesReq);
if (client->swapped) {
swapl(&stuff->dst);
swaps(&stuff->color.red);
swaps(&stuff->color.green);
swaps(&stuff->color.blue);
swaps(&stuff->color.alpha);
SwapRestS(stuff);
}
#ifdef XINERAMA
return (usePanoramiX ? PanoramiXRenderFillRectangles(client, stuff)
: SingleRenderFillRectangles(client, stuff));
#else
return SingleRenderFillRectangles(client, stuff);
#endif
}
static int
ProcRenderSetPictureTransform(ClientPtr client)
{
REQUEST(xRenderSetPictureTransformReq);
REQUEST_SIZE_MATCH(xRenderSetPictureTransformReq);
if (client->swapped) {
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);
}
#ifdef XINERAMA
return (usePanoramiX ? PanoramiXRenderSetPictureTransform(client, stuff)
: SingleRenderSetPictureTransform(client, stuff));
#else
return SingleRenderSetPictureTransform(client, stuff);
#endif
}
static int
ProcRenderSetPictureFilter(ClientPtr client)
{
REQUEST(xRenderSetPictureFilterReq);
REQUEST_AT_LEAST_SIZE(xRenderSetPictureFilterReq);
if (client->swapped) {
swapl(&stuff->picture);
swaps(&stuff->nbytes);
}
#ifdef XINERAMA
return (usePanoramiX ? PanoramiXRenderSetPictureFilter(client, stuff)
: SingleRenderSetPictureFilter(client, stuff));
#else
return SingleRenderSetPictureFilter(client, stuff);
#endif
}
static int
ProcRenderAddTraps(ClientPtr client)
{
REQUEST(xRenderAddTrapsReq);
REQUEST_AT_LEAST_SIZE(xRenderAddTrapsReq);
if (client->swapped) {
swapl(&stuff->picture);
swaps(&stuff->xOff);
swaps(&stuff->yOff);
SwapRestL(stuff);
}
#ifdef XINERAMA
return (usePanoramiX ? PanoramiXRenderAddTraps(client, stuff)
: SingleRenderAddTraps(client, stuff));
#else
return SingleRenderAddTraps(client, stuff);
#endif
}
static int
ProcRenderCreateSolidFill(ClientPtr client)
{
REQUEST(xRenderCreateSolidFillReq);
REQUEST_AT_LEAST_SIZE(xRenderCreateSolidFillReq);
if (client->swapped) {
swapl(&stuff->pid);
swaps(&stuff->color.alpha);
swaps(&stuff->color.red);
swaps(&stuff->color.green);
swaps(&stuff->color.blue);
}
#ifdef XINERAMA
return (usePanoramiX ? PanoramiXRenderCreateSolidFill(client, stuff)
: SingleRenderCreateSolidFill(client, stuff));
#else
return SingleRenderCreateSolidFill(client, stuff);
#endif
}
static int
ProcRenderCreateLinearGradient(ClientPtr client)
{
REQUEST(xRenderCreateLinearGradientReq);
REQUEST_AT_LEAST_SIZE(xRenderCreateLinearGradientReq);
if (client->swapped) {
swapl(&stuff->pid);
swapl(&stuff->p1.x);
swapl(&stuff->p1.y);
swapl(&stuff->p2.x);
swapl(&stuff->p2.y);
swapl(&stuff->nStops);
int 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);
}
#ifdef XINERAMA
return (usePanoramiX ? PanoramiXRenderCreateLinearGradient(client, stuff)
: SingleRenderCreateLinearGradient(client, stuff));
#else
return SingleRenderCreateLinearGradient(client, stuff);
#endif
}
static int
ProcRenderCreateRadialGradient(ClientPtr client)
{
REQUEST(xRenderCreateRadialGradientReq);
REQUEST_AT_LEAST_SIZE(xRenderCreateRadialGradientReq);
if (client->swapped) {
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);
int 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);
}
#ifdef XINERAMA
return (usePanoramiX ? PanoramiXRenderCreateRadialGradient(client, stuff)
: SingleRenderCreateRadialGradient(client, stuff));
#else
return SingleRenderCreateRadialGradient(client, stuff);
#endif
}
static int
ProcRenderCreateConicalGradient(ClientPtr client)
{
REQUEST(xRenderCreateConicalGradientReq);
REQUEST_AT_LEAST_SIZE(xRenderCreateConicalGradientReq);
if (client->swapped) {
swapl(&stuff->pid);
swapl(&stuff->center.x);
swapl(&stuff->center.y);
swapl(&stuff->angle);
swapl(&stuff->nStops);
int 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);
}
#ifdef XINERAMA
return (usePanoramiX ? PanoramiXRenderCreateConicalGradient(client, stuff)
: SingleRenderCreateConicalGradient(client, stuff));
#else
return SingleRenderCreateConicalGradient(client, stuff);
#endif
}