xlib: Find matching Visual for XRenderFormat

Not only is this useful for users to know which Visual matches any
particular Cairo surface, it should also close a few obscure bugs of not
converting images correctly on upload.

Fixes:

  Bug 28492 - cairo_xlib_surface_create_with_xrender_format does not
              create visual for resulting surface
  https://bugs.freedesktop.org/show_bug.cgi?id=28492

  Mozilla Bug 567065 - Try to create offscreen Xlib surface from existing
                       visual if possible
  https://bugzilla.mozilla.org/show_bug.cgi?id=567065

  Mozilla Bug 445250 - cairo_draw_with_xlib should provide a non-NULL visual
                       to callback
  https://bugzilla.mozilla.org/show_bug.cgi?id=445250

Reported-by: Oleg Romashin <romaxa@gmail.com>
This commit is contained in:
Karl Tomlinson 2010-06-11 10:35:43 +01:00 committed by Chris Wilson
parent cf426bce8e
commit 55037bfb24

View file

@ -183,6 +183,56 @@ static const XTransform identity = { {
(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;
/* XXX Consider searching through the list of known cairo_visual_t for
* the reverse mapping.
*/
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)
@ -306,9 +356,11 @@ _cairo_xlib_surface_create_similar (void *abstract_src,
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,
@ -3235,8 +3287,8 @@ cairo_xlib_surface_create_with_xrender_format (Display *dpy,
X_DEBUG ((dpy, "create_with_xrender_format (drawable=%x)", (unsigned int) drawable));
return _cairo_xlib_surface_create_internal (screen, drawable,
NULL, format,
width, height, 0);
_visual_for_xrender_format (scr, format),
format, width, height, 0);
}
slim_hidden_def (cairo_xlib_surface_create_with_xrender_format);
@ -3468,23 +3520,27 @@ cairo_xlib_surface_get_screen (cairo_surface_t *abstract_surface)
* 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;
cairo_xlib_surface_t *xlib_surface = (cairo_xlib_surface_t *) surface;
if (! _cairo_surface_is_xlib (abstract_surface)) {
if (! _cairo_surface_is_xlib (surface)) {
_cairo_error_throw (CAIRO_STATUS_SURFACE_TYPE_MISMATCH);
return NULL;
}
return surface->visual;
return xlib_surface->visual;
}
/**