summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorChris Wilson <chris@chris-wilson.co.uk>2009-09-20 18:46:19 +0100
committerChris Wilson <chris@chris-wilson.co.uk>2009-09-20 20:10:34 +0100
commit9b7c5d95055c4ea5da46c53263050d6ec1331c08 (patch)
tree41ea0a032a20febb7d3be41815a26f34ab05e5fb /src
parent878cef62b525e9f13ab2a8ab562ba8b6628aaa1f (diff)
[xlib] Cleanse creation of similar surfaces.
Reduce two nearly identical routines to one.
Diffstat (limited to 'src')
-rw-r--r--src/cairo-xlib-surface.c197
1 files changed, 91 insertions, 106 deletions
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index 4b2fd1f2..88bad87e 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -215,53 +215,6 @@ _cairo_xlib_surface_set_clip_region (cairo_xlib_surface_t *surface,
return CAIRO_STATUS_SUCCESS;
}
-static cairo_surface_t *
-_cairo_xlib_surface_create_similar_with_format (void *abstract_src,
- cairo_format_t format,
- int width,
- int height)
-{
- cairo_xlib_surface_t *src = abstract_src;
- Display *dpy = src->dpy;
- Pixmap pix;
- cairo_xlib_surface_t *surface;
- XRenderPictFormat *xrender_format;
-
- assert (width <= XLIB_COORD_MAX && height <= XLIB_COORD_MAX);
-
- /* As a good first approximation, if the display doesn't have even
- * the most elementary RENDER operation, then we're better off
- * using image surfaces for all temporary operations, so return NULL
- * and let the fallback code happen.
- */
- if (! CAIRO_SURFACE_RENDER_HAS_COMPOSITE (src))
- return NULL;
-
- xrender_format = _cairo_xlib_display_get_xrender_format (src->display,
- format);
- if (xrender_format == NULL)
- return NULL;
-
- pix = XCreatePixmap (dpy, src->drawable,
- width <= 0 ? 1 : width, height <= 0 ? 1 : height,
- xrender_format->depth);
-
- surface = (cairo_xlib_surface_t *)
- _cairo_xlib_surface_create_internal (src->screen, pix,
- NULL,
- xrender_format,
- width, height,
- xrender_format->depth);
- if (unlikely (surface->base.status)) {
- XFreePixmap (dpy, pix);
- return &surface->base;
- }
-
- surface->owns_pixmap = TRUE;
-
- return &surface->base;
-}
-
static cairo_content_t
_xrender_format_to_content (XRenderPictFormat *xrender_format)
{
@@ -301,6 +254,9 @@ _cairo_xlib_surface_create_similar (void *abstract_src,
if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX)
return NULL;
+ if (! CAIRO_SURFACE_RENDER_HAS_CREATE_PICTURE (src))
+ return NULL;
+
_cairo_xlib_display_notify (src->display);
/* If we never found an XRenderFormat or if it isn't compatible
@@ -309,27 +265,60 @@ _cairo_xlib_surface_create_similar (void *abstract_src,
* arbitrarily pick a visual/depth for the similar surface.
*/
xrender_format = src->xrender_format;
- if (xrender_format == NULL ||
- _xrender_format_to_content (xrender_format) != content)
+ if ((xrender_format != NULL &&
+ _xrender_format_to_content (xrender_format) == content) ||
+ (xrender_format =
+ _cairo_xlib_display_get_xrender_format (src->display,
+ _cairo_format_from_content (content))))
{
- return _cairo_xlib_surface_create_similar_with_format (abstract_src,
- _cairo_format_from_content (content),
- width, height);
+ Visual *visual;
+
+ /* We've got a compatible XRenderFormat now, which means the
+ * similar surface will match the existing surface as closely in
+ * 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;
+
+ surface = (cairo_xlib_surface_t *)
+ _cairo_xlib_surface_create_internal (src->screen, pix,
+ visual,
+ xrender_format,
+ width, height,
+ xrender_format->depth);
+ }
+ else
+ {
+#ifdef DEBUG_FORCE_FALLBACKS
+ Screen *screen = src->screen->screen;
+ int depth;
+
+ /* No compatabile XRenderFormat, see if we can make an ordinary pixmap,
+ * so that we can still accelerate blits with XCopyArea(). */
+ if (content != CAIRO_CONTENT_COLOR)
+ return NULL;
+
+ depth = DefaultDepthOfScreen (screen);
+
+ pix = XCreatePixmap (src->dpy, RootWindowOfScreen (screen),
+ width <= 0 ? 1 : width, height <= 0 ? 1 : height,
+ depth);
+
+ surface = (cairo_xlib_surface_t *)
+ _cairo_xlib_surface_create_internal (src->screen, pix,
+ DefaultVisualOfScreen (screen),
+ NULL,
+ width, height, depth);
+#else
+ /* No compatabile XRenderFormat, just say no. */
+ return NULL;
+#endif
}
- /* We've got a compatible XRenderFormat now, which means the
- * similar surface will match the existing surface as closely in
- * visual/depth etc. as possible. */
- pix = XCreatePixmap (src->dpy, src->drawable,
- width <= 0 ? 1 : width, height <= 0 ? 1 : height,
- xrender_format->depth);
-
- surface = (cairo_xlib_surface_t *)
- _cairo_xlib_surface_create_internal (src->screen, pix,
- src->visual,
- xrender_format,
- width, height,
- xrender_format->depth);
if (unlikely (surface->base.status)) {
XFreePixmap (src->dpy, pix);
return &surface->base;
@@ -1032,15 +1021,14 @@ _draw_image_surface (cairo_xlib_surface_t *surface,
cairo_bool_t true_color;
int ret;
- if (surface->depth > 16) {
+ if (surface->depth > 16)
ximage.bits_per_pixel = 32;
- } else if (surface->depth > 8) {
+ else if (surface->depth > 8)
ximage.bits_per_pixel = 16;
- } else if (surface->depth > 1) {
+ else if (surface->depth > 1)
ximage.bits_per_pixel = 8;
- } else {
+ else
ximage.bits_per_pixel = 1;
- }
stride = CAIRO_STRIDE_FOR_WIDTH_BPP (ximage.width,
ximage.bits_per_pixel);
ximage.bytes_per_line = stride;
@@ -1270,21 +1258,14 @@ _cairo_xlib_surface_clone_similar (void *abstract_surface,
}
} else if (_cairo_surface_is_image (src)) {
cairo_image_surface_t *image_src = (cairo_image_surface_t *)src;
- cairo_format_t format;
if (width > XLIB_COORD_MAX || height > XLIB_COORD_MAX)
return UNSUPPORTED ("roi too large for xlib");
- format = image_src->format;
- if (format == CAIRO_FORMAT_INVALID ||
- (_cairo_content_from_format (format) & ~content))
- {
- format = _cairo_format_from_content (image_src->base.content & content);
- }
clone = (cairo_xlib_surface_t *)
- _cairo_xlib_surface_create_similar_with_format (surface,
- format,
- width, height);
+ _cairo_xlib_surface_create_similar (surface,
+ image_src->base.content & content,
+ width, height);
if (clone == NULL)
return UNSUPPORTED ("unhandled image format, no similar surface");
@@ -2777,34 +2758,42 @@ _cairo_xlib_surface_create_internal (cairo_xlib_screen_t *screen,
CAIRO_MUTEX_INITIALIZE ();
- if (xrender_format) {
- depth = xrender_format->depth;
+ if (depth == 0) {
+ if (xrender_format) {
+ depth = xrender_format->depth;
- /* XXX find matching visual for core/dithering fallbacks? */
- } else if (visual) {
- Screen *scr = screen->screen;
- int j, k;
+ /* XXX find matching visual for core/dithering fallbacks? */
+ } else if (visual) {
+ Screen *scr = screen->screen;
- /* This is ugly, but we have to walk over all visuals
- * for the display to find the correct depth.
- */
- depth = 0;
- for (j = 0; j < scr->ndepths; j++) {
- Depth *d = &scr->depths[j];
- for (k = 0; k < d->nvisuals; k++) {
- if (&d->visuals[k] == visual) {
- depth = d->depth;
- goto found;
+ if (visual == DefaultVisualOfScreen (scr)) {
+ depth = DefaultDepthOfScreen (scr);
+ } else {
+ int j, k;
+
+ /* This is ugly, but we have to walk over all visuals
+ * for the display to find the correct depth.
+ */
+ depth = 0;
+ for (j = 0; j < scr->ndepths; j++) {
+ Depth *d = &scr->depths[j];
+ for (k = 0; k < d->nvisuals; k++) {
+ if (&d->visuals[k] == visual) {
+ depth = d->depth;
+ goto found;
+ }
+ }
}
}
}
- found:
+
+ if (depth == 0)
+ return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_VISUAL));
+
+found:
;
}
- if (depth == 0)
- return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_VISUAL));
-
surface = malloc (sizeof (cairo_xlib_surface_t));
if (unlikely (surface == NULL))
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
@@ -2830,11 +2819,7 @@ _cairo_xlib_surface_create_internal (cairo_xlib_screen_t *screen,
}
}
} else {
- xrender_format = NULL;
- }
-
- /* we cannot use XRender for this surface, so ensure we don't try */
- if (xrender_format == NULL) {
+ /* we cannot use XRender for this surface, so ensure we don't try */
surface->render_major = -1;
surface->render_minor = -1;
}
@@ -2914,7 +2899,7 @@ _cairo_xlib_surface_create_internal (cairo_xlib_screen_t *screen,
surface->b_mask = 0;
}
- return (cairo_surface_t *) surface;
+ return &surface->base;
}
static Screen *