[cairo-commit] src/cairo-directfb-surface.c src/cairo-image-surface.c src/cairo-image-surface-private.h

Chris Wilson ickle at kemper.freedesktop.org
Thu Feb 9 08:23:14 PST 2012


 src/cairo-directfb-surface.c      | 1942 +++++---------------------------------
 src/cairo-image-surface-private.h |   46 
 src/cairo-image-surface.c         |   10 
 3 files changed, 334 insertions(+), 1664 deletions(-)

New commits:
commit a349a312dcf3322d835bc3c58cecedff8914a55a
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Feb 9 16:20:26 2012 +0000

    directfb: Discard long broken code and return to basics
    
    Rewrite the directfb backend as nothing more than a simpler image
    compositor onto a shadowfb that is flushed back to the dfb surface as
    required. Future refinements would be to add damage tracking, and to mix
    the useful directfb operations (such as solid fills and alpha blends).
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-directfb-surface.c b/src/cairo-directfb-surface.c
index dd830f0..dcaff6c 100644
--- a/src/cairo-directfb-surface.c
+++ b/src/cairo-directfb-surface.c
@@ -1,6 +1,6 @@
 /* cairo - a vector graphics library with display and print output
  *
- * Copyright © 2003 University of Southern California
+ * Copyright © 2012 Intel Corporation
  *
  * This library is free software; you can redistribute it and/or
  * modify it either under the terms of the GNU Lesser General Public
@@ -27,21 +27,22 @@
  *
  * The Original Code is the cairo graphics library.
  *
- * The Initial Developer of the Original Code is University of Southern
- * California.
+ * The Initial Developer of the Original Code is Chris Wilson
  *
  * Contributor(s):
- *    Michael Emmel <mike.emmel at gmail.com>
- *    Claudio Ciccani <klan at users.sf.net>
+ *    Chris Wilson <chris at chris-wilson.co.uk>
  */
 
 #include "cairoint.h"
 #include "cairo-directfb.h"
 
 #include "cairo-clip-private.h"
+#include "cairo-compositor-private.h"
 #include "cairo-default-context-private.h"
 #include "cairo-error-private.h"
+#include "cairo-image-surface-private.h"
 #include "cairo-pattern-private.h"
+#include "cairo-surface-backend-private.h"
 
 #include <pixman.h>
 
@@ -51,211 +52,203 @@
 #include <direct/memcpy.h>
 #include <direct/util.h>
 
-/*
- * Rectangle works fine.
- * Bugs 361377, 359553, 359243 in Gnome BTS are caused
- * by GDK/DirectFB, not by Cairo/DirectFB.
- */
-#define DFB_RECTANGLES 1
+slim_hidden_proto(cairo_directfb_surface_create);
 
-/*
- * Composite works fine.
- */
-#define DFB_COMPOSITE 1
+typedef struct _cairo_dfb_surface {
+    cairo_image_surface_t image;
 
-/*
- * CompositeTrapezoids works (without antialiasing).
- */
-#define DFB_COMPOSITE_TRAPEZOIDS 1
+    IDirectFB			*dfb;
+    IDirectFBSurface		*dfb_surface;
 
-/*
- * ShowGlyphs works fine.
- */
-#define DFB_SHOW_GLYPHS 1
+    unsigned             blit_premultiplied : 1;
+} cairo_dfb_surface_t;
 
-#define PIXMAN_invalid (pixman_format_code_t) 0
+static cairo_content_t
+_directfb_format_to_content (DFBSurfacePixelFormat format)
+{
+    cairo_content_t content = 0;
 
+    if (DFB_PIXELFORMAT_HAS_ALPHA (format))
+	content |= CAIRO_CONTENT_ALPHA;
+    if (DFB_COLOR_BITS_PER_PIXEL (format))
+	content |= CAIRO_CONTENT_COLOR_ALPHA;
 
-D_DEBUG_DOMAIN (CairoDFB_Acquire, "CairoDFB/Acquire", "Cairo DirectFB Acquire");
-D_DEBUG_DOMAIN (CairoDFB_Clip,    "CairoDFB/Clip",    "Cairo DirectFB Clipping");
-D_DEBUG_DOMAIN (CairoDFB_Font,    "CairoDFB/Font",    "Cairo DirectFB Font Rendering");
-D_DEBUG_DOMAIN (CairoDFB_Render,  "CairoDFB/Render",  "Cairo DirectFB Rendering");
-D_DEBUG_DOMAIN (CairoDFB_Surface, "CairoDFB/Surface", "Cairo DirectFB Surface");
+    assert(content);
+    return content;
+}
 
-/*****************************************************************************/
+static inline pixman_format_code_t
+_directfb_to_pixman_format (DFBSurfacePixelFormat format)
+{
+    switch (format) {
+    case DSPF_UNKNOWN: return 0;
+    case DSPF_ARGB1555: return PIXMAN_a1r5g5b5;
+    case DSPF_RGB16: return PIXMAN_r5g6b5;
+    case DSPF_RGB24: return PIXMAN_r8g8b8;
+    case DSPF_RGB32: return PIXMAN_x8r8g8b8;
+    case DSPF_ARGB: return PIXMAN_a8r8g8b8;
+    case DSPF_A8: return PIXMAN_a8;
+    case DSPF_YUY2: return PIXMAN_yuy2;
+    case DSPF_RGB332: return PIXMAN_r3g3b2;
+    case DSPF_UYVY: return 0;
+    case DSPF_I420: return 0;
+    case DSPF_YV12: return PIXMAN_yv12;
+    case DSPF_LUT8: return 0;
+    case DSPF_ALUT44: return 0;
+    case DSPF_AiRGB: return 0;
+    case DSPF_A1: return 0; /* bit reversed, oops */
+    case DSPF_NV12: return 0;
+    case DSPF_NV16: return 0;
+    case DSPF_ARGB2554: return 0;
+    case DSPF_ARGB4444: return PIXMAN_a4r4g4b4;
+    case DSPF_NV21: return 0;
+    case DSPF_AYUV: return 0;
+    case DSPF_A4: return PIXMAN_a4;
+    case DSPF_ARGB1666: return 0;
+    case DSPF_ARGB6666: return 0;
+    case DSPF_RGB18: return 0;
+    case DSPF_LUT2: return 0;
+    case DSPF_RGB444: return PIXMAN_x4r4g4b4;
+    case DSPF_RGB555: return PIXMAN_x1r5g5b5;
+#if DFB_NUM_PIXELFORMATS >= 29
+    case DSPF_BGR555: return PIXMAN_x1b5g5r5;
+#endif
+    }
+    return 0;
+}
 
-typedef struct _cairo_directfb_surface {
-    cairo_surface_t	base;
+static cairo_surface_t *
+_cairo_dfb_surface_create_similar (void            *abstract_src,
+				   cairo_content_t  content,
+				   int              width,
+				   int              height)
+{
+    cairo_dfb_surface_t *other  = abstract_src;
+    DFBSurfacePixelFormat     format;
+    IDirectFBSurface      *buffer;
+    DFBSurfaceDescription  dsc;
+    cairo_surface_t *surface;
 
-    pixman_format_code_t	pixman_format;
-    cairo_bool_t		supported_destination;
+    if (width <= 0 || height <= 0)
+	return _cairo_image_surface_create_with_content (content, width, height);
 
-    IDirectFB			*dfb;
-    IDirectFBSurface		*dfbsurface;
-    IDirectFBSurface		*tmpsurface;
-    pixman_format_code_t	 tmpformat;
+    switch (content) {
+    default:
+	ASSERT_NOT_REACHED;
+    case CAIRO_CONTENT_COLOR_ALPHA:
+	format = DSPF_ARGB;
+	break;
+    case CAIRO_CONTENT_COLOR:
+	format = DSPF_RGB32;
+	break;
+    case CAIRO_CONTENT_ALPHA:
+	format = DSPF_A8;
+	break;
+    }
 
-    int                  width;
-    int                  height;
+    dsc.flags       = DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT;
+    dsc.caps        = DSCAPS_PREMULTIPLIED;
+    dsc.width       = width;
+    dsc.height      = height;
+    dsc.pixelformat = format;
 
-    unsigned             local : 1;
-    unsigned             blit_premultiplied : 1;
-} cairo_directfb_surface_t;
+    if (other->dfb->CreateSurface (other->dfb, &dsc, &buffer))
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_DEVICE_ERROR));
 
+    surface = cairo_directfb_surface_create (other->dfb, buffer);
+    buffer->Release (buffer);
 
-typedef struct _cairo_directfb_font_cache {
-    IDirectFB           *dfb;
-    IDirectFBSurface    *dfbsurface;
+    return surface;
+}
 
-    int                  width;
-    int                  height;
+static cairo_status_t
+_cairo_dfb_surface_finish (void *abstract_surface)
+{
+    cairo_dfb_surface_t *surface = abstract_surface;
 
-    /* coordinates within the surface
-     * of the last loaded glyph */
-    int                  x;
-    int                  y;
-} cairo_directfb_font_cache_t;
+    surface->dfb_surface->Release (surface->dfb_surface);
+    return _cairo_image_surface_finish (abstract_surface);
+}
 
-static cairo_surface_backend_t _cairo_directfb_surface_backend;
+static cairo_surface_t *
+_cairo_dfb_surface_map_to_image (void *abstract_surface,
+				 const cairo_rectangle_int_t *extents)
+{
+    cairo_dfb_surface_t *surface = abstract_surface;
 
-/*****************************************************************************/
+    if (surface->image.pixman_image == NULL) {
+	IDirectFBSurface *buffer = surface->dfb_surface;
+	void *data;
+	int pitch;
 
-static int _directfb_argb_font = 0;
+	if (buffer->Lock (buffer, DSLF_READ | DSLF_WRITE, &data, &pitch))
+	    return _cairo_surface_create_in_error(_cairo_error (CAIRO_STATUS_NO_MEMORY));
+
+	surface->image.pixman_image =
+	    pixman_image_create_bits (surface->image.pixman_format,
+				      surface->image.width,
+				      surface->image.height,
+				      data, pitch);
+	if (surface->image.pixman_image == NULL) {
+	    buffer->Unlock (buffer);
+	    return _cairo_surface_create_in_error(_cairo_error (CAIRO_STATUS_NO_MEMORY));
+	}
 
-/*****************************************************************************/
+	surface->image.data = data;
+    }
 
-#define RUN_CLIPPED(surface, clip_region, clip, func) {\
-    if ((clip_region) != NULL) {\
-	int n_clips = cairo_region_num_rectangles (clip_region), n; \
-        for (n = 0; n < n_clips; n++) {\
-            if (clip) {\
-                DFBRegion  reg, *cli = (clip); \
-		cairo_rectangle_int_t rect; \
-		cairo_region_get_rectangle (clip_region, n, &rect); \
-		reg.x1 = rect.x; \
-		reg.y1 = rect.y; \
-		reg.x2 = rect.x + rect.width - 1; \
-		reg.y2 = rect.y + rect.height - 1; \
-                if (reg.x2 < cli->x1 || reg.y2 < cli->y1 ||\
-                    reg.x1 > cli->x2 || reg.y1 > cli->y2)\
-                    continue;\
-                if (reg.x1 < cli->x1)\
-                    reg.x1 = cli->x1;\
-                if (reg.y1 < cli->y1)\
-                    reg.y1 = cli->y1;\
-                if (reg.x2 > cli->x2)\
-                    reg.x2 = cli->x2;\
-                if (reg.y2 > cli->y2)\
-                    reg.y2 = cli->y2;\
-                (surface)->dfbsurface->SetClip ((surface)->dfbsurface, &reg);\
-            } else {\
-		DFBRegion reg; \
-		cairo_rectangle_int_t rect; \
-		cairo_region_get_rectangle (clip_region, n, &rect); \
-		reg.x1 = rect.x; \
-		reg.y1 = rect.y; \
-		reg.x2 = rect.x + rect.width - 1; \
-		reg.y2 = rect.y + rect.height - 1; \
-                (surface)->dfbsurface->SetClip ((surface)->dfbsurface, &reg); \
-            }\
-            func;\
-        }\
-    } else {\
-        (surface)->dfbsurface->SetClip ((surface)->dfbsurface, clip);\
-        func;\
-    }\
+    return _cairo_image_surface_map_to_image (&surface->image, extents);
 }
 
