Xrender.c revision 53bb355a
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;
10153bb355aSmrg
1021f0ac6a5Smrg	_XLockMutex(_Xglobal_lock);
1031f0ac6a5Smrg	for (d = depthChecks; d; d = d->next)
10453bb355aSmrg	{
1051f0ac6a5Smrg	    if (d->dpy == dpy)
1061f0ac6a5Smrg	    {
1071f0ac6a5Smrg		if ((long) (evt->serial - d->serial) >= 0)
1081f0ac6a5Smrg		    d->missing |= DEPTH_MASK(evt->resourceid);
1091f0ac6a5Smrg		break;
1101f0ac6a5Smrg	    }
11153bb355aSmrg        }
1121f0ac6a5Smrg	_XUnlockMutex (_Xglobal_lock);
1131f0ac6a5Smrg    }
1141f0ac6a5Smrg    return 0;
1151f0ac6a5Smrg}
1161f0ac6a5Smrg
1171f0ac6a5Smrgstatic Bool
1181f0ac6a5SmrgXRenderHasDepths (Display *dpy)
1191f0ac6a5Smrg{
1201f0ac6a5Smrg    int	s;
1211f0ac6a5Smrg
1221f0ac6a5Smrg    for (s = 0; s < ScreenCount (dpy); s++)
1231f0ac6a5Smrg    {
1241f0ac6a5Smrg	CARD32		    depths = 0;
1251f0ac6a5Smrg	CARD32		    missing;
1261f0ac6a5Smrg	Screen		    *scr = ScreenOfDisplay (dpy, s);
1271f0ac6a5Smrg	int		    d;
1281f0ac6a5Smrg
1291f0ac6a5Smrg	for (d = 0; d < scr->ndepths; d++)
1301f0ac6a5Smrg	    depths |= DEPTH_MASK(scr->depths[d].depth);
1311f0ac6a5Smrg	missing = ~depths & REQUIRED_DEPTHS;
1321f0ac6a5Smrg	if (missing)
1331f0ac6a5Smrg	{
1341f0ac6a5Smrg	    DepthCheckRec   dc, **dp;
1351f0ac6a5Smrg	    XErrorHandler   previousHandler;
1361f0ac6a5Smrg
1371f0ac6a5Smrg	    /*
1381f0ac6a5Smrg	     * Ok, this is ugly.  It should be sufficient at this
1391f0ac6a5Smrg	     * point to just return False, but Xinerama is broken at
1401f0ac6a5Smrg	     * this point and only advertises depths which have an
1411f0ac6a5Smrg	     * associated visual.  Of course, the other depths still
1421f0ac6a5Smrg	     * work, but the only way to find out is to try them.
1431f0ac6a5Smrg	     */
1441f0ac6a5Smrg	    dc.dpy = dpy;
1451f0ac6a5Smrg	    dc.missing = 0;
1461f0ac6a5Smrg	    dc.serial = XNextRequest (dpy);
1471f0ac6a5Smrg	    _XLockMutex(_Xglobal_lock);
1481f0ac6a5Smrg	    dc.next = depthChecks;
1491f0ac6a5Smrg	    depthChecks = &dc;
1501f0ac6a5Smrg	    _XUnlockMutex (_Xglobal_lock);
1511f0ac6a5Smrg	    /*
1521f0ac6a5Smrg	     * I suspect this is not really thread safe, but Xlib doesn't
1531f0ac6a5Smrg	     * provide a lot of options here
1541f0ac6a5Smrg	     */
1551f0ac6a5Smrg	    previousHandler = XSetErrorHandler (XRenderDepthCheckErrorHandler);
1561f0ac6a5Smrg	    /*
1571f0ac6a5Smrg	     * Try each missing depth and see if pixmap creation succeeds
1581f0ac6a5Smrg	     */
1591f0ac6a5Smrg	    for (d = 1; d <= 32; d++)
1601f0ac6a5Smrg		/* don't check depth 1 == Xcursor recurses... */
1611f0ac6a5Smrg		if ((missing & DEPTH_MASK(d)) && d != 1)
1621f0ac6a5Smrg		{
1631f0ac6a5Smrg		    Pixmap  p;
16453bb355aSmrg		    p = XCreatePixmap (dpy, RootWindow (dpy, s), 1, 1, (unsigned) d);
1651f0ac6a5Smrg		    XFreePixmap (dpy, p);
1661f0ac6a5Smrg		}
1671f0ac6a5Smrg	    XSync (dpy, False);
1681f0ac6a5Smrg	    XSetErrorHandler (previousHandler);
1691f0ac6a5Smrg	    /*
1701f0ac6a5Smrg	     * Unhook from the list of depth check records
1711f0ac6a5Smrg	     */
1721f0ac6a5Smrg	    _XLockMutex(_Xglobal_lock);
1731f0ac6a5Smrg	    for (dp = &depthChecks; *dp; dp = &(*dp)->next)
1741f0ac6a5Smrg	    {
1751f0ac6a5Smrg		if (*dp == &dc)
1761f0ac6a5Smrg		{
1771f0ac6a5Smrg		    *dp = dc.next;
1781f0ac6a5Smrg		    break;
1791f0ac6a5Smrg		}
1801f0ac6a5Smrg	    }
1811f0ac6a5Smrg	    _XUnlockMutex (_Xglobal_lock);
1821f0ac6a5Smrg	    if (dc.missing)
1831f0ac6a5Smrg		return False;
1841f0ac6a5Smrg	}
1851f0ac6a5Smrg    }
1861f0ac6a5Smrg    return True;
1871f0ac6a5Smrg}
1881f0ac6a5Smrg
1891f0ac6a5Smrg/*
1901f0ac6a5Smrg * XRenderExtAddDisplay - add a display to this extension. (Replaces
1911f0ac6a5Smrg * XextAddDisplay)
1921f0ac6a5Smrg */
1931f0ac6a5Smrgstatic XRenderExtDisplayInfo *
1941f0ac6a5SmrgXRenderExtAddDisplay (XRenderExtInfo *extinfo,
1951f0ac6a5Smrg                      Display        *dpy,
1961f0ac6a5Smrg                      char           *ext_name)
1971f0ac6a5Smrg{
1981f0ac6a5Smrg    XRenderExtDisplayInfo *dpyinfo;
1991f0ac6a5Smrg
20053bb355aSmrg    dpyinfo = Xmalloc (sizeof (XRenderExtDisplayInfo));
2011f0ac6a5Smrg    if (!dpyinfo) return NULL;
2021f0ac6a5Smrg    dpyinfo->display = dpy;
2031f0ac6a5Smrg    dpyinfo->info = NULL;
2041f0ac6a5Smrg
2051f0ac6a5Smrg    if (XRenderHasDepths (dpy))
2061f0ac6a5Smrg	dpyinfo->codes = XInitExtension (dpy, ext_name);
2071f0ac6a5Smrg    else
2081f0ac6a5Smrg	dpyinfo->codes = NULL;
2091f0ac6a5Smrg
2101f0ac6a5Smrg    /*
2116fae4e5dSmrg     * if the server has the extension, then we can initialize the
2121f0ac6a5Smrg     * appropriate function vectors
2131f0ac6a5Smrg     */
2141f0ac6a5Smrg    if (dpyinfo->codes) {
2156fae4e5dSmrg        XESetCloseDisplay (dpy, dpyinfo->codes->extension,
2161f0ac6a5Smrg                           XRenderCloseDisplay);
2171f0ac6a5Smrg    } else {
2181f0ac6a5Smrg	/* The server doesn't have this extension.
2191f0ac6a5Smrg	 * Use a private Xlib-internal extension to hang the close_display
2201f0ac6a5Smrg	 * hook on so that the "cache" (extinfo->cur) is properly cleaned.
2211f0ac6a5Smrg	 * (XBUG 7955)
2221f0ac6a5Smrg	 */
2231f0ac6a5Smrg	XExtCodes *codes = XAddExtension(dpy);
2241f0ac6a5Smrg	if (!codes) {
2251f0ac6a5Smrg	    XFree(dpyinfo);
2261f0ac6a5Smrg	    return NULL;
2271f0ac6a5Smrg	}
2281f0ac6a5Smrg        XESetCloseDisplay (dpy, codes->extension, XRenderCloseDisplay);
2291f0ac6a5Smrg    }
2301f0ac6a5Smrg
2311f0ac6a5Smrg    /*
2321f0ac6a5Smrg     * now, chain it onto the list
2331f0ac6a5Smrg     */
2341f0ac6a5Smrg    _XLockMutex(_Xglobal_lock);
2351f0ac6a5Smrg    dpyinfo->next = extinfo->head;
2361f0ac6a5Smrg    extinfo->head = dpyinfo;
2371f0ac6a5Smrg    extinfo->cur = dpyinfo;
2381f0ac6a5Smrg    extinfo->ndisplays++;
2391f0ac6a5Smrg    _XUnlockMutex(_Xglobal_lock);
2401f0ac6a5Smrg    return dpyinfo;
2411f0ac6a5Smrg}
2421f0ac6a5Smrg
2431f0ac6a5Smrg
2441f0ac6a5Smrg/*
2451f0ac6a5Smrg * XRenderExtRemoveDisplay - remove the indicated display from the
2461f0ac6a5Smrg * extension object. (Replaces XextRemoveDisplay.)
2471f0ac6a5Smrg */
2486fae4e5dSmrgstatic int
2491f0ac6a5SmrgXRenderExtRemoveDisplay (XRenderExtInfo *extinfo, Display *dpy)
2501f0ac6a5Smrg{
2511f0ac6a5Smrg    XRenderExtDisplayInfo *dpyinfo, *prev;
2521f0ac6a5Smrg
2531f0ac6a5Smrg    /*
2541f0ac6a5Smrg     * locate this display and its back link so that it can be removed
2551f0ac6a5Smrg     */
2561f0ac6a5Smrg    _XLockMutex(_Xglobal_lock);
2571f0ac6a5Smrg    prev = NULL;
2581f0ac6a5Smrg    for (dpyinfo = extinfo->head; dpyinfo; dpyinfo = dpyinfo->next) {
2591f0ac6a5Smrg	if (dpyinfo->display == dpy) break;
2601f0ac6a5Smrg	prev = dpyinfo;
2611f0ac6a5Smrg    }
2621f0ac6a5Smrg    if (!dpyinfo) {
2631f0ac6a5Smrg	_XUnlockMutex(_Xglobal_lock);
2641f0ac6a5Smrg	return 0;		/* hmm, actually an error */
2651f0ac6a5Smrg    }
2661f0ac6a5Smrg
2671f0ac6a5Smrg    /*
2681f0ac6a5Smrg     * remove the display from the list; handles going to zero
2691f0ac6a5Smrg     */
2701f0ac6a5Smrg    if (prev)
2711f0ac6a5Smrg	prev->next = dpyinfo->next;
2721f0ac6a5Smrg    else
2731f0ac6a5Smrg	extinfo->head = dpyinfo->next;
2741f0ac6a5Smrg
2751f0ac6a5Smrg    extinfo->ndisplays--;
2761f0ac6a5Smrg    if (dpyinfo == extinfo->cur) extinfo->cur = NULL;  /* flush cache */
2771f0ac6a5Smrg    _XUnlockMutex(_Xglobal_lock);
2781f0ac6a5Smrg
27953bb355aSmrg    Xfree (dpyinfo);
2801f0ac6a5Smrg    return 1;
2811f0ac6a5Smrg}
2821f0ac6a5Smrg
2831f0ac6a5Smrg
2841f0ac6a5Smrg
2851f0ac6a5SmrgXRenderExtDisplayInfo *
2861f0ac6a5SmrgXRenderFindDisplay (Display *dpy)
2871f0ac6a5Smrg{
2881f0ac6a5Smrg    XRenderExtDisplayInfo *dpyinfo;
2891f0ac6a5Smrg
2901f0ac6a5Smrg    dpyinfo = XRenderExtFindDisplay (&XRenderExtensionInfo, dpy);
2911f0ac6a5Smrg    if (!dpyinfo)
2926fae4e5dSmrg	dpyinfo = XRenderExtAddDisplay (&XRenderExtensionInfo, dpy,
2931f0ac6a5Smrg                                        XRenderExtensionName);
2941f0ac6a5Smrg    return dpyinfo;
2951f0ac6a5Smrg}
2961f0ac6a5Smrg
2971f0ac6a5Smrgstatic int
29853bb355aSmrgXRenderCloseDisplay (Display *dpy, XExtCodes *codes _X_UNUSED)
2991f0ac6a5Smrg{
3001f0ac6a5Smrg    XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
3011f0ac6a5Smrg    if (info && info->info) XFree (info->info);
3026fae4e5dSmrg
3031f0ac6a5Smrg    return XRenderExtRemoveDisplay (&XRenderExtensionInfo, dpy);
3041f0ac6a5Smrg}
3056fae4e5dSmrg
3061f0ac6a5Smrg/****************************************************************************
3071f0ac6a5Smrg *                                                                          *
3081f0ac6a5Smrg *			    Render public interfaces                        *
3091f0ac6a5Smrg *                                                                          *
3101f0ac6a5Smrg ****************************************************************************/
3111f0ac6a5Smrg
3121f0ac6a5SmrgBool XRenderQueryExtension (Display *dpy, int *event_basep, int *error_basep)
3131f0ac6a5Smrg{
3141f0ac6a5Smrg    XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
3151f0ac6a5Smrg
3161f0ac6a5Smrg    if (RenderHasExtension(info)) {
3171f0ac6a5Smrg	*event_basep = info->codes->first_event;
3181f0ac6a5Smrg	*error_basep = info->codes->first_error;
3191f0ac6a5Smrg	return True;
3201f0ac6a5Smrg    } else {
3211f0ac6a5Smrg	return False;
3221f0ac6a5Smrg    }
3231f0ac6a5Smrg}
3241f0ac6a5Smrg
3251f0ac6a5Smrg
3261f0ac6a5SmrgStatus XRenderQueryVersion (Display *dpy,
3271f0ac6a5Smrg			    int	    *major_versionp,
3281f0ac6a5Smrg			    int	    *minor_versionp)
3291f0ac6a5Smrg{
3301f0ac6a5Smrg    XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
3311f0ac6a5Smrg    XRenderInfo	    *xri;
3321f0ac6a5Smrg
3331f0ac6a5Smrg    if (!RenderHasExtension (info))
3341f0ac6a5Smrg	return 0;
3351f0ac6a5Smrg
3361f0ac6a5Smrg    if (!XRenderQueryFormats (dpy))
3371f0ac6a5Smrg	return 0;
3386fae4e5dSmrg
3396fae4e5dSmrg    xri = info->info;
3401f0ac6a5Smrg    *major_versionp = xri->major_version;
3411f0ac6a5Smrg    *minor_versionp = xri->minor_version;
3421f0ac6a5Smrg    return 1;
3431f0ac6a5Smrg}
3441f0ac6a5Smrg
3451f0ac6a5Smrgstatic XRenderPictFormat *
3461f0ac6a5Smrg_XRenderFindFormat (XRenderInfo *xri, PictFormat format)
3471f0ac6a5Smrg{
3481f0ac6a5Smrg    int	nf;
3496fae4e5dSmrg
3501f0ac6a5Smrg    for (nf = 0; nf < xri->nformat; nf++)
3511f0ac6a5Smrg	if (xri->format[nf].id == format)
3521f0ac6a5Smrg	    return &xri->format[nf];
353e5410a46Smrg    return NULL;
3541f0ac6a5Smrg}
3551f0ac6a5Smrg
3561f0ac6a5Smrgstatic Visual *
3571f0ac6a5Smrg_XRenderFindVisual (Display *dpy, VisualID vid)
3581f0ac6a5Smrg{
3591f0ac6a5Smrg    return _XVIDtoVisual (dpy, vid);
3601f0ac6a5Smrg}
3611f0ac6a5Smrg
3621f0ac6a5Smrgtypedef struct _renderVersionState {
3631f0ac6a5Smrg    unsigned long   version_seq;
3641f0ac6a5Smrg    Bool	    error;
3651f0ac6a5Smrg    int		    major_version;
3661f0ac6a5Smrg    int		    minor_version;
3676fae4e5dSmrg
3681f0ac6a5Smrg} _XrenderVersionState;
3691f0ac6a5Smrg
3701f0ac6a5Smrgstatic Bool
3711f0ac6a5Smrg_XRenderVersionHandler (Display	    *dpy,
3721f0ac6a5Smrg			xReply	    *rep,
3731f0ac6a5Smrg			char	    *buf,
3741f0ac6a5Smrg			int	    len,
3751f0ac6a5Smrg			XPointer    data)
3761f0ac6a5Smrg{
3771f0ac6a5Smrg    xRenderQueryVersionReply	replbuf;
3781f0ac6a5Smrg    xRenderQueryVersionReply	*repl;
3791f0ac6a5Smrg    _XrenderVersionState	*state = (_XrenderVersionState *) data;
3801f0ac6a5Smrg
3811f0ac6a5Smrg    if (dpy->last_request_read != state->version_seq)
3821f0ac6a5Smrg	return False;
3831f0ac6a5Smrg    if (rep->generic.type == X_Error)
3841f0ac6a5Smrg    {
3851f0ac6a5Smrg	state->error = True;
3861f0ac6a5Smrg	return False;
3871f0ac6a5Smrg    }
3881f0ac6a5Smrg    repl = (xRenderQueryVersionReply *)
3891f0ac6a5Smrg	_XGetAsyncReply(dpy, (char *)&replbuf, rep, buf, len,
3901f0ac6a5Smrg		     (SIZEOF(xRenderQueryVersionReply) - SIZEOF(xReply)) >> 2,
3911f0ac6a5Smrg			True);
39253bb355aSmrg    state->major_version = (int) repl->majorVersion;
39353bb355aSmrg    state->minor_version = (int) repl->minorVersion;
3941f0ac6a5Smrg    return True;
3951f0ac6a5Smrg}
3961f0ac6a5Smrg
3971f0ac6a5SmrgStatus
3981f0ac6a5SmrgXRenderQueryFormats (Display *dpy)
3991f0ac6a5Smrg{
40053bb355aSmrg    XRenderExtDisplayInfo	*info = XRenderFindDisplay (dpy);
4011f0ac6a5Smrg    _XAsyncHandler		async;
4021f0ac6a5Smrg    _XrenderVersionState	async_state;
4031f0ac6a5Smrg    xRenderQueryVersionReq	*vreq;
4041f0ac6a5Smrg    xRenderQueryPictFormatsReply rep;
4051f0ac6a5Smrg    xRenderQueryPictFormatsReq  *req;
4061f0ac6a5Smrg    XRenderInfo			*xri;
4071f0ac6a5Smrg    XRenderPictFormat		*format;
4081f0ac6a5Smrg    XRenderScreen		*screen;
4091f0ac6a5Smrg    XRenderDepth		*depth;
4101f0ac6a5Smrg    XRenderVisual		*visual;
4111f0ac6a5Smrg    xPictFormInfo		*xFormat;
4121f0ac6a5Smrg    xPictScreen			*xScreen;
41353bb355aSmrg    xPictDepth			*xPDepth;
4141f0ac6a5Smrg    xPictVisual			*xVisual;
4151f0ac6a5Smrg    CARD32			*xSubpixel;
4161f0ac6a5Smrg    void			*xData;
41753bb355aSmrg    int				ns, nd;
41853bb355aSmrg    unsigned			nf;
419190694daSmrg    unsigned long		rlength;
420190694daSmrg    unsigned long		nbytes;
4216fae4e5dSmrg
4221f0ac6a5Smrg    RenderCheckExtension (dpy, info, 0);
4231f0ac6a5Smrg    LockDisplay (dpy);
4241f0ac6a5Smrg    if (info->info)
4251f0ac6a5Smrg    {
4261f0ac6a5Smrg	UnlockDisplay (dpy);
4271f0ac6a5Smrg	return 1;
4281f0ac6a5Smrg    }
4291f0ac6a5Smrg    GetReq (RenderQueryVersion, vreq);
43053bb355aSmrg    vreq->reqType = (CARD8) info->codes->major_opcode;
4311f0ac6a5Smrg    vreq->renderReqType = X_RenderQueryVersion;
4321f0ac6a5Smrg    vreq->majorVersion = RENDER_MAJOR;
4331f0ac6a5Smrg    vreq->minorVersion = RENDER_MINOR;
4346fae4e5dSmrg
4351f0ac6a5Smrg    async_state.version_seq = dpy->request;
4361f0ac6a5Smrg    async_state.error = False;
4371f0ac6a5Smrg    async.next = dpy->async_handlers;
4381f0ac6a5Smrg    async.handler = _XRenderVersionHandler;
4391f0ac6a5Smrg    async.data = (XPointer) &async_state;
4401f0ac6a5Smrg    dpy->async_handlers = &async;
4416fae4e5dSmrg
4421f0ac6a5Smrg    GetReq (RenderQueryPictFormats, req);
44353bb355aSmrg    req->reqType = (CARD8) info->codes->major_opcode;
4441f0ac6a5Smrg    req->renderReqType = X_RenderQueryPictFormats;
4456fae4e5dSmrg
4466fae4e5dSmrg    if (!_XReply (dpy, (xReply *) &rep, 0, xFalse))
4471f0ac6a5Smrg    {
4481f0ac6a5Smrg	DeqAsyncHandler (dpy, &async);
4491f0ac6a5Smrg	UnlockDisplay (dpy);
4501f0ac6a5Smrg	SyncHandle ();
4511f0ac6a5Smrg	return 0;
4521f0ac6a5Smrg    }
4531f0ac6a5Smrg    DeqAsyncHandler (dpy, &async);
4541f0ac6a5Smrg    if (async_state.error)
4551f0ac6a5Smrg    {
4561f0ac6a5Smrg	UnlockDisplay(dpy);
4571f0ac6a5Smrg	SyncHandle();
4581f0ac6a5Smrg	return 0;
4591f0ac6a5Smrg    }
4601f0ac6a5Smrg    /*
4611f0ac6a5Smrg     * Check for the lack of sub-pixel data
4621f0ac6a5Smrg     */
4631f0ac6a5Smrg    if (async_state.major_version == 0 && async_state.minor_version < 6)
4641f0ac6a5Smrg	rep.numSubpixel = 0;
4656fae4e5dSmrg
466190694daSmrg    if ((rep.numFormats < ((INT_MAX / 4) / sizeof (XRenderPictFormat))) &&
467190694daSmrg	(rep.numScreens < ((INT_MAX / 4) / sizeof (XRenderScreen))) &&
468190694daSmrg	(rep.numDepths  < ((INT_MAX / 4) / sizeof (XRenderDepth))) &&
469190694daSmrg	(rep.numVisuals < ((INT_MAX / 4) / sizeof (XRenderVisual))) &&
470190694daSmrg	(rep.numSubpixel < ((INT_MAX / 4) / 4)) &&
471190694daSmrg	(rep.length < (INT_MAX >> 2)) ) {
472190694daSmrg	xri = Xmalloc (sizeof (XRenderInfo) +
473190694daSmrg		       (rep.numFormats * sizeof (XRenderPictFormat)) +
474190694daSmrg		       (rep.numScreens * sizeof (XRenderScreen)) +
475190694daSmrg		       (rep.numDepths * sizeof (XRenderDepth)) +
476190694daSmrg		       (rep.numVisuals * sizeof (XRenderVisual)));
477190694daSmrg	rlength = ((rep.numFormats * sizeof (xPictFormInfo)) +
478190694daSmrg		   (rep.numScreens * sizeof (xPictScreen)) +
479190694daSmrg		   (rep.numDepths * sizeof (xPictDepth)) +
480190694daSmrg		   (rep.numVisuals * sizeof (xPictVisual)) +
481190694daSmrg		   (rep.numSubpixel * 4));
482190694daSmrg	xData = Xmalloc (rlength);
483190694daSmrg	nbytes = (unsigned long) rep.length << 2;
484190694daSmrg    } else {
485190694daSmrg	xri = NULL;
486190694daSmrg	xData = NULL;
487190694daSmrg	rlength = nbytes = 0;
488190694daSmrg    }
4896fae4e5dSmrg
4901f0ac6a5Smrg    if (!xri || !xData || nbytes < rlength)
4911f0ac6a5Smrg    {
4921f0ac6a5Smrg	if (xri) Xfree (xri);
4931f0ac6a5Smrg	if (xData) Xfree (xData);
494cc1b55f9Smrg	_XEatDataWords (dpy, rep.length);
4951f0ac6a5Smrg	UnlockDisplay (dpy);
4961f0ac6a5Smrg	SyncHandle ();
4971f0ac6a5Smrg	return 0;
4981f0ac6a5Smrg    }
4991f0ac6a5Smrg    xri->major_version = async_state.major_version;
5001f0ac6a5Smrg    xri->minor_version = async_state.minor_version;
5011f0ac6a5Smrg    xri->format = (XRenderPictFormat *) (xri + 1);
50253bb355aSmrg    xri->nformat = (int) rep.numFormats;
5031f0ac6a5Smrg    xri->screen = (XRenderScreen *) (xri->format + rep.numFormats);
50453bb355aSmrg    xri->nscreen = (int) rep.numScreens;
5051f0ac6a5Smrg    xri->depth = (XRenderDepth *) (xri->screen + rep.numScreens);
50653bb355aSmrg    xri->ndepth = (int) rep.numDepths;
5071f0ac6a5Smrg    xri->visual = (XRenderVisual *) (xri->depth + rep.numDepths);
50853bb355aSmrg    xri->nvisual = (int) rep.numVisuals;
50953bb355aSmrg    _XRead (dpy, (char *) xData, (long) rlength);
5101f0ac6a5Smrg    format = xri->format;
5111f0ac6a5Smrg    xFormat = (xPictFormInfo *) xData;
5121f0ac6a5Smrg    for (nf = 0; nf < rep.numFormats; nf++)
5131f0ac6a5Smrg    {
5141f0ac6a5Smrg	format->id = xFormat->id;
5151f0ac6a5Smrg	format->type = xFormat->type;
5161f0ac6a5Smrg	format->depth = xFormat->depth;
51753bb355aSmrg	format->direct.red       = (short) xFormat->direct.red;
51853bb355aSmrg	format->direct.redMask   = (short) xFormat->direct.redMask;
51953bb355aSmrg	format->direct.green     = (short) xFormat->direct.green;
52053bb355aSmrg	format->direct.greenMask = (short) xFormat->direct.greenMask;
52153bb355aSmrg	format->direct.blue      = (short) xFormat->direct.blue;
52253bb355aSmrg	format->direct.blueMask  = (short) xFormat->direct.blueMask;
52353bb355aSmrg	format->direct.alpha     = (short) xFormat->direct.alpha;
52453bb355aSmrg	format->direct.alphaMask = (short) xFormat->direct.alphaMask;
5251f0ac6a5Smrg	format->colormap = xFormat->colormap;
5261f0ac6a5Smrg	format++;
5271f0ac6a5Smrg	xFormat++;
5281f0ac6a5Smrg    }
5291f0ac6a5Smrg    xScreen = (xPictScreen *) xFormat;
5301f0ac6a5Smrg    screen = xri->screen;
5311f0ac6a5Smrg    depth = xri->depth;
5321f0ac6a5Smrg    visual = xri->visual;
5331f0ac6a5Smrg    for (ns = 0; ns < xri->nscreen; ns++)
5341f0ac6a5Smrg    {
5351f0ac6a5Smrg	screen->depths = depth;
53653bb355aSmrg	screen->ndepths = (int) xScreen->nDepth;
5371f0ac6a5Smrg	screen->fallback = _XRenderFindFormat (xri, xScreen->fallback);
5381f0ac6a5Smrg	screen->subpixel = SubPixelUnknown;
53953bb355aSmrg	xPDepth = (xPictDepth *) (xScreen + 1);
540f1c62215Smrg	if (screen->ndepths > rep.numDepths) {
541f1c62215Smrg	    Xfree (xri);
542f1c62215Smrg	    Xfree (xData);
543f1c62215Smrg	    _XEatDataWords (dpy, rep.length);
544f1c62215Smrg	    UnlockDisplay (dpy);
545f1c62215Smrg	    SyncHandle ();
546f1c62215Smrg	    return 0;
547f1c62215Smrg	}
54853bb355aSmrg	rep.numDepths -= (CARD32) screen->ndepths;
5491f0ac6a5Smrg	for (nd = 0; nd < screen->ndepths; nd++)
5501f0ac6a5Smrg	{
55153bb355aSmrg	    int nv;
55253bb355aSmrg
55353bb355aSmrg	    depth->depth = xPDepth->depth;
55453bb355aSmrg	    depth->nvisuals = xPDepth->nPictVisuals;
5551f0ac6a5Smrg	    depth->visuals = visual;
55653bb355aSmrg	    xVisual = (xPictVisual *) (xPDepth + 1);
557f1c62215Smrg	    if (depth->nvisuals > rep.numVisuals) {
558f1c62215Smrg		Xfree (xri);
559f1c62215Smrg		Xfree (xData);
560f1c62215Smrg		_XEatDataWords (dpy, rep.length);
561f1c62215Smrg		UnlockDisplay (dpy);
562f1c62215Smrg		SyncHandle ();
563f1c62215Smrg		return 0;
564f1c62215Smrg	    }
56553bb355aSmrg	    rep.numVisuals -= (CARD32) depth->nvisuals;
5661f0ac6a5Smrg	    for (nv = 0; nv < depth->nvisuals; nv++)
5671f0ac6a5Smrg	    {
5681f0ac6a5Smrg		visual->visual = _XRenderFindVisual (dpy, xVisual->visual);
5691f0ac6a5Smrg		visual->format = _XRenderFindFormat (xri, xVisual->format);
5701f0ac6a5Smrg		visual++;
5711f0ac6a5Smrg		xVisual++;
5721f0ac6a5Smrg	    }
5731f0ac6a5Smrg	    depth++;
57453bb355aSmrg	    xPDepth = (xPictDepth *) xVisual;
5751f0ac6a5Smrg	}
5761f0ac6a5Smrg	screen++;
57753bb355aSmrg	xScreen = (xPictScreen *) xPDepth;
5781f0ac6a5Smrg    }
5791f0ac6a5Smrg    xSubpixel = (CARD32 *) xScreen;
5801f0ac6a5Smrg    screen = xri->screen;
5811f0ac6a5Smrg    for (ns = 0; ns < rep.numSubpixel; ns++)
5821f0ac6a5Smrg    {
58353bb355aSmrg	screen->subpixel = (int) *xSubpixel;
5841f0ac6a5Smrg	xSubpixel++;
5851f0ac6a5Smrg	screen++;
5861f0ac6a5Smrg    }
5871f0ac6a5Smrg    info->info = xri;
5881f0ac6a5Smrg    /*
5891f0ac6a5Smrg     * Skip any extra data
5901f0ac6a5Smrg     */
5911f0ac6a5Smrg    if (nbytes > rlength)
5921f0ac6a5Smrg	_XEatData (dpy, (unsigned long) (nbytes - rlength));
5936fae4e5dSmrg
5941f0ac6a5Smrg    UnlockDisplay (dpy);
5951f0ac6a5Smrg    SyncHandle ();
5961f0ac6a5Smrg    Xfree (xData);
5971f0ac6a5Smrg    return 1;
5981f0ac6a5Smrg}
5991f0ac6a5Smrg
6001f0ac6a5Smrgint
6011f0ac6a5SmrgXRenderQuerySubpixelOrder (Display *dpy, int screen)
6021f0ac6a5Smrg{
6031f0ac6a5Smrg    XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
6041f0ac6a5Smrg    XRenderInfo	    *xri;
6051f0ac6a5Smrg
6061f0ac6a5Smrg    if (!RenderHasExtension (info))
6071f0ac6a5Smrg	return SubPixelUnknown;
6081f0ac6a5Smrg
6091f0ac6a5Smrg    if (!XRenderQueryFormats (dpy))
6101f0ac6a5Smrg	return SubPixelUnknown;
6111f0ac6a5Smrg
6121f0ac6a5Smrg    xri = info->info;
6131f0ac6a5Smrg    return xri->screen[screen].subpixel;
6141f0ac6a5Smrg}
6151f0ac6a5Smrg
6161f0ac6a5SmrgBool
6171f0ac6a5SmrgXRenderSetSubpixelOrder (Display *dpy, int screen, int subpixel)
6181f0ac6a5Smrg{
6191f0ac6a5Smrg    XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
6201f0ac6a5Smrg    XRenderInfo	    *xri;
6211f0ac6a5Smrg
6221f0ac6a5Smrg    if (!RenderHasExtension (info))
6231f0ac6a5Smrg	return False;
6241f0ac6a5Smrg
6251f0ac6a5Smrg    if (!XRenderQueryFormats (dpy))
6261f0ac6a5Smrg	return False;
6271f0ac6a5Smrg
6281f0ac6a5Smrg    xri = info->info;
6291f0ac6a5Smrg    xri->screen[screen].subpixel = subpixel;
6301f0ac6a5Smrg    return True;
6311f0ac6a5Smrg}
6321f0ac6a5Smrg
6331f0ac6a5SmrgXRenderPictFormat *
6341f0ac6a5SmrgXRenderFindVisualFormat (Display *dpy, _Xconst Visual *visual)
6351f0ac6a5Smrg{
6361f0ac6a5Smrg    XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
6371f0ac6a5Smrg    int		    nv;
6381f0ac6a5Smrg    XRenderInfo	    *xri;
6391f0ac6a5Smrg    XRenderVisual   *xrv;
640e5410a46Smrg
641e5410a46Smrg    RenderCheckExtension (dpy, info, NULL);
6421f0ac6a5Smrg    if (!XRenderQueryFormats (dpy))
643e5410a46Smrg        return NULL;
6441f0ac6a5Smrg    xri = info->info;
6451f0ac6a5Smrg    for (nv = 0, xrv = xri->visual; nv < xri->nvisual; nv++, xrv++)
6461f0ac6a5Smrg	if (xrv->visual == visual)
6471f0ac6a5Smrg	    return xrv->format;
648e5410a46Smrg    return NULL;
6491f0ac6a5Smrg}
6501f0ac6a5Smrg
6511f0ac6a5SmrgXRenderPictFormat *
6521f0ac6a5SmrgXRenderFindFormat (Display		*dpy,
6531f0ac6a5Smrg		   unsigned long	mask,
6541f0ac6a5Smrg		   _Xconst XRenderPictFormat	*template,
6551f0ac6a5Smrg		   int			count)
6561f0ac6a5Smrg{
6571f0ac6a5Smrg    XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
6581f0ac6a5Smrg    int		    nf;
6591f0ac6a5Smrg    XRenderInfo     *xri;
660e5410a46Smrg
661e5410a46Smrg    RenderCheckExtension (dpy, info, NULL);
6621f0ac6a5Smrg    if (!XRenderQueryFormats (dpy))
663e5410a46Smrg	return NULL;
6641f0ac6a5Smrg    xri = info->info;
6651f0ac6a5Smrg    for (nf = 0; nf < xri->nformat; nf++)
6661f0ac6a5Smrg    {
6671f0ac6a5Smrg	if (mask & PictFormatID)
6681f0ac6a5Smrg	    if (template->id != xri->format[nf].id)
6691f0ac6a5Smrg		continue;
6701f0ac6a5Smrg	if (mask & PictFormatType)
6711f0ac6a5Smrg	if (template->type != xri->format[nf].type)
6721f0ac6a5Smrg		continue;
6731f0ac6a5Smrg	if (mask & PictFormatDepth)
6741f0ac6a5Smrg	    if (template->depth != xri->format[nf].depth)
6751f0ac6a5Smrg		continue;
6761f0ac6a5Smrg	if (mask & PictFormatRed)
6771f0ac6a5Smrg	    if (template->direct.red != xri->format[nf].direct.red)
6781f0ac6a5Smrg		continue;
6791f0ac6a5Smrg	if (mask & PictFormatRedMask)
6801f0ac6a5Smrg	    if (template->direct.redMask != xri->format[nf].direct.redMask)
6811f0ac6a5Smrg		continue;
6821f0ac6a5Smrg	if (mask & PictFormatGreen)
6831f0ac6a5Smrg	    if (template->direct.green != xri->format[nf].direct.green)
6841f0ac6a5Smrg		continue;
6851f0ac6a5Smrg	if (mask & PictFormatGreenMask)
6861f0ac6a5Smrg	    if (template->direct.greenMask != xri->format[nf].direct.greenMask)
6871f0ac6a5Smrg		continue;
6881f0ac6a5Smrg	if (mask & PictFormatBlue)
6891f0ac6a5Smrg	    if (template->direct.blue != xri->format[nf].direct.blue)
6901f0ac6a5Smrg		continue;
6911f0ac6a5Smrg	if (mask & PictFormatBlueMask)
6921f0ac6a5Smrg	    if (template->direct.blueMask != xri->format[nf].direct.blueMask)
6931f0ac6a5Smrg		continue;
6941f0ac6a5Smrg	if (mask & PictFormatAlpha)
6951f0ac6a5Smrg	    if (template->direct.alpha != xri->format[nf].direct.alpha)
6961f0ac6a5Smrg		continue;
6971f0ac6a5Smrg	if (mask & PictFormatAlphaMask)
6981f0ac6a5Smrg	    if (template->direct.alphaMask != xri->format[nf].direct.alphaMask)
6991f0ac6a5Smrg		continue;
7001f0ac6a5Smrg	if (mask & PictFormatColormap)
7011f0ac6a5Smrg	    if (template->colormap != xri->format[nf].colormap)
7021f0ac6a5Smrg		continue;
7031f0ac6a5Smrg	if (count-- == 0)
7041f0ac6a5Smrg	    return &xri->format[nf];
7051f0ac6a5Smrg    }
706e5410a46Smrg    return NULL;
7071f0ac6a5Smrg}
7081f0ac6a5Smrg
7091f0ac6a5SmrgXRenderPictFormat *
7101f0ac6a5SmrgXRenderFindStandardFormat (Display  *dpy,
7111f0ac6a5Smrg			   int	    format)
7121f0ac6a5Smrg{
7131f0ac6a5Smrg    static struct {
7141f0ac6a5Smrg	XRenderPictFormat   templ;
7151f0ac6a5Smrg	unsigned long	    mask;
7161f0ac6a5Smrg    } standardFormats[PictStandardNUM] = {
7171f0ac6a5Smrg	/* PictStandardARGB32 */
7181f0ac6a5Smrg	{
7191f0ac6a5Smrg	    {
7201f0ac6a5Smrg		0,			    /* id */
7211f0ac6a5Smrg		PictTypeDirect,		    /* type */
7221f0ac6a5Smrg		32,			    /* depth */
7231f0ac6a5Smrg		{			    /* direct */
7241f0ac6a5Smrg		    16,			    /* direct.red */
7251f0ac6a5Smrg		    0xff,		    /* direct.redMask */
7261f0ac6a5Smrg		    8,			    /* direct.green */
7271f0ac6a5Smrg		    0xff,		    /* direct.greenMask */
7281f0ac6a5Smrg		    0,			    /* direct.blue */
7291f0ac6a5Smrg		    0xff,		    /* direct.blueMask */
7301f0ac6a5Smrg		    24,			    /* direct.alpha */
7311f0ac6a5Smrg		    0xff,		    /* direct.alphaMask */
7321f0ac6a5Smrg		},
7331f0ac6a5Smrg		0,			    /* colormap */
7341f0ac6a5Smrg	    },
7356fae4e5dSmrg	    PictFormatType |
7361f0ac6a5Smrg	    PictFormatDepth |
7371f0ac6a5Smrg	    PictFormatRed |
7381f0ac6a5Smrg	    PictFormatRedMask |
7391f0ac6a5Smrg	    PictFormatGreen |
7401f0ac6a5Smrg	    PictFormatGreenMask |
7411f0ac6a5Smrg	    PictFormatBlue |
7421f0ac6a5Smrg	    PictFormatBlueMask |
7431f0ac6a5Smrg	    PictFormatAlpha |
7441f0ac6a5Smrg	    PictFormatAlphaMask,
7451f0ac6a5Smrg	},
7461f0ac6a5Smrg	/* PictStandardRGB24 */
7471f0ac6a5Smrg	{
7481f0ac6a5Smrg	    {
7491f0ac6a5Smrg		0,			    /* id */
7501f0ac6a5Smrg		PictTypeDirect,		    /* type */
7511f0ac6a5Smrg		24,			    /* depth */
7521f0ac6a5Smrg		{			    /* direct */
7531f0ac6a5Smrg		    16,			    /* direct.red */
7541f0ac6a5Smrg		    0xff,		    /* direct.redMask */
7551f0ac6a5Smrg		    8,			    /* direct.green */
7561f0ac6a5Smrg		    0xff,		    /* direct.greenMask */
7571f0ac6a5Smrg		    0,			    /* direct.blue */
7581f0ac6a5Smrg		    0xff,		    /* direct.blueMask */
7591f0ac6a5Smrg		    0,			    /* direct.alpha */
7601f0ac6a5Smrg		    0x00,		    /* direct.alphaMask */
7611f0ac6a5Smrg		},
7621f0ac6a5Smrg		0,			    /* colormap */
7631f0ac6a5Smrg	    },
7646fae4e5dSmrg	    PictFormatType |
7651f0ac6a5Smrg	    PictFormatDepth |
7661f0ac6a5Smrg	    PictFormatRed |
7671f0ac6a5Smrg	    PictFormatRedMask |
7681f0ac6a5Smrg	    PictFormatGreen |
7691f0ac6a5Smrg	    PictFormatGreenMask |
7701f0ac6a5Smrg	    PictFormatBlue |
7711f0ac6a5Smrg	    PictFormatBlueMask |
7721f0ac6a5Smrg	    PictFormatAlphaMask,
7731f0ac6a5Smrg	},
7741f0ac6a5Smrg	/* PictStandardA8 */
7751f0ac6a5Smrg	{
7761f0ac6a5Smrg	    {
7771f0ac6a5Smrg		0,			    /* id */
7781f0ac6a5Smrg		PictTypeDirect,		    /* type */
7791f0ac6a5Smrg		8,			    /* depth */
7801f0ac6a5Smrg		{			    /* direct */
7811f0ac6a5Smrg		    0,			    /* direct.red */
7821f0ac6a5Smrg		    0x00,		    /* direct.redMask */
7831f0ac6a5Smrg		    0,			    /* direct.green */
7841f0ac6a5Smrg		    0x00,		    /* direct.greenMask */
7851f0ac6a5Smrg		    0,			    /* direct.blue */
7861f0ac6a5Smrg		    0x00,		    /* direct.blueMask */
7871f0ac6a5Smrg		    0,			    /* direct.alpha */
7881f0ac6a5Smrg		    0xff,		    /* direct.alphaMask */
7891f0ac6a5Smrg		},
7901f0ac6a5Smrg		0,			    /* colormap */
7911f0ac6a5Smrg	    },
7926fae4e5dSmrg	    PictFormatType |
7931f0ac6a5Smrg	    PictFormatDepth |
7941f0ac6a5Smrg	    PictFormatRedMask |
7951f0ac6a5Smrg	    PictFormatGreenMask |
7961f0ac6a5Smrg	    PictFormatBlueMask |
7971f0ac6a5Smrg	    PictFormatAlpha |
7981f0ac6a5Smrg	    PictFormatAlphaMask,
7991f0ac6a5Smrg	},
8001f0ac6a5Smrg	/* PictStandardA4 */
8011f0ac6a5Smrg	{
8021f0ac6a5Smrg	    {
8031f0ac6a5Smrg		0,			    /* id */
8041f0ac6a5Smrg		PictTypeDirect,		    /* type */
8051f0ac6a5Smrg		4,			    /* depth */
8061f0ac6a5Smrg		{			    /* direct */
8071f0ac6a5Smrg		    0,			    /* direct.red */
8081f0ac6a5Smrg		    0x00,		    /* direct.redMask */
8091f0ac6a5Smrg		    0,			    /* direct.green */
8101f0ac6a5Smrg		    0x00,		    /* direct.greenMask */
8111f0ac6a5Smrg		    0,			    /* direct.blue */
8121f0ac6a5Smrg		    0x00,		    /* direct.blueMask */
8131f0ac6a5Smrg		    0,			    /* direct.alpha */
8141f0ac6a5Smrg		    0x0f,		    /* direct.alphaMask */
8151f0ac6a5Smrg		},
8161f0ac6a5Smrg		0,			    /* colormap */
8171f0ac6a5Smrg	    },
8186fae4e5dSmrg	    PictFormatType |
8191f0ac6a5Smrg	    PictFormatDepth |
8201f0ac6a5Smrg	    PictFormatRedMask |
8211f0ac6a5Smrg	    PictFormatGreenMask |
8221f0ac6a5Smrg	    PictFormatBlueMask |
8231f0ac6a5Smrg	    PictFormatAlpha |
8241f0ac6a5Smrg	    PictFormatAlphaMask,
8251f0ac6a5Smrg	},
8261f0ac6a5Smrg	/* PictStandardA1 */
8271f0ac6a5Smrg	{
8281f0ac6a5Smrg	    {
8291f0ac6a5Smrg		0,			    /* id */
8301f0ac6a5Smrg		PictTypeDirect,		    /* type */
8311f0ac6a5Smrg		1,			    /* depth */
8321f0ac6a5Smrg		{			    /* direct */
8331f0ac6a5Smrg		    0,			    /* direct.red */
8341f0ac6a5Smrg		    0x00,		    /* direct.redMask */
8351f0ac6a5Smrg		    0,			    /* direct.green */
8361f0ac6a5Smrg		    0x00,		    /* direct.greenMask */
8371f0ac6a5Smrg		    0,			    /* direct.blue */
8381f0ac6a5Smrg		    0x00,		    /* direct.blueMask */
8391f0ac6a5Smrg		    0,			    /* direct.alpha */
8401f0ac6a5Smrg		    0x01,		    /* direct.alphaMask */
8411f0ac6a5Smrg		},
8421f0ac6a5Smrg		0,			    /* colormap */
8431f0ac6a5Smrg	    },
8446fae4e5dSmrg	    PictFormatType |
8451f0ac6a5Smrg	    PictFormatDepth |
8461f0ac6a5Smrg	    PictFormatRedMask |
8471f0ac6a5Smrg	    PictFormatGreenMask |
8481f0ac6a5Smrg	    PictFormatBlueMask |
8491f0ac6a5Smrg	    PictFormatAlpha |
8501f0ac6a5Smrg	    PictFormatAlphaMask,
8511f0ac6a5Smrg	},
8521f0ac6a5Smrg    };
8531f0ac6a5Smrg
8541f0ac6a5Smrg    if (0 <= format && format < PictStandardNUM)
8556fae4e5dSmrg	return XRenderFindFormat (dpy,
8561f0ac6a5Smrg				  standardFormats[format].mask,
8571f0ac6a5Smrg				  &standardFormats[format].templ,
8581f0ac6a5Smrg				  0);
859e5410a46Smrg    return NULL;
8601f0ac6a5Smrg}
8611f0ac6a5Smrg
8621f0ac6a5SmrgXIndexValue *
8631f0ac6a5SmrgXRenderQueryPictIndexValues(Display			*dpy,
8641f0ac6a5Smrg			    _Xconst XRenderPictFormat	*format,
8651f0ac6a5Smrg			    int				*num)
8661f0ac6a5Smrg{
86753bb355aSmrg    XRenderExtDisplayInfo		*info = XRenderFindDisplay (dpy);
8681f0ac6a5Smrg    xRenderQueryPictIndexValuesReq	*req;
8691f0ac6a5Smrg    xRenderQueryPictIndexValuesReply	rep;
8701f0ac6a5Smrg    XIndexValue				*values;
87153bb355aSmrg    unsigned int			nbytes, nread, i;
8721f0ac6a5Smrg
873e5410a46Smrg    RenderCheckExtension (dpy, info, NULL);
8741f0ac6a5Smrg
8751f0ac6a5Smrg    LockDisplay (dpy);
8761f0ac6a5Smrg    GetReq (RenderQueryPictIndexValues, req);
87753bb355aSmrg    req->reqType       = (CARD8) info->codes->major_opcode;
8781f0ac6a5Smrg    req->renderReqType = X_RenderQueryPictIndexValues;
87953bb355aSmrg    req->format        = (CARD32) format->id;
8801f0ac6a5Smrg    if (!_XReply (dpy, (xReply *) &rep, 0, xFalse))
8811f0ac6a5Smrg    {
8821f0ac6a5Smrg	UnlockDisplay (dpy);
8831f0ac6a5Smrg	SyncHandle ();
884e5410a46Smrg	return NULL;
8851f0ac6a5Smrg    }
8861f0ac6a5Smrg
887190694daSmrg    if ((rep.length < (INT_MAX >> 2)) &&
888190694daSmrg	(rep.numIndexValues < (INT_MAX / sizeof (XIndexValue)))) {
88953bb355aSmrg	unsigned int rlength;
890190694daSmrg	/* request data length */
891190694daSmrg	nbytes = rep.length << 2;
892190694daSmrg	/* bytes of actual data in the request */
893190694daSmrg	nread = rep.numIndexValues * SIZEOF (xIndexValue);
894190694daSmrg	/* size of array returned to application */
89553bb355aSmrg	rlength = (unsigned) ((unsigned long) rep.numIndexValues * sizeof (XIndexValue));
896190694daSmrg
897190694daSmrg	/* allocate returned data */
898190694daSmrg	values = Xmalloc (rlength);
899190694daSmrg    } else {
90053bb355aSmrg	nbytes = nread = 0;
901190694daSmrg	values = NULL;
902190694daSmrg    }
9031f0ac6a5Smrg
9041f0ac6a5Smrg    if (!values)
9051f0ac6a5Smrg    {
906cc1b55f9Smrg	_XEatDataWords (dpy, rep.length);
9071f0ac6a5Smrg	UnlockDisplay (dpy);
9081f0ac6a5Smrg	SyncHandle ();
909e5410a46Smrg	return NULL;
9101f0ac6a5Smrg    }
9111f0ac6a5Smrg
9121f0ac6a5Smrg    /* read the values one at a time and convert */
91353bb355aSmrg    *num = (int) rep.numIndexValues;
91453bb355aSmrg    for (i = 0; i < rep.numIndexValues; i++)
9151f0ac6a5Smrg    {
9161f0ac6a5Smrg	xIndexValue value;
9176fae4e5dSmrg
9181f0ac6a5Smrg	_XRead (dpy, (char *) &value, SIZEOF (xIndexValue));
9191f0ac6a5Smrg	values[i].pixel = value.pixel;
9201f0ac6a5Smrg	values[i].red = value.red;
9211f0ac6a5Smrg	values[i].green = value.green;
9221f0ac6a5Smrg	values[i].blue = value.blue;
9231f0ac6a5Smrg	values[i].alpha = value.alpha;
9241f0ac6a5Smrg    }
9251f0ac6a5Smrg    /* skip any padding */
9261f0ac6a5Smrg    if(nbytes > nread)
9271f0ac6a5Smrg    {
9281f0ac6a5Smrg	_XEatData (dpy, (unsigned long) (nbytes - nread));
9291f0ac6a5Smrg    }
9301f0ac6a5Smrg    UnlockDisplay (dpy);
9311f0ac6a5Smrg    SyncHandle ();
9321f0ac6a5Smrg    return values;
9331f0ac6a5Smrg}
934