b=484864, b=488910 - cairo ddraw backend for wince; r=vlad
authorcmills@nvidia.com
Wed, 22 Apr 2009 17:48:30 -0700
changeset 27650 f6985866e6be2178331b38625f85c2e58cf10846
parent 27649 fc5d754b08c62e2e8580b6d1a7f580aeddbde6ae
child 27651 fb5b2cd77d38b24457c9db40f76a82f866642b5a
push id6670
push uservladimir@mozilla.com
push dateThu, 23 Apr 2009 01:03:07 +0000
treeherdermozilla-central@7fc81369ff6a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersvlad
bugs484864, 488910
milestone1.9.2a1pre
b=484864, b=488910 - cairo ddraw backend for wince; r=vlad
configure.in
gfx/cairo/cairo/src/Makefile.in
gfx/cairo/cairo/src/cairo-ddraw-private.h
gfx/cairo/cairo/src/cairo-ddraw-surface.c
gfx/cairo/cairo/src/cairo-ddraw.h
gfx/cairo/cairo/src/cairo-features.h.in
gfx/cairo/cairo/src/cairo.h
gfx/thebes/public/Makefile.in
gfx/thebes/public/gfxASurface.h
gfx/thebes/public/gfxDDrawSurface.h
gfx/thebes/src/Makefile.in
gfx/thebes/src/gfxASurface.cpp
gfx/thebes/src/gfxDDrawSurface.cpp
toolkit/library/Makefile.in
widget/src/windows/Makefile.in
widget/src/windows/nsWindow.cpp
--- a/configure.in
+++ b/configure.in
@@ -7592,18 +7592,20 @@ if test "$MOZ_TREE_CAIRO"; then
         QUARTZ_SURFACE_FEATURE="#define CAIRO_HAS_QUARTZ_SURFACE 1"
         QUARTZ_IMAGE_SURFACE_FEATURE="#define CAIRO_HAS_QUARTZ_IMAGE_SURFACE 1"
         QUARTZ_FONT_FEATURE="#define CAIRO_HAS_QUARTZ_FONT 1"
     fi
     if test "$MOZ_WIDGET_TOOLKIT" = "windows"; then
         WIN32_SURFACE_FEATURE="#define CAIRO_HAS_WIN32_SURFACE 1"
         if test -z "$WINCE"; then
            WIN32_FONT_FEATURE="#define CAIRO_HAS_WIN32_FONT 1"
+           DDRAW_SURFACE_FEATURE=
         else
            WIN32_FONT_FEATURE=
+           DDRAW_SURFACE_FEATURE="#define CAIRO_HAS_DDRAW_SURFACE 1"
         fi  
         PDF_SURFACE_FEATURE="#define CAIRO_HAS_PDF_SURFACE 1"
     fi
     if test "$MOZ_WIDGET_TOOLKIT" = "os2"; then
         OS2_SURFACE_FEATURE="#define CAIRO_HAS_OS2_SURFACE 1"
         FT_FONT_FEATURE="#define CAIRO_HAS_FT_FONT 1"
         FC_FONT_FEATURE="#define CAIRO_HAS_FC_FONT 1"
         PDF_SURFACE_FEATURE="#define CAIRO_HAS_PDF_SURFACE 1"
@@ -7633,16 +7635,17 @@ if test "$MOZ_TREE_CAIRO"; then
     AC_SUBST(PDF_SURFACE_FEATURE)
     AC_SUBST(SVG_SURFACE_FEATURE)
     AC_SUBST(XLIB_SURFACE_FEATURE)
     AC_SUBST(XLIB_XRENDER_SURFACE_FEATURE)
     AC_SUBST(QUARTZ_SURFACE_FEATURE)
     AC_SUBST(QUARTZ_IMAGE_SURFACE_FEATURE)
     AC_SUBST(XCB_SURFACE_FEATURE)
     AC_SUBST(WIN32_SURFACE_FEATURE)
+    AC_SUBST(DDRAW_SURFACE_FEATURE)
     AC_SUBST(OS2_SURFACE_FEATURE)
     AC_SUBST(BEOS_SURFACE_FEATURE)
     AC_SUBST(DIRECTFB_SURFACE_FEATURE)
     AC_SUBST(FT_FONT_FEATURE)
     AC_SUBST(FC_FONT_FEATURE)
     AC_SUBST(WIN32_FONT_FEATURE)
     AC_SUBST(QUARTZ_FONT_FEATURE)
     AC_SUBST(PNG_FUNCTIONS_FEATURE)
--- a/gfx/cairo/cairo/src/Makefile.in
+++ b/gfx/cairo/cairo/src/Makefile.in
@@ -152,16 +152,19 @@ PS_CSRCS = cairo-ps-surface.c
 PDF_EXPORTS = cairo-pdf.h
 PS_EXPORTS = cairo-ps.h
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
 CSRCS	+=	cairo-win32-surface.c
 
 ifndef WINCE
 CSRCS	+=	cairo-win32-font.c
+else
+CSRCS	+=	cairo-ddraw-surface.c
+EXPORTS +=	cairo-ddraw.h
 endif
 
 ifdef NS_PRINTING
 CSRCS   += cairo-win32-printing-surface.c
 else
 DEFINES += -DCAIRO_OMIT_WIN32_PRINTING
 endif
 
