Imported Upstream version 0.9.8
[platform/upstream/libXrender.git] / src / Xrender.c
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_CONFIG_H
26 #include <config.h>
27 #endif
28 #include "Xrenderint.h"
29 #include <limits.h>
30
31 XRenderExtInfo XRenderExtensionInfo;
32 char XRenderExtensionName[] = RENDER_NAME;
33
34 static int XRenderCloseDisplay (Display *dpy, XExtCodes *codes);
35
36 /*
37  * XRenderExtFindDisplay - look for a display in this extension; keeps a
38  * cache of the most-recently used for efficiency. (Replaces
39  * XextFindDisplay.)
40  */
41 static XRenderExtDisplayInfo *
42 XRenderExtFindDisplay (XRenderExtInfo *extinfo,
43                        Display        *dpy)
44 {
45     XRenderExtDisplayInfo *dpyinfo;
46
47     /*
48      * see if this was the most recently accessed display
49      */
50     if ((dpyinfo = extinfo->cur) && dpyinfo->display == dpy)
51         return dpyinfo;
52
53     /*
54      * look for display in list
55      */
56     _XLockMutex(_Xglobal_lock);
57     for (dpyinfo = extinfo->head; dpyinfo; dpyinfo = dpyinfo->next) {
58         if (dpyinfo->display == dpy) {
59             extinfo->cur = dpyinfo;     /* cache most recently used */
60             _XUnlockMutex(_Xglobal_lock);
61             return dpyinfo;
62         }
63     }
64     _XUnlockMutex(_Xglobal_lock);
65
66     return NULL;
67 }
68
69 /*
70  * If the server is missing support for any of the required depths on
71  * any screen, tell the application that Render is not present.
72  */
73
74 #define DEPTH_MASK(d)   (1U << ((d) - 1))
75
76 /*
77  * Render requires support for depth 1, 4, 8, 24 and 32 pixmaps
78  */
79
80 #define REQUIRED_DEPTHS (DEPTH_MASK(1) | \
81                          DEPTH_MASK(4) | \
82                          DEPTH_MASK(8) | \
83                          DEPTH_MASK(24) | \
84                          DEPTH_MASK(32))
85
86 typedef struct _DepthCheckRec {
87     struct _DepthCheckRec *next;
88     Display *dpy;
89     CARD32  missing;
90     unsigned long serial;
91 } DepthCheckRec, *DepthCheckPtr;
92
93 static DepthCheckPtr    depthChecks;
94
95 static int
96 XRenderDepthCheckErrorHandler (Display *dpy, XErrorEvent *evt)
97 {
98     if (evt->request_code == X_CreatePixmap && evt->error_code == BadValue)
99     {
100         DepthCheckPtr   d;
101         _XLockMutex(_Xglobal_lock);
102         for (d = depthChecks; d; d = d->next)
103             if (d->dpy == dpy)
104             {
105                 if ((long) (evt->serial - d->serial) >= 0)
106                     d->missing |= DEPTH_MASK(evt->resourceid);
107                 break;
108             }
109         _XUnlockMutex (_Xglobal_lock);
110     }
111     return 0;
112 }
113
114 static Bool
115 XRenderHasDepths (Display *dpy)
116 {
117     int s;
118
119     for (s = 0; s < ScreenCount (dpy); s++)
120     {
121         CARD32              depths = 0;
122         CARD32              missing;
123         Screen              *scr = ScreenOfDisplay (dpy, s);
124         int                 d;
125
126         for (d = 0; d < scr->ndepths; d++)
127             depths |= DEPTH_MASK(scr->depths[d].depth);
128         missing = ~depths & REQUIRED_DEPTHS;
129         if (missing)
130         {
131             DepthCheckRec   dc, **dp;
132             XErrorHandler   previousHandler;
133
134             /*
135              * Ok, this is ugly.  It should be sufficient at this
136              * point to just return False, but Xinerama is broken at
137              * this point and only advertises depths which have an
138              * associated visual.  Of course, the other depths still
139              * work, but the only way to find out is to try them.
140              */
141             dc.dpy = dpy;
142             dc.missing = 0;
143             dc.serial = XNextRequest (dpy);
144             _XLockMutex(_Xglobal_lock);
145             dc.next = depthChecks;
146             depthChecks = &dc;
147             _XUnlockMutex (_Xglobal_lock);
148             /*
149              * I suspect this is not really thread safe, but Xlib doesn't
150              * provide a lot of options here
151              */
152             previousHandler = XSetErrorHandler (XRenderDepthCheckErrorHandler);
153             /*
154              * Try each missing depth and see if pixmap creation succeeds
155              */
156             for (d = 1; d <= 32; d++)
157                 /* don't check depth 1 == Xcursor recurses... */
158                 if ((missing & DEPTH_MASK(d)) && d != 1)
159                 {
160                     Pixmap  p;
161                     p = XCreatePixmap (dpy, RootWindow (dpy, s), 1, 1, d);
162                     XFreePixmap (dpy, p);
163                 }
164             XSync (dpy, False);
165             XSetErrorHandler (previousHandler);
166             /*
167              * Unhook from the list of depth check records
168              */
169             _XLockMutex(_Xglobal_lock);
170             for (dp = &depthChecks; *dp; dp = &(*dp)->next)
171             {
172                 if (*dp == &dc)
173                 {
174                     *dp = dc.next;
175                     break;
176                 }
177             }
178             _XUnlockMutex (_Xglobal_lock);
179             if (dc.missing)
180                 return False;
181         }
182     }
183     return True;
184 }
185
186 /*
187  * XRenderExtAddDisplay - add a display to this extension. (Replaces
188  * XextAddDisplay)
189  */
190 static XRenderExtDisplayInfo *
191 XRenderExtAddDisplay (XRenderExtInfo *extinfo,
192                       Display        *dpy,
193                       char           *ext_name)
194 {
195     XRenderExtDisplayInfo *dpyinfo;
196
197     dpyinfo = (XRenderExtDisplayInfo *) Xmalloc (sizeof (XRenderExtDisplayInfo));
198     if (!dpyinfo) return NULL;
199     dpyinfo->display = dpy;
200     dpyinfo->info = NULL;
201
202     if (XRenderHasDepths (dpy))
203         dpyinfo->codes = XInitExtension (dpy, ext_name);
204     else
205         dpyinfo->codes = NULL;
206
207     /*
208      * if the server has the extension, then we can initialize the
209      * appropriate function vectors
210      */
211     if (dpyinfo->codes) {
212         XESetCloseDisplay (dpy, dpyinfo->codes->extension,
213                            XRenderCloseDisplay);
214     } else {
215         /* The server doesn't have this extension.
216          * Use a private Xlib-internal extension to hang the close_display
217          * hook on so that the "cache" (extinfo->cur) is properly cleaned.
218          * (XBUG 7955)
219          */
220         XExtCodes *codes = XAddExtension(dpy);
221         if (!codes) {
222             XFree(dpyinfo);
223             return NULL;
224         }
225         XESetCloseDisplay (dpy, codes->extension, XRenderCloseDisplay);
226     }
227
228     /*
229      * now, chain it onto the list
230      */
231     _XLockMutex(_Xglobal_lock);
232     dpyinfo->next = extinfo->head;
233     extinfo->head = dpyinfo;
234     extinfo->cur = dpyinfo;
235     extinfo->ndisplays++;
236     _XUnlockMutex(_Xglobal_lock);
237     return dpyinfo;
238 }
239
240
241 /*
242  * XRenderExtRemoveDisplay - remove the indicated display from the
243  * extension object. (Replaces XextRemoveDisplay.)
244  */
245 static int
246 XRenderExtRemoveDisplay (XRenderExtInfo *extinfo, Display *dpy)
247 {
248     XRenderExtDisplayInfo *dpyinfo, *prev;
249
250     /*
251      * locate this display and its back link so that it can be removed
252      */
253     _XLockMutex(_Xglobal_lock);
254     prev = NULL;
255     for (dpyinfo = extinfo->head; dpyinfo; dpyinfo = dpyinfo->next) {
256         if (dpyinfo->display == dpy) break;
257         prev = dpyinfo;
258     }
259     if (!dpyinfo) {
260         _XUnlockMutex(_Xglobal_lock);
261         return 0;               /* hmm, actually an error */
262     }
263
264     /*
265      * remove the display from the list; handles going to zero
266      */
267     if (prev)
268         prev->next = dpyinfo->next;
269     else
270         extinfo->head = dpyinfo->next;
271
272     extinfo->ndisplays--;
273     if (dpyinfo == extinfo->cur) extinfo->cur = NULL;  /* flush cache */
274     _XUnlockMutex(_Xglobal_lock);
275
276     Xfree ((char *) dpyinfo);
277     return 1;
278 }
279
280
281
282 XRenderExtDisplayInfo *
283 XRenderFindDisplay (Display *dpy)
284 {
285     XRenderExtDisplayInfo *dpyinfo;
286
287     dpyinfo = XRenderExtFindDisplay (&XRenderExtensionInfo, dpy);
288     if (!dpyinfo)
289         dpyinfo = XRenderExtAddDisplay (&XRenderExtensionInfo, dpy,
290                                         XRenderExtensionName);
291     return dpyinfo;
292 }
293
294 static int
295 XRenderCloseDisplay (Display *dpy, XExtCodes *codes)
296 {
297     XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
298     if (info && info->info) XFree (info->info);
299
300     return XRenderExtRemoveDisplay (&XRenderExtensionInfo, dpy);
301 }
302
303 /****************************************************************************
304  *                                                                          *
305  *                          Render public interfaces                        *
306  *                                                                          *
307  ****************************************************************************/
308
309 Bool XRenderQueryExtension (Display *dpy, int *event_basep, int *error_basep)
310 {
311     XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
312
313     if (RenderHasExtension(info)) {
314         *event_basep = info->codes->first_event;
315         *error_basep = info->codes->first_error;
316         return True;
317     } else {
318         return False;
319     }
320 }
321
322
323 Status XRenderQueryVersion (Display *dpy,
324                             int     *major_versionp,
325                             int     *minor_versionp)
326 {
327     XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
328     XRenderInfo     *xri;
329
330     if (!RenderHasExtension (info))
331         return 0;
332
333     if (!XRenderQueryFormats (dpy))
334         return 0;
335
336     xri = info->info;
337     *major_versionp = xri->major_version;
338     *minor_versionp = xri->minor_version;
339     return 1;
340 }
341
342 static XRenderPictFormat *
343 _XRenderFindFormat (XRenderInfo *xri, PictFormat format)
344 {
345     int nf;
346
347     for (nf = 0; nf < xri->nformat; nf++)
348         if (xri->format[nf].id == format)
349             return &xri->format[nf];
350     return NULL;
351 }
352
353 static Visual *
354 _XRenderFindVisual (Display *dpy, VisualID vid)
355 {
356     return _XVIDtoVisual (dpy, vid);
357 }
358
359 typedef struct _renderVersionState {
360     unsigned long   version_seq;
361     Bool            error;
362     int             major_version;
363     int             minor_version;
364
365 } _XrenderVersionState;
366
367 static Bool
368 _XRenderVersionHandler (Display     *dpy,
369                         xReply      *rep,
370                         char        *buf,
371                         int         len,
372                         XPointer    data)
373 {
374     xRenderQueryVersionReply    replbuf;
375     xRenderQueryVersionReply    *repl;
376     _XrenderVersionState        *state = (_XrenderVersionState *) data;
377
378     if (dpy->last_request_read != state->version_seq)
379         return False;
380     if (rep->generic.type == X_Error)
381     {
382         state->error = True;
383         return False;
384     }
385     repl = (xRenderQueryVersionReply *)
386         _XGetAsyncReply(dpy, (char *)&replbuf, rep, buf, len,
387                      (SIZEOF(xRenderQueryVersionReply) - SIZEOF(xReply)) >> 2,
388                         True);
389     state->major_version = repl->majorVersion;
390     state->minor_version = repl->minorVersion;
391     return True;
392 }
393
394 Status
395 XRenderQueryFormats (Display *dpy)
396 {
397     XRenderExtDisplayInfo               *info = XRenderFindDisplay (dpy);
398     _XAsyncHandler              async;
399     _XrenderVersionState        async_state;
400     xRenderQueryVersionReq      *vreq;
401     xRenderQueryPictFormatsReply rep;
402     xRenderQueryPictFormatsReq  *req;
403     XRenderInfo                 *xri;
404     XRenderPictFormat           *format;
405     XRenderScreen               *screen;
406     XRenderDepth                *depth;
407     XRenderVisual               *visual;
408     xPictFormInfo               *xFormat;
409     xPictScreen                 *xScreen;
410     xPictDepth                  *xDepth;
411     xPictVisual                 *xVisual;
412     CARD32                      *xSubpixel;
413     void                        *xData;
414     int                         nf, ns, nd, nv;
415     unsigned long               rlength;
416     unsigned long               nbytes;
417
418     RenderCheckExtension (dpy, info, 0);
419     LockDisplay (dpy);
420     if (info->info)
421     {
422         UnlockDisplay (dpy);
423         return 1;
424     }
425     GetReq (RenderQueryVersion, vreq);
426     vreq->reqType = info->codes->major_opcode;
427     vreq->renderReqType = X_RenderQueryVersion;
428     vreq->majorVersion = RENDER_MAJOR;
429     vreq->minorVersion = RENDER_MINOR;
430
431     async_state.version_seq = dpy->request;
432     async_state.error = False;
433     async.next = dpy->async_handlers;
434     async.handler = _XRenderVersionHandler;
435     async.data = (XPointer) &async_state;
436     dpy->async_handlers = &async;
437
438     GetReq (RenderQueryPictFormats, req);
439     req->reqType = info->codes->major_opcode;
440     req->renderReqType = X_RenderQueryPictFormats;
441
442     if (!_XReply (dpy, (xReply *) &rep, 0, xFalse))
443     {
444         DeqAsyncHandler (dpy, &async);
445         UnlockDisplay (dpy);
446         SyncHandle ();
447         return 0;
448     }
449     DeqAsyncHandler (dpy, &async);
450     if (async_state.error)
451     {
452         UnlockDisplay(dpy);
453         SyncHandle();
454         return 0;
455     }
456     /*
457      * Check for the lack of sub-pixel data
458      */
459     if (async_state.major_version == 0 && async_state.minor_version < 6)
460         rep.numSubpixel = 0;
461
462     if ((rep.numFormats < ((INT_MAX / 4) / sizeof (XRenderPictFormat))) &&
463         (rep.numScreens < ((INT_MAX / 4) / sizeof (XRenderScreen))) &&
464         (rep.numDepths  < ((INT_MAX / 4) / sizeof (XRenderDepth))) &&
465         (rep.numVisuals < ((INT_MAX / 4) / sizeof (XRenderVisual))) &&
466         (rep.numSubpixel < ((INT_MAX / 4) / 4)) &&
467         (rep.length < (INT_MAX >> 2)) ) {
468         xri = Xmalloc (sizeof (XRenderInfo) +
469                        (rep.numFormats * sizeof (XRenderPictFormat)) +
470                        (rep.numScreens * sizeof (XRenderScreen)) +
471                        (rep.numDepths * sizeof (XRenderDepth)) +
472                        (rep.numVisuals * sizeof (XRenderVisual)));
473         rlength = ((rep.numFormats * sizeof (xPictFormInfo)) +
474                    (rep.numScreens * sizeof (xPictScreen)) +
475                    (rep.numDepths * sizeof (xPictDepth)) +
476                    (rep.numVisuals * sizeof (xPictVisual)) +
477                    (rep.numSubpixel * 4));
478         xData = Xmalloc (rlength);
479         nbytes = (unsigned long) rep.length << 2;
480     } else {
481         xri = NULL;
482         xData = NULL;
483         rlength = nbytes = 0;
484     }
485
486     if (!xri || !xData || nbytes < rlength)
487     {
488         if (xri) Xfree (xri);
489         if (xData) Xfree (xData);
490         _XEatDataWords (dpy, rep.length);
491         UnlockDisplay (dpy);
492         SyncHandle ();
493         return 0;
494     }
495     xri->major_version = async_state.major_version;
496     xri->minor_version = async_state.minor_version;
497     xri->format = (XRenderPictFormat *) (xri + 1);
498     xri->nformat = rep.numFormats;
499     xri->screen = (XRenderScreen *) (xri->format + rep.numFormats);
500     xri->nscreen = rep.numScreens;
501     xri->depth = (XRenderDepth *) (xri->screen + rep.numScreens);
502     xri->ndepth = rep.numDepths;
503     xri->visual = (XRenderVisual *) (xri->depth + rep.numDepths);
504     xri->nvisual = rep.numVisuals;
505     _XRead (dpy, (char *) xData, rlength);
506     format = xri->format;
507     xFormat = (xPictFormInfo *) xData;
508     for (nf = 0; nf < rep.numFormats; nf++)
509     {
510         format->id = xFormat->id;
511         format->type = xFormat->type;
512         format->depth = xFormat->depth;
513         format->direct.red = xFormat->direct.red;
514         format->direct.redMask = xFormat->direct.redMask;
515         format->direct.green = xFormat->direct.green;
516         format->direct.greenMask = xFormat->direct.greenMask;
517         format->direct.blue = xFormat->direct.blue;
518         format->direct.blueMask = xFormat->direct.blueMask;
519         format->direct.alpha = xFormat->direct.alpha;
520         format->direct.alphaMask = xFormat->direct.alphaMask;
521         format->colormap = xFormat->colormap;
522         format++;
523         xFormat++;
524     }
525     xScreen = (xPictScreen *) xFormat;
526     screen = xri->screen;
527     depth = xri->depth;
528     visual = xri->visual;
529     for (ns = 0; ns < xri->nscreen; ns++)
530     {
531         screen->depths = depth;
532         screen->ndepths = xScreen->nDepth;
533         screen->fallback = _XRenderFindFormat (xri, xScreen->fallback);
534         screen->subpixel = SubPixelUnknown;
535         xDepth = (xPictDepth *) (xScreen + 1);
536         for (nd = 0; nd < screen->ndepths; nd++)
537         {
538             depth->depth = xDepth->depth;
539             depth->nvisuals = xDepth->nPictVisuals;
540             depth->visuals = visual;
541             xVisual = (xPictVisual *) (xDepth + 1);
542             for (nv = 0; nv < depth->nvisuals; nv++)
543             {
544                 visual->visual = _XRenderFindVisual (dpy, xVisual->visual);
545                 visual->format = _XRenderFindFormat (xri, xVisual->format);
546                 visual++;
547                 xVisual++;
548             }
549             depth++;
550             xDepth = (xPictDepth *) xVisual;
551         }
552         screen++;
553         xScreen = (xPictScreen *) xDepth;
554     }
555     xSubpixel = (CARD32 *) xScreen;
556     screen = xri->screen;
557     for (ns = 0; ns < rep.numSubpixel; ns++)
558     {
559         screen->subpixel = *xSubpixel;
560         xSubpixel++;
561         screen++;
562     }
563     info->info = xri;
564     /*
565      * Skip any extra data
566      */
567     if (nbytes > rlength)
568         _XEatData (dpy, (unsigned long) (nbytes - rlength));
569
570     UnlockDisplay (dpy);
571     SyncHandle ();
572     Xfree (xData);
573     return 1;
574 }
575
576 int
577 XRenderQuerySubpixelOrder (Display *dpy, int screen)
578 {
579     XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
580     XRenderInfo     *xri;
581
582     if (!RenderHasExtension (info))
583         return SubPixelUnknown;
584
585     if (!XRenderQueryFormats (dpy))
586         return SubPixelUnknown;
587
588     xri = info->info;
589     return xri->screen[screen].subpixel;
590 }
591
592 Bool
593 XRenderSetSubpixelOrder (Display *dpy, int screen, int subpixel)
594 {
595     XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
596     XRenderInfo     *xri;
597
598     if (!RenderHasExtension (info))
599         return False;
600
601     if (!XRenderQueryFormats (dpy))
602         return False;
603
604     xri = info->info;
605     xri->screen[screen].subpixel = subpixel;
606     return True;
607 }
608
609 XRenderPictFormat *
610 XRenderFindVisualFormat (Display *dpy, _Xconst Visual *visual)
611 {
612     XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
613     int             nv;
614     XRenderInfo     *xri;
615     XRenderVisual   *xrv;
616
617     RenderCheckExtension (dpy, info, NULL);
618     if (!XRenderQueryFormats (dpy))
619         return NULL;
620     xri = info->info;
621     for (nv = 0, xrv = xri->visual; nv < xri->nvisual; nv++, xrv++)
622         if (xrv->visual == visual)
623             return xrv->format;
624     return NULL;
625 }
626
627 XRenderPictFormat *
628 XRenderFindFormat (Display              *dpy,
629                    unsigned long        mask,
630                    _Xconst XRenderPictFormat    *template,
631                    int                  count)
632 {
633     XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
634     int             nf;
635     XRenderInfo     *xri;
636
637     RenderCheckExtension (dpy, info, NULL);
638     if (!XRenderQueryFormats (dpy))
639         return NULL;
640     xri = info->info;
641     for (nf = 0; nf < xri->nformat; nf++)
642     {
643         if (mask & PictFormatID)
644             if (template->id != xri->format[nf].id)
645                 continue;
646         if (mask & PictFormatType)
647         if (template->type != xri->format[nf].type)
648                 continue;
649         if (mask & PictFormatDepth)
650             if (template->depth != xri->format[nf].depth)
651                 continue;
652         if (mask & PictFormatRed)
653             if (template->direct.red != xri->format[nf].direct.red)
654                 continue;
655         if (mask & PictFormatRedMask)
656             if (template->direct.redMask != xri->format[nf].direct.redMask)
657                 continue;
658         if (mask & PictFormatGreen)
659             if (template->direct.green != xri->format[nf].direct.green)
660                 continue;
661         if (mask & PictFormatGreenMask)
662             if (template->direct.greenMask != xri->format[nf].direct.greenMask)
663                 continue;
664         if (mask & PictFormatBlue)
665             if (template->direct.blue != xri->format[nf].direct.blue)
666                 continue;
667         if (mask & PictFormatBlueMask)
668             if (template->direct.blueMask != xri->format[nf].direct.blueMask)
669                 continue;
670         if (mask & PictFormatAlpha)
671             if (template->direct.alpha != xri->format[nf].direct.alpha)
672                 continue;
673         if (mask & PictFormatAlphaMask)
674             if (template->direct.alphaMask != xri->format[nf].direct.alphaMask)
675                 continue;
676         if (mask & PictFormatColormap)
677             if (template->colormap != xri->format[nf].colormap)
678                 continue;
679         if (count-- == 0)
680             return &xri->format[nf];
681     }
682     return NULL;
683 }
684
685 XRenderPictFormat *
686 XRenderFindStandardFormat (Display  *dpy,
687                            int      format)
688 {
689     static struct {
690         XRenderPictFormat   templ;
691         unsigned long       mask;
692     } standardFormats[PictStandardNUM] = {
693         /* PictStandardARGB32 */
694         {
695             {
696                 0,                          /* id */
697                 PictTypeDirect,             /* type */
698                 32,                         /* depth */
699                 {                           /* direct */
700                     16,                     /* direct.red */
701                     0xff,                   /* direct.redMask */
702                     8,                      /* direct.green */
703                     0xff,                   /* direct.greenMask */
704                     0,                      /* direct.blue */
705                     0xff,                   /* direct.blueMask */
706                     24,                     /* direct.alpha */
707                     0xff,                   /* direct.alphaMask */
708                 },
709                 0,                          /* colormap */
710             },
711             PictFormatType |
712             PictFormatDepth |
713             PictFormatRed |
714             PictFormatRedMask |
715             PictFormatGreen |
716             PictFormatGreenMask |
717             PictFormatBlue |
718             PictFormatBlueMask |
719             PictFormatAlpha |
720             PictFormatAlphaMask,
721         },
722         /* PictStandardRGB24 */
723         {
724             {
725                 0,                          /* id */
726                 PictTypeDirect,             /* type */
727                 24,                         /* depth */
728                 {                           /* direct */
729                     16,                     /* direct.red */
730                     0xff,                   /* direct.redMask */
731                     8,                      /* direct.green */
732                     0xff,                   /* direct.greenMask */
733                     0,                      /* direct.blue */
734                     0xff,                   /* direct.blueMask */
735                     0,                      /* direct.alpha */
736                     0x00,                   /* direct.alphaMask */
737                 },
738                 0,                          /* colormap */
739             },
740             PictFormatType |
741             PictFormatDepth |
742             PictFormatRed |
743             PictFormatRedMask |
744             PictFormatGreen |
745             PictFormatGreenMask |
746             PictFormatBlue |
747             PictFormatBlueMask |
748             PictFormatAlphaMask,
749         },
750         /* PictStandardA8 */
751         {
752             {
753                 0,                          /* id */
754                 PictTypeDirect,             /* type */
755                 8,                          /* depth */
756                 {                           /* direct */
757                     0,                      /* direct.red */
758                     0x00,                   /* direct.redMask */
759                     0,                      /* direct.green */
760                     0x00,                   /* direct.greenMask */
761                     0,                      /* direct.blue */
762                     0x00,                   /* direct.blueMask */
763                     0,                      /* direct.alpha */
764                     0xff,                   /* direct.alphaMask */
765                 },
766                 0,                          /* colormap */
767             },
768             PictFormatType |
769             PictFormatDepth |
770             PictFormatRedMask |
771             PictFormatGreenMask |
772             PictFormatBlueMask |
773             PictFormatAlpha |
774             PictFormatAlphaMask,
775         },
776         /* PictStandardA4 */
777         {
778             {
779                 0,                          /* id */
780                 PictTypeDirect,             /* type */
781                 4,                          /* depth */
782                 {                           /* direct */
783                     0,                      /* direct.red */
784                     0x00,                   /* direct.redMask */
785                     0,                      /* direct.green */
786                     0x00,                   /* direct.greenMask */
787                     0,                      /* direct.blue */
788                     0x00,                   /* direct.blueMask */
789                     0,                      /* direct.alpha */
790                     0x0f,                   /* direct.alphaMask */
791                 },
792                 0,                          /* colormap */
793             },
794             PictFormatType |
795             PictFormatDepth |
796             PictFormatRedMask |
797             PictFormatGreenMask |
798             PictFormatBlueMask |
799             PictFormatAlpha |
800             PictFormatAlphaMask,
801         },
802         /* PictStandardA1 */
803         {
804             {
805                 0,                          /* id */
806                 PictTypeDirect,             /* type */
807                 1,                          /* depth */
808                 {                           /* direct */
809                     0,                      /* direct.red */
810                     0x00,                   /* direct.redMask */
811                     0,                      /* direct.green */
812                     0x00,                   /* direct.greenMask */
813                     0,                      /* direct.blue */
814                     0x00,                   /* direct.blueMask */
815                     0,                      /* direct.alpha */
816                     0x01,                   /* direct.alphaMask */
817                 },
818                 0,                          /* colormap */
819             },
820             PictFormatType |
821             PictFormatDepth |
822             PictFormatRedMask |
823             PictFormatGreenMask |
824             PictFormatBlueMask |
825             PictFormatAlpha |
826             PictFormatAlphaMask,
827         },
828     };
829
830     if (0 <= format && format < PictStandardNUM)
831         return XRenderFindFormat (dpy,
832                                   standardFormats[format].mask,
833                                   &standardFormats[format].templ,
834                                   0);
835     return NULL;
836 }
837
838 XIndexValue *
839 XRenderQueryPictIndexValues(Display                     *dpy,
840                             _Xconst XRenderPictFormat   *format,
841                             int                         *num)
842 {
843     XRenderExtDisplayInfo                       *info = XRenderFindDisplay (dpy);
844     xRenderQueryPictIndexValuesReq      *req;
845     xRenderQueryPictIndexValuesReply    rep;
846     XIndexValue                         *values;
847     unsigned int                        nbytes, nread, rlength, i;
848
849     RenderCheckExtension (dpy, info, NULL);
850
851     LockDisplay (dpy);
852     GetReq (RenderQueryPictIndexValues, req);
853     req->reqType = info->codes->major_opcode;
854     req->renderReqType = X_RenderQueryPictIndexValues;
855     req->format = format->id;
856     if (!_XReply (dpy, (xReply *) &rep, 0, xFalse))
857     {
858         UnlockDisplay (dpy);
859         SyncHandle ();
860         return NULL;
861     }
862
863     if ((rep.length < (INT_MAX >> 2)) &&
864         (rep.numIndexValues < (INT_MAX / sizeof (XIndexValue)))) {
865         /* request data length */
866         nbytes = rep.length << 2;
867         /* bytes of actual data in the request */
868         nread = rep.numIndexValues * SIZEOF (xIndexValue);
869         /* size of array returned to application */
870         rlength = rep.numIndexValues * sizeof (XIndexValue);
871
872         /* allocate returned data */
873         values = Xmalloc (rlength);
874     } else {
875         nbytes = nread = rlength = 0;
876         values = NULL;
877     }
878
879     if (!values)
880     {
881         _XEatDataWords (dpy, rep.length);
882         UnlockDisplay (dpy);
883         SyncHandle ();
884         return NULL;
885     }
886
887     /* read the values one at a time and convert */
888     *num = rep.numIndexValues;
889     for(i = 0; i < rep.numIndexValues; i++)
890     {
891         xIndexValue value;
892
893         _XRead (dpy, (char *) &value, SIZEOF (xIndexValue));
894         values[i].pixel = value.pixel;
895         values[i].red = value.red;
896         values[i].green = value.green;
897         values[i].blue = value.blue;
898         values[i].alpha = value.alpha;
899     }
900     /* skip any padding */
901     if(nbytes > nread)
902     {
903         _XEatData (dpy, (unsigned long) (nbytes - nread));
904     }
905     UnlockDisplay (dpy);
906     SyncHandle ();
907     return values;
908 }