3 * Copyright © 2000 SuSE, Inc.
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.
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.
22 * Author: Keith Packard, SuSE, Inc.
28 #include "Xrenderint.h"
31 XRenderExtInfo XRenderExtensionInfo;
32 char XRenderExtensionName[] = RENDER_NAME;
34 static int XRenderCloseDisplay (Display *dpy, XExtCodes *codes);
37 * XRenderExtFindDisplay - look for a display in this extension; keeps a
38 * cache of the most-recently used for efficiency. (Replaces
41 static XRenderExtDisplayInfo *
42 XRenderExtFindDisplay (XRenderExtInfo *extinfo,
45 XRenderExtDisplayInfo *dpyinfo;
48 * see if this was the most recently accessed display
50 if ((dpyinfo = extinfo->cur) && dpyinfo->display == dpy)
54 * look for display in list
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);
64 _XUnlockMutex(_Xglobal_lock);
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.
74 #define DEPTH_MASK(d) (1U << ((d) - 1))
77 * Render requires support for depth 1, 4, 8, 24 and 32 pixmaps
80 #define REQUIRED_DEPTHS (DEPTH_MASK(1) | \
86 typedef struct _DepthCheckRec {
87 struct _DepthCheckRec *next;
91 } DepthCheckRec, *DepthCheckPtr;
93 static DepthCheckPtr depthChecks;
96 XRenderDepthCheckErrorHandler (Display *dpy, XErrorEvent *evt)
98 if (evt->request_code == X_CreatePixmap && evt->error_code == BadValue)
101 _XLockMutex(_Xglobal_lock);
102 for (d = depthChecks; d; d = d->next)
105 if ((long) (evt->serial - d->serial) >= 0)
106 d->missing |= DEPTH_MASK(evt->resourceid);
109 _XUnlockMutex (_Xglobal_lock);
115 XRenderHasDepths (Display *dpy)
119 for (s = 0; s < ScreenCount (dpy); s++)
123 Screen *scr = ScreenOfDisplay (dpy, s);
126 for (d = 0; d < scr->ndepths; d++)
127 depths |= DEPTH_MASK(scr->depths[d].depth);
128 missing = ~depths & REQUIRED_DEPTHS;
131 DepthCheckRec dc, **dp;
132 XErrorHandler previousHandler;
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.
143 dc.serial = XNextRequest (dpy);
144 _XLockMutex(_Xglobal_lock);
145 dc.next = depthChecks;
147 _XUnlockMutex (_Xglobal_lock);
149 * I suspect this is not really thread safe, but Xlib doesn't
150 * provide a lot of options here
152 previousHandler = XSetErrorHandler (XRenderDepthCheckErrorHandler);
154 * Try each missing depth and see if pixmap creation succeeds
156 for (d = 1; d <= 32; d++)
157 /* don't check depth 1 == Xcursor recurses... */
158 if ((missing & DEPTH_MASK(d)) && d != 1)
161 p = XCreatePixmap (dpy, RootWindow (dpy, s), 1, 1, d);
162 XFreePixmap (dpy, p);
165 XSetErrorHandler (previousHandler);
167 * Unhook from the list of depth check records
169 _XLockMutex(_Xglobal_lock);
170 for (dp = &depthChecks; *dp; dp = &(*dp)->next)
178 _XUnlockMutex (_Xglobal_lock);
187 * XRenderExtAddDisplay - add a display to this extension. (Replaces
190 static XRenderExtDisplayInfo *
191 XRenderExtAddDisplay (XRenderExtInfo *extinfo,
195 XRenderExtDisplayInfo *dpyinfo;
197 dpyinfo = (XRenderExtDisplayInfo *) Xmalloc (sizeof (XRenderExtDisplayInfo));
198 if (!dpyinfo) return NULL;
199 dpyinfo->display = dpy;
200 dpyinfo->info = NULL;
202 if (XRenderHasDepths (dpy))
203 dpyinfo->codes = XInitExtension (dpy, ext_name);
205 dpyinfo->codes = NULL;
208 * if the server has the extension, then we can initialize the
209 * appropriate function vectors
211 if (dpyinfo->codes) {
212 XESetCloseDisplay (dpy, dpyinfo->codes->extension,
213 XRenderCloseDisplay);
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.
220 XExtCodes *codes = XAddExtension(dpy);
225 XESetCloseDisplay (dpy, codes->extension, XRenderCloseDisplay);
229 * now, chain it onto the list
231 _XLockMutex(_Xglobal_lock);
232 dpyinfo->next = extinfo->head;
233 extinfo->head = dpyinfo;
234 extinfo->cur = dpyinfo;
235 extinfo->ndisplays++;
236 _XUnlockMutex(_Xglobal_lock);
242 * XRenderExtRemoveDisplay - remove the indicated display from the
243 * extension object. (Replaces XextRemoveDisplay.)
246 XRenderExtRemoveDisplay (XRenderExtInfo *extinfo, Display *dpy)
248 XRenderExtDisplayInfo *dpyinfo, *prev;
251 * locate this display and its back link so that it can be removed
253 _XLockMutex(_Xglobal_lock);
255 for (dpyinfo = extinfo->head; dpyinfo; dpyinfo = dpyinfo->next) {
256 if (dpyinfo->display == dpy) break;
260 _XUnlockMutex(_Xglobal_lock);
261 return 0; /* hmm, actually an error */
265 * remove the display from the list; handles going to zero
268 prev->next = dpyinfo->next;
270 extinfo->head = dpyinfo->next;
272 extinfo->ndisplays--;
273 if (dpyinfo == extinfo->cur) extinfo->cur = NULL; /* flush cache */
274 _XUnlockMutex(_Xglobal_lock);
276 Xfree ((char *) dpyinfo);
282 XRenderExtDisplayInfo *
283 XRenderFindDisplay (Display *dpy)
285 XRenderExtDisplayInfo *dpyinfo;
287 dpyinfo = XRenderExtFindDisplay (&XRenderExtensionInfo, dpy);
289 dpyinfo = XRenderExtAddDisplay (&XRenderExtensionInfo, dpy,
290 XRenderExtensionName);
295 XRenderCloseDisplay (Display *dpy, XExtCodes *codes)
297 XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
298 if (info && info->info) XFree (info->info);
300 return XRenderExtRemoveDisplay (&XRenderExtensionInfo, dpy);
303 /****************************************************************************
305 * Render public interfaces *
307 ****************************************************************************/
309 Bool XRenderQueryExtension (Display *dpy, int *event_basep, int *error_basep)
311 XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
313 if (RenderHasExtension(info)) {
314 *event_basep = info->codes->first_event;
315 *error_basep = info->codes->first_error;
323 Status XRenderQueryVersion (Display *dpy,
327 XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
330 if (!RenderHasExtension (info))
333 if (!XRenderQueryFormats (dpy))
337 *major_versionp = xri->major_version;
338 *minor_versionp = xri->minor_version;
342 static XRenderPictFormat *
343 _XRenderFindFormat (XRenderInfo *xri, PictFormat format)
347 for (nf = 0; nf < xri->nformat; nf++)
348 if (xri->format[nf].id == format)
349 return &xri->format[nf];
354 _XRenderFindVisual (Display *dpy, VisualID vid)
356 return _XVIDtoVisual (dpy, vid);
359 typedef struct _renderVersionState {
360 unsigned long version_seq;
365 } _XrenderVersionState;
368 _XRenderVersionHandler (Display *dpy,
374 xRenderQueryVersionReply replbuf;
375 xRenderQueryVersionReply *repl;
376 _XrenderVersionState *state = (_XrenderVersionState *) data;
378 if (dpy->last_request_read != state->version_seq)
380 if (rep->generic.type == X_Error)
385 repl = (xRenderQueryVersionReply *)
386 _XGetAsyncReply(dpy, (char *)&replbuf, rep, buf, len,
387 (SIZEOF(xRenderQueryVersionReply) - SIZEOF(xReply)) >> 2,
389 state->major_version = repl->majorVersion;
390 state->minor_version = repl->minorVersion;
395 XRenderQueryFormats (Display *dpy)
397 XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
398 _XAsyncHandler async;
399 _XrenderVersionState async_state;
400 xRenderQueryVersionReq *vreq;
401 xRenderQueryPictFormatsReply rep;
402 xRenderQueryPictFormatsReq *req;
404 XRenderPictFormat *format;
405 XRenderScreen *screen;
407 XRenderVisual *visual;
408 xPictFormInfo *xFormat;
409 xPictScreen *xScreen;
411 xPictVisual *xVisual;
415 unsigned long rlength;
416 unsigned long nbytes;
418 RenderCheckExtension (dpy, info, 0);
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;
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;
438 GetReq (RenderQueryPictFormats, req);
439 req->reqType = info->codes->major_opcode;
440 req->renderReqType = X_RenderQueryPictFormats;
442 if (!_XReply (dpy, (xReply *) &rep, 0, xFalse))
444 DeqAsyncHandler (dpy, &async);
449 DeqAsyncHandler (dpy, &async);
450 if (async_state.error)
457 * Check for the lack of sub-pixel data
459 if (async_state.major_version == 0 && async_state.minor_version < 6)
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;
483 rlength = nbytes = 0;
486 if (!xri || !xData || nbytes < rlength)
488 if (xri) Xfree (xri);
489 if (xData) Xfree (xData);
490 _XEatDataWords (dpy, rep.length);
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++)
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;
525 xScreen = (xPictScreen *) xFormat;
526 screen = xri->screen;
528 visual = xri->visual;
529 for (ns = 0; ns < xri->nscreen; ns++)
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 for (nd = 0; nd < screen->ndepths; nd++)
538 depth->depth = xDepth->depth;
539 depth->nvisuals = xDepth->nPictVisuals;
540 depth->visuals = visual;
541 xVisual = (xPictVisual *) (xDepth + 1);
542 for (nv = 0; nv < depth->nvisuals; nv++)
544 visual->visual = _XRenderFindVisual (dpy, xVisual->visual);
545 visual->format = _XRenderFindFormat (xri, xVisual->format);
550 xDepth = (xPictDepth *) xVisual;
553 xScreen = (xPictScreen *) xDepth;
555 xSubpixel = (CARD32 *) xScreen;
556 screen = xri->screen;
557 for (ns = 0; ns < rep.numSubpixel; ns++)
559 screen->subpixel = *xSubpixel;
565 * Skip any extra data
567 if (nbytes > rlength)
568 _XEatData (dpy, (unsigned long) (nbytes - rlength));
577 XRenderQuerySubpixelOrder (Display *dpy, int screen)
579 XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
582 if (!RenderHasExtension (info))
583 return SubPixelUnknown;
585 if (!XRenderQueryFormats (dpy))
586 return SubPixelUnknown;
589 return xri->screen[screen].subpixel;
593 XRenderSetSubpixelOrder (Display *dpy, int screen, int subpixel)
595 XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
598 if (!RenderHasExtension (info))
601 if (!XRenderQueryFormats (dpy))
605 xri->screen[screen].subpixel = subpixel;
610 XRenderFindVisualFormat (Display *dpy, _Xconst Visual *visual)
612 XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
617 RenderCheckExtension (dpy, info, NULL);
618 if (!XRenderQueryFormats (dpy))
621 for (nv = 0, xrv = xri->visual; nv < xri->nvisual; nv++, xrv++)
622 if (xrv->visual == visual)
628 XRenderFindFormat (Display *dpy,
630 _Xconst XRenderPictFormat *template,
633 XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
637 RenderCheckExtension (dpy, info, NULL);
638 if (!XRenderQueryFormats (dpy))
641 for (nf = 0; nf < xri->nformat; nf++)
643 if (mask & PictFormatID)
644 if (template->id != xri->format[nf].id)
646 if (mask & PictFormatType)
647 if (template->type != xri->format[nf].type)
649 if (mask & PictFormatDepth)
650 if (template->depth != xri->format[nf].depth)
652 if (mask & PictFormatRed)
653 if (template->direct.red != xri->format[nf].direct.red)
655 if (mask & PictFormatRedMask)
656 if (template->direct.redMask != xri->format[nf].direct.redMask)
658 if (mask & PictFormatGreen)
659 if (template->direct.green != xri->format[nf].direct.green)
661 if (mask & PictFormatGreenMask)
662 if (template->direct.greenMask != xri->format[nf].direct.greenMask)
664 if (mask & PictFormatBlue)
665 if (template->direct.blue != xri->format[nf].direct.blue)
667 if (mask & PictFormatBlueMask)
668 if (template->direct.blueMask != xri->format[nf].direct.blueMask)
670 if (mask & PictFormatAlpha)
671 if (template->direct.alpha != xri->format[nf].direct.alpha)
673 if (mask & PictFormatAlphaMask)
674 if (template->direct.alphaMask != xri->format[nf].direct.alphaMask)
676 if (mask & PictFormatColormap)
677 if (template->colormap != xri->format[nf].colormap)
680 return &xri->format[nf];
686 XRenderFindStandardFormat (Display *dpy,
690 XRenderPictFormat templ;
692 } standardFormats[PictStandardNUM] = {
693 /* PictStandardARGB32 */
697 PictTypeDirect, /* type */
701 0xff, /* direct.redMask */
702 8, /* direct.green */
703 0xff, /* direct.greenMask */
705 0xff, /* direct.blueMask */
706 24, /* direct.alpha */
707 0xff, /* direct.alphaMask */
716 PictFormatGreenMask |
722 /* PictStandardRGB24 */
726 PictTypeDirect, /* type */
730 0xff, /* direct.redMask */
731 8, /* direct.green */
732 0xff, /* direct.greenMask */
734 0xff, /* direct.blueMask */
735 0, /* direct.alpha */
736 0x00, /* direct.alphaMask */
745 PictFormatGreenMask |
754 PictTypeDirect, /* type */
758 0x00, /* direct.redMask */
759 0, /* direct.green */
760 0x00, /* direct.greenMask */
762 0x00, /* direct.blueMask */
763 0, /* direct.alpha */
764 0xff, /* direct.alphaMask */
771 PictFormatGreenMask |
780 PictTypeDirect, /* type */
784 0x00, /* direct.redMask */
785 0, /* direct.green */
786 0x00, /* direct.greenMask */
788 0x00, /* direct.blueMask */
789 0, /* direct.alpha */
790 0x0f, /* direct.alphaMask */
797 PictFormatGreenMask |
806 PictTypeDirect, /* type */
810 0x00, /* direct.redMask */
811 0, /* direct.green */
812 0x00, /* direct.greenMask */
814 0x00, /* direct.blueMask */
815 0, /* direct.alpha */
816 0x01, /* direct.alphaMask */
823 PictFormatGreenMask |
830 if (0 <= format && format < PictStandardNUM)
831 return XRenderFindFormat (dpy,
832 standardFormats[format].mask,
833 &standardFormats[format].templ,
839 XRenderQueryPictIndexValues(Display *dpy,
840 _Xconst XRenderPictFormat *format,
843 XRenderExtDisplayInfo *info = XRenderFindDisplay (dpy);
844 xRenderQueryPictIndexValuesReq *req;
845 xRenderQueryPictIndexValuesReply rep;
847 unsigned int nbytes, nread, rlength, i;
849 RenderCheckExtension (dpy, info, NULL);
852 GetReq (RenderQueryPictIndexValues, req);
853 req->reqType = info->codes->major_opcode;
854 req->renderReqType = X_RenderQueryPictIndexValues;
855 req->format = format->id;
856 if (!_XReply (dpy, (xReply *) &rep, 0, xFalse))
863 if ((rep.length < (INT_MAX >> 2)) &&
864 (rep.numIndexValues < (INT_MAX / sizeof (XIndexValue)))) {
865 /* request data length */
866 nbytes = rep.length << 2;
867 /* bytes of actual data in the request */
868 nread = rep.numIndexValues * SIZEOF (xIndexValue);
869 /* size of array returned to application */
870 rlength = rep.numIndexValues * sizeof (XIndexValue);
872 /* allocate returned data */
873 values = Xmalloc (rlength);
875 nbytes = nread = rlength = 0;
881 _XEatDataWords (dpy, rep.length);
887 /* read the values one at a time and convert */
888 *num = rep.numIndexValues;
889 for(i = 0; i < rep.numIndexValues; i++)
893 _XRead (dpy, (char *) &value, SIZEOF (xIndexValue));
894 values[i].pixel = value.pixel;
895 values[i].red = value.red;
896 values[i].green = value.green;
897 values[i].blue = value.blue;
898 values[i].alpha = value.alpha;
900 /* skip any padding */
903 _XEatData (dpy, (unsigned long) (nbytes - nread));