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
29741e04fc9Smrgstatic void
29841e04fc9SmrgXRenderFreeXRenderInfo (XRenderInfo *xri)
29941e04fc9Smrg{
30041e04fc9Smrg    Xfree(xri->format);
30141e04fc9Smrg    Xfree(xri->screen);
30241e04fc9Smrg    Xfree(xri->depth);
30341e04fc9Smrg    Xfree(xri->visual);
30441e04fc9Smrg    Xfree(xri);
30541e04fc9Smrg}
30641e04fc9Smrg
3071f0ac6a5Smrgstatic int
30853bb355aSmrgXRenderCloseDisplay (Display *dpy, XExtCodes *codes _X_UNUSED)
3091f0ac6a5Smrg{
3101f0ac6a5Smrg    XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
31141e04fc9Smrg    if (info && info->info) XRenderFreeXRenderInfo (info->info);
3126fae4e5dSmrg
3131f0ac6a5Smrg    return XRenderExtRemoveDisplay (&XRenderExtensionInfo, dpy);
3141f0ac6a5Smrg}
3156fae4e5dSmrg
3161f0ac6a5Smrg/****************************************************************************
3171f0ac6a5Smrg *                                                                          *
3181f0ac6a5Smrg *			    Render public interfaces                        *
3191f0ac6a5Smrg *                                                                          *
3201f0ac6a5Smrg ****************************************************************************/
3211f0ac6a5Smrg
3221f0ac6a5SmrgBool XRenderQueryExtension (Display *dpy, int *event_basep, int *error_basep)
3231f0ac6a5Smrg{
3241f0ac6a5Smrg    XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
3251f0ac6a5Smrg
3261f0ac6a5Smrg    if (RenderHasExtension(info)) {
3271f0ac6a5Smrg	*event_basep = info->codes->first_event;
3281f0ac6a5Smrg	*error_basep = info->codes->first_error;
3291f0ac6a5Smrg	return True;
3301f0ac6a5Smrg    } else {
3311f0ac6a5Smrg	return False;
3321f0ac6a5Smrg    }
3331f0ac6a5Smrg}
3341f0ac6a5Smrg
3351f0ac6a5Smrg
3361f0ac6a5SmrgStatus XRenderQueryVersion (Display *dpy,
3371f0ac6a5Smrg			    int	    *major_versionp,
3381f0ac6a5Smrg			    int	    *minor_versionp)
3391f0ac6a5Smrg{
3401f0ac6a5Smrg    XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
3411f0ac6a5Smrg    XRenderInfo	    *xri;
3421f0ac6a5Smrg
3431f0ac6a5Smrg    if (!RenderHasExtension (info))
3441f0ac6a5Smrg	return 0;
3451f0ac6a5Smrg
3461f0ac6a5Smrg    if (!XRenderQueryFormats (dpy))
3471f0ac6a5Smrg	return 0;
3486fae4e5dSmrg
3496fae4e5dSmrg    xri = info->info;
3501f0ac6a5Smrg    *major_versionp = xri->major_version;
3511f0ac6a5Smrg    *minor_versionp = xri->minor_version;
3521f0ac6a5Smrg    return 1;
3531f0ac6a5Smrg}
3541f0ac6a5Smrg
3551f0ac6a5Smrgstatic XRenderPictFormat *
3561f0ac6a5Smrg_XRenderFindFormat (XRenderInfo *xri, PictFormat format)
3571f0ac6a5Smrg{
3581f0ac6a5Smrg    int	nf;
3596fae4e5dSmrg
3601f0ac6a5Smrg    for (nf = 0; nf < xri->nformat; nf++)
3611f0ac6a5Smrg	if (xri->format[nf].id == format)
3621f0ac6a5Smrg	    return &xri->format[nf];
363e5410a46Smrg    return NULL;
3641f0ac6a5Smrg}
3651f0ac6a5Smrg
3661f0ac6a5Smrgstatic Visual *
3671f0ac6a5Smrg_XRenderFindVisual (Display *dpy, VisualID vid)
3681f0ac6a5Smrg{
3691f0ac6a5Smrg    return _XVIDtoVisual (dpy, vid);
3701f0ac6a5Smrg}
3711f0ac6a5Smrg
3721f0ac6a5Smrgtypedef struct _renderVersionState {
3731f0ac6a5Smrg    unsigned long   version_seq;
3741f0ac6a5Smrg    Bool	    error;
3751f0ac6a5Smrg    int		    major_version;
3761f0ac6a5Smrg    int		    minor_version;
3776fae4e5dSmrg
3781f0ac6a5Smrg} _XrenderVersionState;
3791f0ac6a5Smrg
3801f0ac6a5Smrgstatic Bool
3811f0ac6a5Smrg_XRenderVersionHandler (Display	    *dpy,
3821f0ac6a5Smrg			xReply	    *rep,
3831f0ac6a5Smrg			char	    *buf,
3841f0ac6a5Smrg			int	    len,
3851f0ac6a5Smrg			XPointer    data)
3861f0ac6a5Smrg{
3871f0ac6a5Smrg    xRenderQueryVersionReply	replbuf;
3881f0ac6a5Smrg    xRenderQueryVersionReply	*repl;
3891f0ac6a5Smrg    _XrenderVersionState	*state = (_XrenderVersionState *) data;
3901f0ac6a5Smrg
3911f0ac6a5Smrg    if (dpy->last_request_read != state->version_seq)
3921f0ac6a5Smrg	return False;
3931f0ac6a5Smrg    if (rep->generic.type == X_Error)
3941f0ac6a5Smrg    {
3951f0ac6a5Smrg	state->error = True;
3961f0ac6a5Smrg	return False;
3971f0ac6a5Smrg    }
3981f0ac6a5Smrg    repl = (xRenderQueryVersionReply *)
3991f0ac6a5Smrg	_XGetAsyncReply(dpy, (char *)&replbuf, rep, buf, len,
4001f0ac6a5Smrg		     (SIZEOF(xRenderQueryVersionReply) - SIZEOF(xReply)) >> 2,
4011f0ac6a5Smrg			True);
40253bb355aSmrg    state->major_version = (int) repl->majorVersion;
40353bb355aSmrg    state->minor_version = (int) repl->minorVersion;
4041f0ac6a5Smrg    return True;
4051f0ac6a5Smrg}
4061f0ac6a5Smrg
4071f0ac6a5SmrgStatus
4081f0ac6a5SmrgXRenderQueryFormats (Display *dpy)
4091f0ac6a5Smrg{
41053bb355aSmrg    XRenderExtDisplayInfo	*info = XRenderFindDisplay (dpy);
4111f0ac6a5Smrg    _XAsyncHandler		async;
4121f0ac6a5Smrg    _XrenderVersionState	async_state;
4131f0ac6a5Smrg    xRenderQueryVersionReq	*vreq;
4141f0ac6a5Smrg    xRenderQueryPictFormatsReply rep;
4151f0ac6a5Smrg    xRenderQueryPictFormatsReq  *req;
4161f0ac6a5Smrg    XRenderInfo			*xri;
4171f0ac6a5Smrg    XRenderPictFormat		*format;
4181f0ac6a5Smrg    XRenderScreen		*screen;
4191f0ac6a5Smrg    XRenderDepth		*depth;
4201f0ac6a5Smrg    XRenderVisual		*visual;
4211f0ac6a5Smrg    xPictFormInfo		*xFormat;
4221f0ac6a5Smrg    xPictScreen			*xScreen;
42353bb355aSmrg    xPictDepth			*xPDepth;
4241f0ac6a5Smrg    xPictVisual			*xVisual;
4251f0ac6a5Smrg    CARD32			*xSubpixel;
4261f0ac6a5Smrg    void			*xData;
42753bb355aSmrg    int				ns, nd;
42853bb355aSmrg    unsigned			nf;
429190694daSmrg    unsigned long		rlength;
430190694daSmrg    unsigned long		nbytes;
4316fae4e5dSmrg
4321f0ac6a5Smrg    RenderCheckExtension (dpy, info, 0);
4331f0ac6a5Smrg    LockDisplay (dpy);
4341f0ac6a5Smrg    if (info->info)
4351f0ac6a5Smrg    {
4361f0ac6a5Smrg	UnlockDisplay (dpy);
4371f0ac6a5Smrg	return 1;
4381f0ac6a5Smrg    }
4391f0ac6a5Smrg    GetReq (RenderQueryVersion, vreq);
44053bb355aSmrg    vreq->reqType = (CARD8) info->codes->major_opcode;
4411f0ac6a5Smrg    vreq->renderReqType = X_RenderQueryVersion;
4421f0ac6a5Smrg    vreq->majorVersion = RENDER_MAJOR;
4431f0ac6a5Smrg    vreq->minorVersion = RENDER_MINOR;
4446fae4e5dSmrg
4451f0ac6a5Smrg    async_state.version_seq = dpy->request;
4461f0ac6a5Smrg    async_state.error = False;
4471f0ac6a5Smrg    async.next = dpy->async_handlers;
4481f0ac6a5Smrg    async.handler = _XRenderVersionHandler;
4491f0ac6a5Smrg    async.data = (XPointer) &async_state;
4501f0ac6a5Smrg    dpy->async_handlers = &async;
4516fae4e5dSmrg
4521f0ac6a5Smrg    GetReq (RenderQueryPictFormats, req);
45353bb355aSmrg    req->reqType = (CARD8) info->codes->major_opcode;
4541f0ac6a5Smrg    req->renderReqType = X_RenderQueryPictFormats;
4556fae4e5dSmrg
4566fae4e5dSmrg    if (!_XReply (dpy, (xReply *) &rep, 0, xFalse))
4571f0ac6a5Smrg    {
4581f0ac6a5Smrg	DeqAsyncHandler (dpy, &async);
4591f0ac6a5Smrg	UnlockDisplay (dpy);
4601f0ac6a5Smrg	SyncHandle ();
4611f0ac6a5Smrg	return 0;
4621f0ac6a5Smrg    }
4631f0ac6a5Smrg    DeqAsyncHandler (dpy, &async);
4641f0ac6a5Smrg    if (async_state.error)
4651f0ac6a5Smrg    {
4661f0ac6a5Smrg	UnlockDisplay(dpy);
4671f0ac6a5Smrg	SyncHandle();
4681f0ac6a5Smrg	return 0;
4691f0ac6a5Smrg    }
4701f0ac6a5Smrg    /*
4711f0ac6a5Smrg     * Check for the lack of sub-pixel data
4721f0ac6a5Smrg     */
4731f0ac6a5Smrg    if (async_state.major_version == 0 && async_state.minor_version < 6)
4741f0ac6a5Smrg	rep.numSubpixel = 0;
4756fae4e5dSmrg
476190694daSmrg    if ((rep.numFormats < ((INT_MAX / 4) / sizeof (XRenderPictFormat))) &&
477190694daSmrg	(rep.numScreens < ((INT_MAX / 4) / sizeof (XRenderScreen))) &&
478190694daSmrg	(rep.numDepths  < ((INT_MAX / 4) / sizeof (XRenderDepth))) &&
479190694daSmrg	(rep.numVisuals < ((INT_MAX / 4) / sizeof (XRenderVisual))) &&
480190694daSmrg	(rep.numSubpixel < ((INT_MAX / 4) / 4)) &&
481190694daSmrg	(rep.length < (INT_MAX >> 2)) ) {
48241e04fc9Smrg        /* Zero-initialize so that pointers are NULL if there is a failure. */
48341e04fc9Smrg	xri = Xcalloc (1, sizeof (XRenderInfo));
484190694daSmrg	rlength = ((rep.numFormats * sizeof (xPictFormInfo)) +
485190694daSmrg		   (rep.numScreens * sizeof (xPictScreen)) +
486190694daSmrg		   (rep.numDepths * sizeof (xPictDepth)) +
487190694daSmrg		   (rep.numVisuals * sizeof (xPictVisual)) +
488190694daSmrg		   (rep.numSubpixel * 4));
489190694daSmrg	xData = Xmalloc (rlength);
490190694daSmrg	nbytes = (unsigned long) rep.length << 2;
491190694daSmrg    } else {
492190694daSmrg	xri = NULL;
493190694daSmrg	xData = NULL;
494190694daSmrg	rlength = nbytes = 0;
495190694daSmrg    }
4966fae4e5dSmrg
4971f0ac6a5Smrg    if (!xri || !xData || nbytes < rlength)
4981f0ac6a5Smrg    {
4991f0ac6a5Smrg	if (xri) Xfree (xri);
5001f0ac6a5Smrg	if (xData) Xfree (xData);
501cc1b55f9Smrg	_XEatDataWords (dpy, rep.length);
5021f0ac6a5Smrg	UnlockDisplay (dpy);
5031f0ac6a5Smrg	SyncHandle ();
5041f0ac6a5Smrg	return 0;
5051f0ac6a5Smrg    }
5061f0ac6a5Smrg    xri->major_version = async_state.major_version;
5071f0ac6a5Smrg    xri->minor_version = async_state.minor_version;
50841e04fc9Smrg    xri->format = Xcalloc(rep.numFormats, sizeof(XRenderPictFormat));
50953bb355aSmrg    xri->nformat = (int) rep.numFormats;
51041e04fc9Smrg    xri->screen = Xcalloc(rep.numScreens, sizeof(XRenderScreen));
51153bb355aSmrg    xri->nscreen = (int) rep.numScreens;
51241e04fc9Smrg    xri->depth = Xcalloc(rep.numDepths, sizeof(XRenderDepth));
51353bb355aSmrg    xri->ndepth = (int) rep.numDepths;
51441e04fc9Smrg    xri->visual = Xcalloc(rep.numVisuals, sizeof(XRenderVisual));
51553bb355aSmrg    xri->nvisual = (int) rep.numVisuals;
51641e04fc9Smrg    if (!xri->format || !xri->screen || !xri->depth || !xri->visual)
51741e04fc9Smrg    {
51841e04fc9Smrg	XRenderFreeXRenderInfo(xri);
51941e04fc9Smrg	Xfree (xData);
52041e04fc9Smrg	_XEatDataWords (dpy, rep.length);
52141e04fc9Smrg	UnlockDisplay (dpy);
52241e04fc9Smrg	SyncHandle ();
52341e04fc9Smrg	return 0;
52441e04fc9Smrg    }
52553bb355aSmrg    _XRead (dpy, (char *) xData, (long) rlength);
5261f0ac6a5Smrg    format = xri->format;
5271f0ac6a5Smrg    xFormat = (xPictFormInfo *) xData;
5281f0ac6a5Smrg    for (nf = 0; nf < rep.numFormats; nf++)
5291f0ac6a5Smrg    {
5301f0ac6a5Smrg	format->id = xFormat->id;
5311f0ac6a5Smrg	format->type = xFormat->type;
5321f0ac6a5Smrg	format->depth = xFormat->depth;
53353bb355aSmrg	format->direct.red       = (short) xFormat->direct.red;
53453bb355aSmrg	format->direct.redMask   = (short) xFormat->direct.redMask;
53553bb355aSmrg	format->direct.green     = (short) xFormat->direct.green;
53653bb355aSmrg	format->direct.greenMask = (short) xFormat->direct.greenMask;
53753bb355aSmrg	format->direct.blue      = (short) xFormat->direct.blue;
53853bb355aSmrg	format->direct.blueMask  = (short) xFormat->direct.blueMask;
53953bb355aSmrg	format->direct.alpha     = (short) xFormat->direct.alpha;
54053bb355aSmrg	format->direct.alphaMask = (short) xFormat->direct.alphaMask;
5411f0ac6a5Smrg	format->colormap = xFormat->colormap;
5421f0ac6a5Smrg	format++;
5431f0ac6a5Smrg	xFormat++;
5441f0ac6a5Smrg    }
5451f0ac6a5Smrg    xScreen = (xPictScreen *) xFormat;
5461f0ac6a5Smrg    screen = xri->screen;
5471f0ac6a5Smrg    depth = xri->depth;
5481f0ac6a5Smrg    visual = xri->visual;
5491f0ac6a5Smrg    for (ns = 0; ns < xri->nscreen; ns++)
5501f0ac6a5Smrg    {
5511f0ac6a5Smrg	screen->depths = depth;
55253bb355aSmrg	screen->ndepths = (int) xScreen->nDepth;
5531f0ac6a5Smrg	screen->fallback = _XRenderFindFormat (xri, xScreen->fallback);
5541f0ac6a5Smrg	screen->subpixel = SubPixelUnknown;
55553bb355aSmrg	xPDepth = (xPictDepth *) (xScreen + 1);
556f1c62215Smrg	if (screen->ndepths > rep.numDepths) {
55741e04fc9Smrg	    XRenderFreeXRenderInfo(xri);
558f1c62215Smrg	    Xfree (xData);
559f1c62215Smrg	    _XEatDataWords (dpy, rep.length);
560f1c62215Smrg	    UnlockDisplay (dpy);
561f1c62215Smrg	    SyncHandle ();
562f1c62215Smrg	    return 0;
563f1c62215Smrg	}
56453bb355aSmrg	rep.numDepths -= (CARD32) screen->ndepths;
5651f0ac6a5Smrg	for (nd = 0; nd < screen->ndepths; nd++)
5661f0ac6a5Smrg	{
56753bb355aSmrg	    int nv;
56853bb355aSmrg
56953bb355aSmrg	    depth->depth = xPDepth->depth;
57053bb355aSmrg	    depth->nvisuals = xPDepth->nPictVisuals;
5711f0ac6a5Smrg	    depth->visuals = visual;
57253bb355aSmrg	    xVisual = (xPictVisual *) (xPDepth + 1);
573f1c62215Smrg	    if (depth->nvisuals > rep.numVisuals) {
57441e04fc9Smrg		XRenderFreeXRenderInfo (xri);
575f1c62215Smrg		Xfree (xData);
576f1c62215Smrg		_XEatDataWords (dpy, rep.length);
577f1c62215Smrg		UnlockDisplay (dpy);
578f1c62215Smrg		SyncHandle ();
579f1c62215Smrg		return 0;
580f1c62215Smrg	    }
58153bb355aSmrg	    rep.numVisuals -= (CARD32) depth->nvisuals;
5821f0ac6a5Smrg	    for (nv = 0; nv < depth->nvisuals; nv++)
5831f0ac6a5Smrg	    {
5841f0ac6a5Smrg		visual->visual = _XRenderFindVisual (dpy, xVisual->visual);
5851f0ac6a5Smrg		visual->format = _XRenderFindFormat (xri, xVisual->format);
5861f0ac6a5Smrg		visual++;
5871f0ac6a5Smrg		xVisual++;
5881f0ac6a5Smrg	    }
5891f0ac6a5Smrg	    depth++;
59053bb355aSmrg	    xPDepth = (xPictDepth *) xVisual;
5911f0ac6a5Smrg	}
5921f0ac6a5Smrg	screen++;
59353bb355aSmrg	xScreen = (xPictScreen *) xPDepth;
5941f0ac6a5Smrg    }
5951f0ac6a5Smrg    xSubpixel = (CARD32 *) xScreen;
5961f0ac6a5Smrg    screen = xri->screen;
5971f0ac6a5Smrg    for (ns = 0; ns < rep.numSubpixel; ns++)
5981f0ac6a5Smrg    {
59953bb355aSmrg	screen->subpixel = (int) *xSubpixel;
6001f0ac6a5Smrg	xSubpixel++;
6011f0ac6a5Smrg	screen++;
6021f0ac6a5Smrg    }
6031f0ac6a5Smrg    info->info = xri;
6041f0ac6a5Smrg    /*
6051f0ac6a5Smrg     * Skip any extra data
6061f0ac6a5Smrg     */
6071f0ac6a5Smrg    if (nbytes > rlength)
6081f0ac6a5Smrg	_XEatData (dpy, (unsigned long) (nbytes - rlength));
6096fae4e5dSmrg
6101f0ac6a5Smrg    UnlockDisplay (dpy);
6111f0ac6a5Smrg    SyncHandle ();
6121f0ac6a5Smrg    Xfree (xData);
6131f0ac6a5Smrg    return 1;
6141f0ac6a5Smrg}
6151f0ac6a5Smrg
6161f0ac6a5Smrgint
6171f0ac6a5SmrgXRenderQuerySubpixelOrder (Display *dpy, int screen)
6181f0ac6a5Smrg{
6191f0ac6a5Smrg    XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
6201f0ac6a5Smrg    XRenderInfo	    *xri;
6211f0ac6a5Smrg
6221f0ac6a5Smrg    if (!RenderHasExtension (info))
6231f0ac6a5Smrg	return SubPixelUnknown;
6241f0ac6a5Smrg
6251f0ac6a5Smrg    if (!XRenderQueryFormats (dpy))
6261f0ac6a5Smrg	return SubPixelUnknown;
6271f0ac6a5Smrg
6281f0ac6a5Smrg    xri = info->info;
6291f0ac6a5Smrg    return xri->screen[screen].subpixel;
6301f0ac6a5Smrg}
6311f0ac6a5Smrg
6321f0ac6a5SmrgBool
6331f0ac6a5SmrgXRenderSetSubpixelOrder (Display *dpy, int screen, int subpixel)
6341f0ac6a5Smrg{
6351f0ac6a5Smrg    XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
6361f0ac6a5Smrg    XRenderInfo	    *xri;
6371f0ac6a5Smrg
6381f0ac6a5Smrg    if (!RenderHasExtension (info))
6391f0ac6a5Smrg	return False;
6401f0ac6a5Smrg
6411f0ac6a5Smrg    if (!XRenderQueryFormats (dpy))
6421f0ac6a5Smrg	return False;
6431f0ac6a5Smrg
6441f0ac6a5Smrg    xri = info->info;
6451f0ac6a5Smrg    xri->screen[screen].subpixel = subpixel;
6461f0ac6a5Smrg    return True;
6471f0ac6a5Smrg}
6481f0ac6a5Smrg
6491f0ac6a5SmrgXRenderPictFormat *
6501f0ac6a5SmrgXRenderFindVisualFormat (Display *dpy, _Xconst Visual *visual)
6511f0ac6a5Smrg{
6521f0ac6a5Smrg    XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
6531f0ac6a5Smrg    int		    nv;
6541f0ac6a5Smrg    XRenderInfo	    *xri;
6551f0ac6a5Smrg    XRenderVisual   *xrv;
656e5410a46Smrg
657e5410a46Smrg    RenderCheckExtension (dpy, info, NULL);
6581f0ac6a5Smrg    if (!XRenderQueryFormats (dpy))
659e5410a46Smrg        return NULL;
6601f0ac6a5Smrg    xri = info->info;
6611f0ac6a5Smrg    for (nv = 0, xrv = xri->visual; nv < xri->nvisual; nv++, xrv++)
6621f0ac6a5Smrg	if (xrv->visual == visual)
6631f0ac6a5Smrg	    return xrv->format;
664e5410a46Smrg    return NULL;
6651f0ac6a5Smrg}
6661f0ac6a5Smrg
6671f0ac6a5SmrgXRenderPictFormat *
6681f0ac6a5SmrgXRenderFindFormat (Display		*dpy,
6691f0ac6a5Smrg		   unsigned long	mask,
6701f0ac6a5Smrg		   _Xconst XRenderPictFormat	*template,
6711f0ac6a5Smrg		   int			count)
6721f0ac6a5Smrg{
6731f0ac6a5Smrg    XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
6741f0ac6a5Smrg    int		    nf;
6751f0ac6a5Smrg    XRenderInfo     *xri;
676e5410a46Smrg
677e5410a46Smrg    RenderCheckExtension (dpy, info, NULL);
6781f0ac6a5Smrg    if (!XRenderQueryFormats (dpy))
679e5410a46Smrg	return NULL;
6801f0ac6a5Smrg    xri = info->info;
6811f0ac6a5Smrg    for (nf = 0; nf < xri->nformat; nf++)
6821f0ac6a5Smrg    {
6831f0ac6a5Smrg	if (mask & PictFormatID)
6841f0ac6a5Smrg	    if (template->id != xri->format[nf].id)
6851f0ac6a5Smrg		continue;
6861f0ac6a5Smrg	if (mask & PictFormatType)
6871f0ac6a5Smrg	if (template->type != xri->format[nf].type)
6881f0ac6a5Smrg		continue;
6891f0ac6a5Smrg	if (mask & PictFormatDepth)
6901f0ac6a5Smrg	    if (template->depth != xri->format[nf].depth)
6911f0ac6a5Smrg		continue;
6921f0ac6a5Smrg	if (mask & PictFormatRed)
6931f0ac6a5Smrg	    if (template->direct.red != xri->format[nf].direct.red)
6941f0ac6a5Smrg		continue;
6951f0ac6a5Smrg	if (mask & PictFormatRedMask)
6961f0ac6a5Smrg	    if (template->direct.redMask != xri->format[nf].direct.redMask)
6971f0ac6a5Smrg		continue;
6981f0ac6a5Smrg	if (mask & PictFormatGreen)
6991f0ac6a5Smrg	    if (template->direct.green != xri->format[nf].direct.green)
7001f0ac6a5Smrg		continue;
7011f0ac6a5Smrg	if (mask & PictFormatGreenMask)
7021f0ac6a5Smrg	    if (template->direct.greenMask != xri->format[nf].direct.greenMask)
7031f0ac6a5Smrg		continue;
7041f0ac6a5Smrg	if (mask & PictFormatBlue)
7051f0ac6a5Smrg	    if (template->direct.blue != xri->format[nf].direct.blue)
7061f0ac6a5Smrg		continue;
7071f0ac6a5Smrg	if (mask & PictFormatBlueMask)
7081f0ac6a5Smrg	    if (template->direct.blueMask != xri->format[nf].direct.blueMask)
7091f0ac6a5Smrg		continue;
7101f0ac6a5Smrg	if (mask & PictFormatAlpha)
7111f0ac6a5Smrg	    if (template->direct.alpha != xri->format[nf].direct.alpha)
7121f0ac6a5Smrg		continue;
7131f0ac6a5Smrg	if (mask & PictFormatAlphaMask)
7141f0ac6a5Smrg	    if (template->direct.alphaMask != xri->format[nf].direct.alphaMask)
7151f0ac6a5Smrg		continue;
7161f0ac6a5Smrg	if (mask & PictFormatColormap)
7171f0ac6a5Smrg	    if (template->colormap != xri->format[nf].colormap)
7181f0ac6a5Smrg		continue;
7191f0ac6a5Smrg	if (count-- == 0)
7201f0ac6a5Smrg	    return &xri->format[nf];
7211f0ac6a5Smrg    }
722e5410a46Smrg    return NULL;
7231f0ac6a5Smrg}
7241f0ac6a5Smrg
7251f0ac6a5SmrgXRenderPictFormat *
7261f0ac6a5SmrgXRenderFindStandardFormat (Display  *dpy,
7271f0ac6a5Smrg			   int	    format)
7281f0ac6a5Smrg{
7291f0ac6a5Smrg    static struct {
7301f0ac6a5Smrg	XRenderPictFormat   templ;
7311f0ac6a5Smrg	unsigned long	    mask;
7321f0ac6a5Smrg    } standardFormats[PictStandardNUM] = {
7331f0ac6a5Smrg	/* PictStandardARGB32 */
7341f0ac6a5Smrg	{
7351f0ac6a5Smrg	    {
7361f0ac6a5Smrg		0,			    /* id */
7371f0ac6a5Smrg		PictTypeDirect,		    /* type */
7381f0ac6a5Smrg		32,			    /* depth */
7391f0ac6a5Smrg		{			    /* direct */
7401f0ac6a5Smrg		    16,			    /* direct.red */
7411f0ac6a5Smrg		    0xff,		    /* direct.redMask */
7421f0ac6a5Smrg		    8,			    /* direct.green */
7431f0ac6a5Smrg		    0xff,		    /* direct.greenMask */
7441f0ac6a5Smrg		    0,			    /* direct.blue */
7451f0ac6a5Smrg		    0xff,		    /* direct.blueMask */
7461f0ac6a5Smrg		    24,			    /* direct.alpha */
7471f0ac6a5Smrg		    0xff,		    /* direct.alphaMask */
7481f0ac6a5Smrg		},
7491f0ac6a5Smrg		0,			    /* colormap */
7501f0ac6a5Smrg	    },
7516fae4e5dSmrg	    PictFormatType |
7521f0ac6a5Smrg	    PictFormatDepth |
7531f0ac6a5Smrg	    PictFormatRed |
7541f0ac6a5Smrg	    PictFormatRedMask |
7551f0ac6a5Smrg	    PictFormatGreen |
7561f0ac6a5Smrg	    PictFormatGreenMask |
7571f0ac6a5Smrg	    PictFormatBlue |
7581f0ac6a5Smrg	    PictFormatBlueMask |
7591f0ac6a5Smrg	    PictFormatAlpha |
7601f0ac6a5Smrg	    PictFormatAlphaMask,
7611f0ac6a5Smrg	},
7621f0ac6a5Smrg	/* PictStandardRGB24 */
7631f0ac6a5Smrg	{
7641f0ac6a5Smrg	    {
7651f0ac6a5Smrg		0,			    /* id */
7661f0ac6a5Smrg		PictTypeDirect,		    /* type */
7671f0ac6a5Smrg		24,			    /* depth */
7681f0ac6a5Smrg		{			    /* direct */
7691f0ac6a5Smrg		    16,			    /* direct.red */
7701f0ac6a5Smrg		    0xff,		    /* direct.redMask */
7711f0ac6a5Smrg		    8,			    /* direct.green */
7721f0ac6a5Smrg		    0xff,		    /* direct.greenMask */
7731f0ac6a5Smrg		    0,			    /* direct.blue */
7741f0ac6a5Smrg		    0xff,		    /* direct.blueMask */
7751f0ac6a5Smrg		    0,			    /* direct.alpha */
7761f0ac6a5Smrg		    0x00,		    /* direct.alphaMask */
7771f0ac6a5Smrg		},
7781f0ac6a5Smrg		0,			    /* colormap */
7791f0ac6a5Smrg	    },
7806fae4e5dSmrg	    PictFormatType |
7811f0ac6a5Smrg	    PictFormatDepth |
7821f0ac6a5Smrg	    PictFormatRed |
7831f0ac6a5Smrg	    PictFormatRedMask |
7841f0ac6a5Smrg	    PictFormatGreen |
7851f0ac6a5Smrg	    PictFormatGreenMask |
7861f0ac6a5Smrg	    PictFormatBlue |
7871f0ac6a5Smrg	    PictFormatBlueMask |
7881f0ac6a5Smrg	    PictFormatAlphaMask,
7891f0ac6a5Smrg	},
7901f0ac6a5Smrg	/* PictStandardA8 */
7911f0ac6a5Smrg	{
7921f0ac6a5Smrg	    {
7931f0ac6a5Smrg		0,			    /* id */
7941f0ac6a5Smrg		PictTypeDirect,		    /* type */
7951f0ac6a5Smrg		8,			    /* depth */
7961f0ac6a5Smrg		{			    /* direct */
7971f0ac6a5Smrg		    0,			    /* direct.red */
7981f0ac6a5Smrg		    0x00,		    /* direct.redMask */
7991f0ac6a5Smrg		    0,			    /* direct.green */
8001f0ac6a5Smrg		    0x00,		    /* direct.greenMask */
8011f0ac6a5Smrg		    0,			    /* direct.blue */
8021f0ac6a5Smrg		    0x00,		    /* direct.blueMask */
8031f0ac6a5Smrg		    0,			    /* direct.alpha */
8041f0ac6a5Smrg		    0xff,		    /* direct.alphaMask */
8051f0ac6a5Smrg		},
8061f0ac6a5Smrg		0,			    /* colormap */
8071f0ac6a5Smrg	    },
8086fae4e5dSmrg	    PictFormatType |
8091f0ac6a5Smrg	    PictFormatDepth |
8101f0ac6a5Smrg	    PictFormatRedMask |
8111f0ac6a5Smrg	    PictFormatGreenMask |
8121f0ac6a5Smrg	    PictFormatBlueMask |
8131f0ac6a5Smrg	    PictFormatAlpha |
8141f0ac6a5Smrg	    PictFormatAlphaMask,
8151f0ac6a5Smrg	},
8161f0ac6a5Smrg	/* PictStandardA4 */
8171f0ac6a5Smrg	{
8181f0ac6a5Smrg	    {
8191f0ac6a5Smrg		0,			    /* id */
8201f0ac6a5Smrg		PictTypeDirect,		    /* type */
8211f0ac6a5Smrg		4,			    /* depth */
8221f0ac6a5Smrg		{			    /* direct */
8231f0ac6a5Smrg		    0,			    /* direct.red */
8241f0ac6a5Smrg		    0x00,		    /* direct.redMask */
8251f0ac6a5Smrg		    0,			    /* direct.green */
8261f0ac6a5Smrg		    0x00,		    /* direct.greenMask */
8271f0ac6a5Smrg		    0,			    /* direct.blue */
8281f0ac6a5Smrg		    0x00,		    /* direct.blueMask */
8291f0ac6a5Smrg		    0,			    /* direct.alpha */
8301f0ac6a5Smrg		    0x0f,		    /* direct.alphaMask */
8311f0ac6a5Smrg		},
8321f0ac6a5Smrg		0,			    /* colormap */
8331f0ac6a5Smrg	    },
8346fae4e5dSmrg	    PictFormatType |
8351f0ac6a5Smrg	    PictFormatDepth |
8361f0ac6a5Smrg	    PictFormatRedMask |
8371f0ac6a5Smrg	    PictFormatGreenMask |
8381f0ac6a5Smrg	    PictFormatBlueMask |
8391f0ac6a5Smrg	    PictFormatAlpha |
8401f0ac6a5Smrg	    PictFormatAlphaMask,
8411f0ac6a5Smrg	},
8421f0ac6a5Smrg	/* PictStandardA1 */
8431f0ac6a5Smrg	{
8441f0ac6a5Smrg	    {
8451f0ac6a5Smrg		0,			    /* id */
8461f0ac6a5Smrg		PictTypeDirect,		    /* type */
8471f0ac6a5Smrg		1,			    /* depth */
8481f0ac6a5Smrg		{			    /* direct */
8491f0ac6a5Smrg		    0,			    /* direct.red */
8501f0ac6a5Smrg		    0x00,		    /* direct.redMask */
8511f0ac6a5Smrg		    0,			    /* direct.green */
8521f0ac6a5Smrg		    0x00,		    /* direct.greenMask */
8531f0ac6a5Smrg		    0,			    /* direct.blue */
8541f0ac6a5Smrg		    0x00,		    /* direct.blueMask */
8551f0ac6a5Smrg		    0,			    /* direct.alpha */
8561f0ac6a5Smrg		    0x01,		    /* direct.alphaMask */
8571f0ac6a5Smrg		},
8581f0ac6a5Smrg		0,			    /* colormap */
8591f0ac6a5Smrg	    },
8606fae4e5dSmrg	    PictFormatType |
8611f0ac6a5Smrg	    PictFormatDepth |
8621f0ac6a5Smrg	    PictFormatRedMask |
8631f0ac6a5Smrg	    PictFormatGreenMask |
8641f0ac6a5Smrg	    PictFormatBlueMask |
8651f0ac6a5Smrg	    PictFormatAlpha |
8661f0ac6a5Smrg	    PictFormatAlphaMask,
8671f0ac6a5Smrg	},
8681f0ac6a5Smrg    };
8691f0ac6a5Smrg
8701f0ac6a5Smrg    if (0 <= format && format < PictStandardNUM)
8716fae4e5dSmrg	return XRenderFindFormat (dpy,
8721f0ac6a5Smrg				  standardFormats[format].mask,
8731f0ac6a5Smrg				  &standardFormats[format].templ,
8741f0ac6a5Smrg				  0);
875e5410a46Smrg    return NULL;
8761f0ac6a5Smrg}
8771f0ac6a5Smrg
8781f0ac6a5SmrgXIndexValue *
8791f0ac6a5SmrgXRenderQueryPictIndexValues(Display			*dpy,
8801f0ac6a5Smrg			    _Xconst XRenderPictFormat	*format,
8811f0ac6a5Smrg			    int				*num)
8821f0ac6a5Smrg{
88353bb355aSmrg    XRenderExtDisplayInfo		*info = XRenderFindDisplay (dpy);
8841f0ac6a5Smrg    xRenderQueryPictIndexValuesReq	*req;
8851f0ac6a5Smrg    xRenderQueryPictIndexValuesReply	rep;
8861f0ac6a5Smrg    XIndexValue				*values;
88753bb355aSmrg    unsigned int			nbytes, nread, i;
8881f0ac6a5Smrg
889e5410a46Smrg    RenderCheckExtension (dpy, info, NULL);
8901f0ac6a5Smrg
8911f0ac6a5Smrg    LockDisplay (dpy);
8921f0ac6a5Smrg    GetReq (RenderQueryPictIndexValues, req);
89353bb355aSmrg    req->reqType       = (CARD8) info->codes->major_opcode;
8941f0ac6a5Smrg    req->renderReqType = X_RenderQueryPictIndexValues;
89553bb355aSmrg    req->format        = (CARD32) format->id;
8961f0ac6a5Smrg    if (!_XReply (dpy, (xReply *) &rep, 0, xFalse))
8971f0ac6a5Smrg    {
8981f0ac6a5Smrg	UnlockDisplay (dpy);
8991f0ac6a5Smrg	SyncHandle ();
900e5410a46Smrg	return NULL;
9011f0ac6a5Smrg    }
9021f0ac6a5Smrg
903190694daSmrg    if ((rep.length < (INT_MAX >> 2)) &&
904190694daSmrg	(rep.numIndexValues < (INT_MAX / sizeof (XIndexValue)))) {
90553bb355aSmrg	unsigned int rlength;
906190694daSmrg	/* request data length */
907190694daSmrg	nbytes = rep.length << 2;
908190694daSmrg	/* bytes of actual data in the request */
909190694daSmrg	nread = rep.numIndexValues * SIZEOF (xIndexValue);
910190694daSmrg	/* size of array returned to application */
91153bb355aSmrg	rlength = (unsigned) ((unsigned long) rep.numIndexValues * sizeof (XIndexValue));
912190694daSmrg
913190694daSmrg	/* allocate returned data */
914190694daSmrg	values = Xmalloc (rlength);
915190694daSmrg    } else {
91653bb355aSmrg	nbytes = nread = 0;
917190694daSmrg	values = NULL;
918190694daSmrg    }
9191f0ac6a5Smrg
9201f0ac6a5Smrg    if (!values)
9211f0ac6a5Smrg    {
922cc1b55f9Smrg	_XEatDataWords (dpy, rep.length);
9231f0ac6a5Smrg	UnlockDisplay (dpy);
9241f0ac6a5Smrg	SyncHandle ();
925e5410a46Smrg	return NULL;
9261f0ac6a5Smrg    }
9271f0ac6a5Smrg
9281f0ac6a5Smrg    /* read the values one at a time and convert */
92953bb355aSmrg    *num = (int) rep.numIndexValues;
93053bb355aSmrg    for (i = 0; i < rep.numIndexValues; i++)
9311f0ac6a5Smrg    {
9321f0ac6a5Smrg	xIndexValue value;
9336fae4e5dSmrg
9341f0ac6a5Smrg	_XRead (dpy, (char *) &value, SIZEOF (xIndexValue));
9351f0ac6a5Smrg	values[i].pixel = value.pixel;
9361f0ac6a5Smrg	values[i].red = value.red;
9371f0ac6a5Smrg	values[i].green = value.green;
9381f0ac6a5Smrg	values[i].blue = value.blue;
9391f0ac6a5Smrg	values[i].alpha = value.alpha;
9401f0ac6a5Smrg    }
9411f0ac6a5Smrg    /* skip any padding */
9421f0ac6a5Smrg    if(nbytes > nread)
9431f0ac6a5Smrg    {
9441f0ac6a5Smrg	_XEatData (dpy, (unsigned long) (nbytes - nread));
9451f0ac6a5Smrg    }
9461f0ac6a5Smrg    UnlockDisplay (dpy);
9471f0ac6a5Smrg    SyncHandle ();
9481f0ac6a5Smrg    return values;
9491f0ac6a5Smrg}
950