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.length < (INT_MAX >> 2)) ) {
    482         /* Zero-initialize so that pointers are NULL if there is a failure. */
    483 	xri = Xcalloc (1, sizeof (XRenderInfo));
    484 	rlength = ((rep.numFormats * sizeof (xPictFormInfo)) +
    485 		   (rep.numScreens * sizeof (xPictScreen)) +
    486 		   (rep.numDepths * sizeof (xPictDepth)) +
    487 		   (rep.numVisuals * sizeof (xPictVisual)) +
    488 		   (rep.numSubpixel * 4));
    489 	xData = Xmalloc (rlength);
    490 	nbytes = (unsigned long) rep.length << 2;
    491     } else {
    492 	xri = NULL;
    493 	xData = NULL;
    494 	rlength = nbytes = 0;
    495     }
    496 
    497     if (!xri || !xData || nbytes < rlength)
    498     {
    499 	if (xri) Xfree (xri);
    500 	if (xData) Xfree (xData);
    501 	_XEatDataWords (dpy, rep.length);
    502 	UnlockDisplay (dpy);
    503 	SyncHandle ();
    504 	return 0;
    505     }
    506     xri->major_version = async_state.major_version;
    507     xri->minor_version = async_state.minor_version;
    508     xri->format = Xcalloc(rep.numFormats, sizeof(XRenderPictFormat));
    509     xri->nformat = (int) rep.numFormats;
    510     xri->screen = Xcalloc(rep.numScreens, sizeof(XRenderScreen));
    511     xri->nscreen = (int) rep.numScreens;
    512     xri->depth = Xcalloc(rep.numDepths, sizeof(XRenderDepth));
    513     xri->ndepth = (int) rep.numDepths;
    514     xri->visual = Xcalloc(rep.numVisuals, sizeof(XRenderVisual));
    515     xri->nvisual = (int) rep.numVisuals;
    516     if (!xri->format || !xri->screen || !xri->depth || !xri->visual)
    517     {
    518 	XRenderFreeXRenderInfo(xri);
    519 	Xfree (xData);
    520 	_XEatDataWords (dpy, rep.length);
    521 	UnlockDisplay (dpy);
    522 	SyncHandle ();
    523 	return 0;
    524     }
    525     _XRead (dpy, (char *) xData, (long) rlength);
    526     format = xri->format;
    527     xFormat = (xPictFormInfo *) xData;
    528     for (nf = 0; nf < rep.numFormats; nf++)
    529     {
    530 	format->id = xFormat->id;
    531 	format->type = xFormat->type;
    532 	format->depth = xFormat->depth;
    533 	format->direct.red       = (short) xFormat->direct.red;
    534 	format->direct.redMask   = (short) xFormat->direct.redMask;
    535 	format->direct.green     = (short) xFormat->direct.green;
    536 	format->direct.greenMask = (short) xFormat->direct.greenMask;
    537 	format->direct.blue      = (short) xFormat->direct.blue;
    538 	format->direct.blueMask  = (short) xFormat->direct.blueMask;
    539 	format->direct.alpha     = (short) xFormat->direct.alpha;
    540 	format->direct.alphaMask = (short) xFormat->direct.alphaMask;
    541 	format->colormap = xFormat->colormap;
    542 	format++;
    543 	xFormat++;
    544     }
    545     xScreen = (xPictScreen *) xFormat;
    546     screen = xri->screen;
    547     depth = xri->depth;
    548     visual = xri->visual;
    549     for (ns = 0; ns < xri->nscreen; ns++)
    550     {
    551 	screen->depths = depth;
    552 	screen->ndepths = (int) xScreen->nDepth;
    553 	screen->fallback = _XRenderFindFormat (xri, xScreen->fallback);
    554 	screen->subpixel = SubPixelUnknown;
    555 	xPDepth = (xPictDepth *) (xScreen + 1);
    556 	if (screen->ndepths > rep.numDepths) {
    557 	    XRenderFreeXRenderInfo(xri);
    558 	    Xfree (xData);
    559 	    _XEatDataWords (dpy, rep.length);
    560 	    UnlockDisplay (dpy);
    561 	    SyncHandle ();
    562 	    return 0;
    563 	}
    564 	rep.numDepths -= (CARD32) screen->ndepths;
    565 	for (nd = 0; nd < screen->ndepths; nd++)
    566 	{
    567 	    int nv;
    568 
    569 	    depth->depth = xPDepth->depth;
    570 	    depth->nvisuals = xPDepth->nPictVisuals;
    571 	    depth->visuals = visual;
    572 	    xVisual = (xPictVisual *) (xPDepth + 1);
    573 	    if (depth->nvisuals > rep.numVisuals) {
    574 		XRenderFreeXRenderInfo (xri);
    575 		Xfree (xData);
    576 		_XEatDataWords (dpy, rep.length);
    577 		UnlockDisplay (dpy);
    578 		SyncHandle ();
    579 		return 0;
    580 	    }
    581 	    rep.numVisuals -= (CARD32) depth->nvisuals;
    582 	    for (nv = 0; nv < depth->nvisuals; nv++)
    583 	    {
    584 		visual->visual = _XRenderFindVisual (dpy, xVisual->visual);
    585 		visual->format = _XRenderFindFormat (xri, xVisual->format);
    586 		visual++;
    587 		xVisual++;
    588 	    }
    589 	    depth++;
    590 	    xPDepth = (xPictDepth *) xVisual;
    591 	}
    592 	screen++;
    593 	xScreen = (xPictScreen *) xPDepth;
    594     }
    595     xSubpixel = (CARD32 *) xScreen;
    596     screen = xri->screen;
    597     for (ns = 0; ns < rep.numSubpixel; ns++)
    598     {
    599 	screen->subpixel = (int) *xSubpixel;
    600 	xSubpixel++;
    601 	screen++;
    602     }
    603     info->info = xri;
    604     /*
    605      * Skip any extra data
    606      */
    607     if (nbytes > rlength)
    608 	_XEatData (dpy, (unsigned long) (nbytes - rlength));
    609 
    610     UnlockDisplay (dpy);
    611     SyncHandle ();
    612     Xfree (xData);
    613     return 1;
    614 }
    615 
    616 int
    617 XRenderQuerySubpixelOrder (Display *dpy, int screen)
    618 {
    619     XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
    620     XRenderInfo	    *xri;
    621 
    622     if (!RenderHasExtension (info))
    623 	return SubPixelUnknown;
    624 
    625     if (!XRenderQueryFormats (dpy))
    626 	return SubPixelUnknown;
    627 
    628     xri = info->info;
    629     return xri->screen[screen].subpixel;
    630 }
    631 
    632 Bool
    633 XRenderSetSubpixelOrder (Display *dpy, int screen, int subpixel)
    634 {
    635     XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
    636     XRenderInfo	    *xri;
    637 
    638     if (!RenderHasExtension (info))
    639 	return False;
    640 
    641     if (!XRenderQueryFormats (dpy))
    642 	return False;
    643 
    644     xri = info->info;
    645     xri->screen[screen].subpixel = subpixel;
    646     return True;
    647 }
    648 
    649 XRenderPictFormat *
    650 XRenderFindVisualFormat (Display *dpy, _Xconst Visual *visual)
    651 {
    652     XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
    653     int		    nv;
    654     XRenderInfo	    *xri;
    655     XRenderVisual   *xrv;
    656 
    657     RenderCheckExtension (dpy, info, NULL);
    658     if (!XRenderQueryFormats (dpy))
    659         return NULL;
    660     xri = info->info;
    661     for (nv = 0, xrv = xri->visual; nv < xri->nvisual; nv++, xrv++)
    662 	if (xrv->visual == visual)
    663 	    return xrv->format;
    664     return NULL;
    665 }
    666 
    667 XRenderPictFormat *
    668 XRenderFindFormat (Display		*dpy,
    669 		   unsigned long	mask,
    670 		   _Xconst XRenderPictFormat	*template,
    671 		   int			count)
    672 {
    673     XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
    674     int		    nf;
    675     XRenderInfo     *xri;
    676 
    677     RenderCheckExtension (dpy, info, NULL);
    678     if (!XRenderQueryFormats (dpy))
    679 	return NULL;
    680     xri = info->info;
    681     for (nf = 0; nf < xri->nformat; nf++)
    682     {
    683 	if (mask & PictFormatID)
    684 	    if (template->id != xri->format[nf].id)
    685 		continue;
    686 	if (mask & PictFormatType)
    687 	if (template->type != xri->format[nf].type)
    688 		continue;
    689 	if (mask & PictFormatDepth)
    690 	    if (template->depth != xri->format[nf].depth)
    691 		continue;
    692 	if (mask & PictFormatRed)
    693 	    if (template->direct.red != xri->format[nf].direct.red)
    694 		continue;
    695 	if (mask & PictFormatRedMask)
    696 	    if (template->direct.redMask != xri->format[nf].direct.redMask)
    697 		continue;
    698 	if (mask & PictFormatGreen)
    699 	    if (template->direct.green != xri->format[nf].direct.green)
    700 		continue;
    701 	if (mask & PictFormatGreenMask)
    702 	    if (template->direct.greenMask != xri->format[nf].direct.greenMask)
    703 		continue;
    704 	if (mask & PictFormatBlue)
    705 	    if (template->direct.blue != xri->format[nf].direct.blue)
    706 		continue;
    707 	if (mask & PictFormatBlueMask)
    708 	    if (template->direct.blueMask != xri->format[nf].direct.blueMask)
    709 		continue;
    710 	if (mask & PictFormatAlpha)
    711 	    if (template->direct.alpha != xri->format[nf].direct.alpha)
    712 		continue;
    713 	if (mask & PictFormatAlphaMask)
    714 	    if (template->direct.alphaMask != xri->format[nf].direct.alphaMask)
    715 		continue;
    716 	if (mask & PictFormatColormap)
    717 	    if (template->colormap != xri->format[nf].colormap)
    718 		continue;
    719 	if (count-- == 0)
    720 	    return &xri->format[nf];
    721     }
    722     return NULL;
    723 }
    724 
    725 XRenderPictFormat *
    726 XRenderFindStandardFormat (Display  *dpy,
    727 			   int	    format)
    728 {
    729     static struct {
    730 	XRenderPictFormat   templ;
    731 	unsigned long	    mask;
    732     } standardFormats[PictStandardNUM] = {
    733 	/* PictStandardARGB32 */
    734 	{
    735 	    {
    736 		0,			    /* id */
    737 		PictTypeDirect,		    /* type */
    738 		32,			    /* depth */
    739 		{			    /* direct */
    740 		    16,			    /* direct.red */
    741 		    0xff,		    /* direct.redMask */
    742 		    8,			    /* direct.green */
    743 		    0xff,		    /* direct.greenMask */
    744 		    0,			    /* direct.blue */
    745 		    0xff,		    /* direct.blueMask */
    746 		    24,			    /* direct.alpha */
    747 		    0xff,		    /* direct.alphaMask */
    748 		},
    749 		0,			    /* colormap */
    750 	    },
    751 	    PictFormatType |
    752 	    PictFormatDepth |
    753 	    PictFormatRed |
    754 	    PictFormatRedMask |
    755 	    PictFormatGreen |
    756 	    PictFormatGreenMask |
    757 	    PictFormatBlue |
    758 	    PictFormatBlueMask |
    759 	    PictFormatAlpha |
    760 	    PictFormatAlphaMask,
    761 	},
    762 	/* PictStandardRGB24 */
    763 	{
    764 	    {
    765 		0,			    /* id */
    766 		PictTypeDirect,		    /* type */
    767 		24,			    /* depth */
    768 		{			    /* direct */
    769 		    16,			    /* direct.red */
    770 		    0xff,		    /* direct.redMask */
    771 		    8,			    /* direct.green */
    772 		    0xff,		    /* direct.greenMask */
    773 		    0,			    /* direct.blue */
    774 		    0xff,		    /* direct.blueMask */
    775 		    0,			    /* direct.alpha */
    776 		    0x00,		    /* direct.alphaMask */
    777 		},
    778 		0,			    /* colormap */
    779 	    },
    780 	    PictFormatType |
    781 	    PictFormatDepth |
    782 	    PictFormatRed |
    783 	    PictFormatRedMask |
    784 	    PictFormatGreen |
    785 	    PictFormatGreenMask |
    786 	    PictFormatBlue |
    787 	    PictFormatBlueMask |
    788 	    PictFormatAlphaMask,
    789 	},
    790 	/* PictStandardA8 */
    791 	{
    792 	    {
    793 		0,			    /* id */
    794 		PictTypeDirect,		    /* type */
    795 		8,			    /* depth */
    796 		{			    /* direct */
    797 		    0,			    /* direct.red */
    798 		    0x00,		    /* direct.redMask */
    799 		    0,			    /* direct.green */
    800 		    0x00,		    /* direct.greenMask */
    801 		    0,			    /* direct.blue */
    802 		    0x00,		    /* direct.blueMask */
    803 		    0,			    /* direct.alpha */
    804 		    0xff,		    /* direct.alphaMask */
    805 		},
    806 		0,			    /* colormap */
    807 	    },
    808 	    PictFormatType |
    809 	    PictFormatDepth |
    810 	    PictFormatRedMask |
    811 	    PictFormatGreenMask |
    812 	    PictFormatBlueMask |
    813 	    PictFormatAlpha |
    814 	    PictFormatAlphaMask,
    815 	},
    816 	/* PictStandardA4 */
    817 	{
    818 	    {
    819 		0,			    /* id */
    820 		PictTypeDirect,		    /* type */
    821 		4,			    /* depth */
    822 		{			    /* direct */
    823 		    0,			    /* direct.red */
    824 		    0x00,		    /* direct.redMask */
    825 		    0,			    /* direct.green */
    826 		    0x00,		    /* direct.greenMask */
    827 		    0,			    /* direct.blue */
    828 		    0x00,		    /* direct.blueMask */
    829 		    0,			    /* direct.alpha */
    830 		    0x0f,		    /* direct.alphaMask */
    831 		},
    832 		0,			    /* colormap */
    833 	    },
    834 	    PictFormatType |
    835 	    PictFormatDepth |
    836 	    PictFormatRedMask |
    837 	    PictFormatGreenMask |
    838 	    PictFormatBlueMask |
    839 	    PictFormatAlpha |
    840 	    PictFormatAlphaMask,
    841 	},
    842 	/* PictStandardA1 */
    843 	{
    844 	    {
    845 		0,			    /* id */
    846 		PictTypeDirect,		    /* type */
    847 		1,			    /* depth */
    848 		{			    /* direct */
    849 		    0,			    /* direct.red */
    850 		    0x00,		    /* direct.redMask */
    851 		    0,			    /* direct.green */
    852 		    0x00,		    /* direct.greenMask */
    853 		    0,			    /* direct.blue */
    854 		    0x00,		    /* direct.blueMask */
    855 		    0,			    /* direct.alpha */
    856 		    0x01,		    /* direct.alphaMask */
    857 		},
    858 		0,			    /* colormap */
    859 	    },
    860 	    PictFormatType |
    861 	    PictFormatDepth |
    862 	    PictFormatRedMask |
    863 	    PictFormatGreenMask |
    864 	    PictFormatBlueMask |
    865 	    PictFormatAlpha |
    866 	    PictFormatAlphaMask,
    867 	},
    868     };
    869 
    870     if (0 <= format && format < PictStandardNUM)
    871 	return XRenderFindFormat (dpy,
    872 				  standardFormats[format].mask,
    873 				  &standardFormats[format].templ,
    874 				  0);
    875     return NULL;
    876 }
    877 
    878 XIndexValue *
    879 XRenderQueryPictIndexValues(Display			*dpy,
    880 			    _Xconst XRenderPictFormat	*format,
    881 			    int				*num)
    882 {
    883     XRenderExtDisplayInfo		*info = XRenderFindDisplay (dpy);
    884     xRenderQueryPictIndexValuesReq	*req;
    885     xRenderQueryPictIndexValuesReply	rep;
    886     XIndexValue				*values;
    887     unsigned int			nbytes, nread, i;
    888 
    889     RenderCheckExtension (dpy, info, NULL);
    890 
    891     LockDisplay (dpy);
    892     GetReq (RenderQueryPictIndexValues, req);
    893     req->reqType       = (CARD8) info->codes->major_opcode;
    894     req->renderReqType = X_RenderQueryPictIndexValues;
    895     req->format        = (CARD32) format->id;
    896     if (!_XReply (dpy, (xReply *) &rep, 0, xFalse))
    897     {
    898 	UnlockDisplay (dpy);
    899 	SyncHandle ();
    900 	return NULL;
    901     }
    902 
    903     if ((rep.length < (INT_MAX >> 2)) &&
    904 	(rep.numIndexValues < (INT_MAX / sizeof (XIndexValue)))) {
    905 	unsigned int rlength;
    906 	/* request data length */
    907 	nbytes = rep.length << 2;
    908 	/* bytes of actual data in the request */
    909 	nread = rep.numIndexValues * SIZEOF (xIndexValue);
    910 	/* size of array returned to application */
    911 	rlength = (unsigned) ((unsigned long) rep.numIndexValues * sizeof (XIndexValue));
    912 
    913 	/* allocate returned data */
    914 	values = Xmalloc (rlength);
    915     } else {
    916 	nbytes = nread = 0;
    917 	values = NULL;
    918     }
    919 
    920     if (!values)
    921     {
    922 	_XEatDataWords (dpy, rep.length);
    923 	UnlockDisplay (dpy);
    924 	SyncHandle ();
    925 	return NULL;
    926     }
    927 
    928     /* read the values one at a time and convert */
    929     *num = (int) rep.numIndexValues;
    930     for (i = 0; i < rep.numIndexValues; i++)
    931     {
    932 	xIndexValue value;
    933 
    934 	_XRead (dpy, (char *) &value, SIZEOF (xIndexValue));
    935 	values[i].pixel = value.pixel;
    936 	values[i].red = value.red;
    937 	values[i].green = value.green;
    938 	values[i].blue = value.blue;
    939 	values[i].alpha = value.alpha;
    940     }
    941     /* skip any padding */
    942     if(nbytes > nread)
    943     {
    944 	_XEatData (dpy, (unsigned long) (nbytes - nread));
    945     }
    946     UnlockDisplay (dpy);
    947     SyncHandle ();
    948     return values;
    949 }
    950