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