render.c revision 4e185dc0
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        }
1080        else {
1081            GlyphPtr glyph;
1082
1083            glyph_new->found = FALSE;
1084            glyph_new->glyph = glyph = AllocateGlyph(&gi[i], glyphSet->fdepth);
1085            if (!glyph) {
1086                err = BadAlloc;
1087                goto bail;
1088            }
1089
1090            for (screen = 0; screen < screenInfo.numScreens; screen++) {
1091                int width = gi[i].width;
1092                int height = gi[i].height;
1093                int depth = glyphSet->format->depth;
1094                ScreenPtr pScreen;
1095                int error;
1096
1097                /* Skip work if it's invisibly small anyway */
1098                if (!width || !height)
1099                    break;
1100
1101                pScreen = screenInfo.screens[screen];
1102                pSrcPix = GetScratchPixmapHeader(pScreen,
1103                                                 width, height,
1104                                                 depth, depth, -1, bits);
1105                if (!pSrcPix) {
1106                    err = BadAlloc;
1107                    goto bail;
1108                }
1109
1110                pSrc = CreatePicture(0, &pSrcPix->drawable,
1111                                     glyphSet->format, 0, NULL,
1112                                     serverClient, &error);
1113                if (!pSrc) {
1114                    err = BadAlloc;
1115                    goto bail;
1116                }
1117
1118                pDstPix = (pScreen->CreatePixmap) (pScreen,
1119                                                   width, height, depth,
1120                                                   CREATE_PIXMAP_USAGE_GLYPH_PICTURE);
1121
1122                if (!pDstPix) {
1123                    err = BadAlloc;
1124                    goto bail;
1125                }
1126
1127                pDst = CreatePicture(0, &pDstPix->drawable,
1128                                  glyphSet->format,
1129                                  CPComponentAlpha, &component_alpha,
1130                                  serverClient, &error);
1131                SetGlyphPicture(glyph, pScreen, pDst);
1132
1133                /* The picture takes a reference to the pixmap, so we
1134                   drop ours. */
1135                (pScreen->DestroyPixmap) (pDstPix);
1136                pDstPix = NULL;
1137
1138                if (!pDst) {
1139                    err = BadAlloc;
1140                    goto bail;
1141                }
1142
1143                CompositePicture(PictOpSrc,
1144                                 pSrc,
1145                                 None, pDst, 0, 0, 0, 0, 0, 0, width, height);
1146
1147                FreePicture((void *) pSrc, 0);
1148                pSrc = NULL;
1149                FreeScratchPixmapHeader(pSrcPix);
1150                pSrcPix = NULL;
1151            }
1152
1153            memcpy(glyph_new->glyph->sha1, glyph_new->sha1, 20);
1154        }
1155
1156        glyph_new->id = gids[i];
1157
1158        if (size & 3)
1159            size += 4 - (size & 3);
1160        bits += size;
1161        remain -= size;
1162    }
1163    if (remain || i < nglyphs) {
1164        err = BadLength;
1165        goto bail;
1166    }
1167    if (!ResizeGlyphSet(glyphSet, nglyphs)) {
1168        err = BadAlloc;
1169        goto bail;
1170    }
1171    for (i = 0; i < nglyphs; i++)
1172        AddGlyph(glyphSet, glyphs[i].glyph, glyphs[i].id);
1173
1174    if (glyphsBase != glyphsLocal)
1175        free(glyphsBase);
1176    return Success;
1177 bail:
1178    if (pSrc)
1179        FreePicture((void *) pSrc, 0);
1180    if (pSrcPix)
1181        FreeScratchPixmapHeader(pSrcPix);
1182    for (i = 0; i < nglyphs; i++)
1183        if (glyphs[i].glyph && !glyphs[i].found)
1184            free(glyphs[i].glyph);
1185    if (glyphsBase != glyphsLocal)
1186        free(glyphsBase);
1187    return err;
1188}
1189
1190static int
1191ProcRenderAddGlyphsFromPicture(ClientPtr client)
1192{
1193    return BadImplementation;
1194}
1195
1196static int
1197ProcRenderFreeGlyphs(ClientPtr client)
1198{
1199    REQUEST(xRenderFreeGlyphsReq);
1200    GlyphSetPtr glyphSet;
1201    int rc, nglyph;
1202    CARD32 *gids;
1203    CARD32 glyph;
1204
1205    REQUEST_AT_LEAST_SIZE(xRenderFreeGlyphsReq);
1206    rc = dixLookupResourceByType((void **) &glyphSet, stuff->glyphset,
1207                                 GlyphSetType, client, DixRemoveAccess);
1208    if (rc != Success) {
1209        client->errorValue = stuff->glyphset;
1210        return rc;
1211    }
1212    nglyph =
1213        bytes_to_int32((client->req_len << 2) - sizeof(xRenderFreeGlyphsReq));
1214    gids = (CARD32 *) (stuff + 1);
1215    while (nglyph-- > 0) {
1216        glyph = *gids++;
1217        if (!DeleteGlyph(glyphSet, glyph)) {
1218            client->errorValue = glyph;
1219            return RenderErrBase + BadGlyph;
1220        }
1221    }
1222    return Success;
1223}
1224
1225static int
1226ProcRenderCompositeGlyphs(ClientPtr client)
1227{
1228    GlyphSetPtr glyphSet;
1229    GlyphSet gs;
1230    PicturePtr pSrc, pDst;
1231    PictFormatPtr pFormat;
1232    GlyphListRec listsLocal[NLOCALDELTA];
1233    GlyphListPtr lists, listsBase;
1234    GlyphPtr glyphsLocal[NLOCALGLYPH];
1235    Glyph glyph;
1236    GlyphPtr *glyphs, *glyphsBase;
1237    xGlyphElt *elt;
1238    CARD8 *buffer, *end;
1239    int nglyph;
1240    int nlist;
1241    int space;
1242    int size;
1243    int rc, n;
1244
1245    REQUEST(xRenderCompositeGlyphsReq);
1246
1247    REQUEST_AT_LEAST_SIZE(xRenderCompositeGlyphsReq);
1248
1249    switch (stuff->renderReqType) {
1250    default:
1251        size = 1;
1252        break;
1253    case X_RenderCompositeGlyphs16:
1254        size = 2;
1255        break;
1256    case X_RenderCompositeGlyphs32:
1257        size = 4;
1258        break;
1259    }
1260
1261    if (!PictOpValid(stuff->op)) {
1262        client->errorValue = stuff->op;
1263        return BadValue;
1264    }
1265    VERIFY_PICTURE(pSrc, stuff->src, client, DixReadAccess);
1266    VERIFY_PICTURE(pDst, stuff->dst, client, DixWriteAccess);
1267    if (!pDst->pDrawable)
1268        return BadDrawable;
1269    if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen)
1270        return BadMatch;
1271    if (stuff->maskFormat) {
1272        rc = dixLookupResourceByType((void **) &pFormat, stuff->maskFormat,
1273                                     PictFormatType, client, DixReadAccess);
1274        if (rc != Success)
1275            return rc;
1276    }
1277    else
1278        pFormat = 0;
1279
1280    rc = dixLookupResourceByType((void **) &glyphSet, stuff->glyphset,
1281                                 GlyphSetType, client, DixUseAccess);
1282    if (rc != Success)
1283        return rc;
1284
1285    buffer = (CARD8 *) (stuff + 1);
1286    end = (CARD8 *) stuff + (client->req_len << 2);
1287    nglyph = 0;
1288    nlist = 0;
1289    while (buffer + sizeof(xGlyphElt) < end) {
1290        elt = (xGlyphElt *) buffer;
1291        buffer += sizeof(xGlyphElt);
1292
1293        if (elt->len == 0xff) {
1294            buffer += 4;
1295        }
1296        else {
1297            nlist++;
1298            nglyph += elt->len;
1299            space = size * elt->len;
1300            if (space & 3)
1301                space += 4 - (space & 3);
1302            buffer += space;
1303        }
1304    }
1305    if (nglyph <= NLOCALGLYPH)
1306        glyphsBase = glyphsLocal;
1307    else {
1308        glyphsBase = xallocarray(nglyph, sizeof(GlyphPtr));
1309        if (!glyphsBase)
1310            return BadAlloc;
1311    }
1312    if (nlist <= NLOCALDELTA)
1313        listsBase = listsLocal;
1314    else {
1315        listsBase = xallocarray(nlist, sizeof(GlyphListRec));
1316        if (!listsBase) {
1317            rc = BadAlloc;
1318            goto bail;
1319        }
1320    }
1321    buffer = (CARD8 *) (stuff + 1);
1322    glyphs = glyphsBase;
1323    lists = listsBase;
1324    while (buffer + sizeof(xGlyphElt) < end) {
1325        elt = (xGlyphElt *) buffer;
1326        buffer += sizeof(xGlyphElt);
1327
1328        if (elt->len == 0xff) {
1329            if (buffer + sizeof(GlyphSet) < end) {
1330                memcpy(&gs, buffer, sizeof(GlyphSet));
1331                rc = dixLookupResourceByType((void **) &glyphSet, gs,
1332                                             GlyphSetType, client,
1333                                             DixUseAccess);
1334                if (rc != Success)
1335                    goto bail;
1336            }
1337            buffer += 4;
1338        }
1339        else {
1340            lists->xOff = elt->deltax;
1341            lists->yOff = elt->deltay;
1342            lists->format = glyphSet->format;
1343            lists->len = 0;
1344            n = elt->len;
1345            while (n--) {
1346                if (buffer + size <= end) {
1347                    switch (size) {
1348                    case 1:
1349                        glyph = *((CARD8 *) buffer);
1350                        break;
1351                    case 2:
1352                        glyph = *((CARD16 *) buffer);
1353                        break;
1354                    case 4:
1355                    default:
1356                        glyph = *((CARD32 *) buffer);
1357                        break;
1358                    }
1359                    if ((*glyphs = FindGlyph(glyphSet, glyph))) {
1360                        lists->len++;
1361                        glyphs++;
1362                    }
1363                }
1364                buffer += size;
1365            }
1366            space = size * elt->len;
1367            if (space & 3)
1368                buffer += 4 - (space & 3);
1369            lists++;
1370        }
1371    }
1372    if (buffer > end) {
1373        rc = BadLength;
1374        goto bail;
1375    }
1376
1377    CompositeGlyphs(stuff->op,
1378                    pSrc,
1379                    pDst,
1380                    pFormat,
1381                    stuff->xSrc, stuff->ySrc, nlist, listsBase, glyphsBase);
1382    rc = Success;
1383
1384 bail:
1385    if (glyphsBase != glyphsLocal)
1386        free(glyphsBase);
1387    if (listsBase != listsLocal)
1388        free(listsBase);
1389    return rc;
1390}
1391
1392static int
1393ProcRenderFillRectangles(ClientPtr client)
1394{
1395    PicturePtr pDst;
1396    int things;
1397
1398    REQUEST(xRenderFillRectanglesReq);
1399
1400    REQUEST_AT_LEAST_SIZE(xRenderFillRectanglesReq);
1401    if (!PictOpValid(stuff->op)) {
1402        client->errorValue = stuff->op;
1403        return BadValue;
1404    }
1405    VERIFY_PICTURE(pDst, stuff->dst, client, DixWriteAccess);
1406    if (!pDst->pDrawable)
1407        return BadDrawable;
1408
1409    things = (client->req_len << 2) - sizeof(xRenderFillRectanglesReq);
1410    if (things & 4)
1411        return BadLength;
1412    things >>= 3;
1413
1414    CompositeRects(stuff->op,
1415                   pDst, &stuff->color, things, (xRectangle *) &stuff[1]);
1416
1417    return Success;
1418}
1419
1420static void
1421RenderSetBit(unsigned char *line, int x, int bit)
1422{
1423    unsigned char mask;
1424
1425    if (screenInfo.bitmapBitOrder == LSBFirst)
1426        mask = (1 << (x & 7));
1427    else
1428        mask = (0x80 >> (x & 7));
1429    /* XXX assumes byte order is host byte order */
1430    line += (x >> 3);
1431    if (bit)
1432        *line |= mask;
1433    else
1434        *line &= ~mask;
1435}
1436
1437#define DITHER_DIM 2
1438
1439static CARD32 orderedDither[DITHER_DIM][DITHER_DIM] = {
1440    {1, 3,},
1441    {4, 2,},
1442};
1443
1444#define DITHER_SIZE  ((sizeof orderedDither / sizeof orderedDither[0][0]) + 1)
1445
1446static int
1447ProcRenderCreateCursor(ClientPtr client)
1448{
1449    REQUEST(xRenderCreateCursorReq);
1450    PicturePtr pSrc;
1451    ScreenPtr pScreen;
1452    unsigned short width, height;
1453    CARD32 *argbbits, *argb;
1454    unsigned char *srcbits, *srcline;
1455    unsigned char *mskbits, *mskline;
1456    int stride;
1457    int x, y;
1458    int nbytes_mono;
1459    CursorMetricRec cm;
1460    CursorPtr pCursor;
1461    CARD32 twocolor[3];
1462    int rc, ncolor;
1463
1464    REQUEST_SIZE_MATCH(xRenderCreateCursorReq);
1465    LEGAL_NEW_RESOURCE(stuff->cid, client);
1466
1467    VERIFY_PICTURE(pSrc, stuff->src, client, DixReadAccess);
1468    if (!pSrc->pDrawable)
1469        return BadDrawable;
1470    pScreen = pSrc->pDrawable->pScreen;
1471    width = pSrc->pDrawable->width;
1472    height = pSrc->pDrawable->height;
1473    if (height && width > UINT32_MAX / (height * sizeof(CARD32)))
1474        return BadAlloc;
1475    if (stuff->x > width || stuff->y > height)
1476        return BadMatch;
1477    argbbits = malloc(width * height * sizeof(CARD32));
1478    if (!argbbits)
1479        return BadAlloc;
1480
1481    stride = BitmapBytePad(width);
1482    nbytes_mono = stride * height;
1483    srcbits = calloc(1, nbytes_mono);
1484    if (!srcbits) {
1485        free(argbbits);
1486        return BadAlloc;
1487    }
1488    mskbits = calloc(1, nbytes_mono);
1489    if (!mskbits) {
1490        free(argbbits);
1491        free(srcbits);
1492        return BadAlloc;
1493    }
1494
1495    /* what kind of maniac creates a cursor from a window picture though */
1496    if (pSrc->pDrawable->type == DRAWABLE_WINDOW)
1497        pScreen->SourceValidate(pSrc->pDrawable, 0, 0, width, height,
1498                                IncludeInferiors);
1499
1500    if (pSrc->format == PICT_a8r8g8b8) {
1501        (*pScreen->GetImage) (pSrc->pDrawable,
1502                              0, 0, width, height, ZPixmap,
1503                              0xffffffff, (void *) argbbits);
1504    }
1505    else {
1506        PixmapPtr pPixmap;
1507        PicturePtr pPicture;
1508        PictFormatPtr pFormat;
1509        int error;
1510
1511        pFormat = PictureMatchFormat(pScreen, 32, PICT_a8r8g8b8);
1512        if (!pFormat) {
1513            free(argbbits);
1514            free(srcbits);
1515            free(mskbits);
1516            return BadImplementation;
1517        }
1518        pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, 32,
1519                                            CREATE_PIXMAP_USAGE_SCRATCH);
1520        if (!pPixmap) {
1521            free(argbbits);
1522            free(srcbits);
1523            free(mskbits);
1524            return BadAlloc;
1525        }
1526        pPicture = CreatePicture(0, &pPixmap->drawable, pFormat, 0, 0,
1527                                 client, &error);
1528        if (!pPicture) {
1529            free(argbbits);
1530            free(srcbits);
1531            free(mskbits);
1532            return error;
1533        }
1534        (*pScreen->DestroyPixmap) (pPixmap);
1535        CompositePicture(PictOpSrc,
1536                         pSrc, 0, pPicture, 0, 0, 0, 0, 0, 0, width, height);
1537        (*pScreen->GetImage) (pPicture->pDrawable,
1538                              0, 0, width, height, ZPixmap,
1539                              0xffffffff, (void *) argbbits);
1540        FreePicture(pPicture, 0);
1541    }
1542    /*
1543     * Check whether the cursor can be directly supported by
1544     * the core cursor code
1545     */
1546    ncolor = 0;
1547    argb = argbbits;
1548    for (y = 0; ncolor <= 2 && y < height; y++) {
1549        for (x = 0; ncolor <= 2 && x < width; x++) {
1550            CARD32 p = *argb++;
1551            CARD32 a = (p >> 24);
1552
1553            if (a == 0)         /* transparent */
1554                continue;
1555            if (a == 0xff) {    /* opaque */
1556                int n;
1557
1558                for (n = 0; n < ncolor; n++)
1559                    if (p == twocolor[n])
1560                        break;
1561                if (n == ncolor)
1562                    twocolor[ncolor++] = p;
1563            }
1564            else
1565                ncolor = 3;
1566        }
1567    }
1568
1569    /*
1570     * Convert argb image to two plane cursor
1571     */
1572    srcline = srcbits;
1573    mskline = mskbits;
1574    argb = argbbits;
1575    for (y = 0; y < height; y++) {
1576        for (x = 0; x < width; x++) {
1577            CARD32 p = *argb++;
1578
1579            if (ncolor <= 2) {
1580                CARD32 a = ((p >> 24));
1581
1582                RenderSetBit(mskline, x, a != 0);
1583                RenderSetBit(srcline, x, a != 0 && p == twocolor[0]);
1584            }
1585            else {
1586                CARD32 a = ((p >> 24) * DITHER_SIZE + 127) / 255;
1587                CARD32 i = ((CvtR8G8B8toY15(p) >> 7) * DITHER_SIZE + 127) / 255;
1588                CARD32 d =
1589                    orderedDither[y & (DITHER_DIM - 1)][x & (DITHER_DIM - 1)];
1590                /* Set mask from dithered alpha value */
1591                RenderSetBit(mskline, x, a > d);
1592                /* Set src from dithered intensity value */
1593                RenderSetBit(srcline, x, a > d && i <= d);
1594            }
1595        }
1596        srcline += stride;
1597        mskline += stride;
1598    }
1599    /*
1600     * Dither to white and black if the cursor has more than two colors
1601     */
1602    if (ncolor > 2) {
1603        twocolor[0] = 0xff000000;
1604        twocolor[1] = 0xffffffff;
1605    }
1606    else {
1607        free(argbbits);
1608        argbbits = 0;
1609    }
1610
1611#define GetByte(p,s)	(((p) >> (s)) & 0xff)
1612#define GetColor(p,s)	(GetByte(p,s) | (GetByte(p,s) << 8))
1613
1614    cm.width = width;
1615    cm.height = height;
1616    cm.xhot = stuff->x;
1617    cm.yhot = stuff->y;
1618    rc = AllocARGBCursor(srcbits, mskbits, argbbits, &cm,
1619                         GetColor(twocolor[0], 16),
1620                         GetColor(twocolor[0], 8),
1621                         GetColor(twocolor[0], 0),
1622                         GetColor(twocolor[1], 16),
1623                         GetColor(twocolor[1], 8),
1624                         GetColor(twocolor[1], 0),
1625                         &pCursor, client, stuff->cid);
1626    if (rc != Success)
1627        goto bail;
1628    if (!AddResource(stuff->cid, RT_CURSOR, (void *) pCursor)) {
1629        rc = BadAlloc;
1630        goto bail;
1631    }
1632
1633    return Success;
1634 bail:
1635    free(srcbits);
1636    free(mskbits);
1637    return rc;
1638}
1639
1640static int
1641ProcRenderSetPictureTransform(ClientPtr client)
1642{
1643    REQUEST(xRenderSetPictureTransformReq);
1644    PicturePtr pPicture;
1645
1646    REQUEST_SIZE_MATCH(xRenderSetPictureTransformReq);
1647    VERIFY_PICTURE(pPicture, stuff->picture, client, DixSetAttrAccess);
1648    return SetPictureTransform(pPicture, (PictTransform *) &stuff->transform);
1649}
1650
1651static int
1652ProcRenderQueryFilters(ClientPtr client)
1653{
1654    REQUEST(xRenderQueryFiltersReq);
1655    DrawablePtr pDrawable;
1656    xRenderQueryFiltersReply *reply;
1657    int nbytesName;
1658    int nnames;
1659    ScreenPtr pScreen;
1660    PictureScreenPtr ps;
1661    int i, j, len, total_bytes, rc;
1662    INT16 *aliases;
1663    char *names;
1664
1665    REQUEST_SIZE_MATCH(xRenderQueryFiltersReq);
1666    rc = dixLookupDrawable(&pDrawable, stuff->drawable, client, 0,
1667                           DixGetAttrAccess);
1668    if (rc != Success)
1669        return rc;
1670
1671    pScreen = pDrawable->pScreen;
1672    nbytesName = 0;
1673    nnames = 0;
1674    ps = GetPictureScreenIfSet(pScreen);
1675    if (ps) {
1676        for (i = 0; i < ps->nfilters; i++)
1677            nbytesName += 1 + strlen(ps->filters[i].name);
1678        for (i = 0; i < ps->nfilterAliases; i++)
1679            nbytesName += 1 + strlen(ps->filterAliases[i].alias);
1680        nnames = ps->nfilters + ps->nfilterAliases;
1681    }
1682    len = ((nnames + 1) >> 1) + bytes_to_int32(nbytesName);
1683    total_bytes = sizeof(xRenderQueryFiltersReply) + (len << 2);
1684    reply = (xRenderQueryFiltersReply *) calloc(1, total_bytes);
1685    if (!reply)
1686        return BadAlloc;
1687    aliases = (INT16 *) (reply + 1);
1688    names = (char *) (aliases + ((nnames + 1) & ~1));
1689
1690    reply->type = X_Reply;
1691    reply->sequenceNumber = client->sequence;
1692    reply->length = len;
1693    reply->numAliases = nnames;
1694    reply->numFilters = nnames;
1695    if (ps) {
1696
1697        /* fill in alias values */
1698        for (i = 0; i < ps->nfilters; i++)
1699            aliases[i] = FilterAliasNone;
1700        for (i = 0; i < ps->nfilterAliases; i++) {
1701            for (j = 0; j < ps->nfilters; j++)
1702                if (ps->filterAliases[i].filter_id == ps->filters[j].id)
1703                    break;
1704            if (j == ps->nfilters) {
1705                for (j = 0; j < ps->nfilterAliases; j++)
1706                    if (ps->filterAliases[i].filter_id ==
1707                        ps->filterAliases[j].alias_id) {
1708                        break;
1709                    }
1710                if (j == ps->nfilterAliases)
1711                    j = FilterAliasNone;
1712                else
1713                    j = j + ps->nfilters;
1714            }
1715            aliases[i + ps->nfilters] = j;
1716        }
1717
1718        /* fill in filter names */
1719        for (i = 0; i < ps->nfilters; i++) {
1720            j = strlen(ps->filters[i].name);
1721            *names++ = j;
1722            memcpy(names, ps->filters[i].name, j);
1723            names += j;
1724        }
1725
1726        /* fill in filter alias names */
1727        for (i = 0; i < ps->nfilterAliases; i++) {
1728            j = strlen(ps->filterAliases[i].alias);
1729            *names++ = j;
1730            memcpy(names, ps->filterAliases[i].alias, j);
1731            names += j;
1732        }
1733    }
1734
1735    if (client->swapped) {
1736        for (i = 0; i < reply->numAliases; i++) {
1737            swaps(&aliases[i]);
1738        }
1739        swaps(&reply->sequenceNumber);
1740        swapl(&reply->length);
1741        swapl(&reply->numAliases);
1742        swapl(&reply->numFilters);
1743    }
1744    WriteToClient(client, total_bytes, reply);
1745    free(reply);
1746
1747    return Success;
1748}
1749
1750static int
1751ProcRenderSetPictureFilter(ClientPtr client)
1752{
1753    REQUEST(xRenderSetPictureFilterReq);
1754    PicturePtr pPicture;
1755    int result;
1756    xFixed *params;
1757    int nparams;
1758    char *name;
1759
1760    REQUEST_AT_LEAST_SIZE(xRenderSetPictureFilterReq);
1761    VERIFY_PICTURE(pPicture, stuff->picture, client, DixSetAttrAccess);
1762    name = (char *) (stuff + 1);
1763    params = (xFixed *) (name + pad_to_int32(stuff->nbytes));
1764    nparams = ((xFixed *) stuff + client->req_len) - params;
1765    if (nparams < 0)
1766	return BadLength;
1767
1768    result = SetPictureFilter(pPicture, name, stuff->nbytes, params, nparams);
1769    return result;
1770}
1771
1772static int
1773ProcRenderCreateAnimCursor(ClientPtr client)
1774{
1775    REQUEST(xRenderCreateAnimCursorReq);
1776    CursorPtr *cursors;
1777    CARD32 *deltas;
1778    CursorPtr pCursor;
1779    int ncursor;
1780    xAnimCursorElt *elt;
1781    int i;
1782    int ret;
1783
1784    REQUEST_AT_LEAST_SIZE(xRenderCreateAnimCursorReq);
1785    LEGAL_NEW_RESOURCE(stuff->cid, client);
1786    if (client->req_len & 1)
1787        return BadLength;
1788    ncursor =
1789        (client->req_len -
1790         (bytes_to_int32(sizeof(xRenderCreateAnimCursorReq)))) >> 1;
1791    cursors = xallocarray(ncursor, sizeof(CursorPtr) + sizeof(CARD32));
1792    if (!cursors)
1793        return BadAlloc;
1794    deltas = (CARD32 *) (cursors + ncursor);
1795    elt = (xAnimCursorElt *) (stuff + 1);
1796    for (i = 0; i < ncursor; i++) {
1797        ret = dixLookupResourceByType((void **) (cursors + i), elt->cursor,
1798                                      RT_CURSOR, client, DixReadAccess);
1799        if (ret != Success) {
1800            free(cursors);
1801            return ret;
1802        }
1803        deltas[i] = elt->delay;
1804        elt++;
1805    }
1806    ret = AnimCursorCreate(cursors, deltas, ncursor, &pCursor, client,
1807                           stuff->cid);
1808    free(cursors);
1809    if (ret != Success)
1810        return ret;
1811
1812    if (AddResource(stuff->cid, RT_CURSOR, (void *) pCursor))
1813        return Success;
1814    return BadAlloc;
1815}
1816
1817static int
1818ProcRenderAddTraps(ClientPtr client)
1819{
1820    int ntraps;
1821    PicturePtr pPicture;
1822
1823    REQUEST(xRenderAddTrapsReq);
1824
1825    REQUEST_AT_LEAST_SIZE(xRenderAddTrapsReq);
1826    VERIFY_PICTURE(pPicture, stuff->picture, client, DixWriteAccess);
1827    if (!pPicture->pDrawable)
1828        return BadDrawable;
1829    ntraps = (client->req_len << 2) - sizeof(xRenderAddTrapsReq);
1830    if (ntraps % sizeof(xTrap))
1831        return BadLength;
1832    ntraps /= sizeof(xTrap);
1833    if (ntraps)
1834        AddTraps(pPicture,
1835                 stuff->xOff, stuff->yOff, ntraps, (xTrap *) &stuff[1]);
1836    return Success;
1837}
1838
1839static int
1840ProcRenderCreateSolidFill(ClientPtr client)
1841{
1842    PicturePtr pPicture;
1843    int error = 0;
1844
1845    REQUEST(xRenderCreateSolidFillReq);
1846
1847    REQUEST_AT_LEAST_SIZE(xRenderCreateSolidFillReq);
1848
1849    LEGAL_NEW_RESOURCE(stuff->pid, client);
1850
1851    pPicture = CreateSolidPicture(stuff->pid, &stuff->color, &error);
1852    if (!pPicture)
1853        return error;
1854    /* security creation/labeling check */
1855    error = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, PictureType,
1856                     pPicture, RT_NONE, NULL, DixCreateAccess);
1857    if (error != Success)
1858        return error;
1859    if (!AddResource(stuff->pid, PictureType, (void *) pPicture))
1860        return BadAlloc;
1861    return Success;
1862}
1863
1864static int
1865ProcRenderCreateLinearGradient(ClientPtr client)
1866{
1867    PicturePtr pPicture;
1868    int len;
1869    int error = 0;
1870    xFixed *stops;
1871    xRenderColor *colors;
1872
1873    REQUEST(xRenderCreateLinearGradientReq);
1874
1875    REQUEST_AT_LEAST_SIZE(xRenderCreateLinearGradientReq);
1876
1877    LEGAL_NEW_RESOURCE(stuff->pid, client);
1878
1879    len = (client->req_len << 2) - sizeof(xRenderCreateLinearGradientReq);
1880    if (stuff->nStops > UINT32_MAX / (sizeof(xFixed) + sizeof(xRenderColor)))
1881        return BadLength;
1882    if (len != stuff->nStops * (sizeof(xFixed) + sizeof(xRenderColor)))
1883        return BadLength;
1884
1885    stops = (xFixed *) (stuff + 1);
1886    colors = (xRenderColor *) (stops + stuff->nStops);
1887
1888    pPicture = CreateLinearGradientPicture(stuff->pid, &stuff->p1, &stuff->p2,
1889                                           stuff->nStops, stops, colors,
1890                                           &error);
1891    if (!pPicture)
1892        return error;
1893    /* security creation/labeling check */
1894    error = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, PictureType,
1895                     pPicture, RT_NONE, NULL, DixCreateAccess);
1896    if (error != Success)
1897        return error;
1898    if (!AddResource(stuff->pid, PictureType, (void *) pPicture))
1899        return BadAlloc;
1900    return Success;
1901}
1902
1903static int
1904ProcRenderCreateRadialGradient(ClientPtr client)
1905{
1906    PicturePtr pPicture;
1907    int len;
1908    int error = 0;
1909    xFixed *stops;
1910    xRenderColor *colors;
1911
1912    REQUEST(xRenderCreateRadialGradientReq);
1913
1914    REQUEST_AT_LEAST_SIZE(xRenderCreateRadialGradientReq);
1915
1916    LEGAL_NEW_RESOURCE(stuff->pid, client);
1917
1918    len = (client->req_len << 2) - sizeof(xRenderCreateRadialGradientReq);
1919    if (stuff->nStops > UINT32_MAX / (sizeof(xFixed) + sizeof(xRenderColor)))
1920        return BadLength;
1921    if (len != stuff->nStops * (sizeof(xFixed) + sizeof(xRenderColor)))
1922        return BadLength;
1923
1924    stops = (xFixed *) (stuff + 1);
1925    colors = (xRenderColor *) (stops + stuff->nStops);
1926
1927    pPicture =
1928        CreateRadialGradientPicture(stuff->pid, &stuff->inner, &stuff->outer,
1929                                    stuff->inner_radius, stuff->outer_radius,
1930                                    stuff->nStops, stops, colors, &error);
1931    if (!pPicture)
1932        return error;
1933    /* security creation/labeling check */
1934    error = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, PictureType,
1935                     pPicture, RT_NONE, NULL, DixCreateAccess);
1936    if (error != Success)
1937        return error;
1938    if (!AddResource(stuff->pid, PictureType, (void *) pPicture))
1939        return BadAlloc;
1940    return Success;
1941}
1942
1943static int
1944ProcRenderCreateConicalGradient(ClientPtr client)
1945{
1946    PicturePtr pPicture;
1947    int len;
1948    int error = 0;
1949    xFixed *stops;
1950    xRenderColor *colors;
1951
1952    REQUEST(xRenderCreateConicalGradientReq);
1953
1954    REQUEST_AT_LEAST_SIZE(xRenderCreateConicalGradientReq);
1955
1956    LEGAL_NEW_RESOURCE(stuff->pid, client);
1957
1958    len = (client->req_len << 2) - sizeof(xRenderCreateConicalGradientReq);
1959    if (stuff->nStops > UINT32_MAX / (sizeof(xFixed) + sizeof(xRenderColor)))
1960        return BadLength;
1961    if (len != stuff->nStops * (sizeof(xFixed) + sizeof(xRenderColor)))
1962        return BadLength;
1963
1964    stops = (xFixed *) (stuff + 1);
1965    colors = (xRenderColor *) (stops + stuff->nStops);
1966
1967    pPicture =
1968        CreateConicalGradientPicture(stuff->pid, &stuff->center, stuff->angle,
1969                                     stuff->nStops, stops, colors, &error);
1970    if (!pPicture)
1971        return error;
1972    /* security creation/labeling check */
1973    error = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, PictureType,
1974                     pPicture, RT_NONE, NULL, DixCreateAccess);
1975    if (error != Success)
1976        return error;
1977    if (!AddResource(stuff->pid, PictureType, (void *) pPicture))
1978        return BadAlloc;
1979    return Success;
1980}
1981
1982static int
1983ProcRenderDispatch(ClientPtr client)
1984{
1985    REQUEST(xReq);
1986
1987    if (stuff->data < RenderNumberRequests)
1988        return (*ProcRenderVector[stuff->data]) (client);
1989    else
1990        return BadRequest;
1991}
1992
1993static int _X_COLD
1994SProcRenderQueryVersion(ClientPtr client)
1995{
1996    REQUEST(xRenderQueryVersionReq);
1997    REQUEST_SIZE_MATCH(xRenderQueryVersionReq);
1998    swaps(&stuff->length);
1999    swapl(&stuff->majorVersion);
2000    swapl(&stuff->minorVersion);
2001    return (*ProcRenderVector[stuff->renderReqType]) (client);
2002}
2003
2004static int _X_COLD
2005SProcRenderQueryPictFormats(ClientPtr client)
2006{
2007    REQUEST(xRenderQueryPictFormatsReq);
2008    REQUEST_SIZE_MATCH(xRenderQueryPictFormatsReq);
2009    swaps(&stuff->length);
2010    return (*ProcRenderVector[stuff->renderReqType]) (client);
2011}
2012
2013static int _X_COLD
2014SProcRenderQueryPictIndexValues(ClientPtr client)
2015{
2016    REQUEST(xRenderQueryPictIndexValuesReq);
2017    REQUEST_AT_LEAST_SIZE(xRenderQueryPictIndexValuesReq);
2018    swaps(&stuff->length);
2019    swapl(&stuff->format);
2020    return (*ProcRenderVector[stuff->renderReqType]) (client);
2021}
2022
2023static int _X_COLD
2024SProcRenderQueryDithers(ClientPtr client)
2025{
2026    return BadImplementation;
2027}
2028
2029static int _X_COLD
2030SProcRenderCreatePicture(ClientPtr client)
2031{
2032    REQUEST(xRenderCreatePictureReq);
2033    REQUEST_AT_LEAST_SIZE(xRenderCreatePictureReq);
2034    swaps(&stuff->length);
2035    swapl(&stuff->pid);
2036    swapl(&stuff->drawable);
2037    swapl(&stuff->format);
2038    swapl(&stuff->mask);
2039    SwapRestL(stuff);
2040    return (*ProcRenderVector[stuff->renderReqType]) (client);
2041}
2042
2043static int _X_COLD
2044SProcRenderChangePicture(ClientPtr client)
2045{
2046    REQUEST(xRenderChangePictureReq);
2047    REQUEST_AT_LEAST_SIZE(xRenderChangePictureReq);
2048    swaps(&stuff->length);
2049    swapl(&stuff->picture);
2050    swapl(&stuff->mask);
2051    SwapRestL(stuff);
2052    return (*ProcRenderVector[stuff->renderReqType]) (client);
2053}
2054
2055static int _X_COLD
2056SProcRenderSetPictureClipRectangles(ClientPtr client)
2057{
2058    REQUEST(xRenderSetPictureClipRectanglesReq);
2059    REQUEST_AT_LEAST_SIZE(xRenderSetPictureClipRectanglesReq);
2060    swaps(&stuff->length);
2061    swapl(&stuff->picture);
2062    swaps(&stuff->xOrigin);
2063    swaps(&stuff->yOrigin);
2064    SwapRestS(stuff);
2065    return (*ProcRenderVector[stuff->renderReqType]) (client);
2066}
2067
2068static int _X_COLD
2069SProcRenderFreePicture(ClientPtr client)
2070{
2071    REQUEST(xRenderFreePictureReq);
2072    REQUEST_SIZE_MATCH(xRenderFreePictureReq);
2073    swaps(&stuff->length);
2074    swapl(&stuff->picture);
2075    return (*ProcRenderVector[stuff->renderReqType]) (client);
2076}
2077
2078static int _X_COLD
2079SProcRenderComposite(ClientPtr client)
2080{
2081    REQUEST(xRenderCompositeReq);
2082    REQUEST_SIZE_MATCH(xRenderCompositeReq);
2083    swaps(&stuff->length);
2084    swapl(&stuff->src);
2085    swapl(&stuff->mask);
2086    swapl(&stuff->dst);
2087    swaps(&stuff->xSrc);
2088    swaps(&stuff->ySrc);
2089    swaps(&stuff->xMask);
2090    swaps(&stuff->yMask);
2091    swaps(&stuff->xDst);
2092    swaps(&stuff->yDst);
2093    swaps(&stuff->width);
2094    swaps(&stuff->height);
2095    return (*ProcRenderVector[stuff->renderReqType]) (client);
2096}
2097
2098static int _X_COLD
2099SProcRenderScale(ClientPtr client)
2100{
2101    return BadImplementation;
2102}
2103
2104static int _X_COLD
2105SProcRenderTrapezoids(ClientPtr client)
2106{
2107    REQUEST(xRenderTrapezoidsReq);
2108
2109    REQUEST_AT_LEAST_SIZE(xRenderTrapezoidsReq);
2110    swaps(&stuff->length);
2111    swapl(&stuff->src);
2112    swapl(&stuff->dst);
2113    swapl(&stuff->maskFormat);
2114    swaps(&stuff->xSrc);
2115    swaps(&stuff->ySrc);
2116    SwapRestL(stuff);
2117    return (*ProcRenderVector[stuff->renderReqType]) (client);
2118}
2119
2120static int _X_COLD
2121SProcRenderTriangles(ClientPtr client)
2122{
2123    REQUEST(xRenderTrianglesReq);
2124
2125    REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq);
2126    swaps(&stuff->length);
2127    swapl(&stuff->src);
2128    swapl(&stuff->dst);
2129    swapl(&stuff->maskFormat);
2130    swaps(&stuff->xSrc);
2131    swaps(&stuff->ySrc);
2132    SwapRestL(stuff);
2133    return (*ProcRenderVector[stuff->renderReqType]) (client);
2134}
2135
2136static int _X_COLD
2137SProcRenderTriStrip(ClientPtr client)
2138{
2139    REQUEST(xRenderTriStripReq);
2140
2141    REQUEST_AT_LEAST_SIZE(xRenderTriStripReq);
2142    swaps(&stuff->length);
2143    swapl(&stuff->src);
2144    swapl(&stuff->dst);
2145    swapl(&stuff->maskFormat);
2146    swaps(&stuff->xSrc);
2147    swaps(&stuff->ySrc);
2148    SwapRestL(stuff);
2149    return (*ProcRenderVector[stuff->renderReqType]) (client);
2150}
2151
2152static int _X_COLD
2153SProcRenderTriFan(ClientPtr client)
2154{
2155    REQUEST(xRenderTriFanReq);
2156
2157    REQUEST_AT_LEAST_SIZE(xRenderTriFanReq);
2158    swaps(&stuff->length);
2159    swapl(&stuff->src);
2160    swapl(&stuff->dst);
2161    swapl(&stuff->maskFormat);
2162    swaps(&stuff->xSrc);
2163    swaps(&stuff->ySrc);
2164    SwapRestL(stuff);
2165    return (*ProcRenderVector[stuff->renderReqType]) (client);
2166}
2167
2168static int _X_COLD
2169SProcRenderColorTrapezoids(ClientPtr client)
2170{
2171    return BadImplementation;
2172}
2173
2174static int _X_COLD
2175SProcRenderColorTriangles(ClientPtr client)
2176{
2177    return BadImplementation;
2178}
2179
2180static int _X_COLD
2181SProcRenderTransform(ClientPtr client)
2182{
2183    return BadImplementation;
2184}
2185
2186static int _X_COLD
2187SProcRenderCreateGlyphSet(ClientPtr client)
2188{
2189    REQUEST(xRenderCreateGlyphSetReq);
2190    REQUEST_SIZE_MATCH(xRenderCreateGlyphSetReq);
2191    swaps(&stuff->length);
2192    swapl(&stuff->gsid);
2193    swapl(&stuff->format);
2194    return (*ProcRenderVector[stuff->renderReqType]) (client);
2195}
2196
2197static int _X_COLD
2198SProcRenderReferenceGlyphSet(ClientPtr client)
2199{
2200    REQUEST(xRenderReferenceGlyphSetReq);
2201    REQUEST_SIZE_MATCH(xRenderReferenceGlyphSetReq);
2202    swaps(&stuff->length);
2203    swapl(&stuff->gsid);
2204    swapl(&stuff->existing);
2205    return (*ProcRenderVector[stuff->renderReqType]) (client);
2206}
2207
2208static int _X_COLD
2209SProcRenderFreeGlyphSet(ClientPtr client)
2210{
2211    REQUEST(xRenderFreeGlyphSetReq);
2212    REQUEST_SIZE_MATCH(xRenderFreeGlyphSetReq);
2213    swaps(&stuff->length);
2214    swapl(&stuff->glyphset);
2215    return (*ProcRenderVector[stuff->renderReqType]) (client);
2216}
2217
2218static int _X_COLD
2219SProcRenderAddGlyphs(ClientPtr client)
2220{
2221    register int i;
2222    CARD32 *gids;
2223    void *end;
2224    xGlyphInfo *gi;
2225
2226    REQUEST(xRenderAddGlyphsReq);
2227    REQUEST_AT_LEAST_SIZE(xRenderAddGlyphsReq);
2228    swaps(&stuff->length);
2229    swapl(&stuff->glyphset);
2230    swapl(&stuff->nglyphs);
2231    if (stuff->nglyphs & 0xe0000000)
2232        return BadLength;
2233    end = (CARD8 *) stuff + (client->req_len << 2);
2234    gids = (CARD32 *) (stuff + 1);
2235    gi = (xGlyphInfo *) (gids + stuff->nglyphs);
2236    if ((char *) end - (char *) (gids + stuff->nglyphs) < 0)
2237        return BadLength;
2238    if ((char *) end - (char *) (gi + stuff->nglyphs) < 0)
2239        return BadLength;
2240    for (i = 0; i < stuff->nglyphs; i++) {
2241        swapl(&gids[i]);
2242        swaps(&gi[i].width);
2243        swaps(&gi[i].height);
2244        swaps(&gi[i].x);
2245        swaps(&gi[i].y);
2246        swaps(&gi[i].xOff);
2247        swaps(&gi[i].yOff);
2248    }
2249    return (*ProcRenderVector[stuff->renderReqType]) (client);
2250}
2251
2252static int _X_COLD
2253SProcRenderAddGlyphsFromPicture(ClientPtr client)
2254{
2255    return BadImplementation;
2256}
2257
2258static int _X_COLD
2259SProcRenderFreeGlyphs(ClientPtr client)
2260{
2261    REQUEST(xRenderFreeGlyphsReq);
2262    REQUEST_AT_LEAST_SIZE(xRenderFreeGlyphsReq);
2263    swaps(&stuff->length);
2264    swapl(&stuff->glyphset);
2265    SwapRestL(stuff);
2266    return (*ProcRenderVector[stuff->renderReqType]) (client);
2267}
2268
2269static int _X_COLD
2270SProcRenderCompositeGlyphs(ClientPtr client)
2271{
2272    xGlyphElt *elt;
2273    CARD8 *buffer;
2274    CARD8 *end;
2275    int space;
2276    int i;
2277    int size;
2278
2279    REQUEST(xRenderCompositeGlyphsReq);
2280    REQUEST_AT_LEAST_SIZE(xRenderCompositeGlyphsReq);
2281
2282    switch (stuff->renderReqType) {
2283    default:
2284        size = 1;
2285        break;
2286    case X_RenderCompositeGlyphs16:
2287        size = 2;
2288        break;
2289    case X_RenderCompositeGlyphs32:
2290        size = 4;
2291        break;
2292    }
2293
2294    swaps(&stuff->length);
2295    swapl(&stuff->src);
2296    swapl(&stuff->dst);
2297    swapl(&stuff->maskFormat);
2298    swapl(&stuff->glyphset);
2299    swaps(&stuff->xSrc);
2300    swaps(&stuff->ySrc);
2301    buffer = (CARD8 *) (stuff + 1);
2302    end = (CARD8 *) stuff + (client->req_len << 2);
2303    while (buffer + sizeof(xGlyphElt) < end) {
2304        elt = (xGlyphElt *) buffer;
2305        buffer += sizeof(xGlyphElt);
2306
2307        swaps(&elt->deltax);
2308        swaps(&elt->deltay);
2309
2310        i = elt->len;
2311        if (i == 0xff) {
2312            swapl((int *) buffer);
2313            buffer += 4;
2314        }
2315        else {
2316            space = size * i;
2317            switch (size) {
2318            case 1:
2319                buffer += i;
2320                break;
2321            case 2:
2322                while (i--) {
2323                    swaps((short *) buffer);
2324                    buffer += 2;
2325                }
2326                break;
2327            case 4:
2328                while (i--) {
2329                    swapl((int *) buffer);
2330                    buffer += 4;
2331                }
2332                break;
2333            }
2334            if (space & 3)
2335                buffer += 4 - (space & 3);
2336        }
2337    }
2338    return (*ProcRenderVector[stuff->renderReqType]) (client);
2339}
2340
2341static int _X_COLD
2342SProcRenderFillRectangles(ClientPtr client)
2343{
2344    REQUEST(xRenderFillRectanglesReq);
2345
2346    REQUEST_AT_LEAST_SIZE(xRenderFillRectanglesReq);
2347    swaps(&stuff->length);
2348    swapl(&stuff->dst);
2349    swaps(&stuff->color.red);
2350    swaps(&stuff->color.green);
2351    swaps(&stuff->color.blue);
2352    swaps(&stuff->color.alpha);
2353    SwapRestS(stuff);
2354    return (*ProcRenderVector[stuff->renderReqType]) (client);
2355}
2356
2357static int _X_COLD
2358SProcRenderCreateCursor(ClientPtr client)
2359{
2360    REQUEST(xRenderCreateCursorReq);
2361    REQUEST_SIZE_MATCH(xRenderCreateCursorReq);
2362
2363    swaps(&stuff->length);
2364    swapl(&stuff->cid);
2365    swapl(&stuff->src);
2366    swaps(&stuff->x);
2367    swaps(&stuff->y);
2368    return (*ProcRenderVector[stuff->renderReqType]) (client);
2369}
2370
2371static int _X_COLD
2372SProcRenderSetPictureTransform(ClientPtr client)
2373{
2374    REQUEST(xRenderSetPictureTransformReq);
2375    REQUEST_SIZE_MATCH(xRenderSetPictureTransformReq);
2376
2377    swaps(&stuff->length);
2378    swapl(&stuff->picture);
2379    swapl(&stuff->transform.matrix11);
2380    swapl(&stuff->transform.matrix12);
2381    swapl(&stuff->transform.matrix13);
2382    swapl(&stuff->transform.matrix21);
2383    swapl(&stuff->transform.matrix22);
2384    swapl(&stuff->transform.matrix23);
2385    swapl(&stuff->transform.matrix31);
2386    swapl(&stuff->transform.matrix32);
2387    swapl(&stuff->transform.matrix33);
2388    return (*ProcRenderVector[stuff->renderReqType]) (client);
2389}
2390
2391static int _X_COLD
2392SProcRenderQueryFilters(ClientPtr client)
2393{
2394    REQUEST(xRenderQueryFiltersReq);
2395    REQUEST_SIZE_MATCH(xRenderQueryFiltersReq);
2396
2397    swaps(&stuff->length);
2398    swapl(&stuff->drawable);
2399    return (*ProcRenderVector[stuff->renderReqType]) (client);
2400}
2401
2402static int _X_COLD
2403SProcRenderSetPictureFilter(ClientPtr client)
2404{
2405    REQUEST(xRenderSetPictureFilterReq);
2406    REQUEST_AT_LEAST_SIZE(xRenderSetPictureFilterReq);
2407
2408    swaps(&stuff->length);
2409    swapl(&stuff->picture);
2410    swaps(&stuff->nbytes);
2411    return (*ProcRenderVector[stuff->renderReqType]) (client);
2412}
2413
2414static int _X_COLD
2415SProcRenderCreateAnimCursor(ClientPtr client)
2416{
2417    REQUEST(xRenderCreateAnimCursorReq);
2418    REQUEST_AT_LEAST_SIZE(xRenderCreateAnimCursorReq);
2419
2420    swaps(&stuff->length);
2421    swapl(&stuff->cid);
2422    SwapRestL(stuff);
2423    return (*ProcRenderVector[stuff->renderReqType]) (client);
2424}
2425
2426static int _X_COLD
2427SProcRenderAddTraps(ClientPtr client)
2428{
2429    REQUEST(xRenderAddTrapsReq);
2430    REQUEST_AT_LEAST_SIZE(xRenderAddTrapsReq);
2431
2432    swaps(&stuff->length);
2433    swapl(&stuff->picture);
2434    swaps(&stuff->xOff);
2435    swaps(&stuff->yOff);
2436    SwapRestL(stuff);
2437    return (*ProcRenderVector[stuff->renderReqType]) (client);
2438}
2439
2440static int _X_COLD
2441SProcRenderCreateSolidFill(ClientPtr client)
2442{
2443    REQUEST(xRenderCreateSolidFillReq);
2444    REQUEST_AT_LEAST_SIZE(xRenderCreateSolidFillReq);
2445
2446    swaps(&stuff->length);
2447    swapl(&stuff->pid);
2448    swaps(&stuff->color.alpha);
2449    swaps(&stuff->color.red);
2450    swaps(&stuff->color.green);
2451    swaps(&stuff->color.blue);
2452    return (*ProcRenderVector[stuff->renderReqType]) (client);
2453}
2454
2455static void _X_COLD
2456swapStops(void *stuff, int num)
2457{
2458    int i;
2459    CARD32 *stops;
2460    CARD16 *colors;
2461
2462    stops = (CARD32 *) (stuff);
2463    for (i = 0; i < num; ++i) {
2464        swapl(stops);
2465        ++stops;
2466    }
2467    colors = (CARD16 *) (stops);
2468    for (i = 0; i < 4 * num; ++i) {
2469        swaps(colors);
2470        ++colors;
2471    }
2472}
2473
2474static int _X_COLD
2475SProcRenderCreateLinearGradient(ClientPtr client)
2476{
2477    int len;
2478
2479    REQUEST(xRenderCreateLinearGradientReq);
2480    REQUEST_AT_LEAST_SIZE(xRenderCreateLinearGradientReq);
2481
2482    swaps(&stuff->length);
2483    swapl(&stuff->pid);
2484    swapl(&stuff->p1.x);
2485    swapl(&stuff->p1.y);
2486    swapl(&stuff->p2.x);
2487    swapl(&stuff->p2.y);
2488    swapl(&stuff->nStops);
2489
2490    len = (client->req_len << 2) - sizeof(xRenderCreateLinearGradientReq);
2491    if (stuff->nStops > UINT32_MAX / (sizeof(xFixed) + sizeof(xRenderColor)))
2492        return BadLength;
2493    if (len != stuff->nStops * (sizeof(xFixed) + sizeof(xRenderColor)))
2494        return BadLength;
2495
2496    swapStops(stuff + 1, stuff->nStops);
2497
2498    return (*ProcRenderVector[stuff->renderReqType]) (client);
2499}
2500
2501static int _X_COLD
2502SProcRenderCreateRadialGradient(ClientPtr client)
2503{
2504    int len;
2505
2506    REQUEST(xRenderCreateRadialGradientReq);
2507    REQUEST_AT_LEAST_SIZE(xRenderCreateRadialGradientReq);
2508
2509    swaps(&stuff->length);
2510    swapl(&stuff->pid);
2511    swapl(&stuff->inner.x);
2512    swapl(&stuff->inner.y);
2513    swapl(&stuff->outer.x);
2514    swapl(&stuff->outer.y);
2515    swapl(&stuff->inner_radius);
2516    swapl(&stuff->outer_radius);
2517    swapl(&stuff->nStops);
2518
2519    len = (client->req_len << 2) - sizeof(xRenderCreateRadialGradientReq);
2520    if (stuff->nStops > UINT32_MAX / (sizeof(xFixed) + sizeof(xRenderColor)))
2521        return BadLength;
2522    if (len != stuff->nStops * (sizeof(xFixed) + sizeof(xRenderColor)))
2523        return BadLength;
2524
2525    swapStops(stuff + 1, stuff->nStops);
2526
2527    return (*ProcRenderVector[stuff->renderReqType]) (client);
2528}
2529
2530static int _X_COLD
2531SProcRenderCreateConicalGradient(ClientPtr client)
2532{
2533    int len;
2534
2535    REQUEST(xRenderCreateConicalGradientReq);
2536    REQUEST_AT_LEAST_SIZE(xRenderCreateConicalGradientReq);
2537
2538    swaps(&stuff->length);
2539    swapl(&stuff->pid);
2540    swapl(&stuff->center.x);
2541    swapl(&stuff->center.y);
2542    swapl(&stuff->angle);
2543    swapl(&stuff->nStops);
2544
2545    len = (client->req_len << 2) - sizeof(xRenderCreateConicalGradientReq);
2546    if (stuff->nStops > UINT32_MAX / (sizeof(xFixed) + sizeof(xRenderColor)))
2547        return BadLength;
2548    if (len != stuff->nStops * (sizeof(xFixed) + sizeof(xRenderColor)))
2549        return BadLength;
2550
2551    swapStops(stuff + 1, stuff->nStops);
2552
2553    return (*ProcRenderVector[stuff->renderReqType]) (client);
2554}
2555
2556static int _X_COLD
2557SProcRenderDispatch(ClientPtr client)
2558{
2559    REQUEST(xReq);
2560
2561    if (stuff->data < RenderNumberRequests)
2562        return (*SProcRenderVector[stuff->data]) (client);
2563    else
2564        return BadRequest;
2565}
2566
2567#ifdef PANORAMIX
2568#define VERIFY_XIN_PICTURE(pPicture, pid, client, mode) {\
2569    int rc = dixLookupResourceByType((void **)&(pPicture), pid,\
2570                                     XRT_PICTURE, client, mode);\
2571    if (rc != Success)\
2572	return rc;\
2573}
2574
2575#define VERIFY_XIN_ALPHA(pPicture, pid, client, mode) {\
2576    if (pid == None) \
2577	pPicture = 0; \
2578    else { \
2579	VERIFY_XIN_PICTURE(pPicture, pid, client, mode); \
2580    } \
2581} \
2582
2583int (*PanoramiXSaveRenderVector[RenderNumberRequests]) (ClientPtr);
2584
2585static int
2586PanoramiXRenderCreatePicture(ClientPtr client)
2587{
2588    REQUEST(xRenderCreatePictureReq);
2589    PanoramiXRes *refDraw, *newPict;
2590    int result, j;
2591
2592    REQUEST_AT_LEAST_SIZE(xRenderCreatePictureReq);
2593    result = dixLookupResourceByClass((void **) &refDraw, stuff->drawable,
2594                                      XRC_DRAWABLE, client, DixWriteAccess);
2595    if (result != Success)
2596        return (result == BadValue) ? BadDrawable : result;
2597    if (!(newPict = (PanoramiXRes *) malloc(sizeof(PanoramiXRes))))
2598        return BadAlloc;
2599    newPict->type = XRT_PICTURE;
2600    panoramix_setup_ids(newPict, client, stuff->pid);
2601
2602    if (refDraw->type == XRT_WINDOW &&
2603        stuff->drawable == screenInfo.screens[0]->root->drawable.id) {
2604        newPict->u.pict.root = TRUE;
2605    }
2606    else
2607        newPict->u.pict.root = FALSE;
2608
2609    FOR_NSCREENS_BACKWARD(j) {
2610        stuff->pid = newPict->info[j].id;
2611        stuff->drawable = refDraw->info[j].id;
2612        result = (*PanoramiXSaveRenderVector[X_RenderCreatePicture]) (client);
2613        if (result != Success)
2614            break;
2615    }
2616
2617    if (result == Success)
2618        AddResource(newPict->info[0].id, XRT_PICTURE, newPict);
2619    else
2620        free(newPict);
2621
2622    return result;
2623}
2624
2625static int
2626PanoramiXRenderChangePicture(ClientPtr client)
2627{
2628    PanoramiXRes *pict;
2629    int result = Success, j;
2630
2631    REQUEST(xRenderChangePictureReq);
2632
2633    REQUEST_AT_LEAST_SIZE(xRenderChangePictureReq);
2634
2635    VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixWriteAccess);
2636
2637    FOR_NSCREENS_BACKWARD(j) {
2638        stuff->picture = pict->info[j].id;
2639        result = (*PanoramiXSaveRenderVector[X_RenderChangePicture]) (client);
2640        if (result != Success)
2641            break;
2642    }
2643
2644    return result;
2645}
2646
2647static int
2648PanoramiXRenderSetPictureClipRectangles(ClientPtr client)
2649{
2650    REQUEST(xRenderSetPictureClipRectanglesReq);
2651    int result = Success, j;
2652    PanoramiXRes *pict;
2653
2654    REQUEST_AT_LEAST_SIZE(xRenderSetPictureClipRectanglesReq);
2655
2656    VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixWriteAccess);
2657
2658    FOR_NSCREENS_BACKWARD(j) {
2659        stuff->picture = pict->info[j].id;
2660        result =
2661            (*PanoramiXSaveRenderVector[X_RenderSetPictureClipRectangles])
2662            (client);
2663        if (result != Success)
2664            break;
2665    }
2666
2667    return result;
2668}
2669
2670static int
2671PanoramiXRenderSetPictureTransform(ClientPtr client)
2672{
2673    REQUEST(xRenderSetPictureTransformReq);
2674    int result = Success, j;
2675    PanoramiXRes *pict;
2676
2677    REQUEST_AT_LEAST_SIZE(xRenderSetPictureTransformReq);
2678
2679    VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixWriteAccess);
2680
2681    FOR_NSCREENS_BACKWARD(j) {
2682        stuff->picture = pict->info[j].id;
2683        result =
2684            (*PanoramiXSaveRenderVector[X_RenderSetPictureTransform]) (client);
2685        if (result != Success)
2686            break;
2687    }
2688
2689    return result;
2690}
2691
2692static int
2693PanoramiXRenderSetPictureFilter(ClientPtr client)
2694{
2695    REQUEST(xRenderSetPictureFilterReq);
2696    int result = Success, j;
2697    PanoramiXRes *pict;
2698
2699    REQUEST_AT_LEAST_SIZE(xRenderSetPictureFilterReq);
2700
2701    VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixWriteAccess);
2702
2703    FOR_NSCREENS_BACKWARD(j) {
2704        stuff->picture = pict->info[j].id;
2705        result =
2706            (*PanoramiXSaveRenderVector[X_RenderSetPictureFilter]) (client);
2707        if (result != Success)
2708            break;
2709    }
2710
2711    return result;
2712}
2713
2714static int
2715PanoramiXRenderFreePicture(ClientPtr client)
2716{
2717    PanoramiXRes *pict;
2718    int result = Success, j;
2719
2720    REQUEST(xRenderFreePictureReq);
2721
2722    REQUEST_SIZE_MATCH(xRenderFreePictureReq);
2723
2724    client->errorValue = stuff->picture;
2725
2726    VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixDestroyAccess);
2727
2728    FOR_NSCREENS_BACKWARD(j) {
2729        stuff->picture = pict->info[j].id;
2730        result = (*PanoramiXSaveRenderVector[X_RenderFreePicture]) (client);
2731        if (result != Success)
2732            break;
2733    }
2734
2735    /* Since ProcRenderFreePicture is using FreeResource, it will free
2736       our resource for us on the last pass through the loop above */
2737
2738    return result;
2739}
2740
2741static int
2742PanoramiXRenderComposite(ClientPtr client)
2743{
2744    PanoramiXRes *src, *msk, *dst;
2745    int result = Success, j;
2746    xRenderCompositeReq orig;
2747
2748    REQUEST(xRenderCompositeReq);
2749
2750    REQUEST_SIZE_MATCH(xRenderCompositeReq);
2751
2752    VERIFY_XIN_PICTURE(src, stuff->src, client, DixReadAccess);
2753    VERIFY_XIN_ALPHA(msk, stuff->mask, client, DixReadAccess);
2754    VERIFY_XIN_PICTURE(dst, stuff->dst, client, DixWriteAccess);
2755
2756    orig = *stuff;
2757
2758    FOR_NSCREENS_FORWARD(j) {
2759        stuff->src = src->info[j].id;
2760        if (src->u.pict.root) {
2761            stuff->xSrc = orig.xSrc - screenInfo.screens[j]->x;
2762            stuff->ySrc = orig.ySrc - screenInfo.screens[j]->y;
2763        }
2764        stuff->dst = dst->info[j].id;
2765        if (dst->u.pict.root) {
2766            stuff->xDst = orig.xDst - screenInfo.screens[j]->x;
2767            stuff->yDst = orig.yDst - screenInfo.screens[j]->y;
2768        }
2769        if (msk) {
2770            stuff->mask = msk->info[j].id;
2771            if (msk->u.pict.root) {
2772                stuff->xMask = orig.xMask - screenInfo.screens[j]->x;
2773                stuff->yMask = orig.yMask - screenInfo.screens[j]->y;
2774            }
2775        }
2776        result = (*PanoramiXSaveRenderVector[X_RenderComposite]) (client);
2777        if (result != Success)
2778            break;
2779    }
2780
2781    return result;
2782}
2783
2784static int
2785PanoramiXRenderCompositeGlyphs(ClientPtr client)
2786{
2787    PanoramiXRes *src, *dst;
2788    int result = Success, j;
2789
2790    REQUEST(xRenderCompositeGlyphsReq);
2791    xGlyphElt origElt, *elt;
2792    INT16 xSrc, ySrc;
2793
2794    REQUEST_AT_LEAST_SIZE(xRenderCompositeGlyphsReq);
2795    VERIFY_XIN_PICTURE(src, stuff->src, client, DixReadAccess);
2796    VERIFY_XIN_PICTURE(dst, stuff->dst, client, DixWriteAccess);
2797
2798    if (client->req_len << 2 >= (sizeof(xRenderCompositeGlyphsReq) +
2799                                 sizeof(xGlyphElt))) {
2800        elt = (xGlyphElt *) (stuff + 1);
2801        origElt = *elt;
2802        xSrc = stuff->xSrc;
2803        ySrc = stuff->ySrc;
2804        FOR_NSCREENS_FORWARD(j) {
2805            stuff->src = src->info[j].id;
2806            if (src->u.pict.root) {
2807                stuff->xSrc = xSrc - screenInfo.screens[j]->x;
2808                stuff->ySrc = ySrc - screenInfo.screens[j]->y;
2809            }
2810            stuff->dst = dst->info[j].id;
2811            if (dst->u.pict.root) {
2812                elt->deltax = origElt.deltax - screenInfo.screens[j]->x;
2813                elt->deltay = origElt.deltay - screenInfo.screens[j]->y;
2814            }
2815            result =
2816                (*PanoramiXSaveRenderVector[stuff->renderReqType]) (client);
2817            if (result != Success)
2818                break;
2819        }
2820    }
2821
2822    return result;
2823}
2824
2825static int
2826PanoramiXRenderFillRectangles(ClientPtr client)
2827{
2828    PanoramiXRes *dst;
2829    int result = Success, j;
2830
2831    REQUEST(xRenderFillRectanglesReq);
2832    char *extra;
2833    int extra_len;
2834
2835    REQUEST_AT_LEAST_SIZE(xRenderFillRectanglesReq);
2836    VERIFY_XIN_PICTURE(dst, stuff->dst, client, DixWriteAccess);
2837    extra_len = (client->req_len << 2) - sizeof(xRenderFillRectanglesReq);
2838    if (extra_len && (extra = (char *) malloc(extra_len))) {
2839        memcpy(extra, stuff + 1, extra_len);
2840        FOR_NSCREENS_FORWARD(j) {
2841            if (j)
2842                memcpy(stuff + 1, extra, extra_len);
2843            if (dst->u.pict.root) {
2844                int x_off = screenInfo.screens[j]->x;
2845                int y_off = screenInfo.screens[j]->y;
2846
2847                if (x_off || y_off) {
2848                    xRectangle *rects = (xRectangle *) (stuff + 1);
2849                    int i = extra_len / sizeof(xRectangle);
2850
2851                    while (i--) {
2852                        rects->x -= x_off;
2853                        rects->y -= y_off;
2854                        rects++;
2855                    }
2856                }
2857            }
2858            stuff->dst = dst->info[j].id;
2859            result =
2860                (*PanoramiXSaveRenderVector[X_RenderFillRectangles]) (client);
2861            if (result != Success)
2862                break;
2863        }
2864        free(extra);
2865    }
2866
2867    return result;
2868}
2869
2870static int
2871PanoramiXRenderTrapezoids(ClientPtr client)
2872{
2873    PanoramiXRes *src, *dst;
2874    int result = Success, j;
2875
2876    REQUEST(xRenderTrapezoidsReq);
2877    char *extra;
2878    int extra_len;
2879
2880    REQUEST_AT_LEAST_SIZE(xRenderTrapezoidsReq);
2881
2882    VERIFY_XIN_PICTURE(src, stuff->src, client, DixReadAccess);
2883    VERIFY_XIN_PICTURE(dst, stuff->dst, client, DixWriteAccess);
2884
2885    extra_len = (client->req_len << 2) - sizeof(xRenderTrapezoidsReq);
2886
2887    if (extra_len && (extra = (char *) malloc(extra_len))) {
2888        memcpy(extra, stuff + 1, extra_len);
2889
2890        FOR_NSCREENS_FORWARD(j) {
2891            if (j)
2892                memcpy(stuff + 1, extra, extra_len);
2893            if (dst->u.pict.root) {
2894                int x_off = screenInfo.screens[j]->x;
2895                int y_off = screenInfo.screens[j]->y;
2896
2897                if (x_off || y_off) {
2898                    xTrapezoid *trap = (xTrapezoid *) (stuff + 1);
2899                    int i = extra_len / sizeof(xTrapezoid);
2900
2901                    while (i--) {
2902                        trap->top -= y_off;
2903                        trap->bottom -= y_off;
2904                        trap->left.p1.x -= x_off;
2905                        trap->left.p1.y -= y_off;
2906                        trap->left.p2.x -= x_off;
2907                        trap->left.p2.y -= y_off;
2908                        trap->right.p1.x -= x_off;
2909                        trap->right.p1.y -= y_off;
2910                        trap->right.p2.x -= x_off;
2911                        trap->right.p2.y -= y_off;
2912                        trap++;
2913                    }
2914                }
2915            }
2916
2917            stuff->src = src->info[j].id;
2918            stuff->dst = dst->info[j].id;
2919            result = (*PanoramiXSaveRenderVector[X_RenderTrapezoids]) (client);
2920
2921            if (result != Success)
2922                break;
2923        }
2924
2925        free(extra);
2926    }
2927
2928    return result;
2929}
2930
2931static int
2932PanoramiXRenderTriangles(ClientPtr client)
2933{
2934    PanoramiXRes *src, *dst;
2935    int result = Success, j;
2936
2937    REQUEST(xRenderTrianglesReq);
2938    char *extra;
2939    int extra_len;
2940
2941    REQUEST_AT_LEAST_SIZE(xRenderTrianglesReq);
2942
2943    VERIFY_XIN_PICTURE(src, stuff->src, client, DixReadAccess);
2944    VERIFY_XIN_PICTURE(dst, stuff->dst, client, DixWriteAccess);
2945
2946    extra_len = (client->req_len << 2) - sizeof(xRenderTrianglesReq);
2947
2948    if (extra_len && (extra = (char *) malloc(extra_len))) {
2949        memcpy(extra, stuff + 1, extra_len);
2950
2951        FOR_NSCREENS_FORWARD(j) {
2952            if (j)
2953                memcpy(stuff + 1, extra, extra_len);
2954            if (dst->u.pict.root) {
2955                int x_off = screenInfo.screens[j]->x;
2956                int y_off = screenInfo.screens[j]->y;
2957
2958                if (x_off || y_off) {
2959                    xTriangle *tri = (xTriangle *) (stuff + 1);
2960                    int i = extra_len / sizeof(xTriangle);
2961
2962                    while (i--) {
2963                        tri->p1.x -= x_off;
2964                        tri->p1.y -= y_off;
2965                        tri->p2.x -= x_off;
2966                        tri->p2.y -= y_off;
2967                        tri->p3.x -= x_off;
2968                        tri->p3.y -= y_off;
2969                        tri++;
2970                    }
2971                }
2972            }
2973
2974            stuff->src = src->info[j].id;
2975            stuff->dst = dst->info[j].id;
2976            result = (*PanoramiXSaveRenderVector[X_RenderTriangles]) (client);
2977
2978            if (result != Success)
2979                break;
2980        }
2981
2982        free(extra);
2983    }
2984
2985    return result;
2986}
2987
2988static int
2989PanoramiXRenderTriStrip(ClientPtr client)
2990{
2991    PanoramiXRes *src, *dst;
2992    int result = Success, j;
2993
2994    REQUEST(xRenderTriStripReq);
2995    char *extra;
2996    int extra_len;
2997
2998    REQUEST_AT_LEAST_SIZE(xRenderTriStripReq);
2999
3000    VERIFY_XIN_PICTURE(src, stuff->src, client, DixReadAccess);
3001    VERIFY_XIN_PICTURE(dst, stuff->dst, client, DixWriteAccess);
3002
3003    extra_len = (client->req_len << 2) - sizeof(xRenderTriStripReq);
3004
3005    if (extra_len && (extra = (char *) malloc(extra_len))) {
3006        memcpy(extra, stuff + 1, extra_len);
3007
3008        FOR_NSCREENS_FORWARD(j) {
3009            if (j)
3010                memcpy(stuff + 1, extra, extra_len);
3011            if (dst->u.pict.root) {
3012                int x_off = screenInfo.screens[j]->x;
3013                int y_off = screenInfo.screens[j]->y;
3014
3015                if (x_off || y_off) {
3016                    xPointFixed *fixed = (xPointFixed *) (stuff + 1);
3017                    int i = extra_len / sizeof(xPointFixed);
3018
3019                    while (i--) {
3020                        fixed->x -= x_off;
3021                        fixed->y -= y_off;
3022                        fixed++;
3023                    }
3024                }
3025            }
3026
3027            stuff->src = src->info[j].id;
3028            stuff->dst = dst->info[j].id;
3029            result = (*PanoramiXSaveRenderVector[X_RenderTriStrip]) (client);
3030
3031            if (result != Success)
3032                break;
3033        }
3034
3035        free(extra);
3036    }
3037
3038    return result;
3039}
3040
3041static int
3042PanoramiXRenderTriFan(ClientPtr client)
3043{
3044    PanoramiXRes *src, *dst;
3045    int result = Success, j;
3046
3047    REQUEST(xRenderTriFanReq);
3048    char *extra;
3049    int extra_len;
3050
3051    REQUEST_AT_LEAST_SIZE(xRenderTriFanReq);
3052
3053    VERIFY_XIN_PICTURE(src, stuff->src, client, DixReadAccess);
3054    VERIFY_XIN_PICTURE(dst, stuff->dst, client, DixWriteAccess);
3055
3056    extra_len = (client->req_len << 2) - sizeof(xRenderTriFanReq);
3057
3058    if (extra_len && (extra = (char *) malloc(extra_len))) {
3059        memcpy(extra, stuff + 1, extra_len);
3060
3061        FOR_NSCREENS_FORWARD(j) {
3062            if (j)
3063                memcpy(stuff + 1, extra, extra_len);
3064            if (dst->u.pict.root) {
3065                int x_off = screenInfo.screens[j]->x;
3066                int y_off = screenInfo.screens[j]->y;
3067
3068                if (x_off || y_off) {
3069                    xPointFixed *fixed = (xPointFixed *) (stuff + 1);
3070                    int i = extra_len / sizeof(xPointFixed);
3071
3072                    while (i--) {
3073                        fixed->x -= x_off;
3074                        fixed->y -= y_off;
3075                        fixed++;
3076                    }
3077                }
3078            }
3079
3080            stuff->src = src->info[j].id;
3081            stuff->dst = dst->info[j].id;
3082            result = (*PanoramiXSaveRenderVector[X_RenderTriFan]) (client);
3083
3084            if (result != Success)
3085                break;
3086        }
3087
3088        free(extra);
3089    }
3090
3091    return result;
3092}
3093
3094static int
3095PanoramiXRenderAddTraps(ClientPtr client)
3096{
3097    PanoramiXRes *picture;
3098    int result = Success, j;
3099
3100    REQUEST(xRenderAddTrapsReq);
3101    char *extra;
3102    int extra_len;
3103    INT16 x_off, y_off;
3104
3105    REQUEST_AT_LEAST_SIZE(xRenderAddTrapsReq);
3106    VERIFY_XIN_PICTURE(picture, stuff->picture, client, DixWriteAccess);
3107    extra_len = (client->req_len << 2) - sizeof(xRenderAddTrapsReq);
3108    if (extra_len && (extra = (char *) malloc(extra_len))) {
3109        memcpy(extra, stuff + 1, extra_len);
3110        x_off = stuff->xOff;
3111        y_off = stuff->yOff;
3112        FOR_NSCREENS_FORWARD(j) {
3113            if (j)
3114                memcpy(stuff + 1, extra, extra_len);
3115            stuff->picture = picture->info[j].id;
3116
3117            if (picture->u.pict.root) {
3118                stuff->xOff = x_off + screenInfo.screens[j]->x;
3119                stuff->yOff = y_off + screenInfo.screens[j]->y;
3120            }
3121            result = (*PanoramiXSaveRenderVector[X_RenderAddTraps]) (client);
3122            if (result != Success)
3123                break;
3124        }
3125        free(extra);
3126    }
3127
3128    return result;
3129}
3130
3131static int
3132PanoramiXRenderCreateSolidFill(ClientPtr client)
3133{
3134    REQUEST(xRenderCreateSolidFillReq);
3135    PanoramiXRes *newPict;
3136    int result = Success, j;
3137
3138    REQUEST_AT_LEAST_SIZE(xRenderCreateSolidFillReq);
3139
3140    if (!(newPict = (PanoramiXRes *) malloc(sizeof(PanoramiXRes))))
3141        return BadAlloc;
3142
3143    newPict->type = XRT_PICTURE;
3144    panoramix_setup_ids(newPict, client, stuff->pid);
3145    newPict->u.pict.root = FALSE;
3146
3147    FOR_NSCREENS_BACKWARD(j) {
3148        stuff->pid = newPict->info[j].id;
3149        result = (*PanoramiXSaveRenderVector[X_RenderCreateSolidFill]) (client);
3150        if (result != Success)
3151            break;
3152    }
3153
3154    if (result == Success)
3155        AddResource(newPict->info[0].id, XRT_PICTURE, newPict);
3156    else
3157        free(newPict);
3158
3159    return result;
3160}
3161
3162static int
3163PanoramiXRenderCreateLinearGradient(ClientPtr client)
3164{
3165    REQUEST(xRenderCreateLinearGradientReq);
3166    PanoramiXRes *newPict;
3167    int result = Success, j;
3168
3169    REQUEST_AT_LEAST_SIZE(xRenderCreateLinearGradientReq);
3170
3171    if (!(newPict = (PanoramiXRes *) malloc(sizeof(PanoramiXRes))))
3172        return BadAlloc;
3173
3174    newPict->type = XRT_PICTURE;
3175    panoramix_setup_ids(newPict, client, stuff->pid);
3176    newPict->u.pict.root = FALSE;
3177
3178    FOR_NSCREENS_BACKWARD(j) {
3179        stuff->pid = newPict->info[j].id;
3180        result =
3181            (*PanoramiXSaveRenderVector[X_RenderCreateLinearGradient]) (client);
3182        if (result != Success)
3183            break;
3184    }
3185
3186    if (result == Success)
3187        AddResource(newPict->info[0].id, XRT_PICTURE, newPict);
3188    else
3189        free(newPict);
3190
3191    return result;
3192}
3193
3194static int
3195PanoramiXRenderCreateRadialGradient(ClientPtr client)
3196{
3197    REQUEST(xRenderCreateRadialGradientReq);
3198    PanoramiXRes *newPict;
3199    int result = Success, j;
3200
3201    REQUEST_AT_LEAST_SIZE(xRenderCreateRadialGradientReq);
3202
3203    if (!(newPict = (PanoramiXRes *) malloc(sizeof(PanoramiXRes))))
3204        return BadAlloc;
3205
3206    newPict->type = XRT_PICTURE;
3207    panoramix_setup_ids(newPict, client, stuff->pid);
3208    newPict->u.pict.root = FALSE;
3209
3210    FOR_NSCREENS_BACKWARD(j) {
3211        stuff->pid = newPict->info[j].id;
3212        result =
3213            (*PanoramiXSaveRenderVector[X_RenderCreateRadialGradient]) (client);
3214        if (result != Success)
3215            break;
3216    }
3217
3218    if (result == Success)
3219        AddResource(newPict->info[0].id, XRT_PICTURE, newPict);
3220    else
3221        free(newPict);
3222
3223    return result;
3224}
3225
3226static int
3227PanoramiXRenderCreateConicalGradient(ClientPtr client)
3228{
3229    REQUEST(xRenderCreateConicalGradientReq);
3230    PanoramiXRes *newPict;
3231    int result = Success, j;
3232
3233    REQUEST_AT_LEAST_SIZE(xRenderCreateConicalGradientReq);
3234
3235    if (!(newPict = (PanoramiXRes *) malloc(sizeof(PanoramiXRes))))
3236        return BadAlloc;
3237
3238    newPict->type = XRT_PICTURE;
3239    panoramix_setup_ids(newPict, client, stuff->pid);
3240    newPict->u.pict.root = FALSE;
3241
3242    FOR_NSCREENS_BACKWARD(j) {
3243        stuff->pid = newPict->info[j].id;
3244        result =
3245            (*PanoramiXSaveRenderVector[X_RenderCreateConicalGradient])
3246            (client);
3247        if (result != Success)
3248            break;
3249    }
3250
3251    if (result == Success)
3252        AddResource(newPict->info[0].id, XRT_PICTURE, newPict);
3253    else
3254        free(newPict);
3255
3256    return result;
3257}
3258
3259void
3260PanoramiXRenderInit(void)
3261{
3262    int i;
3263
3264    XRT_PICTURE = CreateNewResourceType(XineramaDeleteResource,
3265                                        "XineramaPicture");
3266    if (RenderErrBase)
3267        SetResourceTypeErrorValue(XRT_PICTURE, RenderErrBase + BadPicture);
3268    for (i = 0; i < RenderNumberRequests; i++)
3269        PanoramiXSaveRenderVector[i] = ProcRenderVector[i];
3270    /*
3271     * Stuff in Xinerama aware request processing hooks
3272     */
3273    ProcRenderVector[X_RenderCreatePicture] = PanoramiXRenderCreatePicture;
3274    ProcRenderVector[X_RenderChangePicture] = PanoramiXRenderChangePicture;
3275    ProcRenderVector[X_RenderSetPictureTransform] =
3276        PanoramiXRenderSetPictureTransform;
3277    ProcRenderVector[X_RenderSetPictureFilter] =
3278        PanoramiXRenderSetPictureFilter;
3279    ProcRenderVector[X_RenderSetPictureClipRectangles] =
3280        PanoramiXRenderSetPictureClipRectangles;
3281    ProcRenderVector[X_RenderFreePicture] = PanoramiXRenderFreePicture;
3282    ProcRenderVector[X_RenderComposite] = PanoramiXRenderComposite;
3283    ProcRenderVector[X_RenderCompositeGlyphs8] = PanoramiXRenderCompositeGlyphs;
3284    ProcRenderVector[X_RenderCompositeGlyphs16] =
3285        PanoramiXRenderCompositeGlyphs;
3286    ProcRenderVector[X_RenderCompositeGlyphs32] =
3287        PanoramiXRenderCompositeGlyphs;
3288    ProcRenderVector[X_RenderFillRectangles] = PanoramiXRenderFillRectangles;
3289
3290    ProcRenderVector[X_RenderTrapezoids] = PanoramiXRenderTrapezoids;
3291    ProcRenderVector[X_RenderTriangles] = PanoramiXRenderTriangles;
3292    ProcRenderVector[X_RenderTriStrip] = PanoramiXRenderTriStrip;
3293    ProcRenderVector[X_RenderTriFan] = PanoramiXRenderTriFan;
3294    ProcRenderVector[X_RenderAddTraps] = PanoramiXRenderAddTraps;
3295
3296    ProcRenderVector[X_RenderCreateSolidFill] = PanoramiXRenderCreateSolidFill;
3297    ProcRenderVector[X_RenderCreateLinearGradient] =
3298        PanoramiXRenderCreateLinearGradient;
3299    ProcRenderVector[X_RenderCreateRadialGradient] =
3300        PanoramiXRenderCreateRadialGradient;
3301    ProcRenderVector[X_RenderCreateConicalGradient] =
3302        PanoramiXRenderCreateConicalGradient;
3303}
3304
3305void
3306PanoramiXRenderReset(void)
3307{
3308    int i;
3309
3310    for (i = 0; i < RenderNumberRequests; i++)
3311        ProcRenderVector[i] = PanoramiXSaveRenderVector[i];
3312    RenderErrBase = 0;
3313}
3314
3315#endif                          /* PANORAMIX */
3316