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