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