render.c revision 6e78d31f
1/*
2 *
3 * Copyright © 2000 SuSE, Inc.
4 *
5 * Permission to use, copy, modify, distribute, and sell this software and its
6 * documentation for any purpose is hereby granted without fee, provided that
7 * the above copyright notice appear in all copies and that both that
8 * copyright notice and this permission notice appear in supporting
9 * documentation, and that the name of SuSE not be used in advertising or
10 * publicity pertaining to distribution of the software without specific,
11 * written prior permission.  SuSE makes no representations about the
12 * suitability of this software for any purpose.  It is provided "as is"
13 * without express or implied warranty.
14 *
15 * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
17 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
18 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
19 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 *
22 * Author:  Keith Packard, SuSE, Inc.
23 */
24
25#ifdef HAVE_DIX_CONFIG_H
26#include <dix-config.h>
27#endif
28
29#include <X11/X.h>
30#include <X11/Xproto.h>
31#include "misc.h"
32#include "os.h"
33#include "dixstruct.h"
34#include "resource.h"
35#include "scrnintstr.h"
36#include "windowstr.h"
37#include "pixmapstr.h"
38#include "colormapst.h"
39#include "extnsionst.h"
40#include "extinit.h"
41#include "servermd.h"
42#include <X11/extensions/render.h>
43#include <X11/extensions/renderproto.h>
44#include "picturestr.h"
45#include "glyphstr.h"
46#include <X11/Xfuncproto.h>
47#include "cursorstr.h"
48#include "xace.h"
49#include "protocol-versions.h"
50
51#ifdef PANORAMIX
52#include "panoramiX.h"
53#include "panoramiXsrv.h"
54#endif
55
56#include <stdint.h>
57
58static int ProcRenderQueryVersion(ClientPtr pClient);
59static int ProcRenderQueryPictFormats(ClientPtr pClient);
60static int ProcRenderQueryPictIndexValues(ClientPtr pClient);
61static int ProcRenderQueryDithers(ClientPtr pClient);
62static int ProcRenderCreatePicture(ClientPtr pClient);
63static int ProcRenderChangePicture(ClientPtr pClient);
64static int ProcRenderSetPictureClipRectangles(ClientPtr pClient);
65static int ProcRenderFreePicture(ClientPtr pClient);
66static int ProcRenderComposite(ClientPtr pClient);
67static int ProcRenderScale(ClientPtr pClient);
68static int ProcRenderTrapezoids(ClientPtr pClient);
69static int ProcRenderTriangles(ClientPtr pClient);
70static int ProcRenderTriStrip(ClientPtr pClient);
71static int ProcRenderTriFan(ClientPtr pClient);
72static int ProcRenderColorTrapezoids(ClientPtr pClient);
73static int ProcRenderColorTriangles(ClientPtr pClient);
74static int ProcRenderTransform(ClientPtr pClient);
75static int ProcRenderCreateGlyphSet(ClientPtr pClient);
76static int ProcRenderReferenceGlyphSet(ClientPtr pClient);
77static int ProcRenderFreeGlyphSet(ClientPtr pClient);
78static int ProcRenderAddGlyphs(ClientPtr pClient);
79static int ProcRenderAddGlyphsFromPicture(ClientPtr pClient);
80static int ProcRenderFreeGlyphs(ClientPtr pClient);
81static int ProcRenderCompositeGlyphs(ClientPtr pClient);
82static int ProcRenderFillRectangles(ClientPtr pClient);
83static int ProcRenderCreateCursor(ClientPtr pClient);
84static int ProcRenderSetPictureTransform(ClientPtr pClient);
85static int ProcRenderQueryFilters(ClientPtr pClient);
86static int ProcRenderSetPictureFilter(ClientPtr pClient);
87static int ProcRenderCreateAnimCursor(ClientPtr pClient);
88static int ProcRenderAddTraps(ClientPtr pClient);
89static int ProcRenderCreateSolidFill(ClientPtr pClient);
90static int ProcRenderCreateLinearGradient(ClientPtr pClient);
91static int ProcRenderCreateRadialGradient(ClientPtr pClient);
92static int ProcRenderCreateConicalGradient(ClientPtr pClient);
93
94static int ProcRenderDispatch(ClientPtr pClient);
95
96static int SProcRenderQueryVersion(ClientPtr pClient);
97static int SProcRenderQueryPictFormats(ClientPtr pClient);
98static int SProcRenderQueryPictIndexValues(ClientPtr pClient);
99static int SProcRenderQueryDithers(ClientPtr pClient);
100static int SProcRenderCreatePicture(ClientPtr pClient);
101static int SProcRenderChangePicture(ClientPtr pClient);
102static int SProcRenderSetPictureClipRectangles(ClientPtr pClient);
103static int SProcRenderFreePicture(ClientPtr pClient);
104static int SProcRenderComposite(ClientPtr pClient);
105static int SProcRenderScale(ClientPtr pClient);
106static int SProcRenderTrapezoids(ClientPtr pClient);
107static int SProcRenderTriangles(ClientPtr pClient);
108static int SProcRenderTriStrip(ClientPtr pClient);
109static int SProcRenderTriFan(ClientPtr pClient);
110static int SProcRenderColorTrapezoids(ClientPtr pClient);
111static int SProcRenderColorTriangles(ClientPtr pClient);
112static int SProcRenderTransform(ClientPtr pClient);
113static int SProcRenderCreateGlyphSet(ClientPtr pClient);
114static int SProcRenderReferenceGlyphSet(ClientPtr pClient);
115static int SProcRenderFreeGlyphSet(ClientPtr pClient);
116static int SProcRenderAddGlyphs(ClientPtr pClient);
117static int SProcRenderAddGlyphsFromPicture(ClientPtr pClient);
118static int SProcRenderFreeGlyphs(ClientPtr pClient);
119static int SProcRenderCompositeGlyphs(ClientPtr pClient);
120static int SProcRenderFillRectangles(ClientPtr pClient);
121static int SProcRenderCreateCursor(ClientPtr pClient);
122static int SProcRenderSetPictureTransform(ClientPtr pClient);
123static int SProcRenderQueryFilters(ClientPtr pClient);
124static int SProcRenderSetPictureFilter(ClientPtr pClient);
125static int SProcRenderCreateAnimCursor(ClientPtr pClient);
126static int SProcRenderAddTraps(ClientPtr pClient);
127static int SProcRenderCreateSolidFill(ClientPtr pClient);
128static int SProcRenderCreateLinearGradient(ClientPtr pClient);
129static int SProcRenderCreateRadialGradient(ClientPtr pClient);
130static int SProcRenderCreateConicalGradient(ClientPtr pClient);
131
132static int SProcRenderDispatch(ClientPtr pClient);
133
134int (*ProcRenderVector[RenderNumberRequests]) (ClientPtr) = {
135ProcRenderQueryVersion,
136        ProcRenderQueryPictFormats,
137        ProcRenderQueryPictIndexValues,
138        ProcRenderQueryDithers,
139        ProcRenderCreatePicture,
140        ProcRenderChangePicture,
141        ProcRenderSetPictureClipRectangles,
142        ProcRenderFreePicture,
143        ProcRenderComposite,
144        ProcRenderScale,
145        ProcRenderTrapezoids,
146        ProcRenderTriangles,
147        ProcRenderTriStrip,
148        ProcRenderTriFan,
149        ProcRenderColorTrapezoids,
150        ProcRenderColorTriangles,
151        ProcRenderTransform,
152        ProcRenderCreateGlyphSet,
153        ProcRenderReferenceGlyphSet,
154        ProcRenderFreeGlyphSet,
155        ProcRenderAddGlyphs,
156        ProcRenderAddGlyphsFromPicture,
157        ProcRenderFreeGlyphs,
158        ProcRenderCompositeGlyphs,
159        ProcRenderCompositeGlyphs,
160        ProcRenderCompositeGlyphs,
161        ProcRenderFillRectangles,
162        ProcRenderCreateCursor,
163        ProcRenderSetPictureTransform,
164        ProcRenderQueryFilters,
165        ProcRenderSetPictureFilter,
166        ProcRenderCreateAnimCursor,
167        ProcRenderAddTraps,
168        ProcRenderCreateSolidFill,
169        ProcRenderCreateLinearGradient,
170        ProcRenderCreateRadialGradient, ProcRenderCreateConicalGradient};
171
172int (*SProcRenderVector[RenderNumberRequests]) (ClientPtr) = {
173SProcRenderQueryVersion,
174        SProcRenderQueryPictFormats,
175        SProcRenderQueryPictIndexValues,
176        SProcRenderQueryDithers,
177        SProcRenderCreatePicture,
178        SProcRenderChangePicture,
179        SProcRenderSetPictureClipRectangles,
180        SProcRenderFreePicture,
181        SProcRenderComposite,
182        SProcRenderScale,
183        SProcRenderTrapezoids,
184        SProcRenderTriangles,
185        SProcRenderTriStrip,
186        SProcRenderTriFan,
187        SProcRenderColorTrapezoids,
188        SProcRenderColorTriangles,
189        SProcRenderTransform,
190        SProcRenderCreateGlyphSet,
191        SProcRenderReferenceGlyphSet,
192        SProcRenderFreeGlyphSet,
193        SProcRenderAddGlyphs,
194        SProcRenderAddGlyphsFromPicture,
195        SProcRenderFreeGlyphs,
196        SProcRenderCompositeGlyphs,
197        SProcRenderCompositeGlyphs,
198        SProcRenderCompositeGlyphs,
199        SProcRenderFillRectangles,
200        SProcRenderCreateCursor,
201        SProcRenderSetPictureTransform,
202        SProcRenderQueryFilters,
203        SProcRenderSetPictureFilter,
204        SProcRenderCreateAnimCursor,
205        SProcRenderAddTraps,
206        SProcRenderCreateSolidFill,
207        SProcRenderCreateLinearGradient,
208        SProcRenderCreateRadialGradient, SProcRenderCreateConicalGradient};
209
210int RenderErrBase;
211static DevPrivateKeyRec RenderClientPrivateKeyRec;
212
213#define RenderClientPrivateKey (&RenderClientPrivateKeyRec )
214
215typedef struct _RenderClient {
216    int major_version;
217    int minor_version;
218} RenderClientRec, *RenderClientPtr;
219
220#define GetRenderClient(pClient) ((RenderClientPtr)dixLookupPrivate(&(pClient)->devPrivates, RenderClientPrivateKey))
221
222static void
223RenderClientCallback(CallbackListPtr *list, void *closure, void *data)
224{
225    NewClientInfoRec *clientinfo = (NewClientInfoRec *) data;
226    ClientPtr pClient = clientinfo->client;
227    RenderClientPtr pRenderClient = GetRenderClient(pClient);
228
229    pRenderClient->major_version = 0;
230    pRenderClient->minor_version = 0;
231}
232
233#ifdef PANORAMIX
234RESTYPE XRT_PICTURE;
235#endif
236
237void
238RenderExtensionInit(void)
239{
240    ExtensionEntry *extEntry;
241
242    if (!PictureType)
243        return;
244    if (!PictureFinishInit())
245        return;
246    if (!dixRegisterPrivateKey
247        (&RenderClientPrivateKeyRec, PRIVATE_CLIENT, sizeof(RenderClientRec)))
248        return;
249    if (!AddCallback(&ClientStateCallback, RenderClientCallback, 0))
250        return;
251
252    extEntry = AddExtension(RENDER_NAME, 0, RenderNumberErrors,
253                            ProcRenderDispatch, SProcRenderDispatch,
254                            NULL, StandardMinorOpcode);
255    if (!extEntry)
256        return;
257    RenderErrBase = extEntry->errorBase;
258#ifdef PANORAMIX
259    if (XRT_PICTURE)
260        SetResourceTypeErrorValue(XRT_PICTURE, RenderErrBase + BadPicture);
261#endif
262    SetResourceTypeErrorValue(PictureType, RenderErrBase + BadPicture);
263    SetResourceTypeErrorValue(PictFormatType, RenderErrBase + BadPictFormat);
264    SetResourceTypeErrorValue(GlyphSetType, RenderErrBase + BadGlyphSet);
265}
266
267static int
268ProcRenderQueryVersion(ClientPtr client)
269{
270    RenderClientPtr pRenderClient = GetRenderClient(client);
271    xRenderQueryVersionReply rep = {
272        .type = X_Reply,
273        .sequenceNumber = client->sequence,
274        .length = 0
275    };
276
277    REQUEST(xRenderQueryVersionReq);
278    REQUEST_SIZE_MATCH(xRenderQueryVersionReq);
279
280    REQUEST_SIZE_MATCH(xRenderQueryVersionReq);
281
282    pRenderClient->major_version = stuff->majorVersion;
283    pRenderClient->minor_version = stuff->minorVersion;
284
285    if ((stuff->majorVersion * 1000 + stuff->minorVersion) <
286        (SERVER_RENDER_MAJOR_VERSION * 1000 + SERVER_RENDER_MINOR_VERSION)) {
287        rep.majorVersion = stuff->majorVersion;
288        rep.minorVersion = stuff->minorVersion;
289    }
290    else {
291        rep.majorVersion = SERVER_RENDER_MAJOR_VERSION;
292        rep.minorVersion = SERVER_RENDER_MINOR_VERSION;
293    }
294
295    if (client->swapped) {
296        swaps(&rep.sequenceNumber);
297        swapl(&rep.length);
298        swapl(&rep.majorVersion);
299        swapl(&rep.minorVersion);
300    }
301    WriteToClient(client, sizeof(xRenderQueryVersionReply), &rep);
302    return Success;
303}
304
305static VisualPtr
306findVisual(ScreenPtr pScreen, VisualID vid)
307{
308    VisualPtr pVisual;
309    int v;
310
311    for (v = 0; v < pScreen->numVisuals; v++) {
312        pVisual = pScreen->visuals + v;
313        if (pVisual->vid == vid)
314            return pVisual;
315    }
316    return 0;
317}
318
319static int
320ProcRenderQueryPictFormats(ClientPtr client)
321{
322    RenderClientPtr pRenderClient = GetRenderClient(client);
323    xRenderQueryPictFormatsReply *reply;
324    xPictScreen *pictScreen;
325    xPictDepth *pictDepth;
326    xPictVisual *pictVisual;
327    xPictFormInfo *pictForm;
328    CARD32 *pictSubpixel;
329    ScreenPtr pScreen;
330    VisualPtr pVisual;
331    DepthPtr pDepth;
332    int v, d;
333    PictureScreenPtr ps;
334    PictFormatPtr pFormat;
335    int nformat;
336    int ndepth;
337    int nvisual;
338    int rlength;
339    int s;
340    int numScreens;
341    int numSubpixel;
342
343/*    REQUEST(xRenderQueryPictFormatsReq); */
344
345    REQUEST_SIZE_MATCH(xRenderQueryPictFormatsReq);
346
347#ifdef PANORAMIX
348    if (noPanoramiXExtension)
349        numScreens = screenInfo.numScreens;
350    else
351        numScreens = ((xConnSetup *) ConnectionInfo)->numRoots;
352#else
353    numScreens = screenInfo.numScreens;
354#endif
355    ndepth = nformat = nvisual = 0;
356    for (s = 0; s < numScreens; s++) {
357        pScreen = screenInfo.screens[s];
358        for (d = 0; d < pScreen->numDepths; d++) {
359            pDepth = pScreen->allowedDepths + d;
360            ++ndepth;
361
362            for (v = 0; v < pDepth->numVids; v++) {
363                pVisual = findVisual(pScreen, pDepth->vids[v]);
364                if (pVisual &&
365                    PictureMatchVisual(pScreen, pDepth->depth, pVisual))
366                    ++nvisual;
367            }
368        }
369        ps = GetPictureScreenIfSet(pScreen);
370        if (ps)
371            nformat += ps->nformats;
372    }
373    if (pRenderClient->major_version == 0 && pRenderClient->minor_version < 6)
374        numSubpixel = 0;
375    else
376        numSubpixel = numScreens;
377
378    rlength = (sizeof(xRenderQueryPictFormatsReply) +
379               nformat * sizeof(xPictFormInfo) +
380               numScreens * sizeof(xPictScreen) +
381               ndepth * sizeof(xPictDepth) +
382               nvisual * sizeof(xPictVisual) + numSubpixel * sizeof(CARD32));
383    reply = (xRenderQueryPictFormatsReply *) calloc(1, rlength);
384    if (!reply)
385        return BadAlloc;
386    reply->type = X_Reply;
387    reply->sequenceNumber = client->sequence;
388    reply->length = bytes_to_int32(rlength - sizeof(xGenericReply));
389    reply->numFormats = nformat;
390    reply->numScreens = numScreens;
391    reply->numDepths = ndepth;
392    reply->numVisuals = nvisual;
393    reply->numSubpixel = numSubpixel;
394
395    pictForm = (xPictFormInfo *) (reply + 1);
396
397    for (s = 0; s < numScreens; s++) {
398        pScreen = screenInfo.screens[s];
399        ps = GetPictureScreenIfSet(pScreen);
400        if (ps) {
401            for (nformat = 0, pFormat = ps->formats;
402                 nformat < ps->nformats; nformat++, pFormat++) {
403                pictForm->id = pFormat->id;
404                pictForm->type = pFormat->type;
405                pictForm->depth = pFormat->depth;
406                pictForm->direct.red = pFormat->direct.red;
407                pictForm->direct.redMask = pFormat->direct.redMask;
408                pictForm->direct.green = pFormat->direct.green;
409                pictForm->direct.greenMask = pFormat->direct.greenMask;
410                pictForm->direct.blue = pFormat->direct.blue;
411                pictForm->direct.blueMask = pFormat->direct.blueMask;
412                pictForm->direct.alpha = pFormat->direct.alpha;
413                pictForm->direct.alphaMask = pFormat->direct.alphaMask;
414                if (pFormat->type == PictTypeIndexed &&
415                    pFormat->index.pColormap)
416                    pictForm->colormap = pFormat->index.pColormap->mid;
417                else
418                    pictForm->colormap = None;
419                if (client->swapped) {
420                    swapl(&pictForm->id);
421                    swaps(&pictForm->direct.red);
422                    swaps(&pictForm->direct.redMask);
423                    swaps(&pictForm->direct.green);
424                    swaps(&pictForm->direct.greenMask);
425                    swaps(&pictForm->direct.blue);
426                    swaps(&pictForm->direct.blueMask);
427                    swaps(&pictForm->direct.alpha);
428                    swaps(&pictForm->direct.alphaMask);
429                    swapl(&pictForm->colormap);
430                }
431                pictForm++;
432            }
433        }
434    }
435
436    pictScreen = (xPictScreen *) pictForm;
437    for (s = 0; s < numScreens; s++) {
438        pScreen = screenInfo.screens[s];
439        pictDepth = (xPictDepth *) (pictScreen + 1);
440        ndepth = 0;
441        for (d = 0; d < pScreen->numDepths; d++) {
442            pictVisual = (xPictVisual *) (pictDepth + 1);
443            pDepth = pScreen->allowedDepths + d;
444
445            nvisual = 0;
446            for (v = 0; v < pDepth->numVids; v++) {
447                pVisual = findVisual(pScreen, pDepth->vids[v]);
448                if (pVisual && (pFormat = PictureMatchVisual(pScreen,
449                                                             pDepth->depth,
450                                                             pVisual))) {
451                    pictVisual->visual = pVisual->vid;
452                    pictVisual->format = pFormat->id;
453                    if (client->swapped) {
454                        swapl(&pictVisual->visual);
455                        swapl(&pictVisual->format);
456                    }
457                    pictVisual++;
458                    nvisual++;
459                }
460            }
461            pictDepth->depth = pDepth->depth;
462            pictDepth->nPictVisuals = nvisual;
463            if (client->swapped) {
464                swaps(&pictDepth->nPictVisuals);
465            }
466            ndepth++;
467            pictDepth = (xPictDepth *) pictVisual;
468        }
469        pictScreen->nDepth = ndepth;
470        ps = GetPictureScreenIfSet(pScreen);
471        if (ps)
472            pictScreen->fallback = ps->fallback->id;
473        else
474            pictScreen->fallback = 0;
475        if (client->swapped) {
476            swapl(&pictScreen->nDepth);
477            swapl(&pictScreen->fallback);
478        }
479        pictScreen = (xPictScreen *) pictDepth;
480    }
481    pictSubpixel = (CARD32 *) pictScreen;
482
483    for (s = 0; s < numSubpixel; s++) {
484        pScreen = screenInfo.screens[s];
485        ps = GetPictureScreenIfSet(pScreen);
486        if (ps)
487            *pictSubpixel = ps->subpixel;
488        else
489            *pictSubpixel = SubPixelUnknown;
490        if (client->swapped) {
491            swapl(pictSubpixel);
492        }
493        ++pictSubpixel;
494    }
495
496    if (client->swapped) {
497        swaps(&reply->sequenceNumber);
498        swapl(&reply->length);
499        swapl(&reply->numFormats);
500        swapl(&reply->numScreens);
501        swapl(&reply->numDepths);
502        swapl(&reply->numVisuals);
503        swapl(&reply->numSubpixel);
504    }
505    WriteToClient(client, rlength, reply);
506    free(reply);
507    return Success;
508}
509
510static int
511ProcRenderQueryPictIndexValues(ClientPtr client)
512{
513    PictFormatPtr pFormat;
514    int rc, num;
515    int rlength;
516    int i;
517
518    REQUEST(xRenderQueryPictIndexValuesReq);
519    xRenderQueryPictIndexValuesReply *reply;
520    xIndexValue *values;
521
522    REQUEST_AT_LEAST_SIZE(xRenderQueryPictIndexValuesReq);
523
524    rc = dixLookupResourceByType((void **) &pFormat, stuff->format,
525                                 PictFormatType, client, DixReadAccess);
526    if (rc != Success)
527        return rc;
528
529    if (pFormat->type != PictTypeIndexed) {
530        client->errorValue = stuff->format;
531        return BadMatch;
532    }
533    num = pFormat->index.nvalues;
534    rlength = (sizeof(xRenderQueryPictIndexValuesReply) +
535               num * sizeof(xIndexValue));
536    reply = (xRenderQueryPictIndexValuesReply *) calloc(1, rlength);
537    if (!reply)
538        return BadAlloc;
539
540    reply->type = X_Reply;
541    reply->sequenceNumber = client->sequence;
542    reply->length = bytes_to_int32(rlength - sizeof(xGenericReply));
543    reply->numIndexValues = num;
544
545    values = (xIndexValue *) (reply + 1);
546
547    memcpy(reply + 1, pFormat->index.pValues, num * sizeof(xIndexValue));
548
549    if (client->swapped) {
550        for (i = 0; i < num; i++) {
551            swapl(&values[i].pixel);
552            swaps(&values[i].red);
553            swaps(&values[i].green);
554            swaps(&values[i].blue);
555            swaps(&values[i].alpha);
556        }
557        swaps(&reply->sequenceNumber);
558        swapl(&reply->length);
559        swapl(&reply->numIndexValues);
560    }
561
562    WriteToClient(client, rlength, reply);
563    free(reply);
564    return Success;
565}
566
567static int
568ProcRenderQueryDithers(ClientPtr client)
569{
570    return BadImplementation;
571}
572
573static int
574ProcRenderCreatePicture(ClientPtr client)
575{
576    PicturePtr pPicture;
577    DrawablePtr pDrawable;
578    PictFormatPtr pFormat;
579    int len, error, rc;
580
581    REQUEST(xRenderCreatePictureReq);
582
583    REQUEST_AT_LEAST_SIZE(xRenderCreatePictureReq);
584
585    LEGAL_NEW_RESOURCE(stuff->pid, client);
586    rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0,
587                           DixReadAccess | DixAddAccess);
588    if (rc != Success)
589        return rc;
590
591    rc = dixLookupResourceByType((void **) &pFormat, stuff->format,
592                                 PictFormatType, client, DixReadAccess);
593    if (rc != Success)
594        return rc;
595
596    if (pFormat->depth != pDrawable->depth)
597        return BadMatch;
598    len = client->req_len - bytes_to_int32(sizeof(xRenderCreatePictureReq));
599    if (Ones(stuff->mask) != len)
600        return BadLength;
601
602    pPicture = CreatePicture(stuff->pid,
603                             pDrawable,
604                             pFormat,
605                             stuff->mask, (XID *) (stuff + 1), client, &error);
606    if (!pPicture)
607        return error;
608    if (!AddResource(stuff->pid, PictureType, (void *) pPicture))
609        return BadAlloc;
610    return Success;
611}
612
613static int
614ProcRenderChangePicture(ClientPtr client)
615{
616    PicturePtr pPicture;
617
618    REQUEST(xRenderChangePictureReq);
619    int len;
620
621    REQUEST_AT_LEAST_SIZE(xRenderChangePictureReq);
622    VERIFY_PICTURE(pPicture, stuff->picture, client, DixSetAttrAccess);
623
624    len = client->req_len - bytes_to_int32(sizeof(xRenderChangePictureReq));
625    if (Ones(stuff->mask) != len)
626        return BadLength;
627
628    return ChangePicture(pPicture, stuff->mask, (XID *) (stuff + 1),
629                         (DevUnion *) 0, client);
630}
631
632static int
633ProcRenderSetPictureClipRectangles(ClientPtr client)
634{
635    REQUEST(xRenderSetPictureClipRectanglesReq);
636    PicturePtr pPicture;
637    int nr;
638
639    REQUEST_AT_LEAST_SIZE(xRenderSetPictureClipRectanglesReq);
640    VERIFY_PICTURE(pPicture, stuff->picture, client, DixSetAttrAccess);
641    if (!pPicture->pDrawable)
642        return RenderErrBase + BadPicture;
643
644    nr = (client->req_len << 2) - sizeof(xRenderSetPictureClipRectanglesReq);
645    if (nr & 4)
646        return BadLength;
647    nr >>= 3;
648    return SetPictureClipRects(pPicture,
649                               stuff->xOrigin, stuff->yOrigin,
650                               nr, (xRectangle *) &stuff[1]);
651}
652
653static int
654ProcRenderFreePicture(ClientPtr client)
655{
656    PicturePtr pPicture;
657
658    REQUEST(xRenderFreePictureReq);
659
660    REQUEST_SIZE_MATCH(xRenderFreePictureReq);
661
662    VERIFY_PICTURE(pPicture, stuff->picture, client, DixDestroyAccess);
663    FreeResource(stuff->picture, RT_NONE);
664    return Success;
665}
666
667static Bool
668PictOpValid(CARD8 op)
669{
670    if ( /*PictOpMinimum <= op && */ op <= PictOpMaximum)
671        return TRUE;
672    if (PictOpDisjointMinimum <= op && op <= PictOpDisjointMaximum)
673        return TRUE;
674    if (PictOpConjointMinimum <= op && op <= PictOpConjointMaximum)
675        return TRUE;
676    if (PictOpBlendMinimum <= op && op <= PictOpBlendMaximum)
677        return TRUE;
678    return FALSE;
679}
680
681static int
682ProcRenderComposite(ClientPtr client)
683{
684    PicturePtr pSrc, pMask, pDst;
685
686    REQUEST(xRenderCompositeReq);
687
688    REQUEST_SIZE_MATCH(xRenderCompositeReq);
689    if (!PictOpValid(stuff->op)) {
690        client->errorValue = stuff->op;
691        return BadValue;
692    }
693    VERIFY_PICTURE(pDst, stuff->dst, client, DixWriteAccess);
694    if (!pDst->pDrawable)
695        return BadDrawable;
696    VERIFY_PICTURE(pSrc, stuff->src, client, DixReadAccess);
697    VERIFY_ALPHA(pMask, stuff->mask, client, DixReadAccess);
698    if ((pSrc->pDrawable &&
699         pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) || (pMask &&
700                                                                   pMask->
701                                                                   pDrawable &&
702                                                                   pDst->
703                                                                   pDrawable->
704                                                                   pScreen !=
705                                                                   pMask->
706                                                                   pDrawable->
707                                                                   pScreen))
708        return BadMatch;
709    CompositePicture(stuff->op,
710                     pSrc,
711                     pMask,
712                     pDst,
713                     stuff->xSrc,
714                     stuff->ySrc,
715                     stuff->xMask,
716                     stuff->yMask,
717                     stuff->xDst, stuff->yDst, stuff->width, stuff->height);
718    return Success;
719}
720
721static int
722ProcRenderScale(ClientPtr client)
723{
724    return BadImplementation;
725}
726
727static int
728ProcRenderTrapezoids(ClientPtr client)
729{
730    int rc, ntraps;
731    PicturePtr pSrc, pDst;
732    PictFormatPtr pFormat;
733
734    REQUEST(xRenderTrapezoidsReq);
735
736    REQUEST_AT_LEAST_SIZE(xRenderTrapezoidsReq);
737    if (!PictOpValid(stuff->op)) {
738        client->errorValue = stuff->op;
739        return BadValue;
740    }
741    VERIFY_PICTURE(pSrc, stuff->src, client, DixReadAccess);
742    VERIFY_PICTURE(pDst, stuff->dst, client, DixWriteAccess);
743    if (!pDst->pDrawable)
744        return BadDrawable;
745    if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen)
746        return BadMatch;
747    if (stuff->maskFormat) {
748        rc = dixLookupResourceByType((void **) &pFormat, stuff->maskFormat,
749                                     PictFormatType, client, DixReadAccess);
750        if (rc != Success)
751            return rc;
752    }
753    else
754        pFormat = 0;
755    ntraps = (client->req_len << 2) - sizeof(xRenderTrapezoidsReq);
756    if (ntraps % sizeof(xTrapezoid))
757        return BadLength;
758    ntraps /= sizeof(xTrapezoid);
759    if (ntraps)
760        CompositeTrapezoids(stuff->op, pSrc, pDst, pFormat,
761                            stuff->xSrc, stuff->ySrc,
762                            ntraps, (xTrapezoid *) &stuff[1]);
763    return Success;
764}
765
766static int
767ProcRenderTriangles(ClientPtr client)
768{
769    int rc, ntris;
770    PicturePtr pSrc, pDst;
771    PictFormatPtr pFormat;
772
773    REQUEST(xRenderTrianglesReq);
774
775    REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq);
776    if (!PictOpValid(stuff->op)) {
777        client->errorValue = stuff->op;
778        return BadValue;
779    }
780    VERIFY_PICTURE(pSrc, stuff->src, client, DixReadAccess);
781    VERIFY_PICTURE(pDst, stuff->dst, client, DixWriteAccess);
782    if (!pDst->pDrawable)
783        return BadDrawable;
784    if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen)
785        return BadMatch;
786    if (stuff->maskFormat) {
787        rc = dixLookupResourceByType((void **) &pFormat, stuff->maskFormat,
788                                     PictFormatType, client, DixReadAccess);
789        if (rc != Success)
790            return rc;
791    }
792    else
793        pFormat = 0;
794    ntris = (client->req_len << 2) - sizeof(xRenderTrianglesReq);
795    if (ntris % sizeof(xTriangle))
796        return BadLength;
797    ntris /= sizeof(xTriangle);
798    if (ntris)
799        CompositeTriangles(stuff->op, pSrc, pDst, pFormat,
800                           stuff->xSrc, stuff->ySrc,
801                           ntris, (xTriangle *) &stuff[1]);
802    return Success;
803}
804
805static int
806ProcRenderTriStrip(ClientPtr client)
807{
808    int rc, npoints;
809    PicturePtr pSrc, pDst;
810    PictFormatPtr pFormat;
811
812    REQUEST(xRenderTrianglesReq);
813
814    REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq);
815    if (!PictOpValid(stuff->op)) {
816        client->errorValue = stuff->op;
817        return BadValue;
818    }
819    VERIFY_PICTURE(pSrc, stuff->src, client, DixReadAccess);
820    VERIFY_PICTURE(pDst, stuff->dst, client, DixWriteAccess);
821    if (!pDst->pDrawable)
822        return BadDrawable;
823    if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen)
824        return BadMatch;
825    if (stuff->maskFormat) {
826        rc = dixLookupResourceByType((void **) &pFormat, stuff->maskFormat,
827                                     PictFormatType, client, DixReadAccess);
828        if (rc != Success)
829            return rc;
830    }
831    else
832        pFormat = 0;
833    npoints = ((client->req_len << 2) - sizeof(xRenderTriStripReq));
834    if (npoints & 4)
835        return BadLength;
836    npoints >>= 3;
837    if (npoints >= 3)
838        CompositeTriStrip(stuff->op, pSrc, pDst, pFormat,
839                          stuff->xSrc, stuff->ySrc,
840                          npoints, (xPointFixed *) &stuff[1]);
841    return Success;
842}
843
844static int
845ProcRenderTriFan(ClientPtr client)
846{
847    int rc, npoints;
848    PicturePtr pSrc, pDst;
849    PictFormatPtr pFormat;
850
851    REQUEST(xRenderTrianglesReq);
852
853    REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq);
854    if (!PictOpValid(stuff->op)) {
855        client->errorValue = stuff->op;
856        return BadValue;
857    }
858    VERIFY_PICTURE(pSrc, stuff->src, client, DixReadAccess);
859    VERIFY_PICTURE(pDst, stuff->dst, client, DixWriteAccess);
860    if (!pDst->pDrawable)
861        return BadDrawable;
862    if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen)
863        return BadMatch;
864    if (stuff->maskFormat) {
865        rc = dixLookupResourceByType((void **) &pFormat, stuff->maskFormat,
866                                     PictFormatType, client, DixReadAccess);
867        if (rc != Success)
868            return rc;
869    }
870    else
871        pFormat = 0;
872    npoints = ((client->req_len << 2) - sizeof(xRenderTriStripReq));
873    if (npoints & 4)
874        return BadLength;
875    npoints >>= 3;
876    if (npoints >= 3)
877        CompositeTriFan(stuff->op, pSrc, pDst, pFormat,
878                        stuff->xSrc, stuff->ySrc,
879                        npoints, (xPointFixed *) &stuff[1]);
880    return Success;
881}
882
883static int
884ProcRenderColorTrapezoids(ClientPtr client)
885{
886    return BadImplementation;
887}
888
889static int
890ProcRenderColorTriangles(ClientPtr client)
891{
892    return BadImplementation;
893}
894
895static int
896ProcRenderTransform(ClientPtr client)
897{
898    return BadImplementation;
899}
900
901static int
902ProcRenderCreateGlyphSet(ClientPtr client)
903{
904    GlyphSetPtr glyphSet;
905    PictFormatPtr format;
906    int rc, f;
907
908    REQUEST(xRenderCreateGlyphSetReq);
909
910    REQUEST_SIZE_MATCH(xRenderCreateGlyphSetReq);
911
912    LEGAL_NEW_RESOURCE(stuff->gsid, client);
913    rc = dixLookupResourceByType((void **) &format, stuff->format,
914                                 PictFormatType, client, DixReadAccess);
915    if (rc != Success)
916        return rc;
917
918    switch (format->depth) {
919    case 1:
920        f = GlyphFormat1;
921        break;
922    case 4:
923        f = GlyphFormat4;
924        break;
925    case 8:
926        f = GlyphFormat8;
927        break;
928    case 16:
929        f = GlyphFormat16;
930        break;
931    case 32:
932        f = GlyphFormat32;
933        break;
934    default:
935        return BadMatch;
936    }
937    if (format->type != PictTypeDirect)
938        return BadMatch;
939    glyphSet = AllocateGlyphSet(f, format);
940    if (!glyphSet)
941        return BadAlloc;
942    /* security creation/labeling check */
943    rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->gsid, GlyphSetType,
944                  glyphSet, RT_NONE, NULL, DixCreateAccess);
945    if (rc != Success)
946        return rc;
947    if (!AddResource(stuff->gsid, GlyphSetType, (void *) glyphSet))
948        return BadAlloc;
949    return Success;
950}
951
952static int
953ProcRenderReferenceGlyphSet(ClientPtr client)
954{
955    GlyphSetPtr glyphSet;
956    int rc;
957
958    REQUEST(xRenderReferenceGlyphSetReq);
959
960    REQUEST_SIZE_MATCH(xRenderReferenceGlyphSetReq);
961
962    LEGAL_NEW_RESOURCE(stuff->gsid, client);
963
964    rc = dixLookupResourceByType((void **) &glyphSet, stuff->existing,
965                                 GlyphSetType, client, DixGetAttrAccess);
966    if (rc != Success) {
967        client->errorValue = stuff->existing;
968        return rc;
969    }
970    glyphSet->refcnt++;
971    if (!AddResource(stuff->gsid, GlyphSetType, (void *) glyphSet))
972        return BadAlloc;
973    return Success;
974}
975
976#define NLOCALDELTA	64
977#define NLOCALGLYPH	256
978
979static int
980ProcRenderFreeGlyphSet(ClientPtr client)
981{
982    GlyphSetPtr glyphSet;
983    int rc;
984
985    REQUEST(xRenderFreeGlyphSetReq);
986
987    REQUEST_SIZE_MATCH(xRenderFreeGlyphSetReq);
988    rc = dixLookupResourceByType((void **) &glyphSet, stuff->glyphset,
989                                 GlyphSetType, client, DixDestroyAccess);
990    if (rc != Success) {
991        client->errorValue = stuff->glyphset;
992        return rc;
993    }
994    FreeResource(stuff->glyphset, RT_NONE);
995    return Success;
996}
997
998typedef struct _GlyphNew {
999    Glyph id;
1000    GlyphPtr glyph;
1001    Bool found;
1002    unsigned char sha1[20];
1003} GlyphNewRec, *GlyphNewPtr;
1004
1005#define NeedsComponent(f) (PICT_FORMAT_A(f) != 0 && PICT_FORMAT_RGB(f) != 0)
1006
1007static int
1008ProcRenderAddGlyphs(ClientPtr client)
1009{
1010    GlyphSetPtr glyphSet;
1011
1012    REQUEST(xRenderAddGlyphsReq);
1013    GlyphNewRec glyphsLocal[NLOCALGLYPH];
1014    GlyphNewPtr glyphsBase, glyphs, glyph_new;
1015    int remain, nglyphs;
1016    CARD32 *gids;
1017    xGlyphInfo *gi;
1018    CARD8 *bits;
1019    unsigned int size;
1020    int err;
1021    int i, screen;
1022    PicturePtr pSrc = NULL, pDst = NULL;
1023    PixmapPtr pSrcPix = NULL, pDstPix = NULL;
1024    CARD32 component_alpha;
1025
1026    REQUEST_AT_LEAST_SIZE(xRenderAddGlyphsReq);
1027    err =
1028        dixLookupResourceByType((void **) &glyphSet, stuff->glyphset,
1029                                GlyphSetType, client, DixAddAccess);
1030    if (err != Success) {
1031        client->errorValue = stuff->glyphset;
1032        return err;
1033    }
1034
1035    err = BadAlloc;
1036    nglyphs = stuff->nglyphs;
1037    if (nglyphs > UINT32_MAX / sizeof(GlyphNewRec))
1038        return BadAlloc;
1039
1040    component_alpha = NeedsComponent(glyphSet->format->format);
1041
1042    if (nglyphs <= NLOCALGLYPH) {
1043        memset(glyphsLocal, 0, sizeof(glyphsLocal));
1044        glyphsBase = glyphsLocal;
1045    }
1046    else {
1047        glyphsBase = (GlyphNewPtr) calloc(nglyphs, sizeof(GlyphNewRec));
1048        if (!glyphsBase)
1049            return BadAlloc;
1050    }
1051
1052    remain = (client->req_len << 2) - sizeof(xRenderAddGlyphsReq);
1053
1054    glyphs = glyphsBase;
1055
1056    gids = (CARD32 *) (stuff + 1);
1057    gi = (xGlyphInfo *) (gids + nglyphs);
1058    bits = (CARD8 *) (gi + nglyphs);
1059    remain -= (sizeof(CARD32) + sizeof(xGlyphInfo)) * nglyphs;
1060
1061    /* protect against bad nglyphs */
1062    if (gi < ((xGlyphInfo *) stuff) ||
1063        gi > ((xGlyphInfo *) ((CARD32 *) stuff + client->req_len)) ||
1064        bits < ((CARD8 *) stuff) ||
1065        bits > ((CARD8 *) ((CARD32 *) stuff + client->req_len))) {
1066        err = BadLength;
1067        goto bail;
1068    }
1069
1070    for (i = 0; i < nglyphs; i++) {
1071        size_t padded_width;
1072
1073        glyph_new = &glyphs[i];
1074
1075        padded_width = PixmapBytePad(gi[i].width, glyphSet->format->depth);
1076
1077        if (gi[i].height &&
1078            padded_width > (UINT32_MAX - sizeof(GlyphRec)) / gi[i].height)
1079            break;
1080
1081        size = gi[i].height * padded_width;
1082        if (remain < size)
1083            break;
1084
1085        err = HashGlyph(&gi[i], bits, size, glyph_new->sha1);
1086        if (err)
1087            goto bail;
1088
1089        glyph_new->glyph = FindGlyphByHash(glyph_new->sha1, glyphSet->fdepth);
1090
1091        if (glyph_new->glyph && glyph_new->glyph != DeletedGlyph) {
1092            glyph_new->found = TRUE;
1093        }
1094        else {
1095            GlyphPtr glyph;
1096
1097            glyph_new->found = FALSE;
1098            glyph_new->glyph = glyph = AllocateGlyph(&gi[i], glyphSet->fdepth);
1099            if (!glyph) {
1100                err = BadAlloc;
1101                goto bail;
1102            }
1103
1104            for (screen = 0; screen < screenInfo.numScreens; screen++) {
1105                int width = gi[i].width;
1106                int height = gi[i].height;
1107                int depth = glyphSet->format->depth;
1108                ScreenPtr pScreen;
1109                int error;
1110
1111                /* Skip work if it's invisibly small anyway */
1112                if (!width || !height)
1113                    break;
1114
1115                pScreen = screenInfo.screens[screen];
1116                pSrcPix = GetScratchPixmapHeader(pScreen,
1117                                                 width, height,
1118                                                 depth, depth, -1, bits);
1119                if (!pSrcPix) {
1120                    err = BadAlloc;
1121                    goto bail;
1122                }
1123
1124                pSrc = CreatePicture(0, &pSrcPix->drawable,
1125                                     glyphSet->format, 0, NULL,
1126                                     serverClient, &error);
1127                if (!pSrc) {
1128                    err = BadAlloc;
1129                    goto bail;
1130                }
1131
1132                pDstPix = (pScreen->CreatePixmap) (pScreen,
1133                                                   width, height, depth,
1134                                                   CREATE_PIXMAP_USAGE_GLYPH_PICTURE);
1135
1136                if (!pDstPix) {
1137                    err = BadAlloc;
1138                    goto bail;
1139                }
1140
1141                pDst = CreatePicture(0, &pDstPix->drawable,
1142                                  glyphSet->format,
1143                                  CPComponentAlpha, &component_alpha,
1144                                  serverClient, &error);
1145                SetGlyphPicture(glyph, pScreen, pDst);
1146
1147                /* The picture takes a reference to the pixmap, so we
1148                   drop ours. */
1149                (pScreen->DestroyPixmap) (pDstPix);
1150                pDstPix = NULL;
1151
1152                if (!pDst) {
1153                    err = BadAlloc;
1154                    goto bail;
1155                }
1156
1157                CompositePicture(PictOpSrc,
1158                                 pSrc,
1159                                 None, pDst, 0, 0, 0, 0, 0, 0, width, height);
1160
1161                FreePicture((void *) pSrc, 0);
1162                pSrc = NULL;
1163                FreeScratchPixmapHeader(pSrcPix);
1164                pSrcPix = NULL;
1165            }
1166
1167            memcpy(glyph_new->glyph->sha1, glyph_new->sha1, 20);
1168        }
1169
1170        glyph_new->id = gids[i];
1171
1172        if (size & 3)
1173            size += 4 - (size & 3);
1174        bits += size;
1175        remain -= size;
1176    }
1177    if (remain || i < nglyphs) {
1178        err = BadLength;
1179        goto bail;
1180    }
1181    if (!ResizeGlyphSet(glyphSet, nglyphs)) {
1182        err = BadAlloc;
1183        goto bail;
1184    }
1185    for (i = 0; i < nglyphs; i++)
1186        AddGlyph(glyphSet, glyphs[i].glyph, glyphs[i].id);
1187
1188    if (glyphsBase != glyphsLocal)
1189        free(glyphsBase);
1190    return Success;
1191 bail:
1192    if (pSrc)
1193        FreePicture((void *) pSrc, 0);
1194    if (pSrcPix)
1195        FreeScratchPixmapHeader(pSrcPix);
1196    for (i = 0; i < nglyphs; i++)
1197        if (glyphs[i].glyph && !glyphs[i].found)
1198            free(glyphs[i].glyph);
1199    if (glyphsBase != glyphsLocal)
1200        free(glyphsBase);
1201    return err;
1202}
1203
1204static int
1205ProcRenderAddGlyphsFromPicture(ClientPtr client)
1206{
1207    return BadImplementation;
1208}
1209
1210static int
1211ProcRenderFreeGlyphs(ClientPtr client)
1212{
1213    REQUEST(xRenderFreeGlyphsReq);
1214    GlyphSetPtr glyphSet;
1215    int rc, nglyph;
1216    CARD32 *gids;
1217    CARD32 glyph;
1218
1219    REQUEST_AT_LEAST_SIZE(xRenderFreeGlyphsReq);
1220    rc = dixLookupResourceByType((void **) &glyphSet, stuff->glyphset,
1221                                 GlyphSetType, client, DixRemoveAccess);
1222    if (rc != Success) {
1223        client->errorValue = stuff->glyphset;
1224        return rc;
1225    }
1226    nglyph =
1227        bytes_to_int32((client->req_len << 2) - sizeof(xRenderFreeGlyphsReq));
1228    gids = (CARD32 *) (stuff + 1);
1229    while (nglyph-- > 0) {
1230        glyph = *gids++;
1231        if (!DeleteGlyph(glyphSet, glyph)) {
1232            client->errorValue = glyph;
1233            return RenderErrBase + BadGlyph;
1234        }
1235    }
1236    return Success;
1237}
1238
1239static int
1240ProcRenderCompositeGlyphs(ClientPtr client)
1241{
1242    GlyphSetPtr glyphSet;
1243    GlyphSet gs;
1244    PicturePtr pSrc, pDst;
1245    PictFormatPtr pFormat;
1246    GlyphListRec listsLocal[NLOCALDELTA];
1247    GlyphListPtr lists, listsBase;
1248    GlyphPtr glyphsLocal[NLOCALGLYPH];
1249    Glyph glyph;
1250    GlyphPtr *glyphs, *glyphsBase;
1251    xGlyphElt *elt;
1252    CARD8 *buffer, *end;
1253    int nglyph;
1254    int nlist;
1255    int space;
1256    int size;
1257    int rc, n;
1258
1259    REQUEST(xRenderCompositeGlyphsReq);
1260
1261    REQUEST_AT_LEAST_SIZE(xRenderCompositeGlyphsReq);
1262
1263    switch (stuff->renderReqType) {
1264    default:
1265        size = 1;
1266        break;
1267    case X_RenderCompositeGlyphs16:
1268        size = 2;
1269        break;
1270    case X_RenderCompositeGlyphs32:
1271        size = 4;
1272        break;
1273    }
1274
1275    if (!PictOpValid(stuff->op)) {
1276        client->errorValue = stuff->op;
1277        return BadValue;
1278    }
1279    VERIFY_PICTURE(pSrc, stuff->src, client, DixReadAccess);
1280    VERIFY_PICTURE(pDst, stuff->dst, client, DixWriteAccess);
1281    if (!pDst->pDrawable)
1282        return BadDrawable;
1283    if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen)
1284        return BadMatch;
1285    if (stuff->maskFormat) {
1286        rc = dixLookupResourceByType((void **) &pFormat, stuff->maskFormat,
1287                                     PictFormatType, client, DixReadAccess);
1288        if (rc != Success)
1289            return rc;
1290    }
1291    else
1292        pFormat = 0;
1293
1294    rc = dixLookupResourceByType((void **) &glyphSet, stuff->glyphset,
1295                                 GlyphSetType, client, DixUseAccess);
1296    if (rc != Success)
1297        return rc;
1298
1299    buffer = (CARD8 *) (stuff + 1);
1300    end = (CARD8 *) stuff + (client->req_len << 2);
1301    nglyph = 0;
1302    nlist = 0;
1303    while (buffer + sizeof(xGlyphElt) < end) {
1304        elt = (xGlyphElt *) buffer;
1305        buffer += sizeof(xGlyphElt);
1306
1307        if (elt->len == 0xff) {
1308            buffer += 4;
1309        }
1310        else {
1311            nlist++;
1312            nglyph += elt->len;
1313            space = size * elt->len;
1314            if (space & 3)
1315                space += 4 - (space & 3);
1316            buffer += space;
1317        }
1318    }
1319    if (nglyph <= NLOCALGLYPH)
1320        glyphsBase = glyphsLocal;
1321    else {
1322        glyphsBase = xallocarray(nglyph, sizeof(GlyphPtr));
1323        if (!glyphsBase)
1324            return BadAlloc;
1325    }
1326    if (nlist <= NLOCALDELTA)
1327        listsBase = listsLocal;
1328    else {
1329        listsBase = xallocarray(nlist, sizeof(GlyphListRec));
1330        if (!listsBase) {
1331            rc = BadAlloc;
1332            goto bail;
1333        }
1334    }
1335    buffer = (CARD8 *) (stuff + 1);
1336    glyphs = glyphsBase;
1337    lists = listsBase;
1338    while (buffer + sizeof(xGlyphElt) < end) {
1339        elt = (xGlyphElt *) buffer;
1340        buffer += sizeof(xGlyphElt);
1341
1342        if (elt->len == 0xff) {
1343            if (buffer + sizeof(GlyphSet) < end) {
1344                memcpy(&gs, buffer, sizeof(GlyphSet));
1345                rc = dixLookupResourceByType((void **) &glyphSet, gs,
1346                                             GlyphSetType, client,
1347                                             DixUseAccess);
1348                if (rc != Success)
1349                    goto bail;
1350            }
1351            buffer += 4;
1352        }
1353        else {
1354            lists->xOff = elt->deltax;
1355            lists->yOff = elt->deltay;
1356            lists->format = glyphSet->format;
1357            lists->len = 0;
1358            n = elt->len;
1359            while (n--) {
1360                if (buffer + size <= end) {
1361                    switch (size) {
1362                    case 1:
1363                        glyph = *((CARD8 *) buffer);
1364                        break;
1365                    case 2:
1366                        glyph = *((CARD16 *) buffer);
1367                        break;
1368                    case 4:
1369                    default:
1370                        glyph = *((CARD32 *) buffer);
1371                        break;
1372                    }
1373                    if ((*glyphs = FindGlyph(glyphSet, glyph))) {
1374                        lists->len++;
1375                        glyphs++;
1376                    }
1377                }
1378                buffer += size;
1379            }
1380            space = size * elt->len;
1381            if (space & 3)
1382                buffer += 4 - (space & 3);
1383            lists++;
1384        }
1385    }
1386    if (buffer > end) {
1387        rc = BadLength;
1388        goto bail;
1389    }
1390
1391    CompositeGlyphs(stuff->op,
1392                    pSrc,
1393                    pDst,
1394                    pFormat,
1395                    stuff->xSrc, stuff->ySrc, nlist, listsBase, glyphsBase);
1396    rc = Success;
1397
1398 bail:
1399    if (glyphsBase != glyphsLocal)
1400        free(glyphsBase);
1401    if (listsBase != listsLocal)
1402        free(listsBase);
1403    return rc;
1404}
1405
1406static int
1407ProcRenderFillRectangles(ClientPtr client)
1408{
1409    PicturePtr pDst;
1410    int things;
1411
1412    REQUEST(xRenderFillRectanglesReq);
1413
1414    REQUEST_AT_LEAST_SIZE(xRenderFillRectanglesReq);
1415    if (!PictOpValid(stuff->op)) {
1416        client->errorValue = stuff->op;
1417        return BadValue;
1418    }
1419    VERIFY_PICTURE(pDst, stuff->dst, client, DixWriteAccess);
1420    if (!pDst->pDrawable)
1421        return BadDrawable;
1422
1423    things = (client->req_len << 2) - sizeof(xRenderFillRectanglesReq);
1424    if (things & 4)
1425        return BadLength;
1426    things >>= 3;
1427
1428    CompositeRects(stuff->op,
1429                   pDst, &stuff->color, things, (xRectangle *) &stuff[1]);
1430
1431    return Success;
1432}
1433
1434static void
1435RenderSetBit(unsigned char *line, int x, int bit)
1436{
1437    unsigned char mask;
1438
1439    if (screenInfo.bitmapBitOrder == LSBFirst)
1440        mask = (1 << (x & 7));
1441    else
1442        mask = (0x80 >> (x & 7));
1443    /* XXX assumes byte order is host byte order */
1444    line += (x >> 3);
1445    if (bit)
1446        *line |= mask;
1447    else
1448        *line &= ~mask;
1449}
1450
1451#define DITHER_DIM 2
1452
1453static CARD32 orderedDither[DITHER_DIM][DITHER_DIM] = {
1454    {1, 3,},
1455    {4, 2,},
1456};
1457
1458#define DITHER_SIZE  ((sizeof orderedDither / sizeof orderedDither[0][0]) + 1)
1459
1460static int
1461ProcRenderCreateCursor(ClientPtr client)
1462{
1463    REQUEST(xRenderCreateCursorReq);
1464    PicturePtr pSrc;
1465    ScreenPtr pScreen;
1466    unsigned short width, height;
1467    CARD32 *argbbits, *argb;
1468    unsigned char *srcbits, *srcline;
1469    unsigned char *mskbits, *mskline;
1470    int stride;
1471    int x, y;
1472    int nbytes_mono;
1473    CursorMetricRec cm;
1474    CursorPtr pCursor;
1475    CARD32 twocolor[3];
1476    int rc, ncolor;
1477
1478    REQUEST_SIZE_MATCH(xRenderCreateCursorReq);
1479    LEGAL_NEW_RESOURCE(stuff->cid, client);
1480
1481    VERIFY_PICTURE(pSrc, stuff->src, client, DixReadAccess);
1482    if (!pSrc->pDrawable)
1483        return BadDrawable;
1484    pScreen = pSrc->pDrawable->pScreen;
1485    width = pSrc->pDrawable->width;
1486    height = pSrc->pDrawable->height;
1487    if (height && width > UINT32_MAX / (height * sizeof(CARD32)))
1488        return BadAlloc;
1489    if (stuff->x > width || stuff->y > height)
1490        return BadMatch;
1491    argbbits = malloc(width * height * sizeof(CARD32));
1492    if (!argbbits)
1493        return BadAlloc;
1494
1495    stride = BitmapBytePad(width);
1496    nbytes_mono = stride * height;
1497    srcbits = calloc(1, nbytes_mono);
1498    if (!srcbits) {
1499        free(argbbits);
1500        return BadAlloc;
1501    }
1502    mskbits = calloc(1, nbytes_mono);
1503    if (!mskbits) {
1504        free(argbbits);
1505        free(srcbits);
1506        return BadAlloc;
1507    }
1508
1509    if (pSrc->format == PICT_a8r8g8b8) {
1510        (*pScreen->GetImage) (pSrc->pDrawable,
1511                              0, 0, width, height, ZPixmap,
1512                              0xffffffff, (void *) argbbits);
1513    }
1514    else {
1515        PixmapPtr pPixmap;
1516        PicturePtr pPicture;
1517        PictFormatPtr pFormat;
1518        int error;
1519
1520        pFormat = PictureMatchFormat(pScreen, 32, PICT_a8r8g8b8);
1521        if (!pFormat) {
1522            free(argbbits);
1523            free(srcbits);
1524            free(mskbits);
1525            return BadImplementation;
1526        }
1527        pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, 32,
1528                                            CREATE_PIXMAP_USAGE_SCRATCH);
1529        if (!pPixmap) {
1530            free(argbbits);
1531            free(srcbits);
1532            free(mskbits);
1533            return BadAlloc;
1534        }
1535        pPicture = CreatePicture(0, &pPixmap->drawable, pFormat, 0, 0,
1536                                 client, &error);
1537        if (!pPicture) {
1538            free(argbbits);
1539            free(srcbits);
1540            free(mskbits);
1541            return error;
1542        }
1543        (*pScreen->DestroyPixmap) (pPixmap);
1544        CompositePicture(PictOpSrc,
1545                         pSrc, 0, pPicture, 0, 0, 0, 0, 0, 0, width, height);
1546        (*pScreen->GetImage) (pPicture->pDrawable,
1547                              0, 0, width, height, ZPixmap,
1548                              0xffffffff, (void *) argbbits);
1549        FreePicture(pPicture, 0);
1550    }
1551    /*
1552     * Check whether the cursor can be directly supported by
1553     * the core cursor code
1554     */
1555    ncolor = 0;
1556    argb = argbbits;
1557    for (y = 0; ncolor <= 2 && y < height; y++) {
1558        for (x = 0; ncolor <= 2 && x < width; x++) {
1559            CARD32 p = *argb++;
1560            CARD32 a = (p >> 24);
1561
1562            if (a == 0)         /* transparent */
1563                continue;
1564            if (a == 0xff) {    /* opaque */
1565                int n;
1566
1567                for (n = 0; n < ncolor; n++)
1568                    if (p == twocolor[n])
1569                        break;
1570                if (n == ncolor)
1571                    twocolor[ncolor++] = p;
1572            }
1573            else
1574                ncolor = 3;
1575        }
1576    }
1577
1578    /*
1579     * Convert argb image to two plane cursor
1580     */
1581    srcline = srcbits;
1582    mskline = mskbits;
1583    argb = argbbits;
1584    for (y = 0; y < height; y++) {
1585        for (x = 0; x < width; x++) {
1586            CARD32 p = *argb++;
1587
1588            if (ncolor <= 2) {
1589                CARD32 a = ((p >> 24));
1590
1591                RenderSetBit(mskline, x, a != 0);
1592                RenderSetBit(srcline, x, a != 0 && p == twocolor[0]);
1593            }
1594            else {
1595                CARD32 a = ((p >> 24) * DITHER_SIZE + 127) / 255;
1596                CARD32 i = ((CvtR8G8B8toY15(p) >> 7) * DITHER_SIZE + 127) / 255;
1597                CARD32 d =
1598                    orderedDither[y & (DITHER_DIM - 1)][x & (DITHER_DIM - 1)];
1599                /* Set mask from dithered alpha value */
1600                RenderSetBit(mskline, x, a > d);
1601                /* Set src from dithered intensity value */
1602                RenderSetBit(srcline, x, a > d && i <= d);
1603            }
1604        }
1605        srcline += stride;
1606        mskline += stride;
1607    }
1608    /*
1609     * Dither to white and black if the cursor has more than two colors
1610     */
1611    if (ncolor > 2) {
1612        twocolor[0] = 0xff000000;
1613        twocolor[1] = 0xffffffff;
1614    }
1615    else {
1616        free(argbbits);
1617        argbbits = 0;
1618    }
1619
1620#define GetByte(p,s)	(((p) >> (s)) & 0xff)
1621#define GetColor(p,s)	(GetByte(p,s) | (GetByte(p,s) << 8))
1622
1623    cm.width = width;
1624    cm.height = height;
1625    cm.xhot = stuff->x;
1626    cm.yhot = stuff->y;
1627    rc = AllocARGBCursor(srcbits, mskbits, argbbits, &cm,
1628                         GetColor(twocolor[0], 16),
1629                         GetColor(twocolor[0], 8),
1630                         GetColor(twocolor[0], 0),
1631                         GetColor(twocolor[1], 16),
1632                         GetColor(twocolor[1], 8),
1633                         GetColor(twocolor[1], 0),
1634                         &pCursor, client, stuff->cid);
1635    if (rc != Success)
1636        goto bail;
1637    if (!AddResource(stuff->cid, RT_CURSOR, (void *) pCursor)) {
1638        rc = BadAlloc;
1639        goto bail;
1640    }
1641
1642    return Success;
1643 bail:
1644    free(srcbits);
1645    free(mskbits);
1646    return rc;
1647}
1648
1649static int
1650ProcRenderSetPictureTransform(ClientPtr client)
1651{
1652    REQUEST(xRenderSetPictureTransformReq);
1653    PicturePtr pPicture;
1654
1655    REQUEST_SIZE_MATCH(xRenderSetPictureTransformReq);
1656    VERIFY_PICTURE(pPicture, stuff->picture, client, DixSetAttrAccess);
1657    return SetPictureTransform(pPicture, (PictTransform *) &stuff->transform);
1658}
1659
1660static int
1661ProcRenderQueryFilters(ClientPtr client)
1662{
1663    REQUEST(xRenderQueryFiltersReq);
1664    DrawablePtr pDrawable;
1665    xRenderQueryFiltersReply *reply;
1666    int nbytesName;
1667    int nnames;
1668    ScreenPtr pScreen;
1669    PictureScreenPtr ps;
1670    int i, j, len, total_bytes, rc;
1671    INT16 *aliases;
1672    char *names;
1673
1674    REQUEST_SIZE_MATCH(xRenderQueryFiltersReq);
1675    rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0,
1676                           DixGetAttrAccess);
1677    if (rc != Success)
1678        return rc;
1679
1680    pScreen = pDrawable->pScreen;
1681    nbytesName = 0;
1682    nnames = 0;
1683    ps = GetPictureScreenIfSet(pScreen);
1684    if (ps) {
1685        for (i = 0; i < ps->nfilters; i++)
1686            nbytesName += 1 + strlen(ps->filters[i].name);
1687        for (i = 0; i < ps->nfilterAliases; i++)
1688            nbytesName += 1 + strlen(ps->filterAliases[i].alias);
1689        nnames = ps->nfilters + ps->nfilterAliases;
1690    }
1691    len = ((nnames + 1) >> 1) + bytes_to_int32(nbytesName);
1692    total_bytes = sizeof(xRenderQueryFiltersReply) + (len << 2);
1693    reply = (xRenderQueryFiltersReply *) calloc(1, total_bytes);
1694    if (!reply)
1695        return BadAlloc;
1696    aliases = (INT16 *) (reply + 1);
1697    names = (char *) (aliases + ((nnames + 1) & ~1));
1698
1699    reply->type = X_Reply;
1700    reply->sequenceNumber = client->sequence;
1701    reply->length = len;
1702    reply->numAliases = nnames;
1703    reply->numFilters = nnames;
1704    if (ps) {
1705
1706        /* fill in alias values */
1707        for (i = 0; i < ps->nfilters; i++)
1708            aliases[i] = FilterAliasNone;
1709        for (i = 0; i < ps->nfilterAliases; i++) {
1710            for (j = 0; j < ps->nfilters; j++)
1711                if (ps->filterAliases[i].filter_id == ps->filters[j].id)
1712                    break;
1713            if (j == ps->nfilters) {
1714                for (j = 0; j < ps->nfilterAliases; j++)
1715                    if (ps->filterAliases[i].filter_id ==
1716                        ps->filterAliases[j].alias_id) {
1717                        break;
1718                    }
1719                if (j == ps->nfilterAliases)
1720                    j = FilterAliasNone;
1721                else
1722                    j = j + ps->nfilters;
1723            }
1724            aliases[i + ps->nfilters] = j;
1725        }
1726
1727        /* fill in filter names */
1728        for (i = 0; i < ps->nfilters; i++) {
1729            j = strlen(ps->filters[i].name);
1730            *names++ = j;
1731            memcpy(names, ps->filters[i].name, j);
1732            names += j;
1733        }
1734
1735        /* fill in filter alias names */
1736        for (i = 0; i < ps->nfilterAliases; i++) {
1737            j = strlen(ps->filterAliases[i].alias);
1738            *names++ = j;
1739            memcpy(names, ps->filterAliases[i].alias, j);
1740            names += j;
1741        }
1742    }
1743
1744    if (client->swapped) {
1745        for (i = 0; i < reply->numAliases; i++) {
1746            swaps(&aliases[i]);
1747        }
1748        swaps(&reply->sequenceNumber);
1749        swapl(&reply->length);
1750        swapl(&reply->numAliases);
1751        swapl(&reply->numFilters);
1752    }
1753    WriteToClient(client, total_bytes, reply);
1754    free(reply);
1755
1756    return Success;
1757}
1758
1759static int
1760ProcRenderSetPictureFilter(ClientPtr client)
1761{
1762    REQUEST(xRenderSetPictureFilterReq);
1763    PicturePtr pPicture;
1764    int result;
1765    xFixed *params;
1766    int nparams;
1767    char *name;
1768
1769    REQUEST_AT_LEAST_SIZE(xRenderSetPictureFilterReq);
1770    VERIFY_PICTURE(pPicture, stuff->picture, client, DixSetAttrAccess);
1771    name = (char *) (stuff + 1);
1772    params = (xFixed *) (name + pad_to_int32(stuff->nbytes));
1773    nparams = ((xFixed *) stuff + client->req_len) - params;
1774    if (nparams < 0)
1775	return BadLength;
1776
1777    result = SetPictureFilter(pPicture, name, stuff->nbytes, params, nparams);
1778    return result;
1779}
1780
1781static int
1782ProcRenderCreateAnimCursor(ClientPtr client)
1783{
1784    REQUEST(xRenderCreateAnimCursorReq);
1785    CursorPtr *cursors;
1786    CARD32 *deltas;
1787    CursorPtr pCursor;
1788    int ncursor;
1789    xAnimCursorElt *elt;
1790    int i;
1791    int ret;
1792
1793    REQUEST_AT_LEAST_SIZE(xRenderCreateAnimCursorReq);
1794    LEGAL_NEW_RESOURCE(stuff->cid, client);
1795    if (client->req_len & 1)
1796        return BadLength;
1797    ncursor =
1798        (client->req_len -
1799         (bytes_to_int32(sizeof(xRenderCreateAnimCursorReq)))) >> 1;
1800    cursors = xallocarray(ncursor, sizeof(CursorPtr) + sizeof(CARD32));
1801    if (!cursors)
1802        return BadAlloc;
1803    deltas = (CARD32 *) (cursors + ncursor);
1804    elt = (xAnimCursorElt *) (stuff + 1);
1805    for (i = 0; i < ncursor; i++) {
1806        ret = dixLookupResourceByType((void **) (cursors + i), elt->cursor,
1807                                      RT_CURSOR, client, DixReadAccess);
1808        if (ret != Success) {
1809            free(cursors);
1810            return ret;
1811        }
1812        deltas[i] = elt->delay;
1813        elt++;
1814    }
1815    ret = AnimCursorCreate(cursors, deltas, ncursor, &pCursor, client,
1816                           stuff->cid);
1817    free(cursors);
1818    if (ret != Success)
1819        return ret;
1820
1821    if (AddResource(stuff->cid, RT_CURSOR, (void *) pCursor))
1822        return Success;
1823    return BadAlloc;
1824}
1825
1826static int
1827ProcRenderAddTraps(ClientPtr client)
1828{
1829    int ntraps;
1830    PicturePtr pPicture;
1831
1832    REQUEST(xRenderAddTrapsReq);
1833
1834    REQUEST_AT_LEAST_SIZE(xRenderAddTrapsReq);
1835    VERIFY_PICTURE(pPicture, stuff->picture, client, DixWriteAccess);
1836    if (!pPicture->pDrawable)
1837        return BadDrawable;
1838    ntraps = (client->req_len << 2) - sizeof(xRenderAddTrapsReq);
1839    if (ntraps % sizeof(xTrap))
1840        return BadLength;
1841    ntraps /= sizeof(xTrap);
1842    if (ntraps)
1843        AddTraps(pPicture,
1844                 stuff->xOff, stuff->yOff, ntraps, (xTrap *) &stuff[1]);
1845    return Success;
1846}
1847
1848static int
1849ProcRenderCreateSolidFill(ClientPtr client)
1850{
1851    PicturePtr pPicture;
1852    int error = 0;
1853
1854    REQUEST(xRenderCreateSolidFillReq);
1855
1856    REQUEST_AT_LEAST_SIZE(xRenderCreateSolidFillReq);
1857
1858    LEGAL_NEW_RESOURCE(stuff->pid, client);
1859
1860    pPicture = CreateSolidPicture(stuff->pid, &stuff->color, &error);
1861    if (!pPicture)
1862        return error;
1863    /* security creation/labeling check */
1864    error = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, PictureType,
1865                     pPicture, RT_NONE, NULL, DixCreateAccess);
1866    if (error != Success)
1867        return error;
1868    if (!AddResource(stuff->pid, PictureType, (void *) pPicture))
1869        return BadAlloc;
1870    return Success;
1871}
1872
1873static int
1874ProcRenderCreateLinearGradient(ClientPtr client)
1875{
1876    PicturePtr pPicture;
1877    int len;
1878    int error = 0;
1879    xFixed *stops;
1880    xRenderColor *colors;
1881
1882    REQUEST(xRenderCreateLinearGradientReq);
1883
1884    REQUEST_AT_LEAST_SIZE(xRenderCreateLinearGradientReq);
1885
1886    LEGAL_NEW_RESOURCE(stuff->pid, client);
1887
1888    len = (client->req_len << 2) - sizeof(xRenderCreateLinearGradientReq);
1889    if (stuff->nStops > UINT32_MAX / (sizeof(xFixed) + sizeof(xRenderColor)))
1890        return BadLength;
1891    if (len != stuff->nStops * (sizeof(xFixed) + sizeof(xRenderColor)))
1892        return BadLength;
1893
1894    stops = (xFixed *) (stuff + 1);
1895    colors = (xRenderColor *) (stops + stuff->nStops);
1896
1897    pPicture = CreateLinearGradientPicture(stuff->pid, &stuff->p1, &stuff->p2,
1898                                           stuff->nStops, stops, colors,
1899                                           &error);
1900    if (!pPicture)
1901        return error;
1902    /* security creation/labeling check */
1903    error = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, PictureType,
1904                     pPicture, RT_NONE, NULL, DixCreateAccess);
1905    if (error != Success)
1906        return error;
1907    if (!AddResource(stuff->pid, PictureType, (void *) pPicture))
1908        return BadAlloc;
1909    return Success;
1910}
1911
1912static int
1913ProcRenderCreateRadialGradient(ClientPtr client)
1914{
1915    PicturePtr pPicture;
1916    int len;
1917    int error = 0;
1918    xFixed *stops;
1919    xRenderColor *colors;
1920
1921    REQUEST(xRenderCreateRadialGradientReq);
1922
1923    REQUEST_AT_LEAST_SIZE(xRenderCreateRadialGradientReq);
1924
1925    LEGAL_NEW_RESOURCE(stuff->pid, client);
1926
1927    len = (client->req_len << 2) - sizeof(xRenderCreateRadialGradientReq);
1928    if (len != stuff->nStops * (sizeof(xFixed) + sizeof(xRenderColor)))
1929        return BadLength;
1930
1931    stops = (xFixed *) (stuff + 1);
1932    colors = (xRenderColor *) (stops + stuff->nStops);
1933
1934    pPicture =
1935        CreateRadialGradientPicture(stuff->pid, &stuff->inner, &stuff->outer,
1936                                    stuff->inner_radius, stuff->outer_radius,
1937                                    stuff->nStops, stops, colors, &error);
1938    if (!pPicture)
1939        return error;
1940    /* security creation/labeling check */
1941    error = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, PictureType,
1942                     pPicture, RT_NONE, NULL, DixCreateAccess);
1943    if (error != Success)
1944        return error;
1945    if (!AddResource(stuff->pid, PictureType, (void *) pPicture))
1946        return BadAlloc;
1947    return Success;
1948}
1949
1950static int
1951ProcRenderCreateConicalGradient(ClientPtr client)
1952{
1953    PicturePtr pPicture;
1954    int len;
1955    int error = 0;
1956    xFixed *stops;
1957    xRenderColor *colors;
1958
1959    REQUEST(xRenderCreateConicalGradientReq);
1960
1961    REQUEST_AT_LEAST_SIZE(xRenderCreateConicalGradientReq);
1962
1963    LEGAL_NEW_RESOURCE(stuff->pid, client);
1964
1965    len = (client->req_len << 2) - sizeof(xRenderCreateConicalGradientReq);
1966    if (len != stuff->nStops * (sizeof(xFixed) + sizeof(xRenderColor)))
1967        return BadLength;
1968
1969    stops = (xFixed *) (stuff + 1);
1970    colors = (xRenderColor *) (stops + stuff->nStops);
1971
1972    pPicture =
1973        CreateConicalGradientPicture(stuff->pid, &stuff->center, stuff->angle,
1974                                     stuff->nStops, stops, colors, &error);
1975    if (!pPicture)
1976        return error;
1977    /* security creation/labeling check */
1978    error = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, PictureType,
1979                     pPicture, RT_NONE, NULL, DixCreateAccess);
1980    if (error != Success)
1981        return error;
1982    if (!AddResource(stuff->pid, PictureType, (void *) pPicture))
1983        return BadAlloc;
1984    return Success;
1985}
1986
1987static int
1988ProcRenderDispatch(ClientPtr client)
1989{
1990    REQUEST(xReq);
1991
1992    if (stuff->data < RenderNumberRequests)
1993        return (*ProcRenderVector[stuff->data]) (client);
1994    else
1995        return BadRequest;
1996}
1997
1998static int
1999SProcRenderQueryVersion(ClientPtr client)
2000{
2001    REQUEST(xRenderQueryVersionReq);
2002    REQUEST_SIZE_MATCH(xRenderQueryVersionReq);
2003    swaps(&stuff->length);
2004    swapl(&stuff->majorVersion);
2005    swapl(&stuff->minorVersion);
2006    return (*ProcRenderVector[stuff->renderReqType]) (client);
2007}
2008
2009static int
2010SProcRenderQueryPictFormats(ClientPtr client)
2011{
2012    REQUEST(xRenderQueryPictFormatsReq);
2013    REQUEST_SIZE_MATCH(xRenderQueryPictFormatsReq);
2014    swaps(&stuff->length);
2015    return (*ProcRenderVector[stuff->renderReqType]) (client);
2016}
2017
2018static int
2019SProcRenderQueryPictIndexValues(ClientPtr client)
2020{
2021    REQUEST(xRenderQueryPictIndexValuesReq);
2022    REQUEST_AT_LEAST_SIZE(xRenderQueryPictIndexValuesReq);
2023    swaps(&stuff->length);
2024    swapl(&stuff->format);
2025    return (*ProcRenderVector[stuff->renderReqType]) (client);
2026}
2027
2028static int
2029SProcRenderQueryDithers(ClientPtr client)
2030{
2031    return BadImplementation;
2032}
2033
2034static int
2035SProcRenderCreatePicture(ClientPtr client)
2036{
2037    REQUEST(xRenderCreatePictureReq);
2038    REQUEST_AT_LEAST_SIZE(xRenderCreatePictureReq);
2039    swaps(&stuff->length);
2040    swapl(&stuff->pid);
2041    swapl(&stuff->drawable);
2042    swapl(&stuff->format);
2043    swapl(&stuff->mask);
2044    SwapRestL(stuff);
2045    return (*ProcRenderVector[stuff->renderReqType]) (client);
2046}
2047
2048static int
2049SProcRenderChangePicture(ClientPtr client)
2050{
2051    REQUEST(xRenderChangePictureReq);
2052    REQUEST_AT_LEAST_SIZE(xRenderChangePictureReq);
2053    swaps(&stuff->length);
2054    swapl(&stuff->picture);
2055    swapl(&stuff->mask);
2056    SwapRestL(stuff);
2057    return (*ProcRenderVector[stuff->renderReqType]) (client);
2058}
2059
2060static int
2061SProcRenderSetPictureClipRectangles(ClientPtr client)
2062{
2063    REQUEST(xRenderSetPictureClipRectanglesReq);
2064    REQUEST_AT_LEAST_SIZE(xRenderSetPictureClipRectanglesReq);
2065    swaps(&stuff->length);
2066    swapl(&stuff->picture);
2067    swaps(&stuff->xOrigin);
2068    swaps(&stuff->yOrigin);
2069    SwapRestS(stuff);
2070    return (*ProcRenderVector[stuff->renderReqType]) (client);
2071}
2072
2073static int
2074SProcRenderFreePicture(ClientPtr client)
2075{
2076    REQUEST(xRenderFreePictureReq);
2077    REQUEST_SIZE_MATCH(xRenderFreePictureReq);
2078    swaps(&stuff->length);
2079    swapl(&stuff->picture);
2080    return (*ProcRenderVector[stuff->renderReqType]) (client);
2081}
2082
2083static int
2084SProcRenderComposite(ClientPtr client)
2085{
2086    REQUEST(xRenderCompositeReq);
2087    REQUEST_SIZE_MATCH(xRenderCompositeReq);
2088    swaps(&stuff->length);
2089    swapl(&stuff->src);
2090    swapl(&stuff->mask);
2091    swapl(&stuff->dst);
2092    swaps(&stuff->xSrc);
2093    swaps(&stuff->ySrc);
2094    swaps(&stuff->xMask);
2095    swaps(&stuff->yMask);
2096    swaps(&stuff->xDst);
2097    swaps(&stuff->yDst);
2098    swaps(&stuff->width);
2099    swaps(&stuff->height);
2100    return (*ProcRenderVector[stuff->renderReqType]) (client);
2101}
2102
2103static int
2104SProcRenderScale(ClientPtr client)
2105{
2106    return BadImplementation;
2107}
2108
2109static int
2110SProcRenderTrapezoids(ClientPtr client)
2111{
2112    REQUEST(xRenderTrapezoidsReq);
2113
2114    REQUEST_AT_LEAST_SIZE(xRenderTrapezoidsReq);
2115    swaps(&stuff->length);
2116    swapl(&stuff->src);
2117    swapl(&stuff->dst);
2118    swapl(&stuff->maskFormat);
2119    swaps(&stuff->xSrc);
2120    swaps(&stuff->ySrc);
2121    SwapRestL(stuff);
2122    return (*ProcRenderVector[stuff->renderReqType]) (client);
2123}
2124
2125static int
2126SProcRenderTriangles(ClientPtr client)
2127{
2128    REQUEST(xRenderTrianglesReq);
2129
2130    REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq);
2131    swaps(&stuff->length);
2132    swapl(&stuff->src);
2133    swapl(&stuff->dst);
2134    swapl(&stuff->maskFormat);
2135    swaps(&stuff->xSrc);
2136    swaps(&stuff->ySrc);
2137    SwapRestL(stuff);
2138    return (*ProcRenderVector[stuff->renderReqType]) (client);
2139}
2140
2141static int
2142SProcRenderTriStrip(ClientPtr client)
2143{
2144    REQUEST(xRenderTriStripReq);
2145
2146    REQUEST_AT_LEAST_SIZE(xRenderTriStripReq);
2147    swaps(&stuff->length);
2148    swapl(&stuff->src);
2149    swapl(&stuff->dst);
2150    swapl(&stuff->maskFormat);
2151    swaps(&stuff->xSrc);
2152    swaps(&stuff->ySrc);
2153    SwapRestL(stuff);
2154    return (*ProcRenderVector[stuff->renderReqType]) (client);
2155}
2156
2157static int
2158SProcRenderTriFan(ClientPtr client)
2159{
2160    REQUEST(xRenderTriFanReq);
2161
2162    REQUEST_AT_LEAST_SIZE(xRenderTriFanReq);
2163    swaps(&stuff->length);
2164    swapl(&stuff->src);
2165    swapl(&stuff->dst);
2166    swapl(&stuff->maskFormat);
2167    swaps(&stuff->xSrc);
2168    swaps(&stuff->ySrc);
2169    SwapRestL(stuff);
2170    return (*ProcRenderVector[stuff->renderReqType]) (client);
2171}
2172
2173static int
2174SProcRenderColorTrapezoids(ClientPtr client)
2175{
2176    return BadImplementation;
2177}
2178
2179static int
2180SProcRenderColorTriangles(ClientPtr client)
2181{
2182    return BadImplementation;
2183}
2184
2185static int
2186SProcRenderTransform(ClientPtr client)
2187{
2188    return BadImplementation;
2189}
2190
2191static int
2192SProcRenderCreateGlyphSet(ClientPtr client)
2193{
2194    REQUEST(xRenderCreateGlyphSetReq);
2195    REQUEST_SIZE_MATCH(xRenderCreateGlyphSetReq);
2196    swaps(&stuff->length);
2197    swapl(&stuff->gsid);
2198    swapl(&stuff->format);
2199    return (*ProcRenderVector[stuff->renderReqType]) (client);
2200}
2201
2202static int
2203SProcRenderReferenceGlyphSet(ClientPtr client)
2204{
2205    REQUEST(xRenderReferenceGlyphSetReq);
2206    REQUEST_SIZE_MATCH(xRenderReferenceGlyphSetReq);
2207    swaps(&stuff->length);
2208    swapl(&stuff->gsid);
2209    swapl(&stuff->existing);
2210    return (*ProcRenderVector[stuff->renderReqType]) (client);
2211}
2212
2213static int
2214SProcRenderFreeGlyphSet(ClientPtr client)
2215{
2216    REQUEST(xRenderFreeGlyphSetReq);
2217    REQUEST_SIZE_MATCH(xRenderFreeGlyphSetReq);
2218    swaps(&stuff->length);
2219    swapl(&stuff->glyphset);
2220    return (*ProcRenderVector[stuff->renderReqType]) (client);
2221}
2222
2223static int
2224SProcRenderAddGlyphs(ClientPtr client)
2225{
2226    register int i;
2227    CARD32 *gids;
2228    void *end;
2229    xGlyphInfo *gi;
2230
2231    REQUEST(xRenderAddGlyphsReq);
2232    REQUEST_AT_LEAST_SIZE(xRenderAddGlyphsReq);
2233    swaps(&stuff->length);
2234    swapl(&stuff->glyphset);
2235    swapl(&stuff->nglyphs);
2236    if (stuff->nglyphs & 0xe0000000)
2237        return BadLength;
2238    end = (CARD8 *) stuff + (client->req_len << 2);
2239    gids = (CARD32 *) (stuff + 1);
2240    gi = (xGlyphInfo *) (gids + stuff->nglyphs);
2241    if ((char *) end - (char *) (gids + stuff->nglyphs) < 0)
2242        return BadLength;
2243    if ((char *) end - (char *) (gi + stuff->nglyphs) < 0)
2244        return BadLength;
2245    for (i = 0; i < stuff->nglyphs; i++) {
2246        swapl(&gids[i]);
2247        swaps(&gi[i].width);
2248        swaps(&gi[i].height);
2249        swaps(&gi[i].x);
2250        swaps(&gi[i].y);
2251        swaps(&gi[i].xOff);
2252        swaps(&gi[i].yOff);
2253    }
2254    return (*ProcRenderVector[stuff->renderReqType]) (client);
2255}
2256
2257static int
2258SProcRenderAddGlyphsFromPicture(ClientPtr client)
2259{
2260    return BadImplementation;
2261}
2262
2263static int
2264SProcRenderFreeGlyphs(ClientPtr client)
2265{
2266    REQUEST(xRenderFreeGlyphsReq);
2267    REQUEST_AT_LEAST_SIZE(xRenderFreeGlyphsReq);
2268    swaps(&stuff->length);
2269    swapl(&stuff->glyphset);
2270    SwapRestL(stuff);
2271    return (*ProcRenderVector[stuff->renderReqType]) (client);
2272}
2273
2274static int
2275SProcRenderCompositeGlyphs(ClientPtr client)
2276{
2277    xGlyphElt *elt;
2278    CARD8 *buffer;
2279    CARD8 *end;
2280    int space;
2281    int i;
2282    int size;
2283
2284    REQUEST(xRenderCompositeGlyphsReq);
2285    REQUEST_AT_LEAST_SIZE(xRenderCompositeGlyphsReq);
2286
2287    switch (stuff->renderReqType) {
2288    default:
2289        size = 1;
2290        break;
2291    case X_RenderCompositeGlyphs16:
2292        size = 2;
2293        break;
2294    case X_RenderCompositeGlyphs32:
2295        size = 4;
2296        break;
2297    }
2298
2299    swaps(&stuff->length);
2300    swapl(&stuff->src);
2301    swapl(&stuff->dst);
2302    swapl(&stuff->maskFormat);
2303    swapl(&stuff->glyphset);
2304    swaps(&stuff->xSrc);
2305    swaps(&stuff->ySrc);
2306    buffer = (CARD8 *) (stuff + 1);
2307    end = (CARD8 *) stuff + (client->req_len << 2);
2308    while (buffer + sizeof(xGlyphElt) < end) {
2309        elt = (xGlyphElt *) buffer;
2310        buffer += sizeof(xGlyphElt);
2311
2312        swaps(&elt->deltax);
2313        swaps(&elt->deltay);
2314
2315        i = elt->len;
2316        if (i == 0xff) {
2317            swapl((int *) buffer);
2318            buffer += 4;
2319        }
2320        else {
2321            space = size * i;
2322            switch (size) {
2323            case 1:
2324                buffer += i;
2325                break;
2326            case 2:
2327                while (i--) {
2328                    swaps((short *) buffer);
2329                    buffer += 2;
2330                }
2331                break;
2332            case 4:
2333                while (i--) {
2334                    swapl((int *) buffer);
2335                    buffer += 4;
2336                }
2337                break;
2338            }
2339            if (space & 3)
2340                buffer += 4 - (space & 3);
2341        }
2342    }
2343    return (*ProcRenderVector[stuff->renderReqType]) (client);
2344}
2345
2346static int
2347SProcRenderFillRectangles(ClientPtr client)
2348{
2349    REQUEST(xRenderFillRectanglesReq);
2350
2351    REQUEST_AT_LEAST_SIZE(xRenderFillRectanglesReq);
2352    swaps(&stuff->length);
2353    swapl(&stuff->dst);
2354    swaps(&stuff->color.red);
2355    swaps(&stuff->color.green);
2356    swaps(&stuff->color.blue);
2357    swaps(&stuff->color.alpha);
2358    SwapRestS(stuff);
2359    return (*ProcRenderVector[stuff->renderReqType]) (client);
2360}
2361
2362static int
2363SProcRenderCreateCursor(ClientPtr client)
2364{
2365    REQUEST(xRenderCreateCursorReq);
2366    REQUEST_SIZE_MATCH(xRenderCreateCursorReq);
2367
2368    swaps(&stuff->length);
2369    swapl(&stuff->cid);
2370    swapl(&stuff->src);
2371    swaps(&stuff->x);
2372    swaps(&stuff->y);
2373    return (*ProcRenderVector[stuff->renderReqType]) (client);
2374}
2375
2376static int
2377SProcRenderSetPictureTransform(ClientPtr client)
2378{
2379    REQUEST(xRenderSetPictureTransformReq);
2380    REQUEST_SIZE_MATCH(xRenderSetPictureTransformReq);
2381
2382    swaps(&stuff->length);
2383    swapl(&stuff->picture);
2384    swapl(&stuff->transform.matrix11);
2385    swapl(&stuff->transform.matrix12);
2386    swapl(&stuff->transform.matrix13);
2387    swapl(&stuff->transform.matrix21);
2388    swapl(&stuff->transform.matrix22);
2389    swapl(&stuff->transform.matrix23);
2390    swapl(&stuff->transform.matrix31);
2391    swapl(&stuff->transform.matrix32);
2392    swapl(&stuff->transform.matrix33);
2393    return (*ProcRenderVector[stuff->renderReqType]) (client);
2394}
2395
2396static int
2397SProcRenderQueryFilters(ClientPtr client)
2398{
2399    REQUEST(xRenderQueryFiltersReq);
2400    REQUEST_SIZE_MATCH(xRenderQueryFiltersReq);
2401
2402    swaps(&stuff->length);
2403    swapl(&stuff->drawable);
2404    return (*ProcRenderVector[stuff->renderReqType]) (client);
2405}
2406
2407static int
2408SProcRenderSetPictureFilter(ClientPtr client)
2409{
2410    REQUEST(xRenderSetPictureFilterReq);
2411    REQUEST_AT_LEAST_SIZE(xRenderSetPictureFilterReq);
2412
2413    swaps(&stuff->length);
2414    swapl(&stuff->picture);
2415    swaps(&stuff->nbytes);
2416    return (*ProcRenderVector[stuff->renderReqType]) (client);
2417}
2418
2419static int
2420SProcRenderCreateAnimCursor(ClientPtr client)
2421{
2422    REQUEST(xRenderCreateAnimCursorReq);
2423    REQUEST_AT_LEAST_SIZE(xRenderCreateAnimCursorReq);
2424
2425    swaps(&stuff->length);
2426    swapl(&stuff->cid);
2427    SwapRestL(stuff);
2428    return (*ProcRenderVector[stuff->renderReqType]) (client);
2429}
2430
2431static int
2432SProcRenderAddTraps(ClientPtr client)
2433{
2434    REQUEST(xRenderAddTrapsReq);
2435    REQUEST_AT_LEAST_SIZE(xRenderAddTrapsReq);
2436
2437    swaps(&stuff->length);
2438    swapl(&stuff->picture);
2439    swaps(&stuff->xOff);
2440    swaps(&stuff->yOff);
2441    SwapRestL(stuff);
2442    return (*ProcRenderVector[stuff->renderReqType]) (client);
2443}
2444
2445static int
2446SProcRenderCreateSolidFill(ClientPtr client)
2447{
2448    REQUEST(xRenderCreateSolidFillReq);
2449    REQUEST_AT_LEAST_SIZE(xRenderCreateSolidFillReq);
2450
2451    swaps(&stuff->length);
2452    swapl(&stuff->pid);
2453    swaps(&stuff->color.alpha);
2454    swaps(&stuff->color.red);
2455    swaps(&stuff->color.green);
2456    swaps(&stuff->color.blue);
2457    return (*ProcRenderVector[stuff->renderReqType]) (client);
2458}
2459
2460static void
2461swapStops(void *stuff, int num)
2462{
2463    int i;
2464    CARD32 *stops;
2465    CARD16 *colors;
2466
2467    stops = (CARD32 *) (stuff);
2468    for (i = 0; i < num; ++i) {
2469        swapl(stops);
2470        ++stops;
2471    }
2472    colors = (CARD16 *) (stops);
2473    for (i = 0; i < 4 * num; ++i) {
2474        swaps(colors);
2475        ++colors;
2476    }
2477}
2478
2479static int
2480SProcRenderCreateLinearGradient(ClientPtr client)
2481{
2482    int len;
2483
2484    REQUEST(xRenderCreateLinearGradientReq);
2485    REQUEST_AT_LEAST_SIZE(xRenderCreateLinearGradientReq);
2486
2487    swaps(&stuff->length);
2488    swapl(&stuff->pid);
2489    swapl(&stuff->p1.x);
2490    swapl(&stuff->p1.y);
2491    swapl(&stuff->p2.x);
2492    swapl(&stuff->p2.y);
2493    swapl(&stuff->nStops);
2494
2495    len = (client->req_len << 2) - sizeof(xRenderCreateLinearGradientReq);
2496    if (stuff->nStops > UINT32_MAX / (sizeof(xFixed) + sizeof(xRenderColor)))
2497        return BadLength;
2498    if (len != stuff->nStops * (sizeof(xFixed) + sizeof(xRenderColor)))
2499        return BadLength;
2500
2501    swapStops(stuff + 1, stuff->nStops);
2502
2503    return (*ProcRenderVector[stuff->renderReqType]) (client);
2504}
2505
2506static int
2507SProcRenderCreateRadialGradient(ClientPtr client)
2508{
2509    int len;
2510
2511    REQUEST(xRenderCreateRadialGradientReq);
2512    REQUEST_AT_LEAST_SIZE(xRenderCreateRadialGradientReq);
2513
2514    swaps(&stuff->length);
2515    swapl(&stuff->pid);
2516    swapl(&stuff->inner.x);
2517    swapl(&stuff->inner.y);
2518    swapl(&stuff->outer.x);
2519    swapl(&stuff->outer.y);
2520    swapl(&stuff->inner_radius);
2521    swapl(&stuff->outer_radius);
2522    swapl(&stuff->nStops);
2523
2524    len = (client->req_len << 2) - sizeof(xRenderCreateRadialGradientReq);
2525    if (stuff->nStops > UINT32_MAX / (sizeof(xFixed) + sizeof(xRenderColor)))
2526        return BadLength;
2527    if (len != stuff->nStops * (sizeof(xFixed) + sizeof(xRenderColor)))
2528        return BadLength;
2529
2530    swapStops(stuff + 1, stuff->nStops);
2531
2532    return (*ProcRenderVector[stuff->renderReqType]) (client);
2533}
2534
2535static int
2536SProcRenderCreateConicalGradient(ClientPtr client)
2537{
2538    int len;
2539
2540    REQUEST(xRenderCreateConicalGradientReq);
2541    REQUEST_AT_LEAST_SIZE(xRenderCreateConicalGradientReq);
2542
2543    swaps(&stuff->length);
2544    swapl(&stuff->pid);
2545    swapl(&stuff->center.x);
2546    swapl(&stuff->center.y);
2547    swapl(&stuff->angle);
2548    swapl(&stuff->nStops);
2549
2550    len = (client->req_len << 2) - sizeof(xRenderCreateConicalGradientReq);
2551    if (stuff->nStops > UINT32_MAX / (sizeof(xFixed) + sizeof(xRenderColor)))
2552        return BadLength;
2553    if (len != stuff->nStops * (sizeof(xFixed) + sizeof(xRenderColor)))
2554        return BadLength;
2555
2556    swapStops(stuff + 1, stuff->nStops);
2557
2558    return (*ProcRenderVector[stuff->renderReqType]) (client);
2559}
2560
2561static int
2562SProcRenderDispatch(ClientPtr client)
2563{
2564    REQUEST(xReq);
2565
2566    if (stuff->data < RenderNumberRequests)
2567        return (*SProcRenderVector[stuff->data]) (client);
2568    else
2569        return BadRequest;
2570}
2571
2572#ifdef PANORAMIX
2573#define VERIFY_XIN_PICTURE(pPicture, pid, client, mode) {\
2574    int rc = dixLookupResourceByType((void **)&(pPicture), pid,\
2575                                     XRT_PICTURE, client, mode);\
2576    if (rc != Success)\
2577	return rc;\
2578}
2579
2580#define VERIFY_XIN_ALPHA(pPicture, pid, client, mode) {\
2581    if (pid == None) \
2582	pPicture = 0; \
2583    else { \
2584	VERIFY_XIN_PICTURE(pPicture, pid, client, mode); \
2585    } \
2586} \
2587
2588int (*PanoramiXSaveRenderVector[RenderNumberRequests]) (ClientPtr);
2589
2590static int
2591PanoramiXRenderCreatePicture(ClientPtr client)
2592{
2593    REQUEST(xRenderCreatePictureReq);
2594    PanoramiXRes *refDraw, *newPict;
2595    int result, j;
2596
2597    REQUEST_AT_LEAST_SIZE(xRenderCreatePictureReq);
2598    result = dixLookupResourceByClass((void **) &refDraw, stuff->drawable,
2599                                      XRC_DRAWABLE, client, DixWriteAccess);
2600    if (result != Success)
2601        return (result == BadValue) ? BadDrawable : result;
2602    if (!(newPict = (PanoramiXRes *) malloc(sizeof(PanoramiXRes))))
2603        return BadAlloc;
2604    newPict->type = XRT_PICTURE;
2605    panoramix_setup_ids(newPict, client, stuff->pid);
2606
2607    if (refDraw->type == XRT_WINDOW &&
2608        stuff->drawable == screenInfo.screens[0]->root->drawable.id) {
2609        newPict->u.pict.root = TRUE;
2610    }
2611    else
2612        newPict->u.pict.root = FALSE;
2613
2614    FOR_NSCREENS_BACKWARD(j) {
2615        stuff->pid = newPict->info[j].id;
2616        stuff->drawable = refDraw->info[j].id;
2617        result = (*PanoramiXSaveRenderVector[X_RenderCreatePicture]) (client);
2618        if (result != Success)
2619            break;
2620    }
2621
2622    if (result == Success)
2623        AddResource(newPict->info[0].id, XRT_PICTURE, newPict);
2624    else
2625        free(newPict);
2626
2627    return result;
2628}
2629
2630static int
2631PanoramiXRenderChangePicture(ClientPtr client)
2632{
2633    PanoramiXRes *pict;
2634    int result = Success, j;
2635
2636    REQUEST(xRenderChangePictureReq);
2637
2638    REQUEST_AT_LEAST_SIZE(xRenderChangePictureReq);
2639
2640    VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixWriteAccess);
2641
2642    FOR_NSCREENS_BACKWARD(j) {
2643        stuff->picture = pict->info[j].id;
2644        result = (*PanoramiXSaveRenderVector[X_RenderChangePicture]) (client);
2645        if (result != Success)
2646            break;
2647    }
2648
2649    return result;
2650}
2651
2652static int
2653PanoramiXRenderSetPictureClipRectangles(ClientPtr client)
2654{
2655    REQUEST(xRenderSetPictureClipRectanglesReq);
2656    int result = Success, j;
2657    PanoramiXRes *pict;
2658
2659    REQUEST_AT_LEAST_SIZE(xRenderSetPictureClipRectanglesReq);
2660
2661    VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixWriteAccess);
2662
2663    FOR_NSCREENS_BACKWARD(j) {
2664        stuff->picture = pict->info[j].id;
2665        result =
2666            (*PanoramiXSaveRenderVector[X_RenderSetPictureClipRectangles])
2667            (client);
2668        if (result != Success)
2669            break;
2670    }
2671
2672    return result;
2673}
2674
2675static int
2676PanoramiXRenderSetPictureTransform(ClientPtr client)
2677{
2678    REQUEST(xRenderSetPictureTransformReq);
2679    int result = Success, j;
2680    PanoramiXRes *pict;
2681
2682    REQUEST_AT_LEAST_SIZE(xRenderSetPictureTransformReq);
2683
2684    VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixWriteAccess);
2685
2686    FOR_NSCREENS_BACKWARD(j) {
2687        stuff->picture = pict->info[j].id;
2688        result =
2689            (*PanoramiXSaveRenderVector[X_RenderSetPictureTransform]) (client);
2690        if (result != Success)
2691            break;
2692    }
2693
2694    return result;
2695}
2696
2697static int
2698PanoramiXRenderSetPictureFilter(ClientPtr client)
2699{
2700    REQUEST(xRenderSetPictureFilterReq);
2701    int result = Success, j;
2702    PanoramiXRes *pict;
2703
2704    REQUEST_AT_LEAST_SIZE(xRenderSetPictureFilterReq);
2705
2706    VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixWriteAccess);
2707
2708    FOR_NSCREENS_BACKWARD(j) {
2709        stuff->picture = pict->info[j].id;
2710        result =
2711            (*PanoramiXSaveRenderVector[X_RenderSetPictureFilter]) (client);
2712        if (result != Success)
2713            break;
2714    }
2715
2716    return result;
2717}
2718
2719static int
2720PanoramiXRenderFreePicture(ClientPtr client)
2721{
2722    PanoramiXRes *pict;
2723    int result = Success, j;
2724
2725    REQUEST(xRenderFreePictureReq);
2726
2727    REQUEST_SIZE_MATCH(xRenderFreePictureReq);
2728
2729    client->errorValue = stuff->picture;
2730
2731    VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixDestroyAccess);
2732
2733    FOR_NSCREENS_BACKWARD(j) {
2734        stuff->picture = pict->info[j].id;
2735        result = (*PanoramiXSaveRenderVector[X_RenderFreePicture]) (client);
2736        if (result != Success)
2737            break;
2738    }
2739
2740    /* Since ProcRenderFreePicture is using FreeResource, it will free
2741       our resource for us on the last pass through the loop above */
2742
2743    return result;
2744}
2745
2746static int
2747PanoramiXRenderComposite(ClientPtr client)
2748{
2749    PanoramiXRes *src, *msk, *dst;
2750    int result = Success, j;
2751    xRenderCompositeReq orig;
2752
2753    REQUEST(xRenderCompositeReq);
2754
2755    REQUEST_SIZE_MATCH(xRenderCompositeReq);
2756
2757    VERIFY_XIN_PICTURE(src, stuff->src, client, DixReadAccess);
2758    VERIFY_XIN_ALPHA(msk, stuff->mask, client, DixReadAccess);
2759    VERIFY_XIN_PICTURE(dst, stuff->dst, client, DixWriteAccess);
2760
2761    orig = *stuff;
2762
2763    FOR_NSCREENS_FORWARD(j) {
2764        stuff->src = src->info[j].id;
2765        if (src->u.pict.root) {
2766            stuff->xSrc = orig.xSrc - screenInfo.screens[j]->x;
2767            stuff->ySrc = orig.ySrc - screenInfo.screens[j]->y;
2768        }
2769        stuff->dst = dst->info[j].id;
2770        if (dst->u.pict.root) {
2771            stuff->xDst = orig.xDst - screenInfo.screens[j]->x;
2772            stuff->yDst = orig.yDst - screenInfo.screens[j]->y;
2773        }
2774        if (msk) {
2775            stuff->mask = msk->info[j].id;
2776            if (msk->u.pict.root) {
2777                stuff->xMask = orig.xMask - screenInfo.screens[j]->x;
2778                stuff->yMask = orig.yMask - screenInfo.screens[j]->y;
2779            }
2780        }
2781        result = (*PanoramiXSaveRenderVector[X_RenderComposite]) (client);
2782        if (result != Success)
2783            break;
2784    }
2785
2786    return result;
2787}
2788
2789static int
2790PanoramiXRenderCompositeGlyphs(ClientPtr client)
2791{
2792    PanoramiXRes *src, *dst;
2793    int result = Success, j;
2794
2795    REQUEST(xRenderCompositeGlyphsReq);
2796    xGlyphElt origElt, *elt;
2797    INT16 xSrc, ySrc;
2798
2799    REQUEST_AT_LEAST_SIZE(xRenderCompositeGlyphsReq);
2800    VERIFY_XIN_PICTURE(src, stuff->src, client, DixReadAccess);
2801    VERIFY_XIN_PICTURE(dst, stuff->dst, client, DixWriteAccess);
2802
2803    if (client->req_len << 2 >= (sizeof(xRenderCompositeGlyphsReq) +
2804                                 sizeof(xGlyphElt))) {
2805        elt = (xGlyphElt *) (stuff + 1);
2806        origElt = *elt;
2807        xSrc = stuff->xSrc;
2808        ySrc = stuff->ySrc;
2809        FOR_NSCREENS_FORWARD(j) {
2810            stuff->src = src->info[j].id;
2811            if (src->u.pict.root) {
2812                stuff->xSrc = xSrc - screenInfo.screens[j]->x;
2813                stuff->ySrc = ySrc - screenInfo.screens[j]->y;
2814            }
2815            stuff->dst = dst->info[j].id;
2816            if (dst->u.pict.root) {
2817                elt->deltax = origElt.deltax - screenInfo.screens[j]->x;
2818                elt->deltay = origElt.deltay - screenInfo.screens[j]->y;
2819            }
2820            result =
2821                (*PanoramiXSaveRenderVector[stuff->renderReqType]) (client);
2822            if (result != Success)
2823                break;
2824        }
2825    }
2826
2827    return result;
2828}
2829
2830static int
2831PanoramiXRenderFillRectangles(ClientPtr client)
2832{
2833    PanoramiXRes *dst;
2834    int result = Success, j;
2835
2836    REQUEST(xRenderFillRectanglesReq);
2837    char *extra;
2838    int extra_len;
2839
2840    REQUEST_AT_LEAST_SIZE(xRenderFillRectanglesReq);
2841    VERIFY_XIN_PICTURE(dst, stuff->dst, client, DixWriteAccess);
2842    extra_len = (client->req_len << 2) - sizeof(xRenderFillRectanglesReq);
2843    if (extra_len && (extra = (char *) malloc(extra_len))) {
2844        memcpy(extra, stuff + 1, extra_len);
2845        FOR_NSCREENS_FORWARD(j) {
2846            if (j)
2847                memcpy(stuff + 1, extra, extra_len);
2848            if (dst->u.pict.root) {
2849                int x_off = screenInfo.screens[j]->x;
2850                int y_off = screenInfo.screens[j]->y;
2851
2852                if (x_off || y_off) {
2853                    xRectangle *rects = (xRectangle *) (stuff + 1);
2854                    int i = extra_len / sizeof(xRectangle);
2855
2856                    while (i--) {
2857                        rects->x -= x_off;
2858                        rects->y -= y_off;
2859                        rects++;
2860                    }
2861                }
2862            }
2863            stuff->dst = dst->info[j].id;
2864            result =
2865                (*PanoramiXSaveRenderVector[X_RenderFillRectangles]) (client);
2866            if (result != Success)
2867                break;
2868        }
2869        free(extra);
2870    }
2871
2872    return result;
2873}
2874
2875static int
2876PanoramiXRenderTrapezoids(ClientPtr client)
2877{
2878    PanoramiXRes *src, *dst;
2879    int result = Success, j;
2880
2881    REQUEST(xRenderTrapezoidsReq);
2882    char *extra;
2883    int extra_len;
2884
2885    REQUEST_AT_LEAST_SIZE(xRenderTrapezoidsReq);
2886
2887    VERIFY_XIN_PICTURE(src, stuff->src, client, DixReadAccess);
2888    VERIFY_XIN_PICTURE(dst, stuff->dst, client, DixWriteAccess);
2889
2890    extra_len = (client->req_len << 2) - sizeof(xRenderTrapezoidsReq);
2891
2892    if (extra_len && (extra = (char *) malloc(extra_len))) {
2893        memcpy(extra, stuff + 1, extra_len);
2894
2895        FOR_NSCREENS_FORWARD(j) {
2896            if (j)
2897                memcpy(stuff + 1, extra, extra_len);
2898            if (dst->u.pict.root) {
2899                int x_off = screenInfo.screens[j]->x;
2900                int y_off = screenInfo.screens[j]->y;
2901
2902                if (x_off || y_off) {
2903                    xTrapezoid *trap = (xTrapezoid *) (stuff + 1);
2904                    int i = extra_len / sizeof(xTrapezoid);
2905
2906                    while (i--) {
2907                        trap->top -= y_off;
2908                        trap->bottom -= y_off;
2909                        trap->left.p1.x -= x_off;
2910                        trap->left.p1.y -= y_off;
2911                        trap->left.p2.x -= x_off;
2912                        trap->left.p2.y -= y_off;
2913                        trap->right.p1.x -= x_off;
2914                        trap->right.p1.y -= y_off;
2915                        trap->right.p2.x -= x_off;
2916                        trap->right.p2.y -= y_off;
2917                        trap++;
2918                    }
2919                }
2920            }
2921
2922            stuff->src = src->info[j].id;
2923            stuff->dst = dst->info[j].id;
2924            result = (*PanoramiXSaveRenderVector[X_RenderTrapezoids]) (client);
2925
2926            if (result != Success)
2927                break;
2928        }
2929
2930        free(extra);
2931    }
2932
2933    return result;
2934}
2935
2936static int
2937PanoramiXRenderTriangles(ClientPtr client)
2938{
2939    PanoramiXRes *src, *dst;
2940    int result = Success, j;
2941
2942    REQUEST(xRenderTrianglesReq);
2943    char *extra;
2944    int extra_len;
2945
2946    REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq);
2947
2948    VERIFY_XIN_PICTURE(src, stuff->src, client, DixReadAccess);
2949    VERIFY_XIN_PICTURE(dst, stuff->dst, client, DixWriteAccess);
2950
2951    extra_len = (client->req_len << 2) - sizeof(xRenderTrianglesReq);
2952
2953    if (extra_len && (extra = (char *) malloc(extra_len))) {
2954        memcpy(extra, stuff + 1, extra_len);
2955
2956        FOR_NSCREENS_FORWARD(j) {
2957            if (j)
2958                memcpy(stuff + 1, extra, extra_len);
2959            if (dst->u.pict.root) {
2960                int x_off = screenInfo.screens[j]->x;
2961                int y_off = screenInfo.screens[j]->y;
2962
2963                if (x_off || y_off) {
2964                    xTriangle *tri = (xTriangle *) (stuff + 1);
2965                    int i = extra_len / sizeof(xTriangle);
2966
2967                    while (i--) {
2968                        tri->p1.x -= x_off;
2969                        tri->p1.y -= y_off;
2970                        tri->p2.x -= x_off;
2971                        tri->p2.y -= y_off;
2972                        tri->p3.x -= x_off;
2973                        tri->p3.y -= y_off;
2974                        tri++;
2975                    }
2976                }
2977            }
2978
2979            stuff->src = src->info[j].id;
2980            stuff->dst = dst->info[j].id;
2981            result = (*PanoramiXSaveRenderVector[X_RenderTriangles]) (client);
2982
2983            if (result != Success)
2984                break;
2985        }
2986
2987        free(extra);
2988    }
2989
2990    return result;
2991}
2992
2993static int
2994PanoramiXRenderTriStrip(ClientPtr client)
2995{
2996    PanoramiXRes *src, *dst;
2997    int result = Success, j;
2998
2999    REQUEST(xRenderTriStripReq);
3000    char *extra;
3001    int extra_len;
3002
3003    REQUEST_AT_LEAST_SIZE(xRenderTriStripReq);
3004
3005    VERIFY_XIN_PICTURE(src, stuff->src, client, DixReadAccess);
3006    VERIFY_XIN_PICTURE(dst, stuff->dst, client, DixWriteAccess);
3007
3008    extra_len = (client->req_len << 2) - sizeof(xRenderTriStripReq);
3009
3010    if (extra_len && (extra = (char *) malloc(extra_len))) {
3011        memcpy(extra, stuff + 1, extra_len);
3012
3013        FOR_NSCREENS_FORWARD(j) {
3014            if (j)
3015                memcpy(stuff + 1, extra, extra_len);
3016            if (dst->u.pict.root) {
3017                int x_off = screenInfo.screens[j]->x;
3018                int y_off = screenInfo.screens[j]->y;
3019
3020                if (x_off || y_off) {
3021                    xPointFixed *fixed = (xPointFixed *) (stuff + 1);
3022                    int i = extra_len / sizeof(xPointFixed);
3023
3024                    while (i--) {
3025                        fixed->x -= x_off;
3026                        fixed->y -= y_off;
3027                        fixed++;
3028                    }
3029                }
3030            }
3031
3032            stuff->src = src->info[j].id;
3033            stuff->dst = dst->info[j].id;
3034            result = (*PanoramiXSaveRenderVector[X_RenderTriStrip]) (client);
3035
3036            if (result != Success)
3037                break;
3038        }
3039
3040        free(extra);
3041    }
3042
3043    return result;
3044}
3045
3046static int
3047PanoramiXRenderTriFan(ClientPtr client)
3048{
3049    PanoramiXRes *src, *dst;
3050    int result = Success, j;
3051
3052    REQUEST(xRenderTriFanReq);
3053    char *extra;
3054    int extra_len;
3055
3056    REQUEST_AT_LEAST_SIZE(xRenderTriFanReq);
3057
3058    VERIFY_XIN_PICTURE(src, stuff->src, client, DixReadAccess);
3059    VERIFY_XIN_PICTURE(dst, stuff->dst, client, DixWriteAccess);
3060
3061    extra_len = (client->req_len << 2) - sizeof(xRenderTriFanReq);
3062
3063    if (extra_len && (extra = (char *) malloc(extra_len))) {
3064        memcpy(extra, stuff + 1, extra_len);
3065
3066        FOR_NSCREENS_FORWARD(j) {
3067            if (j)
3068                memcpy(stuff + 1, extra, extra_len);
3069            if (dst->u.pict.root) {
3070                int x_off = screenInfo.screens[j]->x;
3071                int y_off = screenInfo.screens[j]->y;
3072
3073                if (x_off || y_off) {
3074                    xPointFixed *fixed = (xPointFixed *) (stuff + 1);
3075                    int i = extra_len / sizeof(xPointFixed);
3076
3077                    while (i--) {
3078                        fixed->x -= x_off;
3079                        fixed->y -= y_off;
3080                        fixed++;
3081                    }
3082                }
3083            }
3084
3085            stuff->src = src->info[j].id;
3086            stuff->dst = dst->info[j].id;
3087            result = (*PanoramiXSaveRenderVector[X_RenderTriFan]) (client);
3088
3089            if (result != Success)
3090                break;
3091        }
3092
3093        free(extra);
3094    }
3095
3096    return result;
3097}
3098
3099static int
3100PanoramiXRenderAddTraps(ClientPtr client)
3101{
3102    PanoramiXRes *picture;
3103    int result = Success, j;
3104
3105    REQUEST(xRenderAddTrapsReq);
3106    char *extra;
3107    int extra_len;
3108    INT16 x_off, y_off;
3109
3110    REQUEST_AT_LEAST_SIZE(xRenderAddTrapsReq);
3111    VERIFY_XIN_PICTURE(picture, stuff->picture, client, DixWriteAccess);
3112    extra_len = (client->req_len << 2) - sizeof(xRenderAddTrapsReq);
3113    if (extra_len && (extra = (char *) malloc(extra_len))) {
3114        memcpy(extra, stuff + 1, extra_len);
3115        x_off = stuff->xOff;
3116        y_off = stuff->yOff;
3117        FOR_NSCREENS_FORWARD(j) {
3118            if (j)
3119                memcpy(stuff + 1, extra, extra_len);
3120            stuff->picture = picture->info[j].id;
3121
3122            if (picture->u.pict.root) {
3123                stuff->xOff = x_off + screenInfo.screens[j]->x;
3124                stuff->yOff = y_off + screenInfo.screens[j]->y;
3125            }
3126            result = (*PanoramiXSaveRenderVector[X_RenderAddTraps]) (client);
3127            if (result != Success)
3128                break;
3129        }
3130        free(extra);
3131    }
3132
3133    return result;
3134}
3135
3136static int
3137PanoramiXRenderCreateSolidFill(ClientPtr client)
3138{
3139    REQUEST(xRenderCreateSolidFillReq);
3140    PanoramiXRes *newPict;
3141    int result = Success, j;
3142
3143    REQUEST_AT_LEAST_SIZE(xRenderCreateSolidFillReq);
3144
3145    if (!(newPict = (PanoramiXRes *) malloc(sizeof(PanoramiXRes))))
3146        return BadAlloc;
3147
3148    newPict->type = XRT_PICTURE;
3149    panoramix_setup_ids(newPict, client, stuff->pid);
3150    newPict->u.pict.root = FALSE;
3151
3152    FOR_NSCREENS_BACKWARD(j) {
3153        stuff->pid = newPict->info[j].id;
3154        result = (*PanoramiXSaveRenderVector[X_RenderCreateSolidFill]) (client);
3155        if (result != Success)
3156            break;
3157    }
3158
3159    if (result == Success)
3160        AddResource(newPict->info[0].id, XRT_PICTURE, newPict);
3161    else
3162        free(newPict);
3163
3164    return result;
3165}
3166
3167static int
3168PanoramiXRenderCreateLinearGradient(ClientPtr client)
3169{
3170    REQUEST(xRenderCreateLinearGradientReq);
3171    PanoramiXRes *newPict;
3172    int result = Success, j;
3173
3174    REQUEST_AT_LEAST_SIZE(xRenderCreateLinearGradientReq);
3175
3176    if (!(newPict = (PanoramiXRes *) malloc(sizeof(PanoramiXRes))))
3177        return BadAlloc;
3178
3179    newPict->type = XRT_PICTURE;
3180    panoramix_setup_ids(newPict, client, stuff->pid);
3181    newPict->u.pict.root = FALSE;
3182
3183    FOR_NSCREENS_BACKWARD(j) {
3184        stuff->pid = newPict->info[j].id;
3185        result =
3186            (*PanoramiXSaveRenderVector[X_RenderCreateLinearGradient]) (client);
3187        if (result != Success)
3188            break;
3189    }
3190
3191    if (result == Success)
3192        AddResource(newPict->info[0].id, XRT_PICTURE, newPict);
3193    else
3194        free(newPict);
3195
3196    return result;
3197}
3198
3199static int
3200PanoramiXRenderCreateRadialGradient(ClientPtr client)
3201{
3202    REQUEST(xRenderCreateRadialGradientReq);
3203    PanoramiXRes *newPict;
3204    int result = Success, j;
3205
3206    REQUEST_AT_LEAST_SIZE(xRenderCreateRadialGradientReq);
3207
3208    if (!(newPict = (PanoramiXRes *) malloc(sizeof(PanoramiXRes))))
3209        return BadAlloc;
3210
3211    newPict->type = XRT_PICTURE;
3212    panoramix_setup_ids(newPict, client, stuff->pid);
3213    newPict->u.pict.root = FALSE;
3214
3215    FOR_NSCREENS_BACKWARD(j) {
3216        stuff->pid = newPict->info[j].id;
3217        result =
3218            (*PanoramiXSaveRenderVector[X_RenderCreateRadialGradient]) (client);
3219        if (result != Success)
3220            break;
3221    }
3222
3223    if (result == Success)
3224        AddResource(newPict->info[0].id, XRT_PICTURE, newPict);
3225    else
3226        free(newPict);
3227
3228    return result;
3229}
3230
3231static int
3232PanoramiXRenderCreateConicalGradient(ClientPtr client)
3233{
3234    REQUEST(xRenderCreateConicalGradientReq);
3235    PanoramiXRes *newPict;
3236    int result = Success, j;
3237
3238    REQUEST_AT_LEAST_SIZE(xRenderCreateConicalGradientReq);
3239
3240    if (!(newPict = (PanoramiXRes *) malloc(sizeof(PanoramiXRes))))
3241        return BadAlloc;
3242
3243    newPict->type = XRT_PICTURE;
3244    panoramix_setup_ids(newPict, client, stuff->pid);
3245    newPict->u.pict.root = FALSE;
3246
3247    FOR_NSCREENS_BACKWARD(j) {
3248        stuff->pid = newPict->info[j].id;
3249        result =
3250            (*PanoramiXSaveRenderVector[X_RenderCreateConicalGradient])
3251            (client);
3252        if (result != Success)
3253            break;
3254    }
3255
3256    if (result == Success)
3257        AddResource(newPict->info[0].id, XRT_PICTURE, newPict);
3258    else
3259        free(newPict);
3260
3261    return result;
3262}
3263
3264void
3265PanoramiXRenderInit(void)
3266{
3267    int i;
3268
3269    XRT_PICTURE = CreateNewResourceType(XineramaDeleteResource,
3270                                        "XineramaPicture");
3271    if (RenderErrBase)
3272        SetResourceTypeErrorValue(XRT_PICTURE, RenderErrBase + BadPicture);
3273    for (i = 0; i < RenderNumberRequests; i++)
3274        PanoramiXSaveRenderVector[i] = ProcRenderVector[i];
3275    /*
3276     * Stuff in Xinerama aware request processing hooks
3277     */
3278    ProcRenderVector[X_RenderCreatePicture] = PanoramiXRenderCreatePicture;
3279    ProcRenderVector[X_RenderChangePicture] = PanoramiXRenderChangePicture;
3280    ProcRenderVector[X_RenderSetPictureTransform] =
3281        PanoramiXRenderSetPictureTransform;
3282    ProcRenderVector[X_RenderSetPictureFilter] =
3283        PanoramiXRenderSetPictureFilter;
3284    ProcRenderVector[X_RenderSetPictureClipRectangles] =
3285        PanoramiXRenderSetPictureClipRectangles;
3286    ProcRenderVector[X_RenderFreePicture] = PanoramiXRenderFreePicture;
3287    ProcRenderVector[X_RenderComposite] = PanoramiXRenderComposite;
3288    ProcRenderVector[X_RenderCompositeGlyphs8] = PanoramiXRenderCompositeGlyphs;
3289    ProcRenderVector[X_RenderCompositeGlyphs16] =
3290        PanoramiXRenderCompositeGlyphs;
3291    ProcRenderVector[X_RenderCompositeGlyphs32] =
3292        PanoramiXRenderCompositeGlyphs;
3293    ProcRenderVector[X_RenderFillRectangles] = PanoramiXRenderFillRectangles;
3294
3295    ProcRenderVector[X_RenderTrapezoids] = PanoramiXRenderTrapezoids;
3296    ProcRenderVector[X_RenderTriangles] = PanoramiXRenderTriangles;
3297    ProcRenderVector[X_RenderTriStrip] = PanoramiXRenderTriStrip;
3298    ProcRenderVector[X_RenderTriFan] = PanoramiXRenderTriFan;
3299    ProcRenderVector[X_RenderAddTraps] = PanoramiXRenderAddTraps;
3300
3301    ProcRenderVector[X_RenderCreateSolidFill] = PanoramiXRenderCreateSolidFill;
3302    ProcRenderVector[X_RenderCreateLinearGradient] =
3303        PanoramiXRenderCreateLinearGradient;
3304    ProcRenderVector[X_RenderCreateRadialGradient] =
3305        PanoramiXRenderCreateRadialGradient;
3306    ProcRenderVector[X_RenderCreateConicalGradient] =
3307        PanoramiXRenderCreateConicalGradient;
3308}
3309
3310void
3311PanoramiXRenderReset(void)
3312{
3313    int i;
3314
3315    for (i = 0; i < RenderNumberRequests; i++)
3316        ProcRenderVector[i] = PanoramiXSaveRenderVector[i];
3317    RenderErrBase = 0;
3318}
3319
3320#endif                          /* PANORAMIX */
3321