Xrender.c revision 190694da
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
31XRenderExtInfo XRenderExtensionInfo;
32char XRenderExtensionName[] = RENDER_NAME;
33
34static 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 */
41static XRenderExtDisplayInfo *
42XRenderExtFindDisplay (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
86typedef struct _DepthCheckRec {
87    struct _DepthCheckRec *next;
88    Display *dpy;
89    CARD32  missing;
90    unsigned long serial;
91} DepthCheckRec, *DepthCheckPtr;
92
93static DepthCheckPtr	depthChecks;
94
95static int
96XRenderDepthCheckErrorHandler (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
114static Bool
115XRenderHasDepths (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 */
190static XRenderExtDisplayInfo *
191XRenderExtAddDisplay (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 */
245static int
246XRenderExtRemoveDisplay (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
282XRenderExtDisplayInfo *
283XRenderFindDisplay (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
294static int
295XRenderCloseDisplay (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
309Bool 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
323Status 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
342static 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
353static Visual *
354_XRenderFindVisual (Display *dpy, VisualID vid)
355{
356    return _XVIDtoVisual (dpy, vid);
357}
358
359typedef struct _renderVersionState {
360    unsigned long   version_seq;
361    Bool	    error;
362    int		    major_version;
363    int		    minor_version;
364
365} _XrenderVersionState;
366
367static 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
394Status
395XRenderQueryFormats (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	_XEatData (dpy, nbytes);
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
576int
577XRenderQuerySubpixelOrder (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
592Bool
593XRenderSetSubpixelOrder (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
609XRenderPictFormat *
610XRenderFindVisualFormat (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
627XRenderPictFormat *
628XRenderFindFormat (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
685XRenderPictFormat *
686XRenderFindStandardFormat (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
838XIndexValue *
839XRenderQueryPictIndexValues(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	_XEatData (dpy, nbytes);
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}
909