-#define TRANSFORM_POINT2X(m, x, y, ret_x, ret_y) do { \
-    double _x = (x); \
-    double _y = (y); \
-    (ret_x) = (_x * (m).xx + (m).x0); \
-    (ret_y) = (_y * (m).yy + (m).y0); \
-} while (0)
-
-#define TRANSFORM_POINT3X(m, x, y, ret_x, ret_y) do { \
-    double _x = (x); \
-    double _y = (y); \
-    (ret_x) = (_x * (m).xx + _y * (m).xy + (m).x0); \
-    (ret_y) = (_x * (m).yx + _y * (m).yy + (m).y0); \
-} while (0)
-
-/* XXX: A1 has a different bits ordering in cairo.
- *      Probably we should drop it.
- */
+static cairo_int_status_t
+_cairo_dfb_surface_unmap_image (void *abstract_surface,
+				cairo_image_surface_t *image)
+{
+    return CAIRO_INT_STATUS_SUCCESS;
+}
 
-static cairo_content_t
-_directfb_format_to_content (DFBSurfacePixelFormat format)
+static cairo_status_t
+_cairo_dfb_surface_flush (void *abstract_surface)
 {
-    if (DFB_PIXELFORMAT_HAS_ALPHA (format)) {
-        if (DFB_COLOR_BITS_PER_PIXEL (format))
-            return CAIRO_CONTENT_COLOR_ALPHA;
+    cairo_dfb_surface_t *surface = abstract_surface;
+
+    if (surface->image.pixman_image == NULL) {
+	surface->dfb_surface->Unlock (surface->dfb_surface);
 
-        return CAIRO_CONTENT_ALPHA;
+	pixman_image_unref (surface->image.pixman_image);
+	surface->image.pixman_image = NULL;
+	surface->image.data = NULL;
     }
 
-    return CAIRO_CONTENT_COLOR;
+    return CAIRO_STATUS_SUCCESS;
 }
 
-static inline DFBSurfacePixelFormat
-_cairo_to_directfb_format (cairo_format_t format)
+static cairo_status_t
+_cairo_dfb_surface_acquire_source_image (void                   *abstract_surface,
+					 cairo_image_surface_t **image_out,
+					 void                  **image_extra)
 {
-    switch (format) {
-    case CAIRO_FORMAT_RGB24:
-	return DSPF_RGB32;
-    case CAIRO_FORMAT_ARGB32:
-	return DSPF_ARGB;
-    case CAIRO_FORMAT_A8:
-	return DSPF_A8;
-    case CAIRO_FORMAT_A1:
-	return DSPF_A1;
-    default:
-	break;
-    }
+    cairo_dfb_surface_t *surface = abstract_surface;
+    cairo_rectangle_int_t extents;
 
-    return -1;
+    extents.x = extents.y = 0;
+    extents.width  = surface->image.width;
+    extents.height = surface->image.height;
+
+    *image_out = (cairo_image_surface_t *)
+	_cairo_dfb_surface_map_to_image (abstract_surface, &extents);
+    *image_extra = NULL;
+    return (*image_out)->base.status;
 }
 
-static inline pixman_format_code_t
-_directfb_to_pixman_format (DFBSurfacePixelFormat format)
+static void
+_cairo_dfb_surface_release_source_image (void                  *abstract_surface,
+					 cairo_image_surface_t *image,
+					 void                  *image_extra)
 {
-    switch (format) {
-    case DSPF_UNKNOWN: return PIXMAN_invalid;
-    case DSPF_ARGB1555: return PIXMAN_a1r5g5b5;
-    case DSPF_RGB16: return PIXMAN_r5g6b5;
-    case DSPF_RGB24: return PIXMAN_r8g8b8;
-    case DSPF_RGB32: return PIXMAN_x8r8g8b8;
-    case DSPF_ARGB: return PIXMAN_a8r8g8b8;
-    case DSPF_A8: return PIXMAN_a8;
-    case DSPF_YUY2: return PIXMAN_yuy2;
-    case DSPF_RGB332: return PIXMAN_r3g3b2;
-    case DSPF_UYVY: return PIXMAN_invalid;
-    case DSPF_I420: return PIXMAN_invalid;
-    case DSPF_YV12: return PIXMAN_yv12;
-    case DSPF_LUT8: return PIXMAN_invalid;
-    case DSPF_ALUT44: return PIXMAN_invalid;
-    case DSPF_AiRGB: return PIXMAN_invalid;
-    case DSPF_A1: return PIXMAN_a1; /* bit reversed, oops */
-    case DSPF_NV12: return PIXMAN_invalid;
-    case DSPF_NV16: return PIXMAN_invalid;
-    case DSPF_ARGB2554: return PIXMAN_invalid;
-    case DSPF_ARGB4444: return PIXMAN_a4r4g4b4;
-    case DSPF_NV21: return PIXMAN_invalid;
-    case DSPF_AYUV: return PIXMAN_invalid;
-    case DSPF_A4: return PIXMAN_a4;
-    case DSPF_ARGB1666: return PIXMAN_invalid;
-    case DSPF_ARGB6666: return PIXMAN_invalid;
-    case DSPF_RGB18: return PIXMAN_invalid;
-    case DSPF_LUT2: return PIXMAN_invalid;
-    case DSPF_RGB444: return PIXMAN_x4r4g4b4;
-    case DSPF_RGB555: return PIXMAN_x1r5g5b5;
-#if DFB_NUM_PIXELFORMATS >= 29
-    case DSPF_BGR555: return PIXMAN_x1b5g5r5;
-#endif
-    }
-    return PIXMAN_invalid;
 }
 
+#if 0
 static inline DFBSurfacePixelFormat
 _directfb_from_pixman_format (pixman_format_code_t format)
 {
@@ -373,808 +366,56 @@ _directfb_get_operator (cairo_operator_t         operator,
 
     return TRUE;
 }
-
-static cairo_status_t
-_directfb_buffer_surface_create (IDirectFB             *dfb,
-                                 DFBSurfacePixelFormat  format,
-                                 int                    width,
-                                 int                    height,
-				 IDirectFBSurface     **out)
-{
-    IDirectFBSurface      *buffer;
-    DFBSurfaceDescription  dsc;
-    DFBResult              ret;
-
-    dsc.flags       = DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT;
-    dsc.caps        = DSCAPS_PREMULTIPLIED;
-    dsc.width       = width;
-    dsc.height      = height;
-    dsc.pixelformat = format;
-
-    ret = dfb->CreateSurface (dfb, &dsc, &buffer);
-    if (ret) {
-        DirectFBError ("IDirectFB::CreateSurface()", ret);
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-    }
-
-    *out = buffer;
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_directfb_acquire_surface (cairo_directfb_surface_t  *surface,
-                           cairo_rectangle_int_t     *intrest_rec,
-                           cairo_image_surface_t    **image_out,
-                           cairo_rectangle_int_t     *image_rect_out,
-                           void                     **image_extra,
-                           DFBSurfaceLockFlags        lock_flags)
-{
-    IDirectFBSurface *buffer = NULL;
-    DFBRectangle source_rect;
-    cairo_surface_t *image;
-    pixman_image_t *pixman_image;
-    pixman_format_code_t pixman_format;
-    cairo_status_t status;
-    void *data;
-    int   pitch;
-
-    if (surface->pixman_format == PIXMAN_invalid) {
-        if (intrest_rec != NULL) {
-            source_rect.x = intrest_rec->x;
-            source_rect.y = intrest_rec->y;
-            source_rect.w = intrest_rec->width;
-            source_rect.h = intrest_rec->height;
-        } else {
-            source_rect.x = 0;
-            source_rect.y = 0;
-            surface->dfbsurface->GetSize (surface->dfbsurface,
-                                          &source_rect.w, &source_rect.h);
-        }
-
-        if (surface->tmpsurface != NULL) {
-            int w, h;
-
-            surface->tmpsurface->GetSize (surface->tmpsurface, &w, &h);
-            if (w < source_rect.w || h < source_rect.h) {
-                surface->tmpsurface->Release (surface->tmpsurface);
-                surface->tmpsurface = NULL;
-                surface->tmpformat = PIXMAN_invalid;
-            }
-        }
-
-        if (surface->tmpsurface == NULL) {
-	    DFBSurfacePixelFormat format;
-
-            D_DEBUG_AT (CairoDFB_Acquire, "Allocating buffer for surface %p.\n", surface);
-
-	    format = _cairo_to_directfb_format (_cairo_format_from_content (surface->base.content));
-            status =
-                _directfb_buffer_surface_create (surface->dfb, format,
-                                                 source_rect.w, source_rect.h,
-						 &surface->tmpsurface);
-            if (unlikely (status))
-                goto ERROR;
-
-	    surface->tmpformat = _directfb_to_pixman_format (format);
-        }
-        buffer = surface->tmpsurface;
-	pixman_format = surface->tmpformat;
-
-
-/*        surface->dfbsurface->GetCapabilities (surface->dfbsurface, &caps);
-        DFBSurfaceCapabilities caps;
-        if (caps & DSCAPS_FLIPPING) {
-            DFBRegion region = { .x1 = source_rect.x, .y1 = source_rect.y,
-                                 .x2 = source_rect.x + source_rect.w - 1,
-                                 .y2 = source_rect.y + source_rect.h - 1 };
-            surface->dfbsurface->Flip (surface->dfbsurface, &region, DSFLIP_BLIT);
-        } */
-        buffer->Blit (buffer, surface->dfbsurface, &source_rect, 0, 0);
-    } else {
-        /*might be a subsurface get the offset*/
-        surface->dfbsurface->GetVisibleRectangle (surface->dfbsurface, &source_rect);
-        pixman_format = surface->pixman_format;
-        buffer = surface->dfbsurface;
-    }
-
-    if (buffer->Lock (buffer, lock_flags, &data, &pitch)) {
-        D_DEBUG_AT (CairoDFB_Acquire, "Couldn't lock surface!\n");
-	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-        goto ERROR;
-    }
-
-    pixman_image = pixman_image_create_bits (pixman_format,
-					     source_rect.w, source_rect.h,
-					     data, pitch);
-    if (pixman_image == NULL) {
-	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	goto ERROR;
-    }
-
-    image = _cairo_image_surface_create_for_pixman_image (pixman_image,
-							  pixman_format);
-    status = image->status;
-    if (status)
-        goto ERROR;
-
-    if (image_rect_out) {
-        image_rect_out->x = source_rect.x;
-        image_rect_out->y = source_rect.y;
-        image_rect_out->width = source_rect.w;
-        image_rect_out->height = source_rect.h;
-    } else {
-        /* lock for read */
-        /* might be a subsurface */
-        if (buffer == surface->dfbsurface) {
-            cairo_surface_set_device_offset (image,
-					     source_rect.x, source_rect.y);
-	}
-    }
-
-    *image_extra = buffer;
-    *image_out = (cairo_image_surface_t *) image;
-    return CAIRO_STATUS_SUCCESS;
-
-ERROR:
-    if (buffer) {
-        buffer->Unlock (buffer);
-        if (buffer != surface->dfbsurface)
-            buffer->Release (buffer);
-    }
-    return status;
-}
-
-static cairo_surface_t *
-_cairo_directfb_surface_create_internal (IDirectFB *dfb,
-					 DFBSurfacePixelFormat format,
-					 cairo_content_t content,
-					 int              width,
-					 int              height)
-{
-    cairo_directfb_surface_t *surface;
-    cairo_status_t	      status;
-
-    surface = calloc (1, sizeof (cairo_directfb_surface_t));
-    if (unlikely (surface == NULL))
-	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
-
-    surface->dfb = dfb;
-
-    if (width < 8 || height < 8) {
-        IDirectFBSurface *tmp;
-	DFBRectangle rect = { .x=0, .y=0, .w=width, .h=height };
-
-        /* Some cards (e.g. Matrox) don't support surfaces smaller than 8x8 */
-        status =  _directfb_buffer_surface_create (dfb, format,
-                                        MAX (width, 8), MAX (height, 8),
-					&tmp);
-	if (status) {
-	    free (surface);
-	    return _cairo_surface_create_in_error (status);
-	}
-
-	tmp->GetSubSurface (tmp, &rect, &surface->dfbsurface);
-	tmp->Release (tmp);
-    } else {
-	status = _directfb_buffer_surface_create (dfb, format,
-						  width, height,
-						  &surface->dfbsurface);
-	if (status) {
-	    free (surface);
-	    return _cairo_surface_create_in_error (status);
-	}
-    }
-
-    _cairo_surface_init (&surface->base,
-			 &_cairo_directfb_surface_backend,
-			 NULL, /* device */
-			 content);
-    surface->pixman_format = _directfb_to_pixman_format (format);
-    surface->supported_destination = pixman_format_supported_destination (surface->pixman_format);
-
-    surface->width   = width;
-    surface->height  = height;
-    surface->local   = TRUE;
-    surface->blit_premultiplied = TRUE;
-
-    return &surface->base;
-}
-
-static cairo_surface_t *
-_cairo_directfb_surface_create_similar (void            *abstract_src,
-                                        cairo_content_t  content,
-                                        int              width,
-                                        int              height)
-{
-    cairo_directfb_surface_t *other  = abstract_src;
-    DFBSurfacePixelFormat     format;
-
-    D_DEBUG_AT (CairoDFB_Surface,
-                "%s( src=%p, content=0x%x, width=%d, height=%d).\n",
-                __FUNCTION__, other, content, width, height);
-
-    width = (width <= 0) ? 1 : width;
-    height = (height<= 0) ? 1 : height;
-
-    format = _cairo_to_directfb_format (_cairo_format_from_content (content));
-    return _cairo_directfb_surface_create_internal (other->dfb, format,
-						    content, width, height);
-}
-
-static cairo_status_t
-_cairo_directfb_surface_finish (void *data)
-{
-    cairo_directfb_surface_t *surface = (cairo_directfb_surface_t *)data;
-
-    D_DEBUG_AT (CairoDFB_Surface, "%s( surface=%p ).\n", __FUNCTION__, surface);
-
-    if (surface->tmpsurface) {
-        surface->tmpsurface->Release (surface->tmpsurface);
-        surface->tmpsurface = NULL;
-    }
-
-    if (surface->dfbsurface) {
-        surface->dfbsurface->Release (surface->dfbsurface);
-        surface->dfbsurface = NULL;
-    }
-
-    if (surface->dfb)
-        surface->dfb = NULL;
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_directfb_surface_acquire_source_image (void                   *abstract_surface,
-                                              cairo_image_surface_t **image_out,
-                                              void                  **image_extra)
-{
-    cairo_directfb_surface_t *surface = abstract_surface;
-
-    D_DEBUG_AT (CairoDFB_Acquire,
-		"%s( surface=%p ).\n", __FUNCTION__, surface);
-
-    return _directfb_acquire_surface (surface, NULL, image_out,
-				      NULL, image_extra, DSLF_READ);
-}
-
-static void
-_cairo_directfb_surface_release_source_image (void                  *abstract_surface,
-                                              cairo_image_surface_t *image,
-                                              void                  *image_extra)
-{
-    IDirectFBSurface *buffer = image_extra;
-
-    D_DEBUG_AT (CairoDFB_Acquire,
-		"%s( release=%p ).\n", __FUNCTION__, abstract_surface);
-
-    buffer->Unlock (buffer);
-
-    cairo_surface_destroy (&image->base);
-}
-
-static cairo_status_t
-_cairo_directfb_surface_acquire_dest_image (void                     *abstract_surface,
-                                            cairo_rectangle_int_t    *interest_rect,
-                                            cairo_image_surface_t   **image_out,
-                                            cairo_rectangle_int_t    *image_rect_out,
-                                            void                    **image_extra)
-{
-    cairo_directfb_surface_t *surface = abstract_surface;
-
-    D_DEBUG_AT (CairoDFB_Acquire,
-		"%s( surface=%p (%dx%d), interest_rect={ %u %u %u %u } ).\n",
-		__FUNCTION__, surface, surface->width, surface->height,
-		interest_rect ? interest_rect->x : 0,
-		interest_rect ? interest_rect->y : 0,
-		interest_rect ? interest_rect->width  : (unsigned) surface->width,
-		interest_rect ? interest_rect->height : (unsigned) surface->height);
-
-    return _directfb_acquire_surface (surface, interest_rect, image_out,
-				      image_rect_out, image_extra,
-				      DSLF_READ | DSLF_WRITE);
-}
-
-static void
-_cairo_directfb_surface_release_dest_image (void                  *abstract_surface,
-                                            cairo_rectangle_int_t *interest_rect,
-                                            cairo_image_surface_t *image,
-                                            cairo_rectangle_int_t *image_rect,
-                                            void                  *image_extra)
-{
-    cairo_directfb_surface_t *surface = abstract_surface;
-    IDirectFBSurface *buffer = image_extra;
-
-    D_DEBUG_AT (CairoDFB_Acquire,
-		"%s( surface=%p ).\n", __FUNCTION__, surface);
-
-    buffer->Unlock (buffer);
-
-    if (surface->dfbsurface != buffer) {
-	DFBRegion region = {
-	    .x1 = interest_rect->x,
-	    .y1 = interest_rect->y,
-	    .x2 = interest_rect->x + interest_rect->width - 1,
-	    .y2 = interest_rect->y + interest_rect->height - 1
-	};
-	surface->dfbsurface->SetBlittingFlags (surface->dfbsurface, DSBLIT_NOFX);
-        surface->dfbsurface->SetClip (surface->dfbsurface, &region);
-	surface->dfbsurface->Blit (surface->dfbsurface,
-				   buffer, NULL,
-				   image_rect->x, image_rect->y);
-    }
-
-    cairo_surface_destroy (&image->base);
-}
-
-static cairo_status_t
-_cairo_directfb_surface_clone_similar (void             *abstract_surface,
-                                       cairo_surface_t  *src,
-                                       int               src_x,
-                                       int               src_y,
-                                       int               width,
-                                       int               height,
-                                       int              *clone_offset_x,
-                                       int              *clone_offset_y,
-                                       cairo_surface_t **clone_out)
-{
-    cairo_directfb_surface_t *surface = abstract_surface;
-    cairo_directfb_surface_t *clone;
-
-    D_DEBUG_AT (CairoDFB_Surface,
-		"%s( surface=%p, src=%p ).\n", __FUNCTION__, surface, src);
-
-    if (src->backend == surface->base.backend) {
-	*clone_offset_x = 0;
-	*clone_offset_y = 0;
-	*clone_out = cairo_surface_reference (src);
-
-	return CAIRO_STATUS_SUCCESS;
-    } else if (_cairo_surface_is_image (src)) {
-	cairo_image_surface_t *image_src = (cairo_image_surface_t *) src;
-	DFBSurfacePixelFormat format;
-	DFBResult              ret;
-	pixman_image_t	      *pixman_image;
-	void *data;
-	int pitch;
-
-	format = _directfb_from_pixman_format (image_src->pixman_format);
-	if (format == 0)
-	    return CAIRO_INT_STATUS_UNSUPPORTED;
-
-	clone = (cairo_directfb_surface_t *)
-	    _cairo_directfb_surface_create_internal (surface->dfb, format,
-						     image_src->base.content,
-						     width, height);
-	if (unlikely (clone->base.status))
-	    return clone->base.status;
-
-	ret = clone->dfbsurface->Lock (clone->dfbsurface,
-				       DSLF_WRITE, (void *)&data, &pitch);
-	if (ret) {
-	    DirectFBError ("IDirectFBSurface::Lock()", ret);
-	    cairo_surface_destroy (&clone->base);
-	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	}
-
-	pixman_image = pixman_image_create_bits (clone->pixman_format,
-						 width, height,
-						 data, pitch);
-	if (unlikely (pixman_image == NULL)) {
-	    DirectFBError ("IDirectFBSurface::Lock()", ret);
-	    cairo_surface_destroy (&clone->base);
-	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	}
-
-	pixman_image_composite32 (PIXMAN_OP_SRC,
-                                  image_src->pixman_image,
-                                  NULL,
-                                  pixman_image,
-                                  src_x, src_y,
-                                  0, 0,
-                                  0, 0,
-                                  width, height);
-
-	pixman_image_unref (pixman_image);
-
-	clone->dfbsurface->Unlock (clone->dfbsurface);
-
-	*clone_offset_x = src_x;
-	*clone_offset_y = src_y;
-	*clone_out = &clone->base;
-	return CAIRO_STATUS_SUCCESS;
-    }
-
-    return CAIRO_INT_STATUS_UNSUPPORTED;
-}
-
-#if DFB_COMPOSITE || DFB_COMPOSITE_TRAPEZOIDS
-static cairo_int_status_t
-_directfb_prepare_composite (cairo_directfb_surface_t    *dst,
-                             const cairo_pattern_t       *src_pattern,
-                             const cairo_pattern_t       *mask_pattern,
-                             cairo_operator_t             op,
-                             int *src_x,             int *src_y,
-                             int *mask_x,            int *mask_y,
-                             unsigned int                 width,
-                             unsigned int                 height,
-                             cairo_directfb_surface_t   **ret_src,
-                             cairo_surface_attributes_t  *ret_src_attr)
-{
-    cairo_directfb_surface_t   *src;
-    cairo_surface_attributes_t  src_attr;
-    cairo_status_t              status;
-    DFBSurfaceBlittingFlags     flags;
-    DFBSurfaceBlendFunction     sblend;
-    DFBSurfaceBlendFunction     dblend;
-    const cairo_color_t        *color;
-
-    /* XXX Unbounded operators are not handled correctly */
-    if (! _cairo_operator_bounded_by_source (op))
-        return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    if (! _directfb_get_operator (op, &sblend, &dblend))
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    if (mask_pattern) {
-		return CAIRO_INT_STATUS_UNSUPPORTED;
-	if (mask_pattern->type != CAIRO_PATTERN_TYPE_SOLID) {
-	    const cairo_pattern_t *tmp;
-	    int              tmp_x, tmp_y;
-
-	    if (src_pattern->type != CAIRO_PATTERN_TYPE_SOLID ||
-		sblend == DSBF_INVDESTALPHA) /* Doesn't work correctly */
-		return CAIRO_INT_STATUS_UNSUPPORTED;
-
-	    D_DEBUG_AT (CairoDFB_Render, "Replacing src pattern by mask pattern.\n");
-
-	    tmp = src_pattern;
-	    tmp_x = *src_x; tmp_y = *src_y;
-
-	    src_pattern = mask_pattern;
-	    *src_x = *mask_x; *src_y = *mask_y;
-
-	    mask_pattern = tmp;
-	    *mask_x = tmp_x; *mask_y = tmp_y;
-
-	    if (sblend == DSBF_ONE) {
-		sblend = DSBF_SRCALPHA;
-		/*dblend = DSBF_INVSRCALPHA;*/
-	    }
-	}
-
-	color = &((cairo_solid_pattern_t *) mask_pattern)->color;
-    } else {
-	color = _cairo_stock_color (CAIRO_STOCK_WHITE);
-    }
-
-    status = _cairo_pattern_acquire_surface (src_pattern, &dst->base,
-					     *src_x, *src_y, width, height,
-					     CAIRO_PATTERN_ACQUIRE_NO_REFLECT,
-					     (cairo_surface_t **) &src,
-					     &src_attr);
-    if (status)
-	return status;
-
-    if (src->base.backend != &_cairo_directfb_surface_backend ||
-	src->dfb != dst->dfb)
-    {
-	_cairo_pattern_release_surface (src_pattern, &src->base, &src_attr);
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-    }
-
-    if ((src->base.content & CAIRO_CONTENT_ALPHA) == 0) {
-	if (sblend == DSBF_SRCALPHA)
-	    sblend = DSBF_ONE;
-	else if (sblend == DSBF_INVSRCALPHA)
-	    sblend = DSBF_ZERO;
-
-	if (dblend == DSBF_SRCALPHA)
-	    dblend = DSBF_ONE;
-	else if (dblend == DSBF_INVSRCALPHA)
-	    dblend = DSBF_ZERO;
-    }
-
-    if ((dst->base.content & CAIRO_CONTENT_ALPHA) == 0) {
-	if (sblend == DSBF_DESTALPHA)
-	    sblend = DSBF_ONE;
-	else if (sblend == DSBF_INVDESTALPHA)
-	    sblend = DSBF_ZERO;
-
-	if (dblend == DSBF_DESTALPHA)
-	    dblend = DSBF_ONE;
-	else if (dblend == DSBF_INVDESTALPHA)
-	    dblend = DSBF_ZERO;
-    }
-
-    flags = (sblend == DSBF_ONE && dblend == DSBF_ZERO)
-	? DSBLIT_NOFX : DSBLIT_BLEND_ALPHACHANNEL;
-    if (! CAIRO_COLOR_IS_OPAQUE (color))
-	flags |= DSBLIT_BLEND_COLORALPHA;
-    if (! _cairo_color_equal (color, _cairo_stock_color (CAIRO_STOCK_WHITE)))
-	flags |= DSBLIT_COLORIZE;
-
-    dst->dfbsurface->SetBlittingFlags (dst->dfbsurface, flags);
-
-    if (flags & (DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_BLEND_COLORALPHA)) {
-	dst->dfbsurface->SetSrcBlendFunction (dst->dfbsurface, sblend);
-	dst->dfbsurface->SetDstBlendFunction (dst->dfbsurface, dblend);
-    }
-
-    if (flags & (DSBLIT_BLEND_COLORALPHA | DSBLIT_COLORIZE)) {
-	if (dst->blit_premultiplied) {
-	    dst->dfbsurface->SetColor (dst->dfbsurface,
-				       color->red_short >> 8,
-				       color->green_short >> 8,
-				       color->blue_short >> 8,
-				       color->alpha_short >> 8);
-	} else {
-	    dst->dfbsurface->SetColor (dst->dfbsurface,
-				       color->red * 0xff,
-				       color->green * 0xff,
-				       color->blue * 0xff,
-				       color->alpha * 0xff);
-	}
-    }
-
-    *ret_src = src;
-    *ret_src_attr = src_attr;
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static void
-_directfb_finish_composite (cairo_directfb_surface_t   *dst,
-                            const cairo_pattern_t      *src_pattern,
-                            cairo_surface_t            *src,
-                            cairo_surface_attributes_t *src_attr)
-{
-    _cairo_pattern_release_surface (src_pattern, src, src_attr);
-}
-#endif /* DFB_COMPOSITE || DFB_COMPOSITE_TRAPEZOIDS */
-
-#if DFB_COMPOSITE
-static DFBAccelerationMask
-_directfb_categorize_operation (cairo_surface_attributes_t *src_attr)
-{
-    cairo_matrix_t *m = &src_attr->matrix;
-
-    if (m->xy != 0 || m->yx != 0 || m->xx < 0 || m->yy < 0) {
-	if (src_attr->extend != CAIRO_EXTEND_NONE)
-	    return DFXL_NONE;
-
-	return DFXL_TEXTRIANGLES;
-    }
-
-    if (m->xx != 1 || m->yy != 1) {
-	if (src_attr->extend != CAIRO_EXTEND_NONE)
-	    return DFXL_NONE;
-
-	return DFXL_STRETCHBLIT;
-    }
-
-    switch (src_attr->extend) {
-    case CAIRO_EXTEND_NONE:
-    case CAIRO_EXTEND_REPEAT:
-	if (_cairo_matrix_is_integer_translation (&src_attr->matrix,
-						  NULL, NULL))
-	{
-	    return DFXL_BLIT;
-	}
-	else
-	{
-	    return DFXL_STRETCHBLIT;
-	}
-
-    default:
-    case CAIRO_EXTEND_REFLECT:
-    case CAIRO_EXTEND_PAD:
-	return DFXL_NONE;
-    }
-}
-
-static cairo_int_status_t
-_cairo_directfb_surface_composite (cairo_operator_t  op,
-                                   const cairo_pattern_t  *src_pattern,
-                                   const cairo_pattern_t  *mask_pattern,
-                                   void             *abstract_dst,
-                                   int  src_x,  int  src_y,
-                                   int  mask_x, int  mask_y,
-                                   int  dst_x,  int  dst_y,
-                                   unsigned int      width,
-                                   unsigned int      height,
-				   cairo_region_t   *clip_region)
-{
-    cairo_directfb_surface_t   *dst = abstract_dst;
-    cairo_directfb_surface_t   *src;
-    cairo_surface_attributes_t  src_attr;
-    cairo_bool_t                is_integer_translation;
-    DFBAccelerationMask         accel, mask;
-    cairo_int_status_t          status;
-    int                         tx, ty;
-
-    D_DEBUG_AT (CairoDFB_Render,
-		"%s( op=%d, src_pattern=%p, mask_pattern=%p, dst=%p,"
-		" src_x=%d, src_y=%d, mask_x=%d, mask_y=%d, dst_x=%d,"
-		" dst_y=%d, width=%u, height=%u ).\n",
-		__FUNCTION__, op, src_pattern, mask_pattern, dst,
-		src_x, src_y, mask_x, mask_y, dst_x, dst_y, width, height);
-
-    if (! dst->supported_destination)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    status = _directfb_prepare_composite (dst, src_pattern, mask_pattern, op,
-					  &src_x, &src_y, &mask_x, &mask_y,
-					  width, height, &src, &src_attr);
-    if (status)
-	return status;
-
-    accel = _directfb_categorize_operation (&src_attr);
-    if (accel == DFXL_NONE) {
-	_directfb_finish_composite (dst, src_pattern, &src->base, &src_attr);
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-    }
-
-    dst->dfbsurface->GetAccelerationMask (dst->dfbsurface,
-					  src->dfbsurface,
-					  &mask);
-    if ((mask & accel) == 0) {
-	D_DEBUG_AT (CairoDFB_Render, "No acceleration (%08x)!\n", accel);
-	if (accel != DFXL_BLIT) {
-	    _directfb_finish_composite (dst, src_pattern, &src->base, &src_attr);
-	    return CAIRO_INT_STATUS_UNSUPPORTED;
-	}
-    }
-
-    src_x += src_attr.x_offset;
-    src_y += src_attr.y_offset;
-
-    switch ((int) accel) {
-    case DFXL_BLIT:
-	{
-	    DFBRectangle sr;
-
-	    is_integer_translation =
-		_cairo_matrix_is_integer_translation (&src_attr.matrix,
-						      &tx, &ty);
-	    assert (is_integer_translation);
-
-	    sr.x = src_x + tx;
-	    sr.y = src_y + ty;
-	    sr.w = width;
-	    sr.h = height;
-
-	    if (src_attr.extend == CAIRO_EXTEND_NONE) {
-		D_DEBUG_AT (CairoDFB_Render, "Running Blit().\n");
-
-		RUN_CLIPPED (dst, clip_region, NULL,
-			     dst->dfbsurface->Blit (dst->dfbsurface,
-						    src->dfbsurface,
-						    &sr, dst_x, dst_y));
-	    } else if (src_attr.extend == CAIRO_EXTEND_REPEAT) {
-		DFBRegion clip;
-
-		clip.x1 = dst_x;
-		clip.y1 = dst_y;
-		clip.x2 = dst_x + width  - 1;
-		clip.y2 = dst_y + height - 1;
-
-		D_DEBUG_AT (CairoDFB_Render, "Running TileBlit().\n");
-
-		RUN_CLIPPED (dst, clip_region, &clip,
-			     dst->dfbsurface->TileBlit (dst->dfbsurface,
-							src->dfbsurface,
-							&sr, dst_x, dst_y));
-	    }
-	    break;
-	}
-
-    case DFXL_STRETCHBLIT:
-	{
-	    DFBRectangle sr, dr;
-	    double       x1, y1, x2, y2;
-
-	    TRANSFORM_POINT2X (src_attr.matrix,
-			       src_x, src_y, x1, y1);
-	    TRANSFORM_POINT2X (src_attr.matrix,
-			       src_x+width, src_y+height, x2, y2);
-
-	    sr.x = floor (x1);
-	    sr.y = floor (y1);
-	    sr.w = ceil (x2) - sr.x;
-	    sr.h = ceil (y2) - sr.y;
-
-	    dr.x = dst_x;
-	    dr.y = dst_y;
-	    dr.w = width;
-	    dr.h = height;
-
-	    D_DEBUG_AT (CairoDFB_Render, "Running StretchBlit().\n");
-
-	    RUN_CLIPPED (dst, clip_region, NULL,
-			 dst->dfbsurface->StretchBlit (dst->dfbsurface,
-						       src->dfbsurface,
-						       &sr, &dr));
-	    break;
-	}
-
-    case DFXL_TEXTRIANGLES:
-	{
-	    DFBRegion clip;
-	    DFBVertex v[4];
-	    float     x1, y1, x2, y2;
-	    int       w, h;
-
-	    status = cairo_matrix_invert (&src_attr.matrix);
-	    /* guaranteed by cairo_pattern_set_matrix (); */
-	    assert (status == CAIRO_STATUS_SUCCESS);
-
-	    x1 = src_x;
-	    y1 = src_y;
-	    x2 = width  + x1;
-	    y2 = height + y1;
-
-	    src->dfbsurface->GetSize (src->dfbsurface, &w, &h);
-
-	    TRANSFORM_POINT3X (src_attr.matrix, x1, y1, v[0].x, v[0].y);
-	    v[0].z = 0;
-	    v[0].w = 1;
-	    v[0].s = x1 / w;
-	    v[0].t = y1 / h;
-
-	    TRANSFORM_POINT3X (src_attr.matrix, x2, y1, v[1].x, v[1].y);
-	    v[1].z = 0;
-	    v[1].w = 1;
-	    v[1].s = x2 / w;
-	    v[1].t = y1 / h;
-
-	    TRANSFORM_POINT3X (src_attr.matrix, x2, y2, v[2].x, v[2].y);
-	    v[2].z = 0;
-	    v[2].w = 1;
-	    v[2].s = x2 / w;
-	    v[2].t = y2 / h;
-
-	    TRANSFORM_POINT3X (src_attr.matrix, x1, y2, v[3].x, v[3].y);
-	    v[3].z = 0;
-	    v[3].w = 1;
-	    v[3].s = x1 / w;
-	    v[3].t = y2 / h;
-
-	    clip.x1 = dst_x;
-	    clip.y1 = dst_y;
-	    clip.x2 = dst_x + width  - 1;
-	    clip.y2 = dst_y + height - 1;
-
-	    D_DEBUG_AT (CairoDFB_Render, "Running TextureTriangles().\n");
-
-	    RUN_CLIPPED (dst, clip_region, &clip,
-			 dst->dfbsurface->TextureTriangles (dst->dfbsurface,
-							    src->dfbsurface,
-							    v, NULL,
-							    4, DTTF_FAN));
-	    break;
-	}
-
-    default:
-	D_BUG ("Unexpected operation");
-	break;
-    }
-
-    _directfb_finish_composite (dst, src_pattern, &src->base, &src_attr);
-
-    return CAIRO_STATUS_SUCCESS;
+#define RUN_CLIPPED(surface, clip_region, clip, func) {\
+    if ((clip_region) != NULL) {\
+	int n_clips = cairo_region_num_rectangles (clip_region), n; \
+        for (n = 0; n < n_clips; n++) {\
+            if (clip) {\
+                DFBRegion  reg, *cli = (clip); \
+		cairo_rectangle_int_t rect; \
+		cairo_region_get_rectangle (clip_region, n, &rect); \
+		reg.x1 = rect.x; \
+		reg.y1 = rect.y; \
+		reg.x2 = rect.x + rect.width - 1; \
+		reg.y2 = rect.y + rect.height - 1; \
+                if (reg.x2 < cli->x1 || reg.y2 < cli->y1 ||\
+                    reg.x1 > cli->x2 || reg.y1 > cli->y2)\
+                    continue;\
+                if (reg.x1 < cli->x1)\
+                    reg.x1 = cli->x1;\
+                if (reg.y1 < cli->y1)\
+                    reg.y1 = cli->y1;\
+                if (reg.x2 > cli->x2)\
+                    reg.x2 = cli->x2;\
+                if (reg.y2 > cli->y2)\
+                    reg.y2 = cli->y2;\
+                (surface)->dfbsurface->SetClip ((surface)->dfbsurface, &reg);\
+            } else {\
+		DFBRegion reg; \
+		cairo_rectangle_int_t rect; \
+		cairo_region_get_rectangle (clip_region, n, &rect); \
+		reg.x1 = rect.x; \
+		reg.y1 = rect.y; \
+		reg.x2 = rect.x + rect.width - 1; \
+		reg.y2 = rect.y + rect.height - 1; \
+                (surface)->dfbsurface->SetClip ((surface)->dfbsurface, &reg); \
+            }\
+            func;\
+        }\
+    } else {\
+        (surface)->dfbsurface->SetClip ((surface)->dfbsurface, clip);\
+        func;\
+    }\
 }
-#endif /* DFB_COMPOSITE */
 
-#if DFB_RECTANGLES
 static cairo_int_status_t
-_cairo_directfb_surface_fill_rectangles (void                  *abstract_surface,
+_cairo_dfb_surface_fill_rectangles (void                  *abstract_surface,
                                          cairo_operator_t       op,
                                          const cairo_color_t   *color,
                                          cairo_rectangle_int_t *rects,
                                          int                    n_rects)
 {
-    cairo_directfb_surface_t *dst   = abstract_surface;
+    cairo_dfb_surface_t *dst   = abstract_surface;
     DFBSurfaceDrawingFlags    flags;
     DFBSurfaceBlendFunction   sblend;
     DFBSurfaceBlendFunction   dblend;
@@ -1241,731 +482,114 @@ _cairo_directfb_surface_fill_rectangles (void                  *abstract_surface
 }
 #endif
 
-#if DFB_COMPOSITE_TRAPEZOIDS
+static cairo_surface_backend_t
+_cairo_dfb_surface_backend = {
+    CAIRO_SURFACE_TYPE_DIRECTFB, /*type*/
+    _cairo_dfb_surface_finish, /*finish*/
+    _cairo_default_context_create,
+
+    _cairo_dfb_surface_create_similar,/*create_similar*/
+    NULL, /* create similar image */
+    _cairo_dfb_surface_map_to_image,
+    _cairo_dfb_surface_unmap_image,
+
+    _cairo_surface_default_source,
+    _cairo_dfb_surface_acquire_source_image,
+    _cairo_dfb_surface_release_source_image,
+    NULL,
+
+    NULL, /* copy_page */
+    NULL, /* show_page */
+
+    _cairo_image_surface_get_extents,
+    _cairo_image_surface_get_font_options,
+
+    _cairo_dfb_surface_flush,
+    NULL, /* mark_dirty_rectangle */
+
+    _cairo_image_surface_paint,
+    _cairo_image_surface_mask,
+    _cairo_image_surface_stroke,
+    _cairo_image_surface_fill,
+    NULL, /* fill-stroke */
+    _cairo_image_surface_glyphs,
+};
+
+#if 0
 static cairo_int_status_t
-_cairo_directfb_surface_composite_trapezoids (cairo_operator_t   op,
-                                              const cairo_pattern_t   *pattern,
-                                              void              *abstract_dst,
-                                              cairo_antialias_t  antialias,
-                                              int  src_x,   int  src_y,
-                                              int  dst_x,   int  dst_y,
-                                              unsigned int       width,
-                                              unsigned int       height,
-                                              cairo_trapezoid_t *traps,
-                                              int                num_traps,
-					      cairo_region_t	*clip_region)
+_cairo_dfb_compositor_paint (const cairo_compositor_t	*compositor,
+			     cairo_composite_rectangles_t *extents)
 {
-    cairo_directfb_surface_t   *dst = abstract_dst;
-    cairo_directfb_surface_t   *src;
-    cairo_surface_attributes_t  src_attr;
-    cairo_status_t              status;
-    DFBAccelerationMask         accel;
-
-    D_DEBUG_AT (CairoDFB_Render,
-                "%s( op=%d, pattern=%p, dst=%p, antialias=%d,"
-                   " src_x=%d, src_y=%d, dst_x=%d, dst_y=%d,"
-                   " width=%u, height=%u, traps=%p, num_traps=%d ).\n",
-                __FUNCTION__, op, pattern, dst, antialias,
-                src_x, src_y, dst_x, dst_y, width, height, traps, num_traps);
+    cairo_dfb_surface_t *surface = (cairo_dfb_surface_t *)extents->surface;
+    cairo_int_status_t status;
 
-    if (! dst->supported_destination)
+    if (surface->image.pixman_image)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
-    if (antialias != CAIRO_ANTIALIAS_NONE)
-        return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    /* Textures are not supported yet. */
-    if (pattern->type != CAIRO_PATTERN_TYPE_SOLID)
-        return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    status = _directfb_prepare_composite (dst, pattern, NULL, op,
-					  &src_x, &src_y, NULL, NULL,
-					  width, height, &src, &src_attr);
-    if (status)
-        return status;
-
-    dst->dfbsurface->GetAccelerationMask (dst->dfbsurface,
-					  src->dfbsurface,
-					  &accel);
-
     status = CAIRO_INT_STATUS_UNSUPPORTED;
+    if (_cairo_clip_is_region (extents->clip)) {
+	cairo_boxes_t boxes;
 
-    if (accel & DFXL_TEXTRIANGLES) {
-        DFBVertex  vertex[6*num_traps];
-        DFBVertex *v = &vertex[0];
-        int        n = 0;
-
-#define ADD_TRI_V(V, X, Y) do { \
-    (V)->x = (X); (V)->y = (Y); (V)->w = 1; (V)->z = (V)->s = (V)->t = 0; \
-} while (0)
-#define ADD_TRI(id, x1, y1, x2, y2, x3, y3) do {\
-    const int p = (id)*3;\
-    ADD_TRI_V (v+p+0, x1, y1); \
-    ADD_TRI_V (v+p+1, x2, y2); \
-    ADD_TRI_V (v+p+2, x3, y3); \
-} while (0)
-	while (num_traps--) {
-            double lx1, ly1, lx2, ly2;
-            double rx1, ry1, rx2, ry2;
-
-            lx1 = _cairo_fixed_to_double (traps->left.p1.x);
-            ly1 = _cairo_fixed_to_double (traps->left.p1.y);
-            lx2 = _cairo_fixed_to_double (traps->left.p2.x);
-            ly2 = _cairo_fixed_to_double (traps->left.p2.y);
-            rx1 = _cairo_fixed_to_double (traps->right.p1.x);
-            ry1 = _cairo_fixed_to_double (traps->right.p1.y);
-            rx2 = _cairo_fixed_to_double (traps->right.p2.x);
-            ry2 = _cairo_fixed_to_double (traps->right.p2.y);
-
-            if (traps->left.p1.y < traps->top) {
-                double y = _cairo_fixed_to_double (traps->top);
-                if (lx2 != lx1)
-                    lx1 = (y - ly1) * (lx2 - lx1) / (ly2 - ly1) + lx1;
-                ly1 = y;
-            }
-            if (traps->left.p2.y > traps->bottom) {
-                double y = _cairo_fixed_to_double (traps->bottom);
-                if (lx2 != lx1)
-                    lx2 = (y - ly1) * (lx2 - lx1) / (ly2 - ly1) + lx1;
-                ly2 = y;
-            }
-
-            if (traps->right.p1.y < traps->top) {
-                double y = _cairo_fixed_to_double (traps->top);
-                if (rx2 != rx1)
-                    rx1 = (y - ry1) * (rx2 - rx1) / (ry2 - ry1) + rx1;
-                ry1 = y;
-            }
-            if (traps->right.p2.y > traps->bottom) {
-                double y = _cairo_fixed_to_double (traps->bottom);
-                if (rx2 != rx1)
-                    rx2 = (y - ry1) * (rx2 - rx1) / (ry2 - ry1) + rx1;
-                ry2 = y;
-            }
-
-            if (lx1 == rx1 && ly1 == ry1) {
-                ADD_TRI (0, lx2, ly2, lx1, ly1, rx2, ry2);
-                v += 3;
-                n += 3;
-            } else if (lx2 == rx2 && ly2 == ry2) {
-                ADD_TRI (0, lx1, ly1, lx2, ly2, rx1, ry1);
-                v += 3;
-                n += 3;
-            } else {
-                ADD_TRI (0, lx1, ly1, rx1, ry1, lx2, ly2);
-                ADD_TRI (1, lx2, ly2, rx1, ry1, rx2, ry2);
-                v += 6;
-                n += 6;
-            }
-
-            traps++;
-        }
-#undef ADD_TRI
-#undef ADD_TRI_V
-
-        D_DEBUG_AT (CairoDFB_Render, "Running TextureTriangles().\n");
-
-        RUN_CLIPPED (dst, clip_region, NULL,
-                     dst->dfbsurface->TextureTriangles (dst->dfbsurface,
-							src->dfbsurface,
-							vertex, NULL, n,
-							DTTF_LIST));
-
-        status = CAIRO_STATUS_SUCCESS;
+	 _cairo_clip_steal_boxes (extents->clip, &boxes);
+	 status = draw_boxes (extents, &boxes);
+	 _cairo_clip_unsteal_boxes (extents->clip, &boxes);
     }
 
-    _directfb_finish_composite (dst, pattern, &src->base, &src_attr);
-
     return status;
 }
-#endif /* DFB_COMPOSITE_TRAPEZOIDS */
-
-static cairo_bool_t
-_cairo_directfb_abstract_surface_get_extents (void                  *abstract_surface,
-                                              cairo_rectangle_int_t *rectangle)
-{
-    cairo_directfb_surface_t *surface = abstract_surface;
-
-    D_DEBUG_AT (CairoDFB_Surface,
-		"%s( surface=%p, rectangle=%p ).\n",
-		__FUNCTION__, surface, rectangle);
-
-    if (!surface->local) {
-	surface->dfbsurface->GetSize (surface->dfbsurface,
-				      &surface->width, &surface->height);
-    }
-
-    rectangle->x = 0;
-    rectangle->y = 0;
-    rectangle->width  = surface->width;
-    rectangle->height = surface->height;
-
-    return TRUE;
-}
-
-#if DFB_SHOW_GLYPHS
-static cairo_status_t
-_directfb_allocate_font_cache (IDirectFB *dfb,
-			       int width, int height,
-			       cairo_directfb_font_cache_t **out)
-{
-    cairo_directfb_font_cache_t *cache;
-    cairo_status_t status;
-
-    cache = calloc (1, sizeof (cairo_directfb_font_cache_t));
-    if (cache == NULL)
-        return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-    cache->dfb = dfb;
-    status = _directfb_buffer_surface_create (dfb,
-                            _directfb_argb_font ? DSPF_ARGB : DSPF_A8,
-			    width, height,
-			    &cache->dfbsurface);
-    if (status) {
-        free (cache);
-	return status;
-    }
-
-    cache->width  = width;
-    cache->height = height;
-    *out = cache;
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static void
-_directfb_destroy_font_cache (cairo_directfb_font_cache_t *cache)
-{
-    cache->dfbsurface->Release (cache->dfbsurface);
-    free (cache);
-}
-
-/* XXX hook into rtree font cache from drm */
-static cairo_status_t
-_directfb_acquire_font_cache (cairo_directfb_surface_t     *surface,
-                              cairo_scaled_font_t          *scaled_font,
-                              const cairo_glyph_t          *glyphs,
-                              int                           num_glyphs,
-                              cairo_directfb_font_cache_t **ret_cache,
-                              DFBRectangle                 *rects,
-                              DFBPoint                     *points,
-			      int                          *ret_num)
-{
-    cairo_status_t               status;
-    cairo_scaled_glyph_t        *chars[num_glyphs];
-    int                          num_chars = 0;
-    cairo_directfb_font_cache_t *cache     = NULL;
-    int                          n         = 0;
-    int                          x         = 0;
-    int                          y         = 0;
-    int                          w         = 8;
-    int                          h         = 8;
-    int                          i;
-
-    D_DEBUG_AT (CairoDFB_Font, "%s( %p [%d] )\n", __FUNCTION__, glyphs, num_glyphs );
-
-    _cairo_scaled_font_freeze_cache (scaled_font);
-
-    if (scaled_font->surface_private) {
-	cache = scaled_font->surface_private;
-	x = cache->x;
-	y = cache->y;
-    }
-
-    for (i = 0; i < num_glyphs; i++) {
-	cairo_scaled_glyph_t  *scaled_glyph;
-	cairo_image_surface_t *img;
-
-	D_DEBUG_AT (CairoDFB_Font, "  -> [%2d] = %4lu\n", i, glyphs[i].index );
-
-	status = _cairo_scaled_glyph_lookup (scaled_font, glyphs[i].index,
-					  CAIRO_SCALED_GLYPH_INFO_SURFACE,
-					  &scaled_glyph);
-	if (status) {
-	    _cairo_scaled_font_thaw_cache (scaled_font);
-	    return status;
-	}
-
-	img = scaled_glyph->surface;
-	switch (img->format) {
-	case CAIRO_FORMAT_A1:
-	case CAIRO_FORMAT_A8:
-	case CAIRO_FORMAT_ARGB32:
-	    break;
-	case CAIRO_FORMAT_RGB24:
-	default:
-	    D_DEBUG_AT (CairoDFB_Font,
-			"  -> Unsupported font format %d!\n", img->format);
-	    _cairo_scaled_font_thaw_cache (scaled_font);
-	    return CAIRO_INT_STATUS_UNSUPPORTED;
-	}
-
-	points[n].x = _cairo_lround (glyphs[i].x - img->base.device_transform.x0);
-	points[n].y = _cairo_lround (glyphs[i].y - img->base.device_transform.y0);
-
-	//        D_DEBUG_AT (CairoDFB_Font, "            (%4d,%4d) [%2d]\n", points[n].x, points[n].y, n );
-
-	if (points[n].x >= surface->width  ||
-	    points[n].y >= surface->height ||
-	    points[n].x+img->width  <= 0   ||
-	    points[n].y+img->height <= 0)
-	{
-	    continue;
-	}
-
-	if (scaled_glyph->surface_private == NULL) {
-	    DFBRectangle *rect;
-
-	    if (x+img->width > 2048) {
-		x = 0;
-		y = h;
-		h = 0;
-	    }
-
-	    rects[n].x = x;
-	    rects[n].y = y;
-	    rects[n].w = img->width;
-	    rects[n].h = img->height;
-
-	    x += img->width;
-	    h  = MAX (h, img->height);
-	    w  = MAX (w, x);
-
-	    /* Remember glyph location */
-	    rect = malloc (sizeof (DFBRectangle));
-	    if (rect == NULL) {
-		_cairo_scaled_font_thaw_cache (scaled_font);
-		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	    }
-	    *rect = rects[n];
-
-	    scaled_glyph->surface_private = rect;
-	    chars[num_chars++] = scaled_glyph;
-
-	    D_DEBUG_AT (CairoDFB_Font, "  -> loading at %4d,%2d <- rect %p, img %p, entry %p\n",
-			rects[n].x, rects[n].y, rect, scaled_glyph->surface, scaled_glyph);
-	} else {
-	    rects[n] = *(DFBRectangle *) scaled_glyph->surface_private;
-
-	    D_DEBUG_AT (CairoDFB_Font, "  -> exists at  %4d,%2d\n", rects[n].x, rects[n].y);
-	}
-
-	n++;
-    }
-
-    if (n == 0) {
-	_cairo_scaled_font_thaw_cache (scaled_font);
-	return CAIRO_INT_STATUS_NOTHING_TO_DO;
-    }
-
-    h += y;
-    w = MAX (w, 8);
-    h = MAX (h, 8);
-
-    /* XXX query maximum surface size */
-    if (w > 2048 || h > 2048) {
-	_cairo_scaled_font_thaw_cache (scaled_font);
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-    }
-
-    if (cache) {
-	if (cache->width < w || cache->height < h) {
-	    cairo_directfb_font_cache_t *new_cache;
-
-	    w = MAX (w, cache->width);
-	    h = MAX (h, cache->height);
-
-	    D_DEBUG_AT (CairoDFB_Font, "  -> Reallocating font cache (%dx%d).\n", w, h);
-
-	    status = _directfb_allocate_font_cache (surface->dfb,
-						    w, h,
-						    &new_cache);
-	    if (status) {
-		_cairo_scaled_font_thaw_cache (scaled_font);
-		return status;
-	    }
-
-	    new_cache->dfbsurface->Blit (new_cache->dfbsurface,
-					 cache->dfbsurface, NULL, 0, 0);
-
-	    _directfb_destroy_font_cache (cache);
-	    scaled_font->surface_private = cache = new_cache;
-	}
-    } else {
-	D_DEBUG_AT (CairoDFB_Font, "  -> Allocating font cache (%dx%d).\n", w, h);
-
-	status = _directfb_allocate_font_cache (surface->dfb, w, h, &cache);
-	if (status) {
-	    _cairo_scaled_font_thaw_cache (scaled_font);
-	    return status;
-	}
-
-	scaled_font->surface_backend = &_cairo_directfb_surface_backend;
-	scaled_font->surface_private = cache;
-    }
-
-    if (num_chars) {
-	unsigned char *data;
-	int            pitch;
-
-	if (cache->dfbsurface->Lock (cache->dfbsurface,
-				     DSLF_WRITE, (void *)&data, &pitch))
-	{
-	    _cairo_scaled_font_thaw_cache (scaled_font);
-	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-	}
-
-	D_DEBUG_AT (CairoDFB_Font, "  => %d chars to load, cache %dx%d\n", num_chars, cache->width, cache->height);
-
-	for (i = 0; i < num_chars; i++) {
-	    cairo_image_surface_t *img  = chars[i]->surface;
-	    DFBRectangle          *rect = chars[i]->surface_private;
-	    unsigned char         *dst  = data;
-	    unsigned char         *src;
-	    int                    j;
-
-	    D_DEBUG_AT (CairoDFB_Font, "  -> loading [%2d] <- rect %p, img %p, entry %p\n", i, rect, img, chars[i]);
-
-	    src = img->data;
-
-	    D_DEBUG_AT (CairoDFB_Font, "     from %p\n", src);
-
-	    dst += rect->y * pitch + (_directfb_argb_font ? (rect->x<<2) : rect->x);
-
-	    D_DEBUG_AT (CairoDFB_Font, "     to %4d,%2d (%p)\n", rect->x, rect->y, dst);
-
-	    if (img->format == CAIRO_FORMAT_A1) {
-		for (h = rect->h; h; h--) {
-		    if (_directfb_argb_font) {
-			for (j = 0; j < rect->w; j++)
-			    ((uint32_t *) dst)[j] = (src[j>>3] & (1 << (j&7))) ? 0xffffffff : 0;
-		    } else {
-			for (j = 0; j < rect->w; j++)
-			    dst[j] = (src[j>>3] & (1 << (j&7))) ? 0xff : 0;
-		    }
-
-		    dst += pitch;
-		    src += img->stride;
-		}
-	    } else if (img->format == CAIRO_FORMAT_A8) {
-		for (h = rect->h; h; h--) {
-		    if (_directfb_argb_font) {
-			for (j = 0; j < rect->w; j++)
-			    ((uint32_t *) dst)[j] = src[j] * 0x01010101;
-		    } else {
-			direct_memcpy (dst, src, rect->w);
-		    }
-
-		    dst += pitch;
-		    src += img->stride;
-		}
-	    } else { /* ARGB32 */
-		for (h = rect->h; h; h--) {
-		    if (_directfb_argb_font) {
-			direct_memcpy (dst, src, rect->w<<2);
-		    } else {
-			for (j = 0; j < rect->w; j++)
-			    dst[j] = ((uint32_t *) src)[j] >> 24;
-		    }
-
-		    dst += pitch;
-		    src += img->stride;
-		}
-	    }
-	}
-
-	cache->dfbsurface->Unlock (cache->dfbsurface);
-    }
-
-    _cairo_scaled_font_thaw_cache (scaled_font);
-
-    cache->x = x;
-    cache->y = y;
-
-    D_DEBUG_AT (CairoDFB_Font, "  => cache %d,%d, %p [%d]\n", x, y, cache, n);
-
-    *ret_cache = cache;
-    *ret_num   = n;
-
-    return CAIRO_STATUS_SUCCESS;
-}
-
-static void
-_cairo_directfb_surface_scaled_font_fini (cairo_scaled_font_t *scaled_font)
-{
-    cairo_directfb_font_cache_t *cache = scaled_font->surface_private;
-
-    D_DEBUG_AT (CairoDFB_Font,
-		"%s( scaled_font=%p ).\n", __FUNCTION__, scaled_font);
-
-    if (cache != NULL) {
-	_directfb_destroy_font_cache (cache);
-	scaled_font->surface_private = NULL;
-    }
-}
-
-static void
-_cairo_directfb_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph,
-                                           cairo_scaled_font_t  *scaled_font)
-{
-     D_DEBUG_AT (CairoDFB_Font,
-                 "%s( scaled_glyph=%p, scaled_font=%p ).\n",
-                 __FUNCTION__, scaled_glyph, scaled_font);
-
-     free (scaled_glyph->surface_private);
-     scaled_glyph->surface_private = NULL;
-}
-
-static cairo_int_status_t
-_cairo_directfb_surface_show_glyphs (void		    *abstract_dst,
-                                     cairo_operator_t	     op,
-                                     const cairo_pattern_t  *pattern,
-                                     cairo_glyph_t	    *glyphs,
-                                     int		     num_glyphs,
-                                     cairo_scaled_font_t    *scaled_font,
-				     const cairo_clip_t	    *clip,
-				     int		    *remaining_glyphs)
-{
-    cairo_directfb_surface_t    *dst = abstract_dst;
-    cairo_directfb_font_cache_t *cache;
-    cairo_status_t               status;
-    DFBSurfaceBlittingFlags      flags;
-    DFBSurfaceBlendFunction      sblend;
-    DFBSurfaceBlendFunction      dblend;
-    DFBRectangle                 rects[num_glyphs];
-    DFBPoint                     points[num_glyphs];
-    int                          num;
-    const cairo_color_t         *color;
-    cairo_region_t		*clip_region = NULL;
-
-    D_DEBUG_AT (CairoDFB_Font,
-		"%s( dst=%p, op=%d, pattern=%p, glyphs=%p, num_glyphs=%d, scaled_font=%p ).\n",
-		__FUNCTION__, dst, op, pattern, glyphs, num_glyphs, scaled_font);
-
-    if (! dst->supported_destination)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    if (pattern->type != CAIRO_PATTERN_TYPE_SOLID)
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    /* Fallback if we need to emulate clip regions */
-    if (clip != NULL) {
-	clip_region = _cairo_clip_get_region (clip);
-	if (unlikely (clip_region == NULL))
-	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-    }
-
-    /* XXX Unbounded operators are not handled correctly */
-    if (! _cairo_operator_bounded_by_mask (op))
-        return CAIRO_INT_STATUS_UNSUPPORTED;
-
-    if (! _directfb_get_operator (op, &sblend, &dblend) ||
-	sblend == DSBF_DESTALPHA || sblend == DSBF_INVDESTALPHA)
-    {
-	return CAIRO_INT_STATUS_UNSUPPORTED;
-    }
-
-    status = _directfb_acquire_font_cache (dst, scaled_font, glyphs, num_glyphs,
-					   &cache, &rects[0], &points[0], &num);
-    if (status) {
-	if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
-	    status = CAIRO_STATUS_SUCCESS;
-	return status;
-    }
-
-    color = &((cairo_solid_pattern_t *) pattern)->color;
-
-    flags = DSBLIT_BLEND_ALPHACHANNEL | DSBLIT_COLORIZE;
-    if (! CAIRO_COLOR_IS_OPAQUE (color))
-	flags |= DSBLIT_BLEND_COLORALPHA;
-
-    if (!_directfb_argb_font) {
-	if (sblend == DSBF_ONE) {
-	    sblend = DSBF_SRCALPHA;
-	    if (dblend == DSBF_ZERO)
-		dblend = DSBF_INVSRCALPHA;
-	}
-    }
-
-    dst->dfbsurface->SetBlittingFlags (dst->dfbsurface, flags);
-    dst->dfbsurface->SetSrcBlendFunction (dst->dfbsurface, sblend);
-    dst->dfbsurface->SetDstBlendFunction (dst->dfbsurface, dblend);
-    if (dst->blit_premultiplied) {
-	dst->dfbsurface->SetColor (dst->dfbsurface,
-				   color->red_short >> 8,
-				   color->green_short >> 8,
-				   color->blue_short >> 8,
-				   color->alpha_short >> 8);
-    } else {
-	dst->dfbsurface->SetColor (dst->dfbsurface,
-				   color->red * 0xff,
-				   color->green * 0xff,
-				   color->blue * 0xff,
-				   color->alpha * 0xff);
-    }
-
-    D_DEBUG_AT (CairoDFB_Font, "Running BatchBlit().\n");
-
-    RUN_CLIPPED (dst, clip_region, NULL,
-		 dst->dfbsurface->BatchBlit (dst->dfbsurface,
-					     cache->dfbsurface, rects, points, num));
-
-    return CAIRO_STATUS_SUCCESS;
-}
-#endif /* DFB_SHOW_GLYPHS */
-
-
-static cairo_bool_t
-_cairo_directfb_surface_is_similar (void *surface_a, void *surface_b)
-{
-    cairo_directfb_surface_t *a = (cairo_directfb_surface_t *) surface_a;
-    cairo_directfb_surface_t *b = (cairo_directfb_surface_t *) surface_b;
-
-    return a->dfb == b->dfb;
-}
-
-static cairo_surface_backend_t
-_cairo_directfb_surface_backend = {
-         CAIRO_SURFACE_TYPE_DIRECTFB, /*type*/
-        _cairo_directfb_surface_finish, /*finish*/
-
-	 _cairo_default_context_create,
-
-        _cairo_directfb_surface_create_similar,/*create_similar*/
-	NULL, /* create similar image */
-	NULL, /* map to image */
-	NULL, /* unmap image */
-
-	_cairo_surface_default_source,
-        _cairo_directfb_surface_acquire_source_image,/*acquire_source_image*/
-        _cairo_directfb_surface_release_source_image,/*release_source_image*/
-        _cairo_directfb_surface_acquire_dest_image,/*acquire_dest_image*/
-        _cairo_directfb_surface_release_dest_image,/*release_dest_image*/
-        _cairo_directfb_surface_clone_similar,/*clone_similar*/
-#if DFB_COMPOSITE
-        _cairo_directfb_surface_composite,/*composite*/
-#else
-        NULL,/*composite*/
-#endif
-#if DFB_RECTANGLES
-        _cairo_directfb_surface_fill_rectangles,/*fill_rectangles*/
-#else
-        NULL,/*fill_rectangles*/
-#endif
-#if DFB_COMPOSITE_TRAPEZOIDS
-        _cairo_directfb_surface_composite_trapezoids,/*composite_trapezoids*/
-#else
-        NULL,/*composite_trapezoids*/
 #endif
-        NULL, /* create_span_renderer */
-        NULL, /* check_span_renderer */
-        NULL, /* copy_page */
-        NULL, /* show_page */
-        _cairo_directfb_abstract_surface_get_extents,/* get_extents */
-        NULL, /* old_show_glyphs */
-        NULL, /* get_font_options */
-        NULL, /* flush */
-        NULL, /* mark_dirty_rectangle */
-#if DFB_SHOW_GLYPHS
-        _cairo_directfb_surface_scaled_font_fini,/* scaled_font_fini */
-        _cairo_directfb_surface_scaled_glyph_fini,/* scaled_glyph_fini */
-#else
-        NULL,
-        NULL,
-#endif
-        NULL, /* paint */
-        NULL, /* mask */
-        NULL, /* stroke */
-        NULL, /* fill */
-#if DFB_SHOW_GLYPHS
-        _cairo_directfb_surface_show_glyphs,/* show_glyphs */
-#else
-        NULL, /* show_glyphs */
-#endif
-        NULL, /* snapshot */
-        _cairo_directfb_surface_is_similar,
-};
 
-
-static void
-cairo_directfb_surface_backend_init (IDirectFB *dfb)
+static const cairo_compositor_t *
+_cairo_dfb_compositor_get (void)
 {
-    static int done = 0;
-
-    if (done)
-	return;
-
-    if (getenv ("CAIRO_DIRECTFB_NO_ACCEL")) {
-#if DFB_RECTANGLES
-	_cairo_directfb_surface_backend.fill_rectangles = NULL;
-#endif
-#if DFB_COMPOSITE
-	_cairo_directfb_surface_backend.composite = NULL;
-#endif
-#if DFB_COMPOSITE_TRAPEZOIDS
-	_cairo_directfb_surface_backend.composite_trapezoids = NULL;
-#endif
-#if DFB_SHOW_GLYPHS
-	_cairo_directfb_surface_backend.scaled_font_fini = NULL;
-	_cairo_directfb_surface_backend.scaled_glyph_fini = NULL;
-	_cairo_directfb_surface_backend.show_glyphs = NULL;
-#endif
-	D_DEBUG_AT (CairoDFB_Surface, "Acceleration disabled.\n");
-    } else {
-	DFBGraphicsDeviceDescription dsc;
-
-	dfb->GetDeviceDescription (dfb, &dsc);
-
-#if DFB_COMPOSITE
-	//        if (!(dsc.acceleration_mask & DFXL_BLIT))
-	//            _cairo_directfb_surface_backend.composite = NULL;
-#endif
-
-#if DFB_COMPOSITE_TRAPEZOIDS
-	//        if (!(dsc.acceleration_mask & DFXL_TEXTRIANGLES))
-	//            _cairo_directfb_surface_backend.composite_trapezoids = NULL;
-#endif
-    }
-
-    if (getenv ("CAIRO_DIRECTFB_ARGB_FONT")) {
-	_directfb_argb_font = 1;
-	D_DEBUG_AT (CairoDFB_Surface, "Using ARGB fonts.\n");
-    }
-
-    done = 1;
+    return &_cairo_fallback_compositor;
 }
 
 cairo_surface_t *
 cairo_directfb_surface_create (IDirectFB *dfb, IDirectFBSurface *dfbsurface)
 {
-    cairo_directfb_surface_t *surface;
+    cairo_dfb_surface_t *surface;
     DFBSurfacePixelFormat     format;
     DFBSurfaceCapabilities caps;
+    pixman_format_code_t pixman_format;
+    int width, height;
 
     D_ASSERT (dfb != NULL);
     D_ASSERT (dfbsurface != NULL);
 
-    cairo_directfb_surface_backend_init (dfb);
+    dfbsurface->GetPixelFormat (dfbsurface, &format);
+    dfbsurface->GetSize (dfbsurface, &width, &height);
 
-    surface = calloc (1, sizeof (cairo_directfb_surface_t));
+    pixman_format = _directfb_to_pixman_format (format);
+    if (! pixman_format_supported_destination (pixman_format))
+        return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
+
+    surface = calloc (1, sizeof (cairo_dfb_surface_t));
     if (surface == NULL)
         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 
-    dfbsurface->AddRef (dfbsurface);
-    dfbsurface->GetPixelFormat (dfbsurface, &format);
-    dfbsurface->GetSize (dfbsurface, &surface->width, &surface->height);
+    /* XXX dfb -> device */
+    _cairo_surface_init (&surface->image.base,
+                         &_cairo_dfb_surface_backend,
+			 NULL, /* device */
+			 _directfb_format_to_content (format));
+
+    surface->image.compositor = _cairo_dfb_compositor_get ();
+    surface->image.pixman_format = pixman_format;
+    surface->image.format = _cairo_format_from_pixman_format (pixman_format);
+
+    surface->image.width = width;
+    surface->image.height = height;
+    surface->image.depth = PIXMAN_FORMAT_DEPTH(pixman_format);
+
     surface->dfb = dfb;
-    surface->dfbsurface = dfbsurface;
-    surface->pixman_format = _directfb_to_pixman_format (format);
-    surface->supported_destination = pixman_format_supported_destination (surface->pixman_format);
+    surface->dfb_surface = dfbsurface;
+    dfbsurface->AddRef (dfbsurface);
 
     dfbsurface->GetCapabilities (dfbsurface, &caps);
     if (caps & DSCAPS_PREMULTIPLIED)
 	surface->blit_premultiplied = TRUE;
 
-    _cairo_surface_init (&surface->base,
-                         &_cairo_directfb_surface_backend,
-			 NULL, /* device */
-			 _directfb_format_to_content (format));
-
-    return &surface->base;
+    return &surface->image.base;
 }
+slim_hidden_def(cairo_directfb_surface_create);
diff --git a/src/cairo-image-surface-private.h b/src/cairo-image-surface-private.h
index d580d89..30713a8 100644
--- a/src/cairo-image-surface-private.h
+++ b/src/cairo-image-surface-private.h
@@ -85,6 +85,52 @@ _cairo_image_traps_compositor_get (void);
 cairo_private const cairo_compositor_t *
 _cairo_image_spans_compositor_get (void);
 
+#define _cairo_image_default_compositor_get _cairo_image_spans_compositor_get
+
+cairo_private cairo_int_status_t
+_cairo_image_surface_paint (void			*abstract_surface,
+			    cairo_operator_t		 op,
+			    const cairo_pattern_t	*source,
+			    const cairo_clip_t		*clip);
+
+cairo_private cairo_int_status_t
+_cairo_image_surface_mask (void				*abstract_surface,
+			   cairo_operator_t		 op,
+			   const cairo_pattern_t	*source,
+			   const cairo_pattern_t	*mask,
+			   const cairo_clip_t		*clip);
+
+cairo_private cairo_int_status_t
+_cairo_image_surface_stroke (void			*abstract_surface,
+			     cairo_operator_t		 op,
+			     const cairo_pattern_t	*source,
+			     const cairo_path_fixed_t	*path,
+			     const cairo_stroke_style_t	*style,
+			     const cairo_matrix_t	*ctm,
+			     const cairo_matrix_t	*ctm_inverse,
+			     double			 tolerance,
+			     cairo_antialias_t		 antialias,
+			     const cairo_clip_t		*clip);
+
+cairo_private cairo_int_status_t
+_cairo_image_surface_fill (void				*abstract_surface,
+			   cairo_operator_t		 op,
+			   const cairo_pattern_t	*source,
+			   const cairo_path_fixed_t	*path,
+			   cairo_fill_rule_t		 fill_rule,
+			   double			 tolerance,
+			   cairo_antialias_t		 antialias,
+			   const cairo_clip_t		*clip);
+
+cairo_private cairo_int_status_t
+_cairo_image_surface_glyphs (void			*abstract_surface,
+			     cairo_operator_t		 op,
+			     const cairo_pattern_t	*source,
+			     cairo_glyph_t		*glyphs,
+			     int			 num_glyphs,
+			     cairo_scaled_font_t	*scaled_font,
+			     const cairo_clip_t		*clip);
+
 cairo_private void
 _cairo_image_surface_init (cairo_image_surface_t *surface,
 			   pixman_image_t	*pixman_image,
diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index 212e2b5..05c99b7 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -865,7 +865,7 @@ _cairo_image_surface_get_extents (void			  *abstract_surface,
     return TRUE;
 }
 
-static cairo_int_status_t
+cairo_int_status_t
 _cairo_image_surface_paint (void			*abstract_surface,
 			    cairo_operator_t		 op,
 			    const cairo_pattern_t	*source,
@@ -876,7 +876,7 @@ _cairo_image_surface_paint (void			*abstract_surface,
 				    &surface->base, op, source, clip);
 }
 
-static cairo_int_status_t
+cairo_int_status_t
 _cairo_image_surface_mask (void				*abstract_surface,
 			   cairo_operator_t		 op,
 			   const cairo_pattern_t	*source,
@@ -888,7 +888,7 @@ _cairo_image_surface_mask (void				*abstract_surface,
 				   &surface->base, op, source, mask, clip);
 }
 
-static cairo_int_status_t
+cairo_int_status_t
 _cairo_image_surface_stroke (void			*abstract_surface,
 			     cairo_operator_t		 op,
 			     const cairo_pattern_t	*source,
@@ -907,7 +907,7 @@ _cairo_image_surface_stroke (void			*abstract_surface,
 				     tolerance, antialias, clip);
 }
 
-static cairo_int_status_t
+cairo_int_status_t
 _cairo_image_surface_fill (void				*abstract_surface,
 			   cairo_operator_t		 op,
 			   const cairo_pattern_t	*source,
@@ -924,7 +924,7 @@ _cairo_image_surface_fill (void				*abstract_surface,
 				   clip);
 }
 
-static cairo_int_status_t
+cairo_int_status_t
 _cairo_image_surface_glyphs (void			*abstract_surface,
 			     cairo_operator_t		 op,
 			     const cairo_pattern_t	*source,


More information about the cairo-commit mailing list