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