diff -r a2b2b95a40b6 src/cairo-xlib-surface.c --- a/src/cairo-xlib-surface.c +++ b/src/cairo-xlib-surface.c @@ -190,16 +190,57 @@ static const XTransform identity = { { #define CAIRO_SURFACE_RENDER_HAS_PDF_OPERATORS(surface) CAIRO_SURFACE_RENDER_AT_LEAST((surface), 0, 11) #define CAIRO_SURFACE_RENDER_SUPPORTS_OPERATOR(surface, op) \ ((op) <= CAIRO_OPERATOR_SATURATE || \ (CAIRO_SURFACE_RENDER_HAS_PDF_OPERATORS(surface) && \ (op) <= CAIRO_OPERATOR_HSL_LUMINOSITY)) +static Visual * +_visual_for_xrender_format(Screen *screen, + XRenderPictFormat *xrender_format) +{ + int d, v; + for (d = 0; d < screen->ndepths; d++) { + Depth *d_info = &screen->depths[d]; + if (d_info->depth != xrender_format->depth) + continue; + + for (v = 0; v < d_info->nvisuals; v++) { + Visual *visual = &d_info->visuals[v]; + + switch (visual->class) { + case TrueColor: + if (xrender_format->type != PictTypeDirect) + continue; + break; + case DirectColor: + /* Prefer TrueColor to DirectColor. + (XRenderFindVisualFormat considers both TrueColor and + DirectColor Visuals to match the same PictFormat.) */ + continue; + case StaticGray: + case GrayScale: + case StaticColor: + case PseudoColor: + if (xrender_format->type != PictTypeIndexed) + continue; + break; + } + + if (xrender_format == + XRenderFindVisualFormat (DisplayOfScreen(screen), visual)) + return visual; + } + } + + return NULL; +} + static cairo_status_t _cairo_xlib_surface_set_clip_region (cairo_xlib_surface_t *surface, cairo_region_t *region) { cairo_bool_t had_clip_rects = surface->clip_region != NULL; if (had_clip_rects == FALSE && region == NULL) return CAIRO_STATUS_SUCCESS; @@ -314,16 +355,19 @@ _cairo_xlib_surface_create_similar (void * visual/depth etc. as possible. */ pix = XCreatePixmap (src->dpy, src->drawable, width <= 0 ? 1 : width, height <= 0 ? 1 : height, xrender_format->depth); visual = NULL; if (xrender_format == src->xrender_format) visual = src->visual; + else + visual = _visual_for_xrender_format(src->screen->screen, + xrender_format); surface = (cairo_xlib_surface_t *) _cairo_xlib_surface_create_internal (src->screen, pix, visual, xrender_format, width, height, xrender_format->depth); } @@ -3182,28 +3226,32 @@ cairo_xlib_surface_create_with_xrender_f Screen *scr, XRenderPictFormat *format, int width, int height) { cairo_xlib_screen_t *screen; cairo_surface_t *surface; cairo_status_t status; + Visual *visual; if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX) return _cairo_surface_create_in_error (CAIRO_STATUS_INVALID_SIZE); status = _cairo_xlib_screen_get (dpy, scr, &screen); if (unlikely (status)) return _cairo_surface_create_in_error (status); X_DEBUG ((dpy, "create_with_xrender_format (drawable=%x)", (unsigned int) drawable)); + if (format) + visual = _visual_for_xrender_format (scr, format); + surface = _cairo_xlib_surface_create_internal (screen, drawable, - NULL, format, + visual, format, width, height, 0); _cairo_xlib_screen_destroy (screen); return surface; } slim_hidden_def (cairo_xlib_surface_create_with_xrender_format); /** @@ -3417,33 +3465,37 @@ cairo_xlib_surface_get_screen (cairo_sur return surface->screen->screen; } /** * cairo_xlib_surface_get_visual: * @surface: a #cairo_xlib_surface_t * - * Get the X Visual used for underlying X Drawable. + * Gets the X Visual associated with @surface, suitable for use with the + * underlying X Drawable. If @surface was created by + * cairo_xlib_surface_create(), the return value is the Visual passed to that + * constructor. * - * Return value: the visual. + * Return value: the Visual or %NULL if there is no appropriate Visual for + * @surface. * * Since: 1.2 **/ Visual * -cairo_xlib_surface_get_visual (cairo_surface_t *abstract_surface) +cairo_xlib_surface_get_visual (cairo_surface_t *surface) { - cairo_xlib_surface_t *surface = (cairo_xlib_surface_t *) abstract_surface; - - if (! _cairo_surface_is_xlib (abstract_surface)) { + cairo_xlib_surface_t *xlib_surface = (cairo_xlib_surface_t *) surface; + + if (! _cairo_surface_is_xlib (surface)) { _cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH); return NULL; } - return surface->visual; + return xlib_surface->visual; } /** * cairo_xlib_surface_get_depth: * @surface: a #cairo_xlib_surface_t * * Get the number of bits used to represent each pixel value. *