summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorKarl Tomlinson <karlt+@karlt.net>2010-06-11 10:35:43 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2010-06-11 10:42:15 +0100
commit55037bfb2454a671332d961e061c712ab5471580 (patch)
treedbb004938c6164830e0d409a9909e46d319d69f6 /src
parentcf426bce8ebd3aff5d50c6a54bbd731132b3d312 (diff)
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>
Diffstat (limited to 'src')
-rw-r--r--src/cairo-xlib-surface.c74
1 files changed, 65 insertions, 9 deletions
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index 93467ffe..75933167 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -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;
}
/**