mirror of OpenBSD xenocara tree
github.com/openbsd/xenocara
openbsd
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
31XRenderExtInfo XRenderExtensionInfo;
32char XRenderExtensionName[] = RENDER_NAME;
33
34static 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 */
41static XRenderExtDisplayInfo *
42XRenderExtFindDisplay (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
86typedef struct _DepthCheckRec {
87 struct _DepthCheckRec *next;
88 Display *dpy;
89 CARD32 missing;
90 unsigned long serial;
91} DepthCheckRec, *DepthCheckPtr;
92
93static DepthCheckPtr depthChecks;
94
95static int
96XRenderDepthCheckErrorHandler (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
117static Bool
118XRenderHasDepths (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 */
193static XRenderExtDisplayInfo *
194XRenderExtAddDisplay (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 */
248static int
249XRenderExtRemoveDisplay (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
285XRenderExtDisplayInfo *
286XRenderFindDisplay (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
297static void
298XRenderFreeXRenderInfo (XRenderInfo *xri)
299{
300 Xfree(xri->format);
301 Xfree(xri->screen);
302 Xfree(xri->depth);
303 Xfree(xri->visual);
304 Xfree(xri);
305}
306
307static int
308XRenderCloseDisplay (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
322Bool 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
336Status 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
355static 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
366static Visual *
367_XRenderFindVisual (Display *dpy, VisualID vid)
368{
369 return _XVIDtoVisual (dpy, vid);
370}
371
372typedef struct _renderVersionState {
373 unsigned long version_seq;
374 Bool error;
375 int major_version;
376 int minor_version;
377
378} _XrenderVersionState;
379
380static 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
407Status
408XRenderQueryFormats (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
616int
617XRenderQuerySubpixelOrder (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
632Bool
633XRenderSetSubpixelOrder (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
649XRenderPictFormat *
650XRenderFindVisualFormat (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
667XRenderPictFormat *
668XRenderFindFormat (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
725XRenderPictFormat *
726XRenderFindStandardFormat (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
878XIndexValue *
879XRenderQueryPictIndexValues(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}