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