new file mode 100644
--- /dev/null
+++ b/gfx/cairo/cairo/src/cairo-ddraw-private.h
@@ -0,0 +1,64 @@
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2005 Red Hat, Inc
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is Red Hat, Inc.
+ *
+ * Contributor(s):
+ *	Owen Taylor <otaylor@redhat.com>
+ */
+
+#ifndef CAIRO_DDRAW_PRIVATE_H
+#define CAIRO_DDRAW_PRIVATE_H
+
+#include "cairo-ddraw.h"
+#include "cairoint.h"
+
+#define FILL_THRESHOLD (1024u)
+
+typedef struct _cairo_ddraw_surface {
+  cairo_surface_t base;
+  cairo_format_t format;
+  LPDIRECTDRAWSURFACE lpdds;
+  cairo_surface_t *image;
+  cairo_surface_t *alias;
+  cairo_point_int_t origin;
+  uint32_t data_offset;
+  LPDIRECTDRAWCLIPPER lpddc;
+  LPDIRECTDRAWCLIPPER installed_clipper;
+  cairo_rectangle_int_t extents;
+  cairo_region_t clip_region;
+  cairo_bool_t locked : 1;
+  cairo_bool_t has_clip_region : 1;
+  cairo_bool_t has_image_clip : 1;
+  cairo_bool_t has_clip_list : 1;
+  cairo_bool_t image_clip_invalid : 1;
+  cairo_bool_t clip_list_invalid : 1;
+} cairo_ddraw_surface_t;
+
+#endif /* CAIRO_DDRAW_PRIVATE_H */
new file mode 100644
--- /dev/null
+++ b/gfx/cairo/cairo/src/cairo-ddraw-surface.c
@@ -0,0 +1,827 @@
+/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
+/* Cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2009 NVIDIA Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is NVIDIA Corporation.
+ *
+ * Contributor(s):
+ */
+
+#ifndef WIN32_LEAN_AND_MEAN
+#define WIN32_LEAN_AND_MEAN
+#endif
+
+#include "cairoint.h"
+
+#include "cairo-clip-private.h"
+#include "cairo-ddraw-private.h"
+
+#include <windows.h>
+#include <ddraw.h>
+
+/* DirectDraw helper macros */
+
+#define DDCALL0(fn,p)           ((p)->lpVtbl->fn((p)))
+#define DDCALL1(fn,p,a)         ((p)->lpVtbl->fn((p),(a)))
+#define DDCALL2(fn,p,a,b)       ((p)->lpVtbl->fn((p),(a),(b)))
+#define DDCALL3(fn,p,a,b,c)     ((p)->lpVtbl->fn((p),(a),(b),(c)))
+#define DDCALL4(fn,p,a,b,c,d)   ((p)->lpVtbl->fn((p),(a),(b),(c),(d)))
+#define DDCALL5(fn,p,a,b,c,d,e) ((p)->lpVtbl->fn((p),(a),(b),(c),(d),(e)))
+
+#define IURelease(p)                  DDCALL0(Release,p)
+
+#define IDDCreateClipper(p,a,b,c)     DDCALL3(CreateClipper,p,a,b,c)
+#define IDDCreateSurface(p,a,b,c)     DDCALL3(CreateSurface,p,a,b,c)
+
+#define IDDCSetClipList(p,a,b)        DDCALL2(SetClipList,p,a,b)
+
+#define IDDSBlt(p,a,b,c,d,e)          DDCALL5(Blt,p,a,b,c,d,e)
+#define IDDSGetDDInterface(p,a)       DDCALL1(GetDDInterface,p,a)
+#define IDDSLock(p,a,b,c,d)           DDCALL4(Lock,p,a,b,c,d)
+#define IDDSSetClipper(p,a)           DDCALL1(SetClipper,p,a)
+#define IDDSUnlock(p,a)               DDCALL1(Unlock,p,a)
+#define IDDSGetPixelFormat(p,a)       DDCALL1(GetPixelFormat,p,a)
+
+static const cairo_surface_backend_t cairo_ddraw_surface_backend;
+
+/**
+ * _cairo_ddraw_print_ddraw_error:
+ * @context: context string to display along with the error
+ * @hr: HRESULT code
+ *
+ * Helper function to dump out a human readable form of the
+ * current error code.
+ *
+ * Return value: A cairo status code for the error code
+ **/
+static cairo_status_t
+_cairo_ddraw_print_ddraw_error (const char *context, HRESULT hr)
+{
+    /*XXX make me pretty */
+    fprintf(stderr, "%s: DirectDraw error 0x%08x\n", context, hr);
+
+    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+}
+
+static cairo_status_t
+_cairo_ddraw_surface_set_image_clip (cairo_ddraw_surface_t *surface)
+{
+    if (surface->image_clip_invalid) {
+	surface->image_clip_invalid = FALSE;
+	if (surface->has_clip_region) {
+	    unsigned int serial =
+		_cairo_surface_allocate_clip_serial (surface->image);
+	    surface->has_image_clip = TRUE;
+	    return _cairo_surface_set_clip_region (surface->image,
+						   &surface->clip_region,
+						   serial);
+	} else {
+	    surface->has_image_clip = FALSE;
+	    return _cairo_surface_set_clip_region (surface->image,
+						   NULL, 0);
+	}
+    }
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_ddraw_surface_set_clip_list (cairo_ddraw_surface_t * surface)
+{
+    DWORD stack_data[CAIRO_STACK_BUFFER_SIZE / sizeof (DWORD)];
+    cairo_rectangle_int_t extents;
+    int num_boxes;
+    RGNDATA * rgn;
+    DWORD size;
+    cairo_status_t status;
+    HRESULT hr;
+    RECT * prect;
+    int i;
+
+    if (!surface->clip_list_invalid)
+	return CAIRO_STATUS_SUCCESS;
+
+    surface->clip_list_invalid = FALSE;
+
+    if (!surface->has_clip_region) {
+	surface->has_clip_list = FALSE;
+	return CAIRO_STATUS_SUCCESS;
+    }
+
+    surface->has_clip_list = TRUE;
+	
+    _cairo_region_get_extents (&surface->clip_region, &extents);
+    
+    rgn = (RGNDATA *) stack_data;
+    num_boxes = _cairo_region_num_boxes (&surface->clip_region);
+    
+    size = sizeof (RGNDATAHEADER) + sizeof (RECT) * num_boxes;
+    if (size > sizeof (stack_data)) {
+	if ((rgn = (RGNDATA *) malloc (size)) == 0)
+	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    }
+    
+    rgn->rdh.dwSize = sizeof(RGNDATAHEADER);
+    rgn->rdh.iType = RDH_RECTANGLES;
+    rgn->rdh.nCount = num_boxes;
+    rgn->rdh.nRgnSize = num_boxes * sizeof (RECT);
+    rgn->rdh.rcBound.left = extents.x + surface->origin.x;
+    rgn->rdh.rcBound.top = extents.y + surface->origin.y;
+    rgn->rdh.rcBound.right = extents.x + extents.width + surface->origin.x;
+    rgn->rdh.rcBound.bottom = extents.y + extents.height + surface->origin.y;
+    
+    prect = (RECT *) &rgn->Buffer;
+    for (i = 0; i < num_boxes; ++i) {
+	cairo_box_int_t box;
+	
+	_cairo_region_get_box (&surface->clip_region, i, &box);
+	
+	prect->left = box.p1.x + surface->origin.x;
+	prect->top = box.p1.y + surface->origin.y;
+	prect->right = box.p2.x + surface->origin.x;
+	prect->bottom = box.p2.y + surface->origin.y;
+	++prect;
+    }
+    
+    status = CAIRO_STATUS_SUCCESS;
+    
+    if (FAILED(hr = IDDCSetClipList (surface->lpddc, rgn, 0)))
+	status = _cairo_ddraw_print_ddraw_error ("_set_clip_region", hr);
+    
+    if (rgn != (RGNDATA *) stack_data)
+	free (rgn);
+    
+    return status;
+}
+
+static cairo_status_t
+_cairo_ddraw_surface_lock (cairo_ddraw_surface_t *surface)
+{
+    HRESULT hr;
+    DDSURFACEDESC ddsd;
+    cairo_image_surface_t * img = (cairo_image_surface_t *) surface->image;
+
+    if (surface->alias) {
+	cairo_ddraw_surface_t * base =
+	    (cairo_ddraw_surface_t *) surface->alias;
+	cairo_image_surface_t * base_img;
+
+	if (!base->locked) {
+	    cairo_status_t status =
+		_cairo_ddraw_surface_lock (base);
+	    if (status)
+		return status;
+	}
+
+	base_img = (cairo_image_surface_t *) base->image;
+
+	if (img) {
+	    if (img->data == base_img->data + surface->data_offset &&
+		img->stride == base_img->stride)
+		return CAIRO_STATUS_SUCCESS;
+
+	    cairo_surface_destroy (surface->image);
+	}
+
+	surface->data_offset =
+	    surface->origin.y * base_img->stride + surface->origin.x * 4;
+	surface->image =
+	    cairo_image_surface_create_for_data (base_img->data +
+						 surface->data_offset,
+						 surface->format,
+						 surface->extents.width,
+						 surface->extents.height,
+						 base_img->stride);
+	if (surface->image->status)
+	    return surface->image->status;
+
+	surface->has_image_clip = FALSE;
+	surface->image_clip_invalid = surface->has_clip_region;
+
+	return _cairo_ddraw_surface_set_image_clip (surface);
+    }
+
+    if (surface->locked)
+	return CAIRO_STATUS_SUCCESS;
+
+    ddsd.dwSize = sizeof (ddsd);
+    if (FAILED(hr = IDDSLock (surface->lpdds, NULL, &ddsd,
+			      DDLOCK_WAITNOTBUSY, NULL)))
+	return _cairo_ddraw_print_ddraw_error ("_lock", hr);
+
+    surface->locked = TRUE;
+
+    if (img) {
+	if (img->data == ddsd.lpSurface && img->stride == ddsd.lPitch)
+	    return CAIRO_STATUS_SUCCESS;
+
+	cairo_surface_destroy (surface->image);
+    }
+
+    surface->image =
+	cairo_image_surface_create_for_data (ddsd.lpSurface,
+					     surface->format,
+					     ddsd.dwWidth,
+					     ddsd.dwHeight,
+					     ddsd.lPitch);
+
+    if (surface->image->status)
+	return surface->image->status;
+
+    surface->has_image_clip = FALSE;
+    surface->image_clip_invalid = surface->has_clip_region;
+
+    return _cairo_ddraw_surface_set_image_clip (surface);
+}
+
+static cairo_status_t
+_cairo_ddraw_surface_unlock (cairo_ddraw_surface_t *surface)
+{
+    HRESULT hr;
+
+    if (surface->alias)
+	surface = (cairo_ddraw_surface_t *) surface->alias;
+
+    if (!surface->locked)
+	return CAIRO_STATUS_SUCCESS;
+
+    surface->locked = FALSE;
+
+    if (FAILED(hr = IDDSUnlock (surface->lpdds, NULL)))
+	return _cairo_ddraw_print_ddraw_error ("_unlock", hr);
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_bool_t
+_cairo_ddraw_surface_is_locked (cairo_ddraw_surface_t *surface)
+{
+    if (surface->alias)
+	surface = (cairo_ddraw_surface_t *) surface->alias;
+    return surface->locked;
+}
+
+static cairo_int_status_t
+_cairo_ddraw_surface_set_clipper (cairo_ddraw_surface_t *surface)
+{
+    LPDIRECTDRAWCLIPPER myclip =
+	surface->has_clip_list ? surface->lpddc : NULL;
+
+    if (surface->alias)
+	surface = (cairo_ddraw_surface_t *) surface->alias;
+
+    if (surface->installed_clipper != myclip) {
+	HRESULT hr;
+	if (FAILED(hr = IDDSSetClipper(surface->lpdds, myclip)))
+	    return _cairo_ddraw_print_ddraw_error ("_set_clipper", hr);
+	surface->installed_clipper = myclip;
+    }
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_ddraw_surface_reset_clipper (cairo_ddraw_surface_t *surface)
+{
+    if (surface->alias)
+	surface = (cairo_ddraw_surface_t *) surface->alias;
+
+    if (surface->installed_clipper != NULL) {
+	HRESULT hr;
+	if (FAILED(hr = IDDSSetClipper(surface->lpdds, NULL)))
+	    return _cairo_ddraw_print_ddraw_error ("_reset_clipper", hr);
+	surface->installed_clipper = NULL;
+    }
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+
+static cairo_status_t
+_cairo_ddraw_surface_flush (void *abstract_surface)
+{
+    cairo_ddraw_surface_t *surface = abstract_surface;
+
+    return _cairo_ddraw_surface_unlock (surface);
+}
+
+cairo_status_t
+_cairo_ddraw_surface_reset (cairo_surface_t *surface)
+{
+    return _cairo_surface_reset_clip (surface);
+}
+
+static cairo_status_t
+_cairo_ddraw_surface_finish (void *abstract_surface)
+{
+    cairo_ddraw_surface_t *surface = abstract_surface;
+
+    if (surface->image)
+	cairo_surface_destroy (surface->image);
+
+    if (surface->lpddc)
+	IURelease(surface->lpddc);
+
+    _cairo_region_fini (&surface->clip_region);
+
+    if (surface->alias)
+	cairo_surface_destroy (surface->alias);
+    else if (surface->lpdds)
+	IURelease (surface->lpdds);
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+ static cairo_status_t
+_cairo_ddraw_surface_acquire_source_image (void                    *abstract_surface,
+					   cairo_image_surface_t  **image_out,
+					   void                   **image_extra)
+{
+    cairo_ddraw_surface_t *surface = abstract_surface;
+    cairo_status_t status;
+
+    if ((status = _cairo_ddraw_surface_lock (surface)))
+	return status;
+
+    *image_out = (cairo_image_surface_t *) surface->image;
+    *image_extra = NULL;
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_cairo_ddraw_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,
+					 void                   **image_extra)
+{
+    cairo_ddraw_surface_t *surface = abstract_surface;
+    cairo_status_t status;
+
+    if ((status = _cairo_ddraw_surface_lock (surface)))
+	return status;
+
+    if ((status = _cairo_ddraw_surface_set_image_clip (surface)))
+	return status;
+
+    *image_out = (cairo_image_surface_t *) surface->image;
+    *image_rect = surface->extents;
+    *image_extra = NULL;
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+
+static cairo_int_status_t
+_cairo_ddraw_surface_get_extents (void		          *abstract_surface,
+				  cairo_rectangle_int_t   *rectangle)
+{
+    cairo_ddraw_surface_t *surface = abstract_surface;
+
+    *rectangle = surface->extents;
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+cairo_int_status_t
+_cairo_ddraw_surface_set_clip_region (void *abstract_surface,
+				      cairo_region_t *region)
+{
+    cairo_ddraw_surface_t * surface =
+	(cairo_ddraw_surface_t *) abstract_surface;
+
+    if (region) {
+	surface->has_clip_region = TRUE;
+	surface->image_clip_invalid = TRUE;
+	surface->clip_list_invalid = TRUE;
+	return _cairo_region_copy (&surface->clip_region, region);
+    } else {
+	surface->has_clip_region = FALSE;
+	surface->image_clip_invalid = surface->has_image_clip;
+	surface->clip_list_invalid = surface->has_clip_list;
+    }
+    return CAIRO_STATUS_SUCCESS;
+}
+
+/**
+ * cairo_ddraw_surface_create:
+ * @lpdd: pointer to a DirectDraw object
+ * @format: format of pixels in the surface to create
+ * @width: width of the surface, in pixels
+ * @height: height of the surface, in pixels
+ *
+ * Creates a DirectDraw surface not associated with any particular existing
+ * surface or The created surface will be uninitialized.
+ *
+ * Return value: the newly created surface
+ **/
+cairo_surface_t *
+cairo_ddraw_surface_create (LPDIRECTDRAW lpdd,
+			    cairo_format_t format,
+			    int	    width,
+			    int	    height)
+{
+    cairo_ddraw_surface_t *surface;
+    HRESULT hr;
+    DDSURFACEDESC ddsd;
+
+    if (format != CAIRO_FORMAT_ARGB32 &&
+	format != CAIRO_FORMAT_RGB24)
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_FORMAT));
+
+    surface = malloc (sizeof (cairo_ddraw_surface_t));
+    if (surface == NULL)
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+
+    memset (&ddsd, 0, sizeof (ddsd));
+    ddsd.dwSize = sizeof (ddsd);
+    ddsd.dwFlags = DDSD_HEIGHT | DDSD_WIDTH | DDSD_PIXELFORMAT;
+    ddsd.dwHeight = height ? height : 1;
+    ddsd.dwWidth = width ? width : 1;
+    ddsd.ddpfPixelFormat.dwSize = sizeof (ddsd.ddpfPixelFormat);
+    ddsd.ddpfPixelFormat.dwRGBBitCount = 32;
+    ddsd.ddpfPixelFormat.dwRBitMask = 0x00ff0000;
+    ddsd.ddpfPixelFormat.dwGBitMask = 0x0000ff00;
+    ddsd.ddpfPixelFormat.dwBBitMask = 0x000000ff;
+    if (format == CAIRO_FORMAT_ARGB32) {
+	ddsd.ddpfPixelFormat.dwFlags =
+	    DDPF_ALPHAPIXELS | DDPF_ALPHAPREMULT | DDPF_RGB;
+	ddsd.ddpfPixelFormat.dwRGBAlphaBitMask = 0xff000000;
+    } else {
+	ddsd.ddpfPixelFormat.dwFlags = DDPF_RGB;
+    }
+
+    if (FAILED(hr = IDDCreateSurface (lpdd, &ddsd, &surface->lpdds, NULL))) {
+	cairo_status_t status = _cairo_ddraw_print_ddraw_error ("_surface_create", hr);
+	free (surface);
+	return _cairo_surface_create_in_error (status);
+    }
+
+    if (FAILED(hr = IDDCreateClipper (lpdd, 0, &surface->lpddc, NULL))) {
+	cairo_status_t status = _cairo_ddraw_print_ddraw_error ("_surface_create", hr);
+	IURelease(surface->lpdds);
+	free (surface);
+	return _cairo_surface_create_in_error (status);
+    }
+
+    _cairo_region_init (&surface->clip_region);
+
+    surface->locked = FALSE;
+    surface->has_clip_region = FALSE;
+    surface->has_image_clip = FALSE;
+    surface->has_clip_list = FALSE;
+    surface->image_clip_invalid = FALSE;
+    surface->clip_list_invalid = FALSE;
+
+    surface->format = format;
+    surface->installed_clipper = NULL;
+    surface->image = NULL;
+    surface->alias = NULL;
+    surface->data_offset = 0;
+
+    surface->extents.x = 0;
+    surface->extents.y = 0;
+    surface->extents.width = ddsd.dwWidth;
+    surface->extents.height = ddsd.dwHeight;
+
+    surface->origin.x = 0;
+    surface->origin.y = 0;
+
+    _cairo_surface_init (&surface->base, &cairo_ddraw_surface_backend,
+			 _cairo_content_from_format (format));
+
+    return &surface->base;
+}
+
+/**
+ * cairo_ddraw_surface_create_alias:
+ * @base_surface: pointer to a DirectDraw surface
+ * @x: x-origin of sub-surface
+ * @y: y-origin of sub-surface
+ * @width: width of sub-surface, in pixels
+ * @height: height of the sub-surface, in pixels
+ *
+ * Creates an alias to an existing DirectDraw surface.  The alias is a
+ * sub-surface which occupies a portion of the main surface.
+ *
+ * Return value: the newly created surface
+ **/
+cairo_surface_t *
+cairo_ddraw_surface_create_alias (cairo_surface_t *base_surface,
+				  int x,
+				  int y,
+				  int width,
+				  int height)
+{
+    cairo_ddraw_surface_t * base = (cairo_ddraw_surface_t *) base_surface;
+    cairo_ddraw_surface_t * surface;
+    LPDIRECTDRAW lpdd;
+    HRESULT hr;
+
+    if (base_surface->type != CAIRO_SURFACE_TYPE_DDRAW)
+	_cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
+
+    if (FAILED(hr = IDDSGetDDInterface (base->lpdds, &lpdd))) {
+	cairo_status_t status = _cairo_ddraw_print_ddraw_error ("_create_alias", hr);
+	return _cairo_surface_create_in_error (status);
+    }
+
+    if (base->alias) {
+	x += base->origin.x;
+	y += base->origin.y;
+	base = (cairo_ddraw_surface_t *) base->alias;
+    }
+
+    surface = malloc (sizeof (cairo_ddraw_surface_t));
+    if (surface == NULL)
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+
+    if (FAILED(hr = IDDCreateClipper (lpdd, 0, &surface->lpddc, NULL))) {
+	cairo_status_t status = _cairo_ddraw_print_ddraw_error ("_surface_create", hr);
+	free (surface);
+	return _cairo_surface_create_in_error (status);
+    }
+
+    _cairo_region_init (&surface->clip_region);
+
+    surface->locked = FALSE;
+    surface->has_clip_region = FALSE;
+    surface->has_image_clip = FALSE;
+    surface->has_clip_list = FALSE;
+    surface->image_clip_invalid = FALSE;
+    surface->clip_list_invalid = FALSE;
+
+    surface->format = base->format;
+    surface->lpdds = base->lpdds;
+    surface->installed_clipper = NULL;
+    surface->image = NULL;
+    surface->alias = cairo_surface_reference (base_surface);
+    surface->data_offset = 0;
+
+    surface->extents.x = 0;
+    surface->extents.y = 0;
+    surface->extents.width = width;
+    surface->extents.height = height;
+    
+    surface->origin.x = x;
+    surface->origin.y = y;
+
+    _cairo_surface_init (&surface->base, &cairo_ddraw_surface_backend,
+			 base_surface->content);
+
+    return &surface->base;
+}
+
+/**
+ * cairo_ddraw_surface_get_ddraw_surface:
+ * @surface: pointer to a DirectDraw surface
+ *
+ * Gets a pointer to the DirectDraw Surface.
+ *
+ * Return value: the DirectDraw surface pointer
+ **/
+LPDIRECTDRAWSURFACE
+cairo_ddraw_surface_get_ddraw_surface (cairo_surface_t *surface)
+{
+    cairo_ddraw_surface_t * dd_surf = (cairo_ddraw_surface_t *) surface;
+
+    if (surface->type != CAIRO_SURFACE_TYPE_DDRAW)
+	return NULL;
+
+    _cairo_ddraw_surface_reset_clipper (dd_surf);
+    _cairo_ddraw_surface_unlock (dd_surf);
+
+    return dd_surf->lpdds;
+}
+
+
+
+/* This big function tells us how to optimize operators for the
+ * case of solid destination and constant-alpha source
+ *
+ * Note: This function needs revisiting if we add support for
+ *       super-luminescent colors (a == 0, r,g,b > 0)
+ */
+static enum { DO_CLEAR, DO_SOURCE, DO_NOTHING, DO_UNSUPPORTED }
+categorize_solid_dest_operator (cairo_operator_t op,
+				unsigned short   alpha)
+{
+    enum { SOURCE_TRANSPARENT, SOURCE_LIGHT, SOURCE_SOLID, SOURCE_OTHER } source;
+
+    if (alpha >= 0xff00)
+	source = SOURCE_SOLID;
+    else if (alpha < 0x100)
+	source = SOURCE_TRANSPARENT;
+    else
+	source = SOURCE_OTHER;
+
+    switch (op) {
+    case CAIRO_OPERATOR_CLEAR:    /* 0                 0 */
+    case CAIRO_OPERATOR_OUT:      /* 1 - Ab            0 */
+	return DO_CLEAR;
+	break;
+
+    case CAIRO_OPERATOR_SOURCE:   /* 1                 0 */
+    case CAIRO_OPERATOR_IN:       /* Ab                0 */
+	return DO_SOURCE;
+	break;
+
+    case CAIRO_OPERATOR_OVER:     /* 1            1 - Aa */
+    case CAIRO_OPERATOR_ATOP:     /* Ab           1 - Aa */
+	if (source == SOURCE_SOLID)
+	    return DO_SOURCE;
+	else if (source == SOURCE_TRANSPARENT)
+	    return DO_NOTHING;
+	else
+	    return DO_UNSUPPORTED;
+	break;
+
+    case CAIRO_OPERATOR_DEST_OUT: /* 0            1 - Aa */
+    case CAIRO_OPERATOR_XOR:      /* 1 - Ab       1 - Aa */
+	if (source == SOURCE_SOLID)
+	    return DO_CLEAR;
+	else if (source == SOURCE_TRANSPARENT)
+	    return DO_NOTHING;
+	else
+	    return DO_UNSUPPORTED;
+    	break;
+
+    case CAIRO_OPERATOR_DEST:     /* 0                 1 */
+    case CAIRO_OPERATOR_DEST_OVER:/* 1 - Ab            1 */
+    case CAIRO_OPERATOR_SATURATE: /* min(1,(1-Ab)/Aa)  1 */
+	return DO_NOTHING;
+	break;
+
+    case CAIRO_OPERATOR_DEST_IN:  /* 0                Aa */
+    case CAIRO_OPERATOR_DEST_ATOP:/* 1 - Ab           Aa */
+	if (source == SOURCE_SOLID)
+	    return DO_NOTHING;
+	else if (source == SOURCE_TRANSPARENT)
+	    return DO_CLEAR;
+	else
+	    return DO_UNSUPPORTED;
+	break;
+
+    case CAIRO_OPERATOR_ADD:	  /* 1                1 */
+	if (source == SOURCE_TRANSPARENT)
+	    return DO_NOTHING;
+	else
+	    return DO_UNSUPPORTED;
+	break;
+    }
+
+    ASSERT_NOT_REACHED;
+    return DO_UNSUPPORTED;
+}
+
+static cairo_int_status_t
+_cairo_ddraw_surface_fill_rectangles (void			*abstract_surface,
+				      cairo_operator_t		op,
+				      const cairo_color_t	*color,
+				      cairo_rectangle_int_t	*rects,
+				      int			num_rects)
+{
+    DDBLTFX ddbltfx;
+    COLORREF new_color;
+    cairo_ddraw_surface_t *surface = abstract_surface;
+    cairo_status_t status;
+    int i;
+
+    /* XXXperf If it's not RGB24, we need to do a little more checking
+     * to figure out when we can use GDI.  We don't have that checking
+     * anywhere at the moment, so just bail and use the fallback
+     * paths. */
+    if (surface->format != CAIRO_FORMAT_RGB24)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    switch (categorize_solid_dest_operator (op, color->alpha_short)) {
+    case DO_CLEAR:
+        new_color = 0x00000000u;
+	break;
+    case DO_SOURCE:
+        new_color = 0xff000000u |
+            ((color->red_short & 0xff00u) << 8) |
+            (color->green_short & 0xff00u) |
+            (color->blue_short >> 8);
+	break;
+    case DO_NOTHING:
+	return CAIRO_STATUS_SUCCESS;
+    case DO_UNSUPPORTED:
+    default:
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
+
+    if (_cairo_ddraw_surface_is_locked (surface)) {
+	uint32_t sum = 0;
+
+	/* check to see if we have enough work to do */
+	for (i = 0; i < num_rects; ++i) {
+	    sum += rects[i].width * rects[i].height;
+	    if (sum >= FILL_THRESHOLD)
+		break;
+	}
+
+	if (sum < FILL_THRESHOLD)
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
+
+	if ((status = _cairo_ddraw_surface_unlock (surface)))
+	    return status;
+    }
+
+    if ((status = _cairo_ddraw_surface_unlock (surface)))
+	return status;
+
+    if ((status = _cairo_ddraw_surface_set_clip_list (surface)))
+	return status;
+
+    if ((status = _cairo_ddraw_surface_set_clipper (surface)))
+	return status;
+
+    memset (&ddbltfx, 0, sizeof (ddbltfx));
+    ddbltfx.dwSize = sizeof (ddbltfx);
+    ddbltfx.dwFillColor = new_color;
+
+    for (i = 0; i < num_rects; i++) {
+	RECT rect;
+	HRESULT hr;
+
+	rect.left = rects[i].x + surface->origin.x;
+	rect.top = rects[i].y + surface->origin.y;
+	rect.right = rects[i].x + rects[i].width + surface->origin.x;
+	rect.bottom = rects[i].y + rects[i].height + surface->origin.y;
+
+	if (FAILED (hr = IDDSBlt (surface->lpdds, &rect,
+				 NULL, NULL,
+				 DDBLT_COLORFILL | DDBLT_WAITNOTBUSY,
+				 &ddbltfx)))
+	    return _cairo_ddraw_print_ddraw_error ("_fill_rectangles", hr);
+    }
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+
+static const cairo_surface_backend_t cairo_ddraw_surface_backend = {
+    CAIRO_SURFACE_TYPE_DDRAW,
+    NULL, /* create_similar */
+    _cairo_ddraw_surface_finish,
+    _cairo_ddraw_surface_acquire_source_image,
+    NULL, /* release_source_image */
+    _cairo_ddraw_surface_acquire_dest_image,
+    NULL, /* release_dest_image */
+    NULL, /* clone_similar */
+    NULL, /* composite */
+    _cairo_ddraw_surface_fill_rectangles,
+    NULL, /* composite_trapezoids */
+    NULL, /* create_span_renderer */
+    NULL, /* check_span_renderer */
+    NULL, /* copy_page */
+    NULL, /* show_page */
+    _cairo_ddraw_surface_set_clip_region,
+    NULL, /* intersect_clip_path */
+    _cairo_ddraw_surface_get_extents,
+    NULL, /* old_show_glyphs */
+    NULL, /* get_font_options */
+    _cairo_ddraw_surface_flush,
+    NULL, /* mark_dirty_rectangle */
+    NULL, /* scaled_font_fini */
+    NULL, /* scaled_glyph_fini */
+
+    NULL, /* paint */
+    NULL, /* mask */
+    NULL, /* stroke */
+    NULL, /* fill */
+    NULL, /* show_glyphs */
+
+    NULL,  /* snapshot */
+    NULL, /* is_similar */
+
+    _cairo_ddraw_surface_reset,
+};
+
new file mode 100644
--- /dev/null
+++ b/gfx/cairo/cairo/src/cairo-ddraw.h
@@ -0,0 +1,70 @@
+/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
+/* cairo - a vector graphics library with display and print output
+ *
+ * Copyright © 2009 NVIDIA Corporation
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * The Original Code is the cairo graphics library.
+ *
+ * The Initial Developer of the Original Code is NVIDIA Corporation.
+ *
+ * Contributor(s):
+ */
+
+#ifndef _CAIRO_DDRAW_H_
+#define _CAIRO_DDRAW_H_
+
+#include "cairo.h"
+
+#if CAIRO_HAS_DDRAW_SURFACE
+
+#include <windows.h>
+#include <ddraw.h>
+
+CAIRO_BEGIN_DECLS
+
+cairo_public cairo_surface_t *
+cairo_ddraw_surface_create (LPDIRECTDRAW lpdd,
+			    cairo_format_t format,
+			    int width,
+			    int height);
+
+cairo_public cairo_surface_t *
+cairo_ddraw_surface_create_alias (cairo_surface_t *surface,
+				  int x,
+				  int y,
+				  int width,
+				  int height);
+
+cairo_public LPDIRECTDRAWSURFACE
+cairo_ddraw_surface_get_ddraw_surface (cairo_surface_t *surface);
+
+CAIRO_END_DECLS
+
+#else  /* CAIRO_HAS_DDRAW_SURFACE */
+# error Cairo was not compiled with support for the direct draw backend
+#endif /* CAIRO_HAS_DDRAW_SURFACE */
+
+#endif /* _CAIRO_DDRAW_H_ */
--- a/gfx/cairo/cairo/src/cairo-features.h.in
+++ b/gfx/cairo/cairo/src/cairo-features.h.in
@@ -76,16 +76,18 @@
 @OS2_SURFACE_FEATURE@
 
 @BEOS_SURFACE_FEATURE@
 
 @DIRECTFB_SURFACE_FEATURE@
 
 @QPAINTER_SURFACE_FEATURE@
 
+@DDRAW_SURFACE_FEATURE@
+
 @FT_FONT_FEATURE@
 
 @WIN32_FONT_FEATURE@
 
 @QUARTZ_FONT_FEATURE@
 
 @PNG_FUNCTIONS_FEATURE@
 
--- a/gfx/cairo/cairo/src/cairo.h
+++ b/gfx/cairo/cairo/src/cairo.h
@@ -1882,16 +1882,17 @@ cairo_surface_status (cairo_surface_t *s
  * @CAIRO_SURFACE_TYPE_BEOS: The surface is of type beos
  * @CAIRO_SURFACE_TYPE_DIRECTFB: The surface is of type directfb
  * @CAIRO_SURFACE_TYPE_SVG: The surface is of type svg
  * @CAIRO_SURFACE_TYPE_OS2: The surface is of type os2
  * @CAIRO_SURFACE_TYPE_WIN32_PRINTING: The surface is a win32 printing surface
  * @CAIRO_SURFACE_TYPE_QUARTZ_IMAGE: The surface is of type quartz_image
  * @CAIRO_SURFACE_TYPE_SCRIPT: The surface is of type script, since 1.10
  * @CAIRO_SURFACE_TYPE_QPAINTER: The surface is of type qpainter
+ * @CAIRO_SURFACE_TYPE_DDRAW: The surface is of type ddraw
  *
  * #cairo_surface_type_t is used to describe the type of a given
  * surface. The surface types are also known as "backends" or "surface
  * backends" within cairo.
  *
  * The type of a surface is determined by the function used to create
  * it, which will generally be of the form cairo_<emphasis>type</emphasis>_surface_create(),
  * (though see cairo_surface_create_similar() as well).
@@ -1922,17 +1923,18 @@ typedef enum _cairo_surface_type {
     CAIRO_SURFACE_TYPE_WIN32,
     CAIRO_SURFACE_TYPE_BEOS,
     CAIRO_SURFACE_TYPE_DIRECTFB,
     CAIRO_SURFACE_TYPE_SVG,
     CAIRO_SURFACE_TYPE_OS2,
     CAIRO_SURFACE_TYPE_WIN32_PRINTING,
     CAIRO_SURFACE_TYPE_QUARTZ_IMAGE,
     CAIRO_SURFACE_TYPE_SCRIPT,
-    CAIRO_SURFACE_TYPE_QPAINTER
+    CAIRO_SURFACE_TYPE_QPAINTER,
+    CAIRO_SURFACE_TYPE_DDRAW
 } cairo_surface_type_t;
 
 cairo_public cairo_surface_type_t
 cairo_surface_get_type (cairo_surface_t *surface);
 
 cairo_public cairo_content_t
 cairo_surface_get_content (cairo_surface_t *surface);
 
--- a/gfx/thebes/public/Makefile.in
+++ b/gfx/thebes/public/Makefile.in
@@ -40,17 +40,19 @@ EXPORTS += gfxFontTest.h
 ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
 EXPORTS	+=	gfxWindowsPlatform.h \
 		gfxWindowsSurface.h \
 		gfxWindowsNativeDrawing.h \
 		$(NULL)
 EXPORTS +=	gfxPDFSurface.h
 
 ifdef WINCE
-EXPORTS +=	gfxFT2Fonts.h 
+EXPORTS +=	gfxFT2Fonts.h \
+		gfxDDrawSurface.h \
+		$(NULL)
 else
 EXPORTS +=	gfxWindowsFonts.h 
 endif
 
 endif
 
 ifeq ($(MOZ_WIDGET_TOOLKIT),gtk2)
 
--- a/gfx/thebes/public/gfxASurface.h
+++ b/gfx/thebes/public/gfxASurface.h
@@ -78,17 +78,18 @@ public:
         SurfaceTypeQuartz,
         SurfaceTypeWin32,
         SurfaceTypeBeOS,
         SurfaceTypeDirectFB,
         SurfaceTypeSVG,
         SurfaceTypeOS2,
         SurfaceTypeWin32Printing,
         SurfaceTypeQuartzImage,
-        SurfaceTypeQPainter
+        SurfaceTypeQPainter,
+        SurfaceTypeDDraw,
     } gfxSurfaceType;
 
     typedef enum {
         CONTENT_COLOR       = 0x1000,
         CONTENT_ALPHA       = 0x2000,
         CONTENT_COLOR_ALPHA = 0x3000
     } gfxContentType;
 
new file mode 100644
--- /dev/null
+++ b/gfx/thebes/public/gfxDDrawSurface.h
@@ -0,0 +1,69 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Oracle Corporation code.
+ *
+ * The Initial Developer of the Original Code is Oracle Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Stuart Parmenter <pavlov@pavlov.net>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#ifndef GFX_DDRAWSURFACE_H
+#define GFX_DDRAWSURFACE_H
+
+#include "gfxASurface.h"
+#include "gfxImageSurface.h"
+
+#include <windows.h>
+#include <ddraw.h>
+
+class THEBES_API gfxDDrawSurface : public gfxASurface {
+public:
+    gfxDDrawSurface(LPDIRECTDRAW lpdd, const gfxIntSize& size,
+                    gfxImageFormat imageFormat = ImageFormatRGB24);
+
+    gfxDDrawSurface(gfxDDrawSurface * psurf, const RECT & rect);
+
+    gfxDDrawSurface(cairo_surface_t *csurf);
+
+    LPDIRECTDRAWSURFACE GetDDSurface();
+
+    virtual ~gfxDDrawSurface();
+
+    nsresult BeginPrinting(const nsAString& aTitle, const nsAString& aPrintToFileName);
+    nsresult EndPrinting();
+    nsresult AbortPrinting();
+    nsresult BeginPage();
+    nsresult EndPage();
+
+    virtual PRInt32 GetDefaultContextFlags() const;
+};
+
+#endif /* GFX_DDRAWSURFACE_H */
--- a/gfx/thebes/src/Makefile.in
+++ b/gfx/thebes/src/Makefile.in
@@ -56,17 +56,20 @@ ifeq ($(MOZ_WIDGET_TOOLKIT),windows)
 CPPSRCS	+= 	gfxWindowsPlatform.cpp \
 		gfxWindowsSurface.cpp \
 		gfxWindowsNativeDrawing.cpp \
 		nsUnicodeRange.cpp \
 		$(NULL)
 
 ifdef WINCE
 DEFINES += -DMOZ_FT2_FONTS
-CPPSRCS	+= gfxFT2Fonts.cpp
+CPPSRCS	+= gfxFT2Fonts.cpp \
+	   gfxDDrawSurface.cpp \
+	   $(NULL)
+EXTRA_DSO_LDOPTS += ddraw.lib
 else
 CPPSRCS	+= gfxWindowsFonts.cpp 
 endif
 
 CPPSRCS +=	gfxPDFSurface.cpp
 
 _OS_LIBS	= usp10 msimg32
 ifdef GNU_CXX
--- a/gfx/thebes/src/gfxASurface.cpp
+++ b/gfx/thebes/src/gfxASurface.cpp
@@ -58,16 +58,20 @@
 #ifdef CAIRO_HAS_DIRECTFB_SURFACE
 #include "gfxDirectFBSurface.h"
 #endif
 
 #ifdef CAIRO_HAS_QPAINTER_SURFACE
 #include "gfxQPainterSurface.h"
 #endif
 
+#ifdef CAIRO_HAS_DDRAW_SURFACE
+#include "gfxDDrawSurface.h"
+#endif
+
 #include <stdio.h>
 #include <limits.h>
 
 static cairo_user_data_key_t gfxasurface_pointer_key;
 
 // Surfaces use refcounting that's tied to the cairo surface refcnt, to avoid
 // refcount mismatch issues.
 nsrefcnt
@@ -176,16 +180,21 @@ gfxASurface::Wrap (cairo_surface_t *csur
         result = new gfxDirectFBSurface(csurf);
     }
 #endif
 #ifdef CAIRO_HAS_QPAINTER_SURFACE
     else if (stype == CAIRO_SURFACE_TYPE_QPAINTER) {
         result = new gfxQPainterSurface(csurf);
     }
 #endif
+#ifdef CAIRO_HAS_DDRAW_SURFACE
+    else if (stype == CAIRO_SURFACE_TYPE_DDRAW) {
+        result = new gfxDDrawSurface(csurf);
+    }
+#endif
     else {
         result = new gfxUnknownSurface(csurf);
     }
 
     // fprintf(stderr, "New wrapper for %p -> %p\n", csurf, result);
 
     NS_ADDREF(result);
     return result;
new file mode 100644
--- /dev/null
+++ b/gfx/thebes/src/gfxDDrawSurface.cpp
@@ -0,0 +1,110 @@
+/* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 4 -*-
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is Oracle Corporation code.
+ *
+ * The Initial Developer of the Original Code is Oracle Corporation.
+ * Portions created by the Initial Developer are Copyright (C) 2005
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Contributor(s):
+ *   Stuart Parmenter <pavlov@pavlov.net>
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+
+#include "gfxDDrawSurface.h"
+#include "gfxContext.h"
+#include "gfxPlatform.h"
+
+#include "cairo.h"
+#include "cairo-ddraw.h"
+
+#include "nsString.h"
+
+gfxDDrawSurface::gfxDDrawSurface(LPDIRECTDRAW lpdd,
+                                 const gfxIntSize& size, gfxImageFormat imageFormat)
+{
+    if (!CheckSurfaceSize(size))
+        return;
+
+    cairo_surface_t *surf = cairo_ddraw_surface_create(lpdd, (cairo_format_t)imageFormat,
+                                                       size.width, size.height);
+    Init(surf);
+}
+
+gfxDDrawSurface::gfxDDrawSurface(gfxDDrawSurface * psurf, const RECT & rect)
+{
+    cairo_surface_t *surf = cairo_ddraw_surface_create_alias(psurf->CairoSurface(),
+                                                             rect.left, rect.top,
+                                                             rect.right - rect.left,
+                                                             rect.bottom - rect.top);
+    Init(surf);
+}
+
+gfxDDrawSurface::gfxDDrawSurface(cairo_surface_t *csurf)
+{
+    Init(csurf, PR_TRUE);
+}
+
+gfxDDrawSurface::~gfxDDrawSurface()
+{
+}
+
+LPDIRECTDRAWSURFACE gfxDDrawSurface::GetDDSurface()
+{
+    return cairo_ddraw_surface_get_ddraw_surface(CairoSurface());
+}
+
+nsresult gfxDDrawSurface::BeginPrinting(const nsAString& aTitle,
+                                          const nsAString& aPrintToFileName)
+{
+    return NS_OK;
+}
+
+nsresult gfxDDrawSurface::EndPrinting()
+{
+    return NS_OK;
+}
+
+nsresult gfxDDrawSurface::AbortPrinting()
+{
+    return NS_OK;
+}
+
+nsresult gfxDDrawSurface::BeginPage()
+{
+    return NS_OK;
+}
+
+nsresult gfxDDrawSurface::EndPage()
+{
+    return NS_OK;
+}
+
+PRInt32 gfxDDrawSurface::GetDefaultContextFlags() const
+{
+    return 0;
+}
--- a/toolkit/library/Makefile.in
+++ b/toolkit/library/Makefile.in
@@ -260,17 +260,17 @@ endif
 
 ifeq ($(OS_ARCH),WINNT)
 EXTRA_DSO_LDOPTS += $(call EXPAND_LIBNAME,shell32 ole32 uuid version winspool comdlg32 imm32 winmm wsock32 msimg32)
 ifneq (,$(MOZ_DEBUG)$(NS_TRACE_MALLOC))
 EXTRA_DSO_LDOPTS += $(call EXPAND_LIBNAME,imagehlp)
 endif
 endif # WINNT
 ifeq ($(OS_ARCH),WINCE)
-EXTRA_DSO_LDOPTS += $(call EXPAND_LIBNAME, aygshell uuid ole32 oleaut32 Ws2)
+EXTRA_DSO_LDOPTS += $(call EXPAND_LIBNAME, aygshell uuid ole32 oleaut32 Ws2 ddraw)
 ifdef WINCE_WINDOWS_MOBILE
 EXTRA_DSO_LDOPTS += $(call EXPAND_LIBNAME, cellcore)
 endif
 endif
 
 
 ifdef MOZ_JPROF
 EXTRA_DSO_LDOPTS += -ljprof
--- a/widget/src/windows/Makefile.in
+++ b/widget/src/windows/Makefile.in
@@ -130,13 +130,17 @@ EXPORTS		= nsdefs.h
 LOCAL_INCLUDES	= \
 		-I. \
 		-I$(srcdir)/../xpwidgets \
 		-I$(srcdir) \
 		$(NULL)
 
 FORCE_STATIC_LIB = 1
 
+ifdef WINCE
+EXTRA_DSO_LDOPTS += ddraw.lib
+endif
+
 ifndef WINCE
 ENABLE_CXX_EXCEPTIONS = 1
 endif
 
 include $(topsrcdir)/config/rules.mk
--- a/widget/src/windows/nsWindow.cpp
+++ b/widget/src/windows/nsWindow.cpp
@@ -77,16 +77,17 @@
 #include "gfxImageSurface.h"
 #include "nsIDOMNSUIEvent.h"
 
 #ifdef WINCE
 
 #include "aygshell.h"
 #include "imm.h"
 
+//#define PAINT_USE_DDRAW_SURFACE
 #define PAINT_USE_IMAGE_SURFACE
 
 // do 32->24 conversion before calling StretchDIBits
 #define PAINT_USE_IMAGE_SURFACE_24BPP
 
 #ifdef WINCE_WINDOWS_MOBILE
 #define WINCE_HAVE_SOFTKB
 #include "tpcshell.h"
@@ -164,16 +165,35 @@
 
 #include "prprf.h"
 #include "prmem.h"
 
 #ifdef NS_ENABLE_TSF
 #include "nsTextStore.h"
 #endif //NS_ENABLE_TSF
 
+#ifdef PAINT_USE_DDRAW_SURFACE
+#include "gfxDDrawSurface.h"
+#include <ddraw.h>
+#include "cairo-ddraw.h"
+
+/*XXX handle clean-up */
+static LPDIRECTDRAW glpDD = NULL;
+static LPDIRECTDRAWSURFACE glpDDPrimary = NULL;
+static LPDIRECTDRAWCLIPPER glpDDClipper = NULL;
+static nsAutoPtr<gfxDDrawSurface> gpDDSurf;
+
+static void DDError(const char *msg, HRESULT hr)
+{
+  /*XXX make nicer */
+  fprintf(stderr, "direct draw error %s: 0x%08x\n", msg, hr);
+}
+
+#endif
+
 // Don't put more than this many rects in the dirty region, just fluff
 // out to the bounding-box if there are more
 #define MAX_RECTS_IN_REGION 100
 
 #ifdef PAINT_USE_IMAGE_SURFACE
 static nsAutoPtr<PRUint8> gSharedSurfaceData;
 static gfxIntSize gSharedSurfaceSize;
 #endif
@@ -5972,26 +5992,65 @@ PRBool nsWindow::OnPaint(HDC aDC)
 #ifdef NS_DEBUG
       debug_DumpPaintEvent(stdout,
                            this,
                            &event,
                            nsCAutoString("noname"),
                            (PRInt32) mWnd);
 #endif // NS_DEBUG
 
-#if defined(MOZ_XUL) && !defined(PAINT_USE_IMAGE_SURFACE)
+#if defined(MOZ_XUL) && !defined(PAINT_USE_IMAGE_SURFACE) && !defined(PAINT_USE_DDRAW_SURFACE)
       nsRefPtr<gfxASurface> targetSurface;
       if (eTransparencyTransparent == mTransparencyMode) {
         if (mTransparentSurface == nsnull)
           SetupTranslucentWindowMemoryBitmap(mTransparencyMode);
         targetSurface = mTransparentSurface;
       } else {
         targetSurface = new gfxWindowsSurface(hDC);
       }
+#elif defined(PAINT_USE_DDRAW_SURFACE)
+
+      HRESULT hr;
+
+      if (!glpDD) {
+        // create all the direct-draw goodies
+        if (FAILED(hr = DirectDrawCreate(NULL, &glpDD, NULL)))
+          DDError("DirectDrawCreate", hr);
+        if (FAILED(hr = glpDD->SetCooperativeLevel(NULL, DDSCL_NORMAL)))
+          DDError("SetCooperativeLevel", hr);
+        DDSURFACEDESC ddsd;
+        memset(&ddsd, 0, sizeof(ddsd));
+        ddsd.dwSize = sizeof(ddsd);
+        ddsd.dwFlags = DDSD_CAPS;
+        ddsd.ddpfPixelFormat.dwSize = sizeof(ddsd.ddpfPixelFormat);
+        ddsd.ddsCaps.dwCaps = DDSCAPS_PRIMARYSURFACE;
+        if (FAILED(hr = glpDD->CreateSurface(&ddsd, &glpDDPrimary, NULL)))
+          DDError("CreateSurface", hr);
+        if (FAILED(hr = glpDD->CreateClipper(0, &glpDDClipper, NULL)))
+          DDError("CreateClipper", hr);
+        if (FAILED(hr = glpDDPrimary->SetClipper(glpDDClipper)))
+          DDError("SetClipper", hr);
+        gfxIntSize screen_size(GetSystemMetrics(SM_CXSCREEN), GetSystemMetrics(SM_CYSCREEN));
+        gpDDSurf = new gfxDDrawSurface(glpDD, screen_size, gfxASurface::ImageFormatRGB24);
+        if (!gpDDSurf) {
+          /*XXX*/
+          fprintf(stderr, "couldn't create ddsurf\n");
+        }
+      }
+
+      // create a rect that maps the window in screen space
+      RECT winrect;
+      GetClientRect(mWnd, &winrect);
+      MapWindowPoints(mWnd, NULL, (LPPOINT)&winrect, 2);
+
+      // create a new sub-surface that aliases this one
+      nsRefPtr<gfxDDrawSurface> targetSurface = new gfxDDrawSurface(gpDDSurf.get(), winrect);
+
 #elif defined(PAINT_USE_IMAGE_SURFACE)
+
       if (!gSharedSurfaceData) {
         gSharedSurfaceSize.height = GetSystemMetrics(SM_CYSCREEN);
         gSharedSurfaceSize.width = GetSystemMetrics(SM_CXSCREEN);
         gSharedSurfaceData = (PRUint8*) malloc(gSharedSurfaceSize.width * gSharedSurfaceSize.height * 4);
       }
 
       gfxIntSize surfaceSize(ps.rcPaint.right - ps.rcPaint.left,
                              ps.rcPaint.bottom - ps.rcPaint.top);
@@ -6025,17 +6084,17 @@ PRBool nsWindow::OnPaint(HDC aDC)
       nsRefPtr<gfxASurface> targetSurface = new gfxWindowsSurface(hDC);
 #endif
 
       nsRefPtr<gfxContext> thebesContext = new gfxContext(targetSurface);
       thebesContext->SetFlag(gfxContext::FLAG_DESTINED_FOR_SCREEN);
 
       // don't need to double buffer with PAINT_USE_IMAGE_SURFACE;
       // it's implicitly double buffered
-#if !defined(PAINT_USE_IMAGE_SURFACE)
+#if !defined(PAINT_USE_IMAGE_SURFACE) && !defined(PAINT_USE_DDRAW_SURFACE)
 # if defined(MOZ_XUL)
       if (eTransparencyGlass == mTransparencyMode && nsUXThemeData::sHaveCompositor) {
         thebesContext->PushGroup(gfxASurface::CONTENT_COLOR_ALPHA);
       } else if (eTransparencyTransparent == mTransparencyMode) {
         // If we're rendering with translucency, we're going to be
         // rendering the whole window; make sure we clear it first
         thebesContext->SetOperator(gfxContext::OPERATOR_CLEAR);
         thebesContext->Paint();
@@ -6071,23 +6130,45 @@ PRBool nsWindow::OnPaint(HDC aDC)
       if (eTransparencyTransparent == mTransparencyMode) {
         // Data from offscreen drawing surface was copied to memory bitmap of transparent
         // bitmap. Now it can be read from memory bitmap to apply alpha channel and after
         // that displayed on the screen.
         UpdateTranslucentWindow();
       } else
 #endif
       if (result) {
-#ifndef PAINT_USE_IMAGE_SURFACE
+#if !defined(PAINT_USE_IMAGE_SURFACE) && !defined(PAINT_USE_DDRAW_SURFACE)
         // Only update if DispatchWindowEvent returned TRUE; otherwise, nothing handled
         // this, and we'll just end up painting with black.
         thebesContext->PopGroupToSource();
         thebesContext->SetOperator(gfxContext::OPERATOR_SOURCE);
         thebesContext->Paint();
-#else
+
+#elif defined(PAINT_USE_DDRAW_SURFACE)
+
+        // blit with direct draw
+
+        if (FAILED(hr = glpDDClipper->SetHWnd(0, mWnd)))
+          DDError("SetHWnd", hr);
+
+        // blt from the affected area from the window back-buffer to the
+        // screen-relative coordinates of the window paint area
+        RECT dst_rect = ps.rcPaint;
+        MapWindowPoints(mWnd, NULL, (LPPOINT)&dst_rect, 2);
+
+        if (FAILED(hr = glpDDPrimary->Blt(&dst_rect,
+                                          targetSurface->GetDDSurface(),
+                                          &dst_rect,
+                                          DDBLT_WAITNOTBUSY,
+                                          NULL)))
+          DDError("Blt", hr);
+        
+
+#else // PAINT_USE_IMAGE_SURFACE
+
         // Just blit this directly
         BITMAPINFOHEADER bi;
         memset(&bi, 0, sizeof(BITMAPINFOHEADER));
         bi.biSize = sizeof(BITMAPINFOHEADER);
         bi.biWidth = surfaceSize.width;
         bi.biHeight = - surfaceSize.height;
         bi.biPlanes = 1;
         bi.biBitCount = 32;