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