From 9f4fd5ba1973cf3f9ea1b0955d38809a7bf402c7 Mon Sep 17 00:00:00 2001 From: Oleg Romashin Date: Wed, 16 Jun 2010 04:32:26 -0400 Subject: [PATCH] Bug 567065 - Try to create offscreen Xlib surface from existing visual if possible. r=jmuizelaar. --- gfx/cairo/README | 2 + gfx/cairo/cairo-x-visual.patch | 160 +++++++++++++++++++++++ gfx/cairo/cairo/src/cairo-xlib-surface.c | 66 +++++++++- 3 files changed, 221 insertions(+), 7 deletions(-) create mode 100644 gfx/cairo/cairo-x-visual.patch diff --git a/gfx/cairo/README b/gfx/cairo/README index 234182cb1e0d..a2966966473f 100644 --- a/gfx/cairo/README +++ b/gfx/cairo/README @@ -122,6 +122,8 @@ ensure-text-flushed.patch: PDF-operators: ensure text operations flushed before fix-xcopyarea-with-clips.patch: 5d07307b691afccccbb15f773d5231669ba44f5a +cairo-x-visual.patch: make valid visua for cairo_xlib_surface_create_with_xrender_format (55037bfb2454a671332d961e061c712ab5471580) + ==== pixman patches ==== pixman-android-cpu-detect.patch: Add CPU detection support for Android, where we can't reliably access /proc/self/auxv. diff --git a/gfx/cairo/cairo-x-visual.patch b/gfx/cairo/cairo-x-visual.patch new file mode 100644 index 000000000000..29f6c737e8c8 --- /dev/null +++ b/gfx/cairo/cairo-x-visual.patch @@ -0,0 +1,160 @@ +diff -r c1195334f839 gfx/cairo/cairo/src/cairo-xlib-surface.c +--- a/gfx/cairo/cairo/src/cairo-xlib-surface.c Fri May 21 17:42:55 2010 +0300 ++++ b/gfx/cairo/cairo/src/cairo-xlib-surface.c Fri May 21 19:12:29 2010 +0300 +@@ -189,16 +189,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; +@@ -313,16 +354,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); + } +@@ -3178,28 +3222,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); + + /** +@@ -3413,33 +3461,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. + * diff --git a/gfx/cairo/cairo/src/cairo-xlib-surface.c b/gfx/cairo/cairo/src/cairo-xlib-surface.c index 885a05772c0a..f3d6eb131802 100644 --- a/gfx/cairo/cairo/src/cairo-xlib-surface.c +++ b/gfx/cairo/cairo/src/cairo-xlib-surface.c @@ -194,6 +194,47 @@ 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; + 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) @@ -318,6 +359,9 @@ _cairo_xlib_surface_create_similar (void *abstract_src, 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, @@ -3183,6 +3227,7 @@ cairo_xlib_surface_create_with_xrender_format (Display *dpy, 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); @@ -3193,8 +3238,11 @@ cairo_xlib_surface_create_with_xrender_format (Display *dpy, 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); @@ -3418,23 +3466,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; } /**