Xrender.c revision 190694da
11f0ac6a5Smrg/*
21f0ac6a5Smrg *
31f0ac6a5Smrg * Copyright © 2000 SuSE, Inc.
41f0ac6a5Smrg *
51f0ac6a5Smrg * Permission to use, copy, modify, distribute, and sell this software and its
61f0ac6a5Smrg * documentation for any purpose is hereby granted without fee, provided that
71f0ac6a5Smrg * the above copyright notice appear in all copies and that both that
81f0ac6a5Smrg * copyright notice and this permission notice appear in supporting
91f0ac6a5Smrg * documentation, and that the name of SuSE not be used in advertising or
101f0ac6a5Smrg * publicity pertaining to distribution of the software without specific,
111f0ac6a5Smrg * written prior permission.  SuSE makes no representations about the
121f0ac6a5Smrg * suitability of this software for any purpose.  It is provided "as is"
131f0ac6a5Smrg * without express or implied warranty.
141f0ac6a5Smrg *
151f0ac6a5Smrg * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
161f0ac6a5Smrg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
171f0ac6a5Smrg * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
181f0ac6a5Smrg * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
196fae4e5dSmrg * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
201f0ac6a5Smrg * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
211f0ac6a5Smrg *
221f0ac6a5Smrg * Author:  Keith Packard, SuSE, Inc.
231f0ac6a5Smrg */
241f0ac6a5Smrg
251f0ac6a5Smrg#ifdef HAVE_CONFIG_H
261f0ac6a5Smrg#include <config.h>
271f0ac6a5Smrg#endif
281f0ac6a5Smrg#include "Xrenderint.h"
29190694daSmrg#include <limits.h>
301f0ac6a5Smrg
311f0ac6a5SmrgXRenderExtInfo XRenderExtensionInfo;
321f0ac6a5Smrgchar XRenderExtensionName[] = RENDER_NAME;
331f0ac6a5Smrg
341f0ac6a5Smrgstatic int XRenderCloseDisplay (Display *dpy, XExtCodes *codes);
351f0ac6a5Smrg
361f0ac6a5Smrg/*
371f0ac6a5Smrg * XRenderExtFindDisplay - look for a display in this extension; keeps a
381f0ac6a5Smrg * cache of the most-recently used for efficiency. (Replaces
391f0ac6a5Smrg * XextFindDisplay.)
401f0ac6a5Smrg */
411f0ac6a5Smrgstatic XRenderExtDisplayInfo *
426fae4e5dSmrgXRenderExtFindDisplay (XRenderExtInfo *extinfo,
431f0ac6a5Smrg                       Display        *dpy)
441f0ac6a5Smrg{
451f0ac6a5Smrg    XRenderExtDisplayInfo *dpyinfo;
461f0ac6a5Smrg
471f0ac6a5Smrg    /*
481f0ac6a5Smrg     * see if this was the most recently accessed display
491f0ac6a5Smrg     */
506fae4e5dSmrg    if ((dpyinfo = extinfo->cur) && dpyinfo->display == dpy)
511f0ac6a5Smrg        return dpyinfo;
521f0ac6a5Smrg
531f0ac6a5Smrg    /*
541f0ac6a5Smrg     * look for display in list
551f0ac6a5Smrg     */
561f0ac6a5Smrg    _XLockMutex(_Xglobal_lock);
571f0ac6a5Smrg    for (dpyinfo = extinfo->head; dpyinfo; dpyinfo = dpyinfo->next) {
581f0ac6a5Smrg        if (dpyinfo->display == dpy) {
591f0ac6a5Smrg            extinfo->cur = dpyinfo;     /* cache most recently used */
601f0ac6a5Smrg            _XUnlockMutex(_Xglobal_lock);
611f0ac6a5Smrg            return dpyinfo;
621f0ac6a5Smrg        }
631f0ac6a5Smrg    }
641f0ac6a5Smrg    _XUnlockMutex(_Xglobal_lock);
651f0ac6a5Smrg
661f0ac6a5Smrg    return NULL;
671f0ac6a5Smrg}
681f0ac6a5Smrg
691f0ac6a5Smrg/*
701f0ac6a5Smrg * If the server is missing support for any of the required depths on
711f0ac6a5Smrg * any screen, tell the application that Render is not present.
721f0ac6a5Smrg */
731f0ac6a5Smrg
746fae4e5dSmrg#define DEPTH_MASK(d)	(1U << ((d) - 1))
756fae4e5dSmrg
761f0ac6a5Smrg/*
771f0ac6a5Smrg * Render requires support for depth 1, 4, 8, 24 and 32 pixmaps
781f0ac6a5Smrg */
791f0ac6a5Smrg
801f0ac6a5Smrg#define REQUIRED_DEPTHS	(DEPTH_MASK(1) | \
811f0ac6a5Smrg			 DEPTH_MASK(4) | \
821f0ac6a5Smrg			 DEPTH_MASK(8) | \
831f0ac6a5Smrg			 DEPTH_MASK(24) | \
841f0ac6a5Smrg			 DEPTH_MASK(32))
856fae4e5dSmrg
861f0ac6a5Smrgtypedef struct _DepthCheckRec {
871f0ac6a5Smrg    struct _DepthCheckRec *next;
881f0ac6a5Smrg    Display *dpy;
891f0ac6a5Smrg    CARD32  missing;
901f0ac6a5Smrg    unsigned long serial;
911f0ac6a5Smrg} DepthCheckRec, *DepthCheckPtr;
921f0ac6a5Smrg
931f0ac6a5Smrgstatic DepthCheckPtr	depthChecks;
941f0ac6a5Smrg
951f0ac6a5Smrgstatic int
961f0ac6a5SmrgXRenderDepthCheckErrorHandler (Display *dpy, XErrorEvent *evt)
971f0ac6a5Smrg{
981f0ac6a5Smrg    if (evt->request_code == X_CreatePixmap && evt->error_code == BadValue)
991f0ac6a5Smrg    {
1001f0ac6a5Smrg	DepthCheckPtr	d;
1011f0ac6a5Smrg	_XLockMutex(_Xglobal_lock);
1021f0ac6a5Smrg	for (d = depthChecks; d; d = d->next)
1031f0ac6a5Smrg	    if (d->dpy == dpy)
1041f0ac6a5Smrg	    {
1051f0ac6a5Smrg		if ((long) (evt->serial - d->serial) >= 0)
1061f0ac6a5Smrg		    d->missing |= DEPTH_MASK(evt->resourceid);
1071f0ac6a5Smrg		break;
1081f0ac6a5Smrg	    }
1091f0ac6a5Smrg	_XUnlockMutex (_Xglobal_lock);
1101f0ac6a5Smrg    }
1111f0ac6a5Smrg    return 0;
1121f0ac6a5Smrg}
1131f0ac6a5Smrg
1141f0ac6a5Smrgstatic Bool
1151f0ac6a5SmrgXRenderHasDepths (Display *dpy)
1161f0ac6a5Smrg{
1171f0ac6a5Smrg    int	s;
1181f0ac6a5Smrg
1191f0ac6a5Smrg    for (s = 0; s < ScreenCount (dpy); s++)
1201f0ac6a5Smrg    {
1211f0ac6a5Smrg	CARD32		    depths = 0;
1221f0ac6a5Smrg	CARD32		    missing;
1231f0ac6a5Smrg	Screen		    *scr = ScreenOfDisplay (dpy, s);
1241f0ac6a5Smrg	int		    d;
1251f0ac6a5Smrg
1261f0ac6a5Smrg	for (d = 0; d < scr->ndepths; d++)
1271f0ac6a5Smrg	    depths |= DEPTH_MASK(scr->depths[d].depth);
1281f0ac6a5Smrg	missing = ~depths & REQUIRED_DEPTHS;
1291f0ac6a5Smrg	if (missing)
1301f0ac6a5Smrg	{
1311f0ac6a5Smrg	    DepthCheckRec   dc, **dp;
1321f0ac6a5Smrg	    XErrorHandler   previousHandler;
1331f0ac6a5Smrg
1341f0ac6a5Smrg	    /*
1351f0ac6a5Smrg	     * Ok, this is ugly.  It should be sufficient at this
1361f0ac6a5Smrg	     * point to just return False, but Xinerama is broken at
1371f0ac6a5Smrg	     * this point and only advertises depths which have an
1381f0ac6a5Smrg	     * associated visual.  Of course, the other depths still
1391f0ac6a5Smrg	     * work, but the only way to find out is to try them.
1401f0ac6a5Smrg	     */
1411f0ac6a5Smrg	    dc.dpy = dpy;
1421f0ac6a5Smrg	    dc.missing = 0;
1431f0ac6a5Smrg	    dc.serial = XNextRequest (dpy);
1441f0ac6a5Smrg	    _XLockMutex(_Xglobal_lock);
1451f0ac6a5Smrg	    dc.next = depthChecks;
1461f0ac6a5Smrg	    depthChecks = &dc;
1471f0ac6a5Smrg	    _XUnlockMutex (_Xglobal_lock);
1481f0ac6a5Smrg	    /*
1491f0ac6a5Smrg	     * I suspect this is not really thread safe, but Xlib doesn't
1501f0ac6a5Smrg	     * provide a lot of options here
1511f0ac6a5Smrg	     */
1521f0ac6a5Smrg	    previousHandler = XSetErrorHandler (XRenderDepthCheckErrorHandler);
1531f0ac6a5Smrg	    /*
1541f0ac6a5Smrg	     * Try each missing depth and see if pixmap creation succeeds
1551f0ac6a5Smrg	     */
1561f0ac6a5Smrg	    for (d = 1; d <= 32; d++)
1571f0ac6a5Smrg		/* don't check depth 1 == Xcursor recurses... */
1581f0ac6a5Smrg		if ((missing & DEPTH_MASK(d)) && d != 1)
1591f0ac6a5Smrg		{
1601f0ac6a5Smrg		    Pixmap  p;
1611f0ac6a5Smrg		    p = XCreatePixmap (dpy, RootWindow (dpy, s), 1, 1, d);
1621f0ac6a5Smrg		    XFreePixmap (dpy, p);
1631f0ac6a5Smrg		}
1641f0ac6a5Smrg	    XSync (dpy, False);
1651f0ac6a5Smrg	    XSetErrorHandler (previousHandler);
1661f0ac6a5Smrg	    /*
1671f0ac6a5Smrg	     * Unhook from the list of depth check records
1681f0ac6a5Smrg	     */
1691f0ac6a5Smrg	    _XLockMutex(_Xglobal_lock);
1701f0ac6a5Smrg	    for (dp = &depthChecks; *dp; dp = &(*dp)->next)
1711f0ac6a5Smrg	    {
1721f0ac6a5Smrg		if (*dp == &dc)
1731f0ac6a5Smrg		{
1741f0ac6a5Smrg		    *dp = dc.next;
1751f0ac6a5Smrg		    break;
1761f0ac6a5Smrg		}
1771f0ac6a5Smrg	    }
1781f0ac6a5Smrg	    _XUnlockMutex (_Xglobal_lock);
1791f0ac6a5Smrg	    if (dc.missing)
1801f0ac6a5Smrg		return False;
1811f0ac6a5Smrg	}
1821f0ac6a5Smrg    }
1831f0ac6a5Smrg    return True;
1841f0ac6a5Smrg}
1851f0ac6a5Smrg
1861f0ac6a5Smrg/*
1871f0ac6a5Smrg * XRenderExtAddDisplay - add a display to this extension. (Replaces
1881f0ac6a5Smrg * XextAddDisplay)
1891f0ac6a5Smrg */
1901f0ac6a5Smrgstatic XRenderExtDisplayInfo *
1911f0ac6a5SmrgXRenderExtAddDisplay (XRenderExtInfo *extinfo,
1921f0ac6a5Smrg                      Display        *dpy,
1931f0ac6a5Smrg                      char           *ext_name)
1941f0ac6a5Smrg{
1951f0ac6a5Smrg    XRenderExtDisplayInfo *dpyinfo;
1961f0ac6a5Smrg
1971f0ac6a5Smrg    dpyinfo = (XRenderExtDisplayInfo *) Xmalloc (sizeof (XRenderExtDisplayInfo));
1981f0ac6a5Smrg    if (!dpyinfo) return NULL;
1991f0ac6a5Smrg    dpyinfo->display = dpy;
2001f0ac6a5Smrg    dpyinfo->info = NULL;
2011f0ac6a5Smrg
2021f0ac6a5Smrg    if (XRenderHasDepths (dpy))
2031f0ac6a5Smrg	dpyinfo->codes = XInitExtension (dpy, ext_name);
2041f0ac6a5Smrg    else
2051f0ac6a5Smrg	dpyinfo->codes = NULL;
2061f0ac6a5Smrg
2071f0ac6a5Smrg    /*
2086fae4e5dSmrg     * if the server has the extension, then we can initialize the
2091f0ac6a5Smrg     * appropriate function vectors
2101f0ac6a5Smrg     */
2111f0ac6a5Smrg    if (dpyinfo->codes) {
2126fae4e5dSmrg        XESetCloseDisplay (dpy, dpyinfo->codes->extension,
2131f0ac6a5Smrg                           XRenderCloseDisplay);
2141f0ac6a5Smrg    } else {
2151f0ac6a5Smrg	/* The server doesn't have this extension.
2161f0ac6a5Smrg	 * Use a private Xlib-internal extension to hang the close_display
2171f0ac6a5Smrg	 * hook on so that the "cache" (extinfo->cur) is properly cleaned.
2181f0ac6a5Smrg	 * (XBUG 7955)
2191f0ac6a5Smrg	 */
2201f0ac6a5Smrg	XExtCodes *codes = XAddExtension(dpy);
2211f0ac6a5Smrg	if (!codes) {
2221f0ac6a5Smrg	    XFree(dpyinfo);
2231f0ac6a5Smrg	    return NULL;
2241f0ac6a5Smrg	}
2251f0ac6a5Smrg        XESetCloseDisplay (dpy, codes->extension, XRenderCloseDisplay);
2261f0ac6a5Smrg    }
2271f0ac6a5Smrg
2281f0ac6a5Smrg    /*
2291f0ac6a5Smrg     * now, chain it onto the list
2301f0ac6a5Smrg     */
2311f0ac6a5Smrg    _XLockMutex(_Xglobal_lock);
2321f0ac6a5Smrg    dpyinfo->next = extinfo->head;
2331f0ac6a5Smrg    extinfo->head = dpyinfo;
2341f0ac6a5Smrg    extinfo->cur = dpyinfo;
2351f0ac6a5Smrg    extinfo->ndisplays++;
2361f0ac6a5Smrg    _XUnlockMutex(_Xglobal_lock);
2371f0ac6a5Smrg    return dpyinfo;
2381f0ac6a5Smrg}
2391f0ac6a5Smrg
2401f0ac6a5Smrg
2411f0ac6a5Smrg/*
2421f0ac6a5Smrg * XRenderExtRemoveDisplay - remove the indicated display from the
2431f0ac6a5Smrg * extension object. (Replaces XextRemoveDisplay.)
2441f0ac6a5Smrg */
2456fae4e5dSmrgstatic int
2461f0ac6a5SmrgXRenderExtRemoveDisplay (XRenderExtInfo *extinfo, Display *dpy)
2471f0ac6a5Smrg{
2481f0ac6a5Smrg    XRenderExtDisplayInfo *dpyinfo, *prev;
2491f0ac6a5Smrg
2501f0ac6a5Smrg    /*
2511f0ac6a5Smrg     * locate this display and its back link so that it can be removed
2521f0ac6a5Smrg     */
2531f0ac6a5Smrg    _XLockMutex(_Xglobal_lock);
2541f0ac6a5Smrg    prev = NULL;
2551f0ac6a5Smrg    for (dpyinfo = extinfo->head; dpyinfo; dpyinfo = dpyinfo->next) {
2561f0ac6a5Smrg	if (dpyinfo->display == dpy) break;
2571f0ac6a5Smrg	prev = dpyinfo;
2581f0ac6a5Smrg    }
2591f0ac6a5Smrg    if (!dpyinfo) {
2601f0ac6a5Smrg	_XUnlockMutex(_Xglobal_lock);
2611f0ac6a5Smrg	return 0;		/* hmm, actually an error */
2621f0ac6a5Smrg    }
2631f0ac6a5Smrg
2641f0ac6a5Smrg    /*
2651f0ac6a5Smrg     * remove the display from the list; handles going to zero
2661f0ac6a5Smrg     */
2671f0ac6a5Smrg    if (prev)
2681f0ac6a5Smrg	prev->next = dpyinfo->next;
2691f0ac6a5Smrg    else
2701f0ac6a5Smrg	extinfo->head = dpyinfo->next;
2711f0ac6a5Smrg
2721f0ac6a5Smrg    extinfo->ndisplays--;
2731f0ac6a5Smrg    if (dpyinfo == extinfo->cur) extinfo->cur = NULL;  /* flush cache */
2741f0ac6a5Smrg    _XUnlockMutex(_Xglobal_lock);
2751f0ac6a5Smrg
2761f0ac6a5Smrg    Xfree ((char *) dpyinfo);
2771f0ac6a5Smrg    return 1;
2781f0ac6a5Smrg}
2791f0ac6a5Smrg
2801f0ac6a5Smrg
2811f0ac6a5Smrg
2821f0ac6a5SmrgXRenderExtDisplayInfo *
2831f0ac6a5SmrgXRenderFindDisplay (Display *dpy)
2841f0ac6a5Smrg{
2851f0ac6a5Smrg    XRenderExtDisplayInfo *dpyinfo;
2861f0ac6a5Smrg
2871f0ac6a5Smrg    dpyinfo = XRenderExtFindDisplay (&XRenderExtensionInfo, dpy);
2881f0ac6a5Smrg    if (!dpyinfo)
2896fae4e5dSmrg	dpyinfo = XRenderExtAddDisplay (&XRenderExtensionInfo, dpy,
2901f0ac6a5Smrg                                        XRenderExtensionName);
2911f0ac6a5Smrg    return dpyinfo;
2921f0ac6a5Smrg}
2931f0ac6a5Smrg
2941f0ac6a5Smrgstatic int
2951f0ac6a5SmrgXRenderCloseDisplay (Display *dpy, XExtCodes *codes)
2961f0ac6a5Smrg{
2971f0ac6a5Smrg    XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
2981f0ac6a5Smrg    if (info && info->info) XFree (info->info);
2996fae4e5dSmrg
3001f0ac6a5Smrg    return XRenderExtRemoveDisplay (&XRenderExtensionInfo, dpy);
3011f0ac6a5Smrg}
3026fae4e5dSmrg
3031f0ac6a5Smrg/****************************************************************************
3041f0ac6a5Smrg *                                                                          *
3051f0ac6a5Smrg *			    Render public interfaces                        *
3061f0ac6a5Smrg *                                                                          *
3071f0ac6a5Smrg ****************************************************************************/
3081f0ac6a5Smrg
3091f0ac6a5SmrgBool XRenderQueryExtension (Display *dpy, int *event_basep, int *error_basep)
3101f0ac6a5Smrg{
3111f0ac6a5Smrg    XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
3121f0ac6a5Smrg
3131f0ac6a5Smrg    if (RenderHasExtension(info)) {
3141f0ac6a5Smrg	*event_basep = info->codes->first_event;
3151f0ac6a5Smrg	*error_basep = info->codes->first_error;
3161f0ac6a5Smrg	return True;
3171f0ac6a5Smrg    } else {
3181f0ac6a5Smrg	return False;
3191f0ac6a5Smrg    }
3201f0ac6a5Smrg}
3211f0ac6a5Smrg
3221f0ac6a5Smrg
3231f0ac6a5SmrgStatus XRenderQueryVersion (Display *dpy,
3241f0ac6a5Smrg			    int	    *major_versionp,
3251f0ac6a5Smrg			    int	    *minor_versionp)
3261f0ac6a5Smrg{
3271f0ac6a5Smrg    XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
3281f0ac6a5Smrg    XRenderInfo	    *xri;
3291f0ac6a5Smrg
3301f0ac6a5Smrg    if (!RenderHasExtension (info))
3311f0ac6a5Smrg	return 0;
3321f0ac6a5Smrg
3331f0ac6a5Smrg    if (!XRenderQueryFormats (dpy))
3341f0ac6a5Smrg	return 0;
3356fae4e5dSmrg
3366fae4e5dSmrg    xri = info->info;
3371f0ac6a5Smrg    *major_versionp = xri->major_version;
3381f0ac6a5Smrg    *minor_versionp = xri->minor_version;
3391f0ac6a5Smrg    return 1;
3401f0ac6a5Smrg}
3411f0ac6a5Smrg
3421f0ac6a5Smrgstatic XRenderPictFormat *
3431f0ac6a5Smrg_XRenderFindFormat (XRenderInfo *xri, PictFormat format)
3441f0ac6a5Smrg{
3451f0ac6a5Smrg    int	nf;
3466fae4e5dSmrg
3471f0ac6a5Smrg    for (nf = 0; nf < xri->nformat; nf++)
3481f0ac6a5Smrg	if (xri->format[nf].id == format)
3491f0ac6a5Smrg	    return &xri->format[nf];
350e5410a46Smrg    return NULL;
3511f0ac6a5Smrg}
3521f0ac6a5Smrg
3531f0ac6a5Smrgstatic Visual *
3541f0ac6a5Smrg_XRenderFindVisual (Display *dpy, VisualID vid)
3551f0ac6a5Smrg{
3561f0ac6a5Smrg    return _XVIDtoVisual (dpy, vid);
3571f0ac6a5Smrg}
3581f0ac6a5Smrg
3591f0ac6a5Smrgtypedef struct _renderVersionState {
3601f0ac6a5Smrg    unsigned long   version_seq;
3611f0ac6a5Smrg    Bool	    error;
3621f0ac6a5Smrg    int		    major_version;
3631f0ac6a5Smrg    int		    minor_version;
3646fae4e5dSmrg
3651f0ac6a5Smrg} _XrenderVersionState;
3661f0ac6a5Smrg
3671f0ac6a5Smrgstatic Bool
3681f0ac6a5Smrg_XRenderVersionHandler (Display	    *dpy,
3691f0ac6a5Smrg			xReply	    *rep,
3701f0ac6a5Smrg			char	    *buf,
3711f0ac6a5Smrg			int	    len,
3721f0ac6a5Smrg			XPointer    data)
3731f0ac6a5Smrg{
3741f0ac6a5Smrg    xRenderQueryVersionReply	replbuf;
3751f0ac6a5Smrg    xRenderQueryVersionReply	*repl;
3761f0ac6a5Smrg    _XrenderVersionState	*state = (_XrenderVersionState *) data;
3771f0ac6a5Smrg
3781f0ac6a5Smrg    if (dpy->last_request_read != state->version_seq)
3791f0ac6a5Smrg	return False;
3801f0ac6a5Smrg    if (rep->generic.type == X_Error)
3811f0ac6a5Smrg    {
3821f0ac6a5Smrg	state->error = True;
3831f0ac6a5Smrg	return False;
3841f0ac6a5Smrg    }
3851f0ac6a5Smrg    repl = (xRenderQueryVersionReply *)
3861f0ac6a5Smrg	_XGetAsyncReply(dpy, (char *)&replbuf, rep, buf, len,
3871f0ac6a5Smrg		     (SIZEOF(xRenderQueryVersionReply) - SIZEOF(xReply)) >> 2,
3881f0ac6a5Smrg			True);
3891f0ac6a5Smrg    state->major_version = repl->majorVersion;
3901f0ac6a5Smrg    state->minor_version = repl->minorVersion;
3911f0ac6a5Smrg    return True;
3921f0ac6a5Smrg}
3931f0ac6a5Smrg
3941f0ac6a5SmrgStatus
3951f0ac6a5SmrgXRenderQueryFormats (Display *dpy)
3961f0ac6a5Smrg{
3971f0ac6a5Smrg    XRenderExtDisplayInfo		*info = XRenderFindDisplay (dpy);
3981f0ac6a5Smrg    _XAsyncHandler		async;
3991f0ac6a5Smrg    _XrenderVersionState	async_state;
4001f0ac6a5Smrg    xRenderQueryVersionReq	*vreq;
4011f0ac6a5Smrg    xRenderQueryPictFormatsReply rep;
4021f0ac6a5Smrg    xRenderQueryPictFormatsReq  *req;
4031f0ac6a5Smrg    XRenderInfo			*xri;
4041f0ac6a5Smrg    XRenderPictFormat		*format;
4051f0ac6a5Smrg    XRenderScreen		*screen;
4061f0ac6a5Smrg    XRenderDepth		*depth;
4071f0ac6a5Smrg    XRenderVisual		*visual;
4081f0ac6a5Smrg    xPictFormInfo		*xFormat;
4091f0ac6a5Smrg    xPictScreen			*xScreen;
4101f0ac6a5Smrg    xPictDepth			*xDepth;
4111f0ac6a5Smrg    xPictVisual			*xVisual;
4121f0ac6a5Smrg    CARD32			*xSubpixel;
4131f0ac6a5Smrg    void			*xData;
4141f0ac6a5Smrg    int				nf, ns, nd, nv;
415190694daSmrg    unsigned long		rlength;
416190694daSmrg    unsigned long		nbytes;
4176fae4e5dSmrg
4181f0ac6a5Smrg    RenderCheckExtension (dpy, info, 0);
4191f0ac6a5Smrg    LockDisplay (dpy);
4201f0ac6a5Smrg    if (info->info)
4211f0ac6a5Smrg    {
4221f0ac6a5Smrg	UnlockDisplay (dpy);
4231f0ac6a5Smrg	return 1;
4241f0ac6a5Smrg    }
4251f0ac6a5Smrg    GetReq (RenderQueryVersion, vreq);
4261f0ac6a5Smrg    vreq->reqType = info->codes->major_opcode;
4271f0ac6a5Smrg    vreq->renderReqType = X_RenderQueryVersion;
4281f0ac6a5Smrg    vreq->majorVersion = RENDER_MAJOR;
4291f0ac6a5Smrg    vreq->minorVersion = RENDER_MINOR;
4306fae4e5dSmrg
4311f0ac6a5Smrg    async_state.version_seq = dpy->request;
4321f0ac6a5Smrg    async_state.error = False;
4331f0ac6a5Smrg    async.next = dpy->async_handlers;
4341f0ac6a5Smrg    async.handler = _XRenderVersionHandler;
4351f0ac6a5Smrg    async.data = (XPointer) &async_state;
4361f0ac6a5Smrg    dpy->async_handlers = &async;
4376fae4e5dSmrg
4381f0ac6a5Smrg    GetReq (RenderQueryPictFormats, req);
4391f0ac6a5Smrg    req->reqType = info->codes->major_opcode;
4401f0ac6a5Smrg    req->renderReqType = X_RenderQueryPictFormats;
4416fae4e5dSmrg
4426fae4e5dSmrg    if (!_XReply (dpy, (xReply *) &rep, 0, xFalse))
4431f0ac6a5Smrg    {
4441f0ac6a5Smrg	DeqAsyncHandler (dpy, &async);
4451f0ac6a5Smrg	UnlockDisplay (dpy);
4461f0ac6a5Smrg	SyncHandle ();
4471f0ac6a5Smrg	return 0;
4481f0ac6a5Smrg    }
4491f0ac6a5Smrg    DeqAsyncHandler (dpy, &async);
4501f0ac6a5Smrg    if (async_state.error)
4511f0ac6a5Smrg    {
4521f0ac6a5Smrg	UnlockDisplay(dpy);
4531f0ac6a5Smrg	SyncHandle();
4541f0ac6a5Smrg	return 0;
4551f0ac6a5Smrg    }
4561f0ac6a5Smrg    /*
4571f0ac6a5Smrg     * Check for the lack of sub-pixel data
4581f0ac6a5Smrg     */
4591f0ac6a5Smrg    if (async_state.major_version == 0 && async_state.minor_version < 6)
4601f0ac6a5Smrg	rep.numSubpixel = 0;
4616fae4e5dSmrg
462190694daSmrg    if ((rep.numFormats < ((INT_MAX / 4) / sizeof (XRenderPictFormat))) &&
463190694daSmrg	(rep.numScreens < ((INT_MAX / 4) / sizeof (XRenderScreen))) &&
464190694daSmrg	(rep.numDepths  < ((INT_MAX / 4) / sizeof (XRenderDepth))) &&
465190694daSmrg	(rep.numVisuals < ((INT_MAX / 4) / sizeof (XRenderVisual))) &&
466190694daSmrg	(rep.numSubpixel < ((INT_MAX / 4) / 4)) &&
467190694daSmrg	(rep.length < (INT_MAX >> 2)) ) {
468190694daSmrg	xri = Xmalloc (sizeof (XRenderInfo) +
469190694daSmrg		       (rep.numFormats * sizeof (XRenderPictFormat)) +
470190694daSmrg		       (rep.numScreens * sizeof (XRenderScreen)) +
471190694daSmrg		       (rep.numDepths * sizeof (XRenderDepth)) +
472190694daSmrg		       (rep.numVisuals * sizeof (XRenderVisual)));
473190694daSmrg	rlength = ((rep.numFormats * sizeof (xPictFormInfo)) +
474190694daSmrg		   (rep.numScreens * sizeof (xPictScreen)) +
475190694daSmrg		   (rep.numDepths * sizeof (xPictDepth)) +
476190694daSmrg		   (rep.numVisuals * sizeof (xPictVisual)) +
477190694daSmrg		   (rep.numSubpixel * 4));
478190694daSmrg	xData = Xmalloc (rlength);
479190694daSmrg	nbytes = (unsigned long) rep.length << 2;
480190694daSmrg    } else {
481190694daSmrg	xri = NULL;
482190694daSmrg	xData = NULL;
483190694daSmrg	rlength = nbytes = 0;
484190694daSmrg    }
4856fae4e5dSmrg
4861f0ac6a5Smrg    if (!xri || !xData || nbytes < rlength)
4871f0ac6a5Smrg    {
4881f0ac6a5Smrg	if (xri) Xfree (xri);
4891f0ac6a5Smrg	if (xData) Xfree (xData);
4901f0ac6a5Smrg	_XEatData (dpy, nbytes);
4911f0ac6a5Smrg	UnlockDisplay (dpy);
4921f0ac6a5Smrg	SyncHandle ();
4931f0ac6a5Smrg	return 0;
4941f0ac6a5Smrg    }
4951f0ac6a5Smrg    xri->major_version = async_state.major_version;
4961f0ac6a5Smrg    xri->minor_version = async_state.minor_version;
4971f0ac6a5Smrg    xri->format = (XRenderPictFormat *) (xri + 1);
4981f0ac6a5Smrg    xri->nformat = rep.numFormats;
4991f0ac6a5Smrg    xri->screen = (XRenderScreen *) (xri->format + rep.numFormats);
5001f0ac6a5Smrg    xri->nscreen = rep.numScreens;
5011f0ac6a5Smrg    xri->depth = (XRenderDepth *) (xri->screen + rep.numScreens);
5021f0ac6a5Smrg    xri->ndepth = rep.numDepths;
5031f0ac6a5Smrg    xri->visual = (XRenderVisual *) (xri->depth + rep.numDepths);
5041f0ac6a5Smrg    xri->nvisual = rep.numVisuals;
5051f0ac6a5Smrg    _XRead (dpy, (char *) xData, rlength);
5061f0ac6a5Smrg    format = xri->format;
5071f0ac6a5Smrg    xFormat = (xPictFormInfo *) xData;
5081f0ac6a5Smrg    for (nf = 0; nf < rep.numFormats; nf++)
5091f0ac6a5Smrg    {
5101f0ac6a5Smrg	format->id = xFormat->id;
5111f0ac6a5Smrg	format->type = xFormat->type;
5121f0ac6a5Smrg	format->depth = xFormat->depth;
5131f0ac6a5Smrg	format->direct.red = xFormat->direct.red;
5141f0ac6a5Smrg	format->direct.redMask = xFormat->direct.redMask;
5151f0ac6a5Smrg	format->direct.green = xFormat->direct.green;
5161f0ac6a5Smrg	format->direct.greenMask = xFormat->direct.greenMask;
5171f0ac6a5Smrg	format->direct.blue = xFormat->direct.blue;
5181f0ac6a5Smrg	format->direct.blueMask = xFormat->direct.blueMask;
5191f0ac6a5Smrg	format->direct.alpha = xFormat->direct.alpha;
5201f0ac6a5Smrg	format->direct.alphaMask = xFormat->direct.alphaMask;
5211f0ac6a5Smrg	format->colormap = xFormat->colormap;
5221f0ac6a5Smrg	format++;
5231f0ac6a5Smrg	xFormat++;
5241f0ac6a5Smrg    }
5251f0ac6a5Smrg    xScreen = (xPictScreen *) xFormat;
5261f0ac6a5Smrg    screen = xri->screen;
5271f0ac6a5Smrg    depth = xri->depth;
5281f0ac6a5Smrg    visual = xri->visual;
5291f0ac6a5Smrg    for (ns = 0; ns < xri->nscreen; ns++)
5301f0ac6a5Smrg    {
5311f0ac6a5Smrg	screen->depths = depth;
5321f0ac6a5Smrg	screen->ndepths = xScreen->nDepth;
5331f0ac6a5Smrg	screen->fallback = _XRenderFindFormat (xri, xScreen->fallback);
5341f0ac6a5Smrg	screen->subpixel = SubPixelUnknown;
5351f0ac6a5Smrg	xDepth = (xPictDepth *) (xScreen + 1);
5361f0ac6a5Smrg	for (nd = 0; nd < screen->ndepths; nd++)
5371f0ac6a5Smrg	{
5381f0ac6a5Smrg	    depth->depth = xDepth->depth;
5391f0ac6a5Smrg	    depth->nvisuals = xDepth->nPictVisuals;
5401f0ac6a5Smrg	    depth->visuals = visual;
5411f0ac6a5Smrg	    xVisual = (xPictVisual *) (xDepth + 1);
5421f0ac6a5Smrg	    for (nv = 0; nv < depth->nvisuals; nv++)
5431f0ac6a5Smrg	    {
5441f0ac6a5Smrg		visual->visual = _XRenderFindVisual (dpy, xVisual->visual);
5451f0ac6a5Smrg		visual->format = _XRenderFindFormat (xri, xVisual->format);
5461f0ac6a5Smrg		visual++;
5471f0ac6a5Smrg		xVisual++;
5481f0ac6a5Smrg	    }
5491f0ac6a5Smrg	    depth++;
5501f0ac6a5Smrg	    xDepth = (xPictDepth *) xVisual;
5511f0ac6a5Smrg	}
5521f0ac6a5Smrg	screen++;
5536fae4e5dSmrg	xScreen = (xPictScreen *) xDepth;
5541f0ac6a5Smrg    }
5551f0ac6a5Smrg    xSubpixel = (CARD32 *) xScreen;
5561f0ac6a5Smrg    screen = xri->screen;
5571f0ac6a5Smrg    for (ns = 0; ns < rep.numSubpixel; ns++)
5581f0ac6a5Smrg    {
5591f0ac6a5Smrg	screen->subpixel = *xSubpixel;
5601f0ac6a5Smrg	xSubpixel++;
5611f0ac6a5Smrg	screen++;
5621f0ac6a5Smrg    }
5631f0ac6a5Smrg    info->info = xri;
5641f0ac6a5Smrg    /*
5651f0ac6a5Smrg     * Skip any extra data
5661f0ac6a5Smrg     */
5671f0ac6a5Smrg    if (nbytes > rlength)
5681f0ac6a5Smrg	_XEatData (dpy, (unsigned long) (nbytes - rlength));
5696fae4e5dSmrg
5701f0ac6a5Smrg    UnlockDisplay (dpy);
5711f0ac6a5Smrg    SyncHandle ();
5721f0ac6a5Smrg    Xfree (xData);
5731f0ac6a5Smrg    return 1;
5741f0ac6a5Smrg}
5751f0ac6a5Smrg
5761f0ac6a5Smrgint
5771f0ac6a5SmrgXRenderQuerySubpixelOrder (Display *dpy, int screen)
5781f0ac6a5Smrg{
5791f0ac6a5Smrg    XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
5801f0ac6a5Smrg    XRenderInfo	    *xri;
5811f0ac6a5Smrg
5821f0ac6a5Smrg    if (!RenderHasExtension (info))
5831f0ac6a5Smrg	return SubPixelUnknown;
5841f0ac6a5Smrg
5851f0ac6a5Smrg    if (!XRenderQueryFormats (dpy))
5861f0ac6a5Smrg	return SubPixelUnknown;
5871f0ac6a5Smrg
5881f0ac6a5Smrg    xri = info->info;
5891f0ac6a5Smrg    return xri->screen[screen].subpixel;
5901f0ac6a5Smrg}
5911f0ac6a5Smrg
5921f0ac6a5SmrgBool
5931f0ac6a5SmrgXRenderSetSubpixelOrder (Display *dpy, int screen, int subpixel)
5941f0ac6a5Smrg{
5951f0ac6a5Smrg    XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
5961f0ac6a5Smrg    XRenderInfo	    *xri;
5971f0ac6a5Smrg
5981f0ac6a5Smrg    if (!RenderHasExtension (info))
5991f0ac6a5Smrg	return False;
6001f0ac6a5Smrg
6011f0ac6a5Smrg    if (!XRenderQueryFormats (dpy))
6021f0ac6a5Smrg	return False;
6031f0ac6a5Smrg
6041f0ac6a5Smrg    xri = info->info;
6051f0ac6a5Smrg    xri->screen[screen].subpixel = subpixel;
6061f0ac6a5Smrg    return True;
6071f0ac6a5Smrg}
6081f0ac6a5Smrg
6091f0ac6a5SmrgXRenderPictFormat *
6101f0ac6a5SmrgXRenderFindVisualFormat (Display *dpy, _Xconst Visual *visual)
6111f0ac6a5Smrg{
6121f0ac6a5Smrg    XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
6131f0ac6a5Smrg    int		    nv;
6141f0ac6a5Smrg    XRenderInfo	    *xri;
6151f0ac6a5Smrg    XRenderVisual   *xrv;
616e5410a46Smrg
617e5410a46Smrg    RenderCheckExtension (dpy, info, NULL);
6181f0ac6a5Smrg    if (!XRenderQueryFormats (dpy))
619e5410a46Smrg        return NULL;
6201f0ac6a5Smrg    xri = info->info;
6211f0ac6a5Smrg    for (nv = 0, xrv = xri->visual; nv < xri->nvisual; nv++, xrv++)
6221f0ac6a5Smrg	if (xrv->visual == visual)
6231f0ac6a5Smrg	    return xrv->format;
624e5410a46Smrg    return NULL;
6251f0ac6a5Smrg}
6261f0ac6a5Smrg
6271f0ac6a5SmrgXRenderPictFormat *
6281f0ac6a5SmrgXRenderFindFormat (Display		*dpy,
6291f0ac6a5Smrg		   unsigned long	mask,
6301f0ac6a5Smrg		   _Xconst XRenderPictFormat	*template,
6311f0ac6a5Smrg		   int			count)
6321f0ac6a5Smrg{
6331f0ac6a5Smrg    XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
6341f0ac6a5Smrg    int		    nf;
6351f0ac6a5Smrg    XRenderInfo     *xri;
636e5410a46Smrg
637e5410a46Smrg    RenderCheckExtension (dpy, info, NULL);
6381f0ac6a5Smrg    if (!XRenderQueryFormats (dpy))
639e5410a46Smrg	return NULL;
6401f0ac6a5Smrg    xri = info->info;
6411f0ac6a5Smrg    for (nf = 0; nf < xri->nformat; nf++)
6421f0ac6a5Smrg    {
6431f0ac6a5Smrg	if (mask & PictFormatID)
6441f0ac6a5Smrg	    if (template->id != xri->format[nf].id)
6451f0ac6a5Smrg		continue;
6461f0ac6a5Smrg	if (mask & PictFormatType)
6471f0ac6a5Smrg	if (template->type != xri->format[nf].type)
6481f0ac6a5Smrg		continue;
6491f0ac6a5Smrg	if (mask & PictFormatDepth)
6501f0ac6a5Smrg	    if (template->depth != xri->format[nf].depth)
6511f0ac6a5Smrg		continue;
6521f0ac6a5Smrg	if (mask & PictFormatRed)
6531f0ac6a5Smrg	    if (template->direct.red != xri->format[nf].direct.red)
6541f0ac6a5Smrg		continue;
6551f0ac6a5Smrg	if (mask & PictFormatRedMask)
6561f0ac6a5Smrg	    if (template->direct.redMask != xri->format[nf].direct.redMask)
6571f0ac6a5Smrg		continue;
6581f0ac6a5Smrg	if (mask & PictFormatGreen)
6591f0ac6a5Smrg	    if (template->direct.green != xri->format[nf].direct.green)
6601f0ac6a5Smrg		continue;
6611f0ac6a5Smrg	if (mask & PictFormatGreenMask)
6621f0ac6a5Smrg	    if (template->direct.greenMask != xri->format[nf].direct.greenMask)
6631f0ac6a5Smrg		continue;
6641f0ac6a5Smrg	if (mask & PictFormatBlue)
6651f0ac6a5Smrg	    if (template->direct.blue != xri->format[nf].direct.blue)
6661f0ac6a5Smrg		continue;
6671f0ac6a5Smrg	if (mask & PictFormatBlueMask)
6681f0ac6a5Smrg	    if (template->direct.blueMask != xri->format[nf].direct.blueMask)
6691f0ac6a5Smrg		continue;
6701f0ac6a5Smrg	if (mask & PictFormatAlpha)
6711f0ac6a5Smrg	    if (template->direct.alpha != xri->format[nf].direct.alpha)
6721f0ac6a5Smrg		continue;
6731f0ac6a5Smrg	if (mask & PictFormatAlphaMask)
6741f0ac6a5Smrg	    if (template->direct.alphaMask != xri->format[nf].direct.alphaMask)
6751f0ac6a5Smrg		continue;
6761f0ac6a5Smrg	if (mask & PictFormatColormap)
6771f0ac6a5Smrg	    if (template->colormap != xri->format[nf].colormap)
6781f0ac6a5Smrg		continue;
6791f0ac6a5Smrg	if (count-- == 0)
6801f0ac6a5Smrg	    return &xri->format[nf];
6811f0ac6a5Smrg    }
682e5410a46Smrg    return NULL;
6831f0ac6a5Smrg}
6841f0ac6a5Smrg
6851f0ac6a5SmrgXRenderPictFormat *
6861f0ac6a5SmrgXRenderFindStandardFormat (Display  *dpy,
6871f0ac6a5Smrg			   int	    format)
6881f0ac6a5Smrg{
6891f0ac6a5Smrg    static struct {
6901f0ac6a5Smrg	XRenderPictFormat   templ;
6911f0ac6a5Smrg	unsigned long	    mask;
6921f0ac6a5Smrg    } standardFormats[PictStandardNUM] = {
6931f0ac6a5Smrg	/* PictStandardARGB32 */
6941f0ac6a5Smrg	{
6951f0ac6a5Smrg	    {
6961f0ac6a5Smrg		0,			    /* id */
6971f0ac6a5Smrg		PictTypeDirect,		    /* type */
6981f0ac6a5Smrg		32,			    /* depth */
6991f0ac6a5Smrg		{			    /* direct */
7001f0ac6a5Smrg		    16,			    /* direct.red */
7011f0ac6a5Smrg		    0xff,		    /* direct.redMask */
7021f0ac6a5Smrg		    8,			    /* direct.green */
7031f0ac6a5Smrg		    0xff,		    /* direct.greenMask */
7041f0ac6a5Smrg		    0,			    /* direct.blue */
7051f0ac6a5Smrg		    0xff,		    /* direct.blueMask */
7061f0ac6a5Smrg		    24,			    /* direct.alpha */
7071f0ac6a5Smrg		    0xff,		    /* direct.alphaMask */
7081f0ac6a5Smrg		},
7091f0ac6a5Smrg		0,			    /* colormap */
7101f0ac6a5Smrg	    },
7116fae4e5dSmrg	    PictFormatType |
7121f0ac6a5Smrg	    PictFormatDepth |
7131f0ac6a5Smrg	    PictFormatRed |
7141f0ac6a5Smrg	    PictFormatRedMask |
7151f0ac6a5Smrg	    PictFormatGreen |
7161f0ac6a5Smrg	    PictFormatGreenMask |
7171f0ac6a5Smrg	    PictFormatBlue |
7181f0ac6a5Smrg	    PictFormatBlueMask |
7191f0ac6a5Smrg	    PictFormatAlpha |
7201f0ac6a5Smrg	    PictFormatAlphaMask,
7211f0ac6a5Smrg	},
7221f0ac6a5Smrg	/* PictStandardRGB24 */
7231f0ac6a5Smrg	{
7241f0ac6a5Smrg	    {
7251f0ac6a5Smrg		0,			    /* id */
7261f0ac6a5Smrg		PictTypeDirect,		    /* type */
7271f0ac6a5Smrg		24,			    /* depth */
7281f0ac6a5Smrg		{			    /* direct */
7291f0ac6a5Smrg		    16,			    /* direct.red */
7301f0ac6a5Smrg		    0xff,		    /* direct.redMask */
7311f0ac6a5Smrg		    8,			    /* direct.green */
7321f0ac6a5Smrg		    0xff,		    /* direct.greenMask */
7331f0ac6a5Smrg		    0,			    /* direct.blue */
7341f0ac6a5Smrg		    0xff,		    /* direct.blueMask */
7351f0ac6a5Smrg		    0,			    /* direct.alpha */
7361f0ac6a5Smrg		    0x00,		    /* direct.alphaMask */
7371f0ac6a5Smrg		},
7381f0ac6a5Smrg		0,			    /* colormap */
7391f0ac6a5Smrg	    },
7406fae4e5dSmrg	    PictFormatType |
7411f0ac6a5Smrg	    PictFormatDepth |
7421f0ac6a5Smrg	    PictFormatRed |
7431f0ac6a5Smrg	    PictFormatRedMask |
7441f0ac6a5Smrg	    PictFormatGreen |
7451f0ac6a5Smrg	    PictFormatGreenMask |
7461f0ac6a5Smrg	    PictFormatBlue |
7471f0ac6a5Smrg	    PictFormatBlueMask |
7481f0ac6a5Smrg	    PictFormatAlphaMask,
7491f0ac6a5Smrg	},
7501f0ac6a5Smrg	/* PictStandardA8 */
7511f0ac6a5Smrg	{
7521f0ac6a5Smrg	    {
7531f0ac6a5Smrg		0,			    /* id */
7541f0ac6a5Smrg		PictTypeDirect,		    /* type */
7551f0ac6a5Smrg		8,			    /* depth */
7561f0ac6a5Smrg		{			    /* direct */
7571f0ac6a5Smrg		    0,			    /* direct.red */
7581f0ac6a5Smrg		    0x00,		    /* direct.redMask */
7591f0ac6a5Smrg		    0,			    /* direct.green */
7601f0ac6a5Smrg		    0x00,		    /* direct.greenMask */
7611f0ac6a5Smrg		    0,			    /* direct.blue */
7621f0ac6a5Smrg		    0x00,		    /* direct.blueMask */
7631f0ac6a5Smrg		    0,			    /* direct.alpha */
7641f0ac6a5Smrg		    0xff,		    /* direct.alphaMask */
7651f0ac6a5Smrg		},
7661f0ac6a5Smrg		0,			    /* colormap */
7671f0ac6a5Smrg	    },
7686fae4e5dSmrg	    PictFormatType |
7691f0ac6a5Smrg	    PictFormatDepth |
7701f0ac6a5Smrg	    PictFormatRedMask |
7711f0ac6a5Smrg	    PictFormatGreenMask |
7721f0ac6a5Smrg	    PictFormatBlueMask |
7731f0ac6a5Smrg	    PictFormatAlpha |
7741f0ac6a5Smrg	    PictFormatAlphaMask,
7751f0ac6a5Smrg	},
7761f0ac6a5Smrg	/* PictStandardA4 */
7771f0ac6a5Smrg	{
7781f0ac6a5Smrg	    {
7791f0ac6a5Smrg		0,			    /* id */
7801f0ac6a5Smrg		PictTypeDirect,		    /* type */
7811f0ac6a5Smrg		4,			    /* depth */
7821f0ac6a5Smrg		{			    /* direct */
7831f0ac6a5Smrg		    0,			    /* direct.red */
7841f0ac6a5Smrg		    0x00,		    /* direct.redMask */
7851f0ac6a5Smrg		    0,			    /* direct.green */
7861f0ac6a5Smrg		    0x00,		    /* direct.greenMask */
7871f0ac6a5Smrg		    0,			    /* direct.blue */
7881f0ac6a5Smrg		    0x00,		    /* direct.blueMask */
7891f0ac6a5Smrg		    0,			    /* direct.alpha */
7901f0ac6a5Smrg		    0x0f,		    /* direct.alphaMask */
7911f0ac6a5Smrg		},
7921f0ac6a5Smrg		0,			    /* colormap */
7931f0ac6a5Smrg	    },
7946fae4e5dSmrg	    PictFormatType |
7951f0ac6a5Smrg	    PictFormatDepth |
7961f0ac6a5Smrg	    PictFormatRedMask |
7971f0ac6a5Smrg	    PictFormatGreenMask |
7981f0ac6a5Smrg	    PictFormatBlueMask |
7991f0ac6a5Smrg	    PictFormatAlpha |
8001f0ac6a5Smrg	    PictFormatAlphaMask,
8011f0ac6a5Smrg	},
8021f0ac6a5Smrg	/* PictStandardA1 */
8031f0ac6a5Smrg	{
8041f0ac6a5Smrg	    {
8051f0ac6a5Smrg		0,			    /* id */
8061f0ac6a5Smrg		PictTypeDirect,		    /* type */
8071f0ac6a5Smrg		1,			    /* depth */
8081f0ac6a5Smrg		{			    /* direct */
8091f0ac6a5Smrg		    0,			    /* direct.red */
8101f0ac6a5Smrg		    0x00,		    /* direct.redMask */
8111f0ac6a5Smrg		    0,			    /* direct.green */
8121f0ac6a5Smrg		    0x00,		    /* direct.greenMask */
8131f0ac6a5Smrg		    0,			    /* direct.blue */
8141f0ac6a5Smrg		    0x00,		    /* direct.blueMask */
8151f0ac6a5Smrg		    0,			    /* direct.alpha */
8161f0ac6a5Smrg		    0x01,		    /* direct.alphaMask */
8171f0ac6a5Smrg		},
8181f0ac6a5Smrg		0,			    /* colormap */
8191f0ac6a5Smrg	    },
8206fae4e5dSmrg	    PictFormatType |
8211f0ac6a5Smrg	    PictFormatDepth |
8221f0ac6a5Smrg	    PictFormatRedMask |
8231f0ac6a5Smrg	    PictFormatGreenMask |
8241f0ac6a5Smrg	    PictFormatBlueMask |
8251f0ac6a5Smrg	    PictFormatAlpha |
8261f0ac6a5Smrg	    PictFormatAlphaMask,
8271f0ac6a5Smrg	},
8281f0ac6a5Smrg    };
8291f0ac6a5Smrg
8301f0ac6a5Smrg    if (0 <= format && format < PictStandardNUM)
8316fae4e5dSmrg	return XRenderFindFormat (dpy,
8321f0ac6a5Smrg				  standardFormats[format].mask,
8331f0ac6a5Smrg				  &standardFormats[format].templ,
8341f0ac6a5Smrg				  0);
835e5410a46Smrg    return NULL;
8361f0ac6a5Smrg}
8371f0ac6a5Smrg
8381f0ac6a5SmrgXIndexValue *
8391f0ac6a5SmrgXRenderQueryPictIndexValues(Display			*dpy,
8401f0ac6a5Smrg			    _Xconst XRenderPictFormat	*format,
8411f0ac6a5Smrg			    int				*num)
8421f0ac6a5Smrg{
8431f0ac6a5Smrg    XRenderExtDisplayInfo			*info = XRenderFindDisplay (dpy);
8441f0ac6a5Smrg    xRenderQueryPictIndexValuesReq	*req;
8451f0ac6a5Smrg    xRenderQueryPictIndexValuesReply	rep;
8461f0ac6a5Smrg    XIndexValue				*values;
847190694daSmrg    unsigned int			nbytes, nread, rlength, i;
8481f0ac6a5Smrg
849e5410a46Smrg    RenderCheckExtension (dpy, info, NULL);
8501f0ac6a5Smrg
8511f0ac6a5Smrg    LockDisplay (dpy);
8521f0ac6a5Smrg    GetReq (RenderQueryPictIndexValues, req);
8531f0ac6a5Smrg    req->reqType = info->codes->major_opcode;
8541f0ac6a5Smrg    req->renderReqType = X_RenderQueryPictIndexValues;
8551f0ac6a5Smrg    req->format = format->id;
8561f0ac6a5Smrg    if (!_XReply (dpy, (xReply *) &rep, 0, xFalse))
8571f0ac6a5Smrg    {
8581f0ac6a5Smrg	UnlockDisplay (dpy);
8591f0ac6a5Smrg	SyncHandle ();
860e5410a46Smrg	return NULL;
8611f0ac6a5Smrg    }
8621f0ac6a5Smrg
863190694daSmrg    if ((rep.length < (INT_MAX >> 2)) &&
864190694daSmrg	(rep.numIndexValues < (INT_MAX / sizeof (XIndexValue)))) {
865190694daSmrg	/* request data length */
866190694daSmrg	nbytes = rep.length << 2;
867190694daSmrg	/* bytes of actual data in the request */
868190694daSmrg	nread = rep.numIndexValues * SIZEOF (xIndexValue);
869190694daSmrg	/* size of array returned to application */
870190694daSmrg	rlength = rep.numIndexValues * sizeof (XIndexValue);
871190694daSmrg
872190694daSmrg	/* allocate returned data */
873190694daSmrg	values = Xmalloc (rlength);
874190694daSmrg    } else {
875190694daSmrg	nbytes = nread = rlength = 0;
876190694daSmrg	values = NULL;
877190694daSmrg    }
8781f0ac6a5Smrg
8791f0ac6a5Smrg    if (!values)
8801f0ac6a5Smrg    {
8811f0ac6a5Smrg	_XEatData (dpy, nbytes);
8821f0ac6a5Smrg	UnlockDisplay (dpy);
8831f0ac6a5Smrg	SyncHandle ();
884e5410a46Smrg	return NULL;
8851f0ac6a5Smrg    }
8861f0ac6a5Smrg
8871f0ac6a5Smrg    /* read the values one at a time and convert */
8881f0ac6a5Smrg    *num = rep.numIndexValues;
8891f0ac6a5Smrg    for(i = 0; i < rep.numIndexValues; i++)
8901f0ac6a5Smrg    {
8911f0ac6a5Smrg	xIndexValue value;
8926fae4e5dSmrg
8931f0ac6a5Smrg	_XRead (dpy, (char *) &value, SIZEOF (xIndexValue));
8941f0ac6a5Smrg	values[i].pixel = value.pixel;
8951f0ac6a5Smrg	values[i].red = value.red;
8961f0ac6a5Smrg	values[i].green = value.green;
8971f0ac6a5Smrg	values[i].blue = value.blue;
8981f0ac6a5Smrg	values[i].alpha = value.alpha;
8991f0ac6a5Smrg    }
9001f0ac6a5Smrg    /* skip any padding */
9011f0ac6a5Smrg    if(nbytes > nread)
9021f0ac6a5Smrg    {
9031f0ac6a5Smrg	_XEatData (dpy, (unsigned long) (nbytes - nread));
9041f0ac6a5Smrg    }
9051f0ac6a5Smrg    UnlockDisplay (dpy);
9061f0ac6a5Smrg    SyncHandle ();
9071f0ac6a5Smrg    return values;
9081f0ac6a5Smrg}
909