/* Test each depth not explicitly advertised to see if pixmap creation * succeeds: if it does, that depth is usable. */ static int pixmap_depths_usable (xcb_connection_t *c, uint32_t missing, xcb_pixmap_t pixmap, xcb_drawable_t root) { xcb_void_cookie_t create_cookie[32] = { { 0 } }; xcb_void_cookie_t free_cookie[32] = { { 0 } }; int d; int success = 1; for (d = 1; d <= 32; d++) if (missing & DEPTH_MASK(d)) { create_cookie[d - 1] = xcb_create_pixmap_checked (c, d, pixmap, root, 1, 1); free_cookie[d - 1] = xcb_free_pixmap_checked (c, pixmap); if (!create_cookie[d - 1].sequence || !free_cookie[d - 1].sequence) { success = 0; break; } } for (d = 0; d < 32; d++) if (create_cookie[d].sequence || free_cookie[d].sequence) { xcb_generic_error_t *create_error = xcb_request_check (c, create_cookie[d]); xcb_generic_error_t *free_error = xcb_request_check (c, free_cookie[d]); success = success && !create_error; free(create_error); free(free_error); } return success; }
static int XRenderDepthCheckErrorHandler (Display *dpy, XErrorEvent *evt) { if (evt->request_code == X_CreatePixmap && evt->error_code == BadValue) { DepthCheckPtr d; _XLockMutex(_Xglobal_lock); for (d = depthChecks; d; d = d->next) if (d->dpy == dpy) { if ((long) (evt->serial - d->serial) >= 0) d->missing |= DEPTH_MASK(evt->resourceid); break; } _XUnlockMutex (_Xglobal_lock); } return 0; }
static Bool XRenderHasDepths (Display *dpy) { int s; for (s = 0; s < ScreenCount (dpy); s++) { CARD32 depths = 0; CARD32 missing; Screen *scr = ScreenOfDisplay (dpy, s); int d; for (d = 0; d < scr->ndepths; d++) depths |= DEPTH_MASK(scr->depths[d].depth); missing = ~depths & REQUIRED_DEPTHS; if (missing) { DepthCheckRec dc, **dp; XErrorHandler previousHandler; /* * Ok, this is ugly. It should be sufficient at this * point to just return False, but Xinerama is broken at * this point and only advertises depths which have an * associated visual. Of course, the other depths still * work, but the only way to find out is to try them. */ dc.dpy = dpy; dc.missing = 0; dc.serial = XNextRequest (dpy); _XLockMutex(_Xglobal_lock); dc.next = depthChecks; depthChecks = &dc; _XUnlockMutex (_Xglobal_lock); /* * I suspect this is not really thread safe, but Xlib doesn't * provide a lot of options here */ previousHandler = XSetErrorHandler (XRenderDepthCheckErrorHandler); /* * Try each missing depth and see if pixmap creation succeeds */ for (d = 1; d <= 32; d++) /* don't check depth 1 == Xcursor recurses... */ if ((missing & DEPTH_MASK(d)) && d != 1) { Pixmap p; p = XCreatePixmap (dpy, RootWindow (dpy, s), 1, 1, d); XFreePixmap (dpy, p); } XSync (dpy, False); XSetErrorHandler (previousHandler); /* * Unhook from the list of depth check records */ _XLockMutex(_Xglobal_lock); for (dp = &depthChecks; *dp; dp = &(*dp)->next) { if (*dp == &dc) { *dp = dc.next; break; } } _XUnlockMutex (_Xglobal_lock); if (dc.missing) return False; } } return True; }