Bug 907544 - Pass the D3DSurface9 down into Cairo for LockRect. r=jrmuizel
authorBenoit Girard <b56girard@gmail.com>
Wed, 04 Sep 2013 16:53:54 -0400
changeset 145501 b5d62f5c733c1b2da7e1f79979303c45fb37dc57
parent 145500 365e150efda033ec762f658877354ea0622fc006
child 145502 8628391a5a8bd2eafede7e31257be60ff9c661ba
push id33301
push userb56girard@gmail.com
push dateWed, 04 Sep 2013 20:55:35 +0000
treeherdermozilla-inbound@b5d62f5c733c [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs907544
milestone26.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 907544 - Pass the D3DSurface9 down into Cairo for LockRect. r=jrmuizel
gfx/cairo/README
gfx/cairo/cairo/src/cairo-rename.h
gfx/cairo/cairo/src/cairo-win32-printing-surface.c
gfx/cairo/cairo/src/cairo-win32-private.h
gfx/cairo/cairo/src/cairo-win32-surface.c
gfx/cairo/cairo/src/cairo-win32.h
gfx/cairo/win32-d3dsurface9.patch
gfx/layers/d3d9/ThebesLayerD3D9.cpp
gfx/thebes/gfxWindowsSurface.cpp
gfx/thebes/gfxWindowsSurface.h
layout/media/symbols.def.in
--- a/gfx/cairo/README
+++ b/gfx/cairo/README
@@ -229,14 +229,16 @@ pixman-16-bit-pipeline.patch: 16 bit pip
 pixman-dither.patch: Add dithering of 16 bit gradients
 
 quartz-support-color-emoji-font.patch: support Apple Color Emoji font in cairo-quartz backend
 
 use-show-text-glyphs-if-glyph-path-fails.patch: fall back to show_text_glyphs even at huge sizes if scaled_font_glyph_path didn't work
 
 pixman-enable-altivec-acceleration.patch: enable building the altivec acceleration
 
+win32-d3dsurface9.patch: Create a win32 d3d9 surface to support LockRect
+
 ==== disable printing patch ====
 
 disable-printing.patch:  allows us to use NS_PRINTING to disable printing.
 
 ==== cairo clamp bounday patch ====
 cairo-clamp-boundary.patch: don't call pixman_fill with negative starts or negative sizes
--- a/gfx/cairo/cairo/src/cairo-rename.h
+++ b/gfx/cairo/cairo/src/cairo-rename.h
@@ -335,16 +335,17 @@
 #define cairo_win32_font_face_create_for_logfontw_hfont _moz_cairo_win32_font_face_create_for_logfontw_hfont
 #define cairo_win32_printing_surface_create _moz_cairo_win32_printing_surface_create
 #define cairo_win32_scaled_font_done_font _moz_cairo_win32_scaled_font_done_font
 #define cairo_win32_scaled_font_get_device_to_logical _moz_cairo_win32_scaled_font_get_device_to_logical
 #define cairo_win32_scaled_font_get_logical_to_device _moz_cairo_win32_scaled_font_get_logical_to_device
 #define cairo_win32_scaled_font_get_metrics_factor _moz_cairo_win32_scaled_font_get_metrics_factor
 #define cairo_win32_scaled_font_select_font _moz_cairo_win32_scaled_font_select_font
 #define cairo_win32_surface_create _moz_cairo_win32_surface_create
+#define cairo_win32_surface_create_with_d3dsurface9 _moz_cairo_win32_surface_create_with_d3dsurface9
 #define cairo_win32_surface_create_with_ddb _moz_cairo_win32_surface_create_with_ddb
 #define cairo_win32_surface_create_with_dib _moz_cairo_win32_surface_create_with_dib
 #define cairo_win32_surface_get_dc _moz_cairo_win32_surface_get_dc
 #define cairo_win32_surface_get_image _moz_cairo_win32_surface_get_image
 #define cairo_xcb_surface_create _moz_cairo_xcb_surface_create
 #define cairo_xcb_surface_create_for_bitmap _moz_cairo_xcb_surface_create_for_bitmap
 #define cairo_xcb_surface_create_with_xrender_format _moz_cairo_xcb_surface_create_with_xrender_format
 #define cairo_xcb_surface_set_size _moz_cairo_xcb_surface_set_size
--- a/gfx/cairo/cairo/src/cairo-win32-printing-surface.c
+++ b/gfx/cairo/cairo/src/cairo-win32-printing-surface.c
@@ -1852,16 +1852,17 @@ cairo_win32_printing_surface_create (HDC
     }
 
     _cairo_surface_clipper_init (&surface->clipper,
 				 _cairo_win32_printing_surface_clipper_intersect_clip_path);
 
     surface->image = NULL;
     surface->format = CAIRO_FORMAT_RGB24;
     surface->content = CAIRO_CONTENT_COLOR_ALPHA;
+    surface->d3d9surface = NULL;
 
     surface->dc = hdc;
     surface->bitmap = NULL;
     surface->is_dib = FALSE;
     surface->saved_dc_bitmap = NULL;
     surface->brush = NULL;
     surface->old_brush = NULL;
     surface->font_subsets = _cairo_scaled_font_subsets_create_scaled ();
--- a/gfx/cairo/cairo/src/cairo-win32-private.h
+++ b/gfx/cairo/cairo/src/cairo-win32-private.h
@@ -54,16 +54,18 @@ CAIRO_BEGIN_DECLS
 
 typedef struct _cairo_win32_surface {
     cairo_surface_t base;
 
     cairo_format_t format;
 
     HDC dc;
 
+    struct IDirect3DSurface9 *d3d9surface;
+
     /* We create off-screen surfaces as DIBs or DDBs, based on what we created
      * originally*/
     HBITMAP bitmap;
     cairo_bool_t is_dib;
 
     /* Used to save the initial 1x1 monochrome bitmap for the DC to
      * select back into the DC before deleting the DC and our
      * bitmap. For Windows XP, this doesn't seem to be necessary
--- a/gfx/cairo/cairo/src/cairo-win32-surface.c
+++ b/gfx/cairo/cairo/src/cairo-win32-surface.c
@@ -54,16 +54,17 @@
 #include "cairo-win32-private.h"
 #include "cairo-scaled-font-subsets-private.h"
 #include "cairo-surface-fallback-private.h"
 #include "cairo-surface-clipper-private.h"
 #include "cairo-gstate-private.h"
 #include "cairo-private.h"
 #include <wchar.h>
 #include <windows.h>
+#include <D3D9.h>
 
 #if defined(__MINGW32__) && !defined(ETO_PDY)
 # define ETO_PDY 0x2000
 #endif
 
 #undef DEBUG_COMPOSITE
 
 /* for older SDKs */
@@ -384,16 +385,17 @@ static cairo_surface_t *
 
     surface->image = cairo_image_surface_create_for_data (bits, format,
 							  width, height, rowstride);
     status = surface->image->status;
     if (status)
 	goto FAIL;
 
     surface->format = format;
+    surface->d3d9surface = NULL;
 
     surface->clip_rect.x = 0;
     surface->clip_rect.y = 0;
     surface->clip_rect.width = width;
     surface->clip_rect.height = height;
 
     surface->initial_clip_rgn = NULL;
     surface->had_simple_clip = FALSE;
@@ -481,26 +483,73 @@ cairo_status_t
     if (surface->bitmap) {
 	SelectObject (surface->dc, surface->saved_dc_bitmap);
 	DeleteObject (surface->bitmap);
 	DeleteDC (surface->dc);
     } else {
 	_cairo_win32_restore_initial_clip (surface);
     }
 
+    if (surface->d3d9surface) {
+        IDirect3DSurface9_ReleaseDC (surface->d3d9surface, surface->dc);
+        IDirect3DSurface9_Release (surface->d3d9surface);
+    }
+
     if (surface->initial_clip_rgn)
 	DeleteObject (surface->initial_clip_rgn);
 
     if (surface->font_subsets != NULL)
 	_cairo_scaled_font_subsets_destroy (surface->font_subsets);
 
     return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_status_t
+_cairo_win32_surface_d3d9_lock_rect (cairo_win32_surface_t  *surface,
+				   int                     x,
+				   int                     y,
+				   int                     width,
+				   int                     height,
+				   cairo_image_surface_t **local_out)
+{
+    cairo_image_surface_t *local;
+    cairo_int_status_t status;
+
+    RECT rectin = { x, y, x+width, y+height };
+    D3DLOCKED_RECT rectout;
+    HRESULT hr;
+    hr = IDirect3DSurface9_ReleaseDC (surface->d3d9surface, surface->dc);
+    hr = IDirect3DSurface9_LockRect (surface->d3d9surface,
+	                             &rectout, &rectin, 0);
+    surface->dc = 0; // Don't use the DC when this is locked!
+    if (hr) {
+        IDirect3DSurface9_GetDC (surface->d3d9surface, &surface->dc);
+        return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
+    local = cairo_image_surface_create_for_data (rectout.pBits,
+	                                         surface->format,
+						 width, height,
+						 rectout.Pitch);
+    if (local == NULL) {
+	IDirect3DSurface9_UnlockRect (surface->d3d9surface);
+	IDirect3DSurface9_GetDC (surface->d3d9surface, &surface->dc);
+        return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
+    if (local->base.status) {
+	IDirect3DSurface9_UnlockRect (surface->d3d9surface);
+	IDirect3DSurface9_GetDC (surface->d3d9surface, &surface->dc);
+        return local->base.status;
+    }
+
+    *local_out = local;
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
 _cairo_win32_surface_get_subimage (cairo_win32_surface_t  *surface,
 				   int                     x,
 				   int                     y,
 				   int                     width,
 				   int                     height,
 				   cairo_win32_surface_t **local_out)
 {
     cairo_win32_surface_t *local;
@@ -599,17 +648,16 @@ static void
 }
 
 static cairo_status_t
 _cairo_win32_surface_acquire_source_image (void                    *abstract_surface,
 					   cairo_image_surface_t  **image_out,
 					   void                   **image_extra)
 {
     cairo_win32_surface_t *surface = abstract_surface;
-    cairo_win32_surface_t *local;
     cairo_status_t status;
 
     if (!surface->image && !surface->is_dib && surface->bitmap &&
 	(surface->flags & CAIRO_WIN32_SURFACE_CAN_CONVERT_TO_DIB) != 0)
     {
 	/* This is a DDB, and we're being asked to use it as a source for
 	 * something that we couldn't support natively.  So turn it into
 	 * a DIB, so that we have an equivalent image surface, as long
@@ -619,69 +667,109 @@ static cairo_status_t
     }
 
     if (surface->image) {
 	*image_out = (cairo_image_surface_t *)surface->image;
 	*image_extra = NULL;
 	return CAIRO_STATUS_SUCCESS;
     }
 
-    status = _cairo_win32_surface_get_subimage (abstract_surface, 0, 0,
-						surface->extents.width,
-						surface->extents.height, &local);
-    if (status)
-	return status;
-
-    *image_out = (cairo_image_surface_t *)local->image;
-    *image_extra = local;
+    if (surface->d3d9surface) {
+	cairo_image_surface_t *local;
+	status = _cairo_win32_surface_d3d9_lock_rect (abstract_surface, 0, 0,
+						      surface->extents.width,
+						      surface->extents.height, &local);
+	if (status)
+	    return status;
+
+	*image_out = local;
+	*image_extra = surface;
+    } else {
+	cairo_win32_surface_t *local;
+	status = _cairo_win32_surface_get_subimage (abstract_surface, 0, 0,
+						    surface->extents.width,
+						    surface->extents.height, &local);
+	if (status)
+	    return status;
+
+	*image_out = (cairo_image_surface_t *)local->image;
+	*image_extra = local;
+    }
+    // image_extra is always of type cairo_win32_surface_t. For d3d9surface it points
+    // to the original surface to get back the d3d9surface and properly unlock.
+
     return CAIRO_STATUS_SUCCESS;
 }
 
 static void
 _cairo_win32_surface_release_source_image (void                   *abstract_surface,
 					   cairo_image_surface_t  *image,
 					   void                   *image_extra)
 {
+    cairo_win32_surface_t *surface = abstract_surface;
     cairo_win32_surface_t *local = image_extra;
 
-    if (local)
+    if (local && local->d3d9surface) {
+	IDirect3DSurface9_UnlockRect (local->d3d9surface);
+	IDirect3DSurface9_GetDC (local->d3d9surface, &local->dc);
+	cairo_surface_destroy ((cairo_surface_t *)image);
+    } else {
 	cairo_surface_destroy ((cairo_surface_t *)local);
+    }
 }
 
 static cairo_status_t
 _cairo_win32_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_win32_surface_t *surface = abstract_surface;
-    cairo_win32_surface_t *local = NULL;
     cairo_status_t status;
 
     if (surface->image) {
 	GdiFlush();
 
 	*image_out = (cairo_image_surface_t *) surface->image;
 	*image_extra = NULL;
 	*image_rect = surface->extents;
 	return CAIRO_STATUS_SUCCESS;
     }
 
-    status = _cairo_win32_surface_get_subimage (abstract_surface,
+    if (surface->d3d9surface) {
+	cairo_image_surface_t *local = NULL;
+	status = _cairo_win32_surface_d3d9_lock_rect (abstract_surface,
 						interest_rect->x,
 						interest_rect->y,
 						interest_rect->width,
-						interest_rect->height,
-						&local);
-    if (status)
-	return status;
-
-    *image_out = (cairo_image_surface_t *) local->image;
-    *image_extra = local;
+						interest_rect->height, &local);
+
+	if (status)
+	    return status;
+
+	*image_out = local;
+	*image_extra = surface;
+    } else {
+	cairo_win32_surface_t *local = NULL;
+	status = _cairo_win32_surface_get_subimage (abstract_surface,
+						interest_rect->x,
+						interest_rect->y,
+						interest_rect->width,
+						interest_rect->height, &local);
+
+	if (status)
+	    return status;
+
+	*image_out = (cairo_image_surface_t *) local->image;
+	*image_extra = local;
+    }
+    // image_extra is always of type cairo_win32_surface_t. For d3d9surface it points
+    // to the original surface to get back the d3d9surface and properly unlock.
+
     *image_rect = *interest_rect;
     return CAIRO_STATUS_SUCCESS;
 }
 
 static void
 _cairo_win32_surface_release_dest_image (void                    *abstract_surface,
 					 cairo_rectangle_int_t   *interest_rect,
 					 cairo_image_surface_t   *image,
@@ -689,29 +777,37 @@ static void
 					 void                    *image_extra)
 {
     cairo_win32_surface_t *surface = abstract_surface;
     cairo_win32_surface_t *local = image_extra;
 
     if (!local)
 	return;
 
-    /* clear any clip that's currently set on the surface
-       so that we can blit uninhibited. */
-    _cairo_win32_surface_set_clip_region (surface, NULL);
-
-    if (!BitBlt (surface->dc,
-		 image_rect->x, image_rect->y,
-		 image_rect->width, image_rect->height,
-		 local->dc,
-		 0, 0,
-		 SRCCOPY))
-	_cairo_win32_print_gdi_error ("_cairo_win32_surface_release_dest_image");
-
-    cairo_surface_destroy ((cairo_surface_t *)local);
+    if (local->d3d9surface) {
+	IDirect3DSurface9_UnlockRect (local->d3d9surface);
+	IDirect3DSurface9_GetDC (local->d3d9surface, &local->dc);
+	cairo_surface_destroy ((cairo_surface_t *)image);
+    } else {
+
+	/* clear any clip that's currently set on the surface
+	   so that we can blit uninhibited. */
+	_cairo_win32_surface_set_clip_region (surface, NULL);
+
+	if (!BitBlt (surface->dc,
+		     image_rect->x, image_rect->y,
+		     image_rect->width, image_rect->height,
+		     local->dc,
+		     0, 0,
+		     SRCCOPY))
+	    _cairo_win32_print_gdi_error ("_cairo_win32_surface_release_dest_image");
+
+	cairo_surface_destroy ((cairo_surface_t *)local);
+    }
+
 }
 
 cairo_status_t
 _cairo_win32_surface_set_clip_region (void           *abstract_surface,
 				      cairo_region_t *region)
 {
     cairo_win32_surface_t *surface = abstract_surface;
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
@@ -1849,16 +1945,17 @@ cairo_win32_surface_create_internal (HDC
 	free (surface);
 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
     }
 
     surface->clip_region = NULL;
     surface->image = NULL;
     surface->format = format;
 
+    surface->d3d9surface = NULL;
     surface->dc = hdc;
     surface->bitmap = NULL;
     surface->is_dib = FALSE;
     surface->saved_dc_bitmap = NULL;
     surface->brush = NULL;
     surface->old_brush = NULL;
     surface->font_subsets = NULL;
 
@@ -2009,16 +2106,29 @@ cairo_win32_surface_create_with_ddb (HDC
 
 FINISH:
     if (screen_dc)
 	ReleaseDC (NULL, screen_dc);
 
     return (cairo_surface_t*) new_surf;
 }
 
+cairo_public cairo_surface_t *
+cairo_win32_surface_create_with_d3dsurface9 (IDirect3DSurface9 *surface)
+{
+    HDC dc;
+    cairo_win32_surface_t *win_surface;
+
+    IDirect3DSurface9_AddRef (surface);
+    IDirect3DSurface9_GetDC (surface, &dc);
+    win_surface = cairo_win32_surface_create_internal(dc, CAIRO_FORMAT_RGB24);
+    win_surface->d3d9surface = surface;
+    return (cairo_surface_t*) win_surface;
+
+}
 /**
  * _cairo_surface_is_win32:
  * @surface: a #cairo_surface_t
  *
  * Checks if a surface is a win32 surface.  This will
  * return False if this is a win32 printing surface; use
  * _cairo_surface_is_win32_printing() to check for that.
  *
--- a/gfx/cairo/cairo/src/cairo-win32.h
+++ b/gfx/cairo/cairo/src/cairo-win32.h
@@ -59,17 +59,16 @@ cairo_win32_surface_create_with_ddb (HDC
                                      cairo_format_t format,
                                      int width,
                                      int height);
 
 cairo_public cairo_surface_t *
 cairo_win32_surface_create_with_dib (cairo_format_t format,
                                      int width,
                                      int height);
-
 cairo_public HDC
 cairo_win32_surface_get_dc (cairo_surface_t *surface);
 
 cairo_public HDC
 cairo_win32_get_dc_with_clip (cairo_t *cr);
 
 cairo_public cairo_surface_t *
 cairo_win32_surface_get_image (cairo_surface_t *surface);
@@ -143,16 +142,20 @@ cairo_dwrite_scaled_font_get_force_GDI_c
 void
 cairo_dwrite_set_cleartype_params(FLOAT gamma, FLOAT contrast, FLOAT level, int geometry, int mode);
 
 int
 cairo_dwrite_get_cleartype_rendering_mode();
 
 #endif /* CAIRO_HAS_DWRITE_FONT */
 
+cairo_public cairo_surface_t *
+cairo_win32_surface_create_with_d3dsurface9 (struct IDirect3DSurface9 *surface);
+
+
 #if CAIRO_HAS_D2D_SURFACE
 
 struct _cairo_device
 {
     int type;
     int refcount;
 };
 
new file mode 100644
--- /dev/null
+++ b/gfx/cairo/win32-d3dsurface9.patch
@@ -0,0 +1,464 @@
+diff --git a/gfx/cairo/cairo/src/cairo-rename.h b/gfx/cairo/cairo/src/cairo-rename.h
+--- a/gfx/cairo/cairo/src/cairo-rename.h
++++ b/gfx/cairo/cairo/src/cairo-rename.h
+@@ -335,16 +335,17 @@
+ #define cairo_win32_font_face_create_for_logfontw_hfont _moz_cairo_win32_font_face_create_for_logfontw_hfont
+ #define cairo_win32_printing_surface_create _moz_cairo_win32_printing_surface_create
+ #define cairo_win32_scaled_font_done_font _moz_cairo_win32_scaled_font_done_font
+ #define cairo_win32_scaled_font_get_device_to_logical _moz_cairo_win32_scaled_font_get_device_to_logical
+ #define cairo_win32_scaled_font_get_logical_to_device _moz_cairo_win32_scaled_font_get_logical_to_device
+ #define cairo_win32_scaled_font_get_metrics_factor _moz_cairo_win32_scaled_font_get_metrics_factor
+ #define cairo_win32_scaled_font_select_font _moz_cairo_win32_scaled_font_select_font
+ #define cairo_win32_surface_create _moz_cairo_win32_surface_create
++#define cairo_win32_surface_create_with_d3dsurface9 _moz_cairo_win32_surface_create_with_d3dsurface9
+ #define cairo_win32_surface_create_with_ddb _moz_cairo_win32_surface_create_with_ddb
+ #define cairo_win32_surface_create_with_dib _moz_cairo_win32_surface_create_with_dib
+ #define cairo_win32_surface_get_dc _moz_cairo_win32_surface_get_dc
+ #define cairo_win32_surface_get_image _moz_cairo_win32_surface_get_image
+ #define cairo_xcb_surface_create _moz_cairo_xcb_surface_create
+ #define cairo_xcb_surface_create_for_bitmap _moz_cairo_xcb_surface_create_for_bitmap
+ #define cairo_xcb_surface_create_with_xrender_format _moz_cairo_xcb_surface_create_with_xrender_format
+ #define cairo_xcb_surface_set_size _moz_cairo_xcb_surface_set_size
+diff --git a/gfx/cairo/cairo/src/cairo-win32-printing-surface.c b/gfx/cairo/cairo/src/cairo-win32-printing-surface.c
+--- a/gfx/cairo/cairo/src/cairo-win32-printing-surface.c
++++ b/gfx/cairo/cairo/src/cairo-win32-printing-surface.c
+@@ -1852,16 +1852,17 @@ cairo_win32_printing_surface_create (HDC
+     }
+ 
+     _cairo_surface_clipper_init (&surface->clipper,
+ 				 _cairo_win32_printing_surface_clipper_intersect_clip_path);
+ 
+     surface->image = NULL;
+     surface->format = CAIRO_FORMAT_RGB24;
+     surface->content = CAIRO_CONTENT_COLOR_ALPHA;
++    surface->d3d9surface = NULL;
+ 
+     surface->dc = hdc;
+     surface->bitmap = NULL;
+     surface->is_dib = FALSE;
+     surface->saved_dc_bitmap = NULL;
+     surface->brush = NULL;
+     surface->old_brush = NULL;
+     surface->font_subsets = _cairo_scaled_font_subsets_create_scaled ();
+diff --git a/gfx/cairo/cairo/src/cairo-win32-private.h b/gfx/cairo/cairo/src/cairo-win32-private.h
+--- a/gfx/cairo/cairo/src/cairo-win32-private.h
++++ b/gfx/cairo/cairo/src/cairo-win32-private.h
+@@ -54,16 +54,18 @@ CAIRO_BEGIN_DECLS
+ 
+ typedef struct _cairo_win32_surface {
+     cairo_surface_t base;
+ 
+     cairo_format_t format;
+ 
+     HDC dc;
+ 
++    struct IDirect3DSurface9 *d3d9surface;
++
+     /* We create off-screen surfaces as DIBs or DDBs, based on what we created
+      * originally*/
+     HBITMAP bitmap;
+     cairo_bool_t is_dib;
+ 
+     /* Used to save the initial 1x1 monochrome bitmap for the DC to
+      * select back into the DC before deleting the DC and our
+      * bitmap. For Windows XP, this doesn't seem to be necessary
+diff --git a/gfx/cairo/cairo/src/cairo-win32-surface.c b/gfx/cairo/cairo/src/cairo-win32-surface.c
+--- a/gfx/cairo/cairo/src/cairo-win32-surface.c
++++ b/gfx/cairo/cairo/src/cairo-win32-surface.c
+@@ -54,16 +54,17 @@
+ #include "cairo-win32-private.h"
+ #include "cairo-scaled-font-subsets-private.h"
+ #include "cairo-surface-fallback-private.h"
+ #include "cairo-surface-clipper-private.h"
+ #include "cairo-gstate-private.h"
+ #include "cairo-private.h"
+ #include <wchar.h>
+ #include <windows.h>
++#include <D3D9.h>
+ 
+ #if defined(__MINGW32__) && !defined(ETO_PDY)
+ # define ETO_PDY 0x2000
+ #endif
+ 
+ #undef DEBUG_COMPOSITE
+ 
+ /* for older SDKs */
+@@ -384,16 +385,17 @@ static cairo_surface_t *
+ 
+     surface->image = cairo_image_surface_create_for_data (bits, format,
+ 							  width, height, rowstride);
+     status = surface->image->status;
+     if (status)
+ 	goto FAIL;
+ 
+     surface->format = format;
++    surface->d3d9surface = NULL;
+ 
+     surface->clip_rect.x = 0;
+     surface->clip_rect.y = 0;
+     surface->clip_rect.width = width;
+     surface->clip_rect.height = height;
+ 
+     surface->initial_clip_rgn = NULL;
+     surface->had_simple_clip = FALSE;
+@@ -481,26 +483,73 @@ cairo_status_t
+     if (surface->bitmap) {
+ 	SelectObject (surface->dc, surface->saved_dc_bitmap);
+ 	DeleteObject (surface->bitmap);
+ 	DeleteDC (surface->dc);
+     } else {
+ 	_cairo_win32_restore_initial_clip (surface);
+     }
+ 
++    if (surface->d3d9surface) {
++        IDirect3DSurface9_ReleaseDC (surface->d3d9surface, surface->dc);
++        IDirect3DSurface9_Release (surface->d3d9surface);
++    }
++
+     if (surface->initial_clip_rgn)
+ 	DeleteObject (surface->initial_clip_rgn);
+ 
+     if (surface->font_subsets != NULL)
+ 	_cairo_scaled_font_subsets_destroy (surface->font_subsets);
+ 
+     return CAIRO_STATUS_SUCCESS;
+ }
+ 
+ static cairo_status_t
++_cairo_win32_surface_d3d9_lock_rect (cairo_win32_surface_t  *surface,
++				   int                     x,
++				   int                     y,
++				   int                     width,
++				   int                     height,
++				   cairo_image_surface_t **local_out)
++{
++    cairo_image_surface_t *local;
++    cairo_int_status_t status;
++
++    RECT rectin = { x, y, x+width, y+height };
++    D3DLOCKED_RECT rectout;
++    HRESULT hr;
++    hr = IDirect3DSurface9_ReleaseDC (surface->d3d9surface, surface->dc);
++    hr = IDirect3DSurface9_LockRect (surface->d3d9surface,
++	                             &rectout, &rectin, 0);
++    surface->dc = 0; // Don't use the DC when this is locked!
++    if (hr) {
++        IDirect3DSurface9_GetDC (surface->d3d9surface, &surface->dc);
++        return CAIRO_INT_STATUS_UNSUPPORTED;
++    }
++    local = cairo_image_surface_create_for_data (rectout.pBits,
++	                                         surface->format,
++						 width, height,
++						 rectout.Pitch);
++    if (local == NULL) {
++	IDirect3DSurface9_UnlockRect (surface->d3d9surface);
++	IDirect3DSurface9_GetDC (surface->d3d9surface, &surface->dc);
++        return CAIRO_INT_STATUS_UNSUPPORTED;
++    }
++    if (local->base.status) {
++	IDirect3DSurface9_UnlockRect (surface->d3d9surface);
++	IDirect3DSurface9_GetDC (surface->d3d9surface, &surface->dc);
++        return local->base.status;
++    }
++
++    *local_out = local;
++
++    return CAIRO_STATUS_SUCCESS;
++}
++
++static cairo_status_t
+ _cairo_win32_surface_get_subimage (cairo_win32_surface_t  *surface,
+ 				   int                     x,
+ 				   int                     y,
+ 				   int                     width,
+ 				   int                     height,
+ 				   cairo_win32_surface_t **local_out)
+ {
+     cairo_win32_surface_t *local;
+@@ -599,17 +648,16 @@ static void
+ }
+ 
+ static cairo_status_t
+ _cairo_win32_surface_acquire_source_image (void                    *abstract_surface,
+ 					   cairo_image_surface_t  **image_out,
+ 					   void                   **image_extra)
+ {
+     cairo_win32_surface_t *surface = abstract_surface;
+-    cairo_win32_surface_t *local;
+     cairo_status_t status;
+ 
+     if (!surface->image && !surface->is_dib && surface->bitmap &&
+ 	(surface->flags & CAIRO_WIN32_SURFACE_CAN_CONVERT_TO_DIB) != 0)
+     {
+ 	/* This is a DDB, and we're being asked to use it as a source for
+ 	 * something that we couldn't support natively.  So turn it into
+ 	 * a DIB, so that we have an equivalent image surface, as long
+@@ -619,69 +667,109 @@ static cairo_status_t
+     }
+ 
+     if (surface->image) {
+ 	*image_out = (cairo_image_surface_t *)surface->image;
+ 	*image_extra = NULL;
+ 	return CAIRO_STATUS_SUCCESS;
+     }
+ 
+-    status = _cairo_win32_surface_get_subimage (abstract_surface, 0, 0,
+-						surface->extents.width,
+-						surface->extents.height, &local);
+-    if (status)
+-	return status;
+-
+-    *image_out = (cairo_image_surface_t *)local->image;
+-    *image_extra = local;
++    if (surface->d3d9surface) {
++	cairo_image_surface_t *local;
++	status = _cairo_win32_surface_d3d9_lock_rect (abstract_surface, 0, 0,
++						      surface->extents.width,
++						      surface->extents.height, &local);
++	if (status)
++	    return status;
++
++	*image_out = local;
++	*image_extra = surface;
++    } else {
++	cairo_win32_surface_t *local;
++	status = _cairo_win32_surface_get_subimage (abstract_surface, 0, 0,
++						    surface->extents.width,
++						    surface->extents.height, &local);
++	if (status)
++	    return status;
++
++	*image_out = (cairo_image_surface_t *)local->image;
++	*image_extra = local;
++    }
++    // image_extra is always of type cairo_win32_surface_t. For d3d9surface it points
++    // to the original surface to get back the d3d9surface and properly unlock.
++
+     return CAIRO_STATUS_SUCCESS;
+ }
+ 
+ static void
+ _cairo_win32_surface_release_source_image (void                   *abstract_surface,
+ 					   cairo_image_surface_t  *image,
+ 					   void                   *image_extra)
+ {
++    cairo_win32_surface_t *surface = abstract_surface;
+     cairo_win32_surface_t *local = image_extra;
+ 
+-    if (local)
++    if (local && local->d3d9surface) {
++	IDirect3DSurface9_UnlockRect (local->d3d9surface);
++	IDirect3DSurface9_GetDC (local->d3d9surface, &local->dc);
++	cairo_surface_destroy ((cairo_surface_t *)image);
++    } else {
+ 	cairo_surface_destroy ((cairo_surface_t *)local);
++    }
+ }
+ 
+ static cairo_status_t
+ _cairo_win32_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_win32_surface_t *surface = abstract_surface;
+-    cairo_win32_surface_t *local = NULL;
+     cairo_status_t status;
+ 
+     if (surface->image) {
+ 	GdiFlush();
+ 
+ 	*image_out = (cairo_image_surface_t *) surface->image;
+ 	*image_extra = NULL;
+ 	*image_rect = surface->extents;
+ 	return CAIRO_STATUS_SUCCESS;
+     }
+ 
+-    status = _cairo_win32_surface_get_subimage (abstract_surface,
++    if (surface->d3d9surface) {
++	cairo_image_surface_t *local = NULL;
++	status = _cairo_win32_surface_d3d9_lock_rect (abstract_surface,
+ 						interest_rect->x,
+ 						interest_rect->y,
+ 						interest_rect->width,
+-						interest_rect->height,
+-						&local);
+-    if (status)
+-	return status;
+-
+-    *image_out = (cairo_image_surface_t *) local->image;
+-    *image_extra = local;
++						interest_rect->height, &local);
++
++	if (status)
++	    return status;
++
++	*image_out = local;
++	*image_extra = surface;
++    } else {
++	cairo_win32_surface_t *local = NULL;
++	status = _cairo_win32_surface_get_subimage (abstract_surface,
++						interest_rect->x,
++						interest_rect->y,
++						interest_rect->width,
++						interest_rect->height, &local);
++
++	if (status)
++	    return status;
++
++	*image_out = (cairo_image_surface_t *) local->image;
++	*image_extra = local;
++    }
++    // image_extra is always of type cairo_win32_surface_t. For d3d9surface it points
++    // to the original surface to get back the d3d9surface and properly unlock.
++
+     *image_rect = *interest_rect;
+     return CAIRO_STATUS_SUCCESS;
+ }
+ 
+ static void
+ _cairo_win32_surface_release_dest_image (void                    *abstract_surface,
+ 					 cairo_rectangle_int_t   *interest_rect,
+ 					 cairo_image_surface_t   *image,
+@@ -689,29 +777,37 @@ static void
+ 					 void                    *image_extra)
+ {
+     cairo_win32_surface_t *surface = abstract_surface;
+     cairo_win32_surface_t *local = image_extra;
+ 
+     if (!local)
+ 	return;
+ 
+-    /* clear any clip that's currently set on the surface
+-       so that we can blit uninhibited. */
+-    _cairo_win32_surface_set_clip_region (surface, NULL);
+-
+-    if (!BitBlt (surface->dc,
+-		 image_rect->x, image_rect->y,
+-		 image_rect->width, image_rect->height,
+-		 local->dc,
+-		 0, 0,
+-		 SRCCOPY))
+-	_cairo_win32_print_gdi_error ("_cairo_win32_surface_release_dest_image");
+-
+-    cairo_surface_destroy ((cairo_surface_t *)local);
++    if (local->d3d9surface) {
++	IDirect3DSurface9_UnlockRect (local->d3d9surface);
++	IDirect3DSurface9_GetDC (local->d3d9surface, &local->dc);
++	cairo_surface_destroy ((cairo_surface_t *)image);
++    } else {
++
++	/* clear any clip that's currently set on the surface
++	   so that we can blit uninhibited. */
++	_cairo_win32_surface_set_clip_region (surface, NULL);
++
++	if (!BitBlt (surface->dc,
++		     image_rect->x, image_rect->y,
++		     image_rect->width, image_rect->height,
++		     local->dc,
++		     0, 0,
++		     SRCCOPY))
++	    _cairo_win32_print_gdi_error ("_cairo_win32_surface_release_dest_image");
++
++	cairo_surface_destroy ((cairo_surface_t *)local);
++    }
++
+ }
+ 
+ cairo_status_t
+ _cairo_win32_surface_set_clip_region (void           *abstract_surface,
+ 				      cairo_region_t *region)
+ {
+     cairo_win32_surface_t *surface = abstract_surface;
+     cairo_status_t status = CAIRO_STATUS_SUCCESS;
+@@ -1849,16 +1945,17 @@ cairo_win32_surface_create_internal (HDC
+ 	free (surface);
+ 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
+     }
+ 
+     surface->clip_region = NULL;
+     surface->image = NULL;
+     surface->format = format;
+ 
++    surface->d3d9surface = NULL;
+     surface->dc = hdc;
+     surface->bitmap = NULL;
+     surface->is_dib = FALSE;
+     surface->saved_dc_bitmap = NULL;
+     surface->brush = NULL;
+     surface->old_brush = NULL;
+     surface->font_subsets = NULL;
+ 
+@@ -2009,16 +2106,29 @@ cairo_win32_surface_create_with_ddb (HDC
+ 
+ FINISH:
+     if (screen_dc)
+ 	ReleaseDC (NULL, screen_dc);
+ 
+     return (cairo_surface_t*) new_surf;
+ }
+ 
++cairo_public cairo_surface_t *
++cairo_win32_surface_create_with_d3dsurface9 (IDirect3DSurface9 *surface)
++{
++    HDC dc;
++    cairo_win32_surface_t *win_surface;
++
++    IDirect3DSurface9_AddRef (surface);
++    IDirect3DSurface9_GetDC (surface, &dc);
++    win_surface = cairo_win32_surface_create_internal(dc, CAIRO_FORMAT_RGB24);
++    win_surface->d3d9surface = surface;
++    return (cairo_surface_t*) win_surface;
++
++}
+ /**
+  * _cairo_surface_is_win32:
+  * @surface: a #cairo_surface_t
+  *
+  * Checks if a surface is a win32 surface.  This will
+  * return False if this is a win32 printing surface; use
+  * _cairo_surface_is_win32_printing() to check for that.
+  *
+diff --git a/gfx/cairo/cairo/src/cairo-win32.h b/gfx/cairo/cairo/src/cairo-win32.h
+--- a/gfx/cairo/cairo/src/cairo-win32.h
++++ b/gfx/cairo/cairo/src/cairo-win32.h
+@@ -59,17 +59,16 @@ cairo_win32_surface_create_with_ddb (HDC
+                                      cairo_format_t format,
+                                      int width,
+                                      int height);
+ 
+ cairo_public cairo_surface_t *
+ cairo_win32_surface_create_with_dib (cairo_format_t format,
+                                      int width,
+                                      int height);
+-
+ cairo_public HDC
+ cairo_win32_surface_get_dc (cairo_surface_t *surface);
+ 
+ cairo_public HDC
+ cairo_win32_get_dc_with_clip (cairo_t *cr);
+ 
+ cairo_public cairo_surface_t *
+ cairo_win32_surface_get_image (cairo_surface_t *surface);
+@@ -143,16 +142,20 @@ cairo_dwrite_scaled_font_get_force_GDI_c
+ void
+ cairo_dwrite_set_cleartype_params(FLOAT gamma, FLOAT contrast, FLOAT level, int geometry, int mode);
+ 
+ int
+ cairo_dwrite_get_cleartype_rendering_mode();
+ 
+ #endif /* CAIRO_HAS_DWRITE_FONT */
+ 
++cairo_public cairo_surface_t *
++cairo_win32_surface_create_with_d3dsurface9 (struct IDirect3DSurface9 *surface);
++
++
+ #if CAIRO_HAS_D2D_SURFACE
+ 
+ struct _cairo_device
+ {
+     int type;
+     int refcount;
+ };
+ 
--- a/gfx/layers/d3d9/ThebesLayerD3D9.cpp
+++ b/gfx/layers/d3d9/ThebesLayerD3D9.cpp
@@ -338,27 +338,27 @@ ThebesLayerD3D9::VerifyContentType(Surfa
   mTexture = nullptr;
   mTextureOnWhite = nullptr;
   mValidRegion.SetEmpty();
 }
 
 class OpaqueRenderer {
 public:
   OpaqueRenderer(const nsIntRegion& aUpdateRegion) :
-    mUpdateRegion(aUpdateRegion), mDC(nullptr) {}
+    mUpdateRegion(aUpdateRegion) {}
   ~OpaqueRenderer() { End(); }
   already_AddRefed<gfxWindowsSurface> Begin(LayerD3D9* aLayer);
   void End();
   IDirect3DTexture9* GetTexture() { return mTmpTexture; }
 
 private:
   const nsIntRegion& mUpdateRegion;
   nsRefPtr<IDirect3DTexture9> mTmpTexture;
   nsRefPtr<IDirect3DSurface9> mSurface;
-  HDC mDC;
+  nsRefPtr<gfxWindowsSurface> mD3D9ThebesSurface;
 };
 
 already_AddRefed<gfxWindowsSurface>
 OpaqueRenderer::Begin(LayerD3D9* aLayer)
 {
   nsIntRect bounds = mUpdateRegion.GetBounds();
 
   HRESULT hr = aLayer->device()->
@@ -373,34 +373,42 @@ OpaqueRenderer::Begin(LayerD3D9* aLayer)
   hr = mTmpTexture->GetSurfaceLevel(0, getter_AddRefs(mSurface));
 
   if (FAILED(hr)) {
     // Uh-oh, bail.
     NS_WARNING("Failed to get texture surface level.");
     return nullptr;
   }
 
-  hr = mSurface->GetDC(&mDC);
-  if (FAILED(hr)) {
-    NS_WARNING("Failed to get device context for texture surface.");
+  nsRefPtr<gfxWindowsSurface> result = new gfxWindowsSurface(mSurface);
+  if (!result) {
+    NS_WARNING("Failed to d3d9 cairo surface.");
     return nullptr;
   }
+  mD3D9ThebesSurface = result;
 
-  nsRefPtr<gfxWindowsSurface> result = new gfxWindowsSurface(mDC);
   return result.forget();
 }
 
 void
 OpaqueRenderer::End()
 {
-  if (mSurface && mDC) {
-    mSurface->ReleaseDC(mDC);
-    mSurface = nullptr;
-    mDC = nullptr;
+  mSurface = nullptr;
+  // gfxWindowsSurface returned from ::Begin() should be released before the
+  // texture is used. This will assert that this is the case
+#if 1
+  if (mD3D9ThebesSurface) {
+    mD3D9ThebesSurface->AddRef();
+    nsrefcnt c = mD3D9ThebesSurface->Release();
+    if (c != 1)
+      NS_RUNTIMEABORT("Reference mD3D9ThebesSurface must be released by caller of Begin() before calling End()");
   }
+#endif
+  mD3D9ThebesSurface = nullptr;
+
 }
 
 static void
 FillSurface(gfxASurface* aSurface, const nsIntRegion& aRegion,
             const nsIntPoint& aOffset, const gfxRGBA& aColor)
 {
   nsRefPtr<gfxContext> ctx = new gfxContext(aSurface);
   ctx->Translate(-gfxPoint(aOffset.x, aOffset.y));
@@ -498,21 +506,26 @@ ThebesLayerD3D9::DrawRegion(nsIntRegion 
     if (ctx) {
       ctx->Translate(gfxPoint(offset.x, offset.y));
       ctx->SetSource(destinationSurface, gfxPoint(bounds.x, bounds.y));
       ctx->Paint();
       update.mLayer->GetSink()->EndUpdate(ctx, update.mUpdateRect + offset);
     }
   }
 
+  // Release the cairo d3d9 surface before we try to composite it
+  context = nullptr;
+
   nsAutoTArray<IDirect3DTexture9*,2> srcTextures;
   nsAutoTArray<IDirect3DTexture9*,2> destTextures;
   switch (aMode)
   {
     case SURFACE_OPAQUE:
+      // Must release reference to dest surface before ending drawing
+      destinationSurface = nullptr;
       opaqueRenderer.End();
       srcTextures.AppendElement(opaqueRenderer.GetTexture());
       destTextures.AppendElement(mTexture);
       break;
 
     case SURFACE_SINGLE_CHANNEL_ALPHA: {
       LockTextureRectD3D9 textureLock(tmpTexture);
       if (!textureLock.HasLock()) {
@@ -530,34 +543,39 @@ ThebesLayerD3D9::DrawRegion(nsIntRegion 
 
       if (destinationSurface) {
         nsRefPtr<gfxContext> context = new gfxContext(imgSurface);
         context->SetSource(destinationSurface);
         context->SetOperator(gfxContext::OPERATOR_SOURCE);
         context->Paint();
       }
 
+      // Must release reference to dest surface before ending drawing
+      destinationSurface = nullptr;
       imgSurface = nullptr;
 
       srcTextures.AppendElement(tmpTexture);
       destTextures.AppendElement(mTexture);
       break;
     }
 
     case SURFACE_COMPONENT_ALPHA: {
+      // Must release reference to dest surface before ending drawing
+      destinationSurface = nullptr;
       opaqueRenderer.End();
       opaqueRendererOnWhite.End();
       srcTextures.AppendElement(opaqueRenderer.GetTexture());
       destTextures.AppendElement(mTexture);
       srcTextures.AppendElement(opaqueRendererOnWhite.GetTexture());
       destTextures.AppendElement(mTextureOnWhite);
       break;
     }
   }
   NS_ASSERTION(srcTextures.Length() == destTextures.Length(), "Mismatched lengths");
+  
 
   // Copy to the texture.
   for (uint32_t i = 0; i < srcTextures.Length(); ++i) {
     nsRefPtr<IDirect3DSurface9> srcSurface;
     nsRefPtr<IDirect3DSurface9> dstSurface;
 
     destTextures[i]->GetSurfaceLevel(0, getter_AddRefs(dstSurface));
     srcTextures[i]->GetSurfaceLevel(0, getter_AddRefs(srcSurface));
--- a/gfx/thebes/gfxWindowsSurface.cpp
+++ b/gfx/thebes/gfxWindowsSurface.cpp
@@ -29,16 +29,24 @@ gfxWindowsSurface::gfxWindowsSurface(HDC
     if (flags & FLAG_FOR_PRINTING) {
         Init(cairo_win32_printing_surface_create(mDC));
         mForPrinting = true;
     } else
 #endif
     InitWithDC(flags);
 }
 
+gfxWindowsSurface::gfxWindowsSurface(IDirect3DSurface9 *surface, uint32_t flags) :
+    mOwnsDC(false), mForPrinting(false), mDC(0), mWnd(nullptr)
+{
+    cairo_surface_t *surf = cairo_win32_surface_create_with_d3dsurface9(surface);
+    Init(surf);
+}
+
+
 void
 gfxWindowsSurface::MakeInvalid(gfxIntSize& size)
 {
     size = gfxIntSize(-1, -1);
 }
 
 gfxWindowsSurface::gfxWindowsSurface(const gfxIntSize& realSize, gfxImageFormat imageFormat) :
     mOwnsDC(false), mForPrinting(false), mWnd(nullptr)
@@ -156,16 +164,23 @@ gfxWindowsSurface::~gfxWindowsSurface()
 }
 
 HDC
 gfxWindowsSurface::GetDCWithClip(gfxContext *ctx)
 {
     return cairo_win32_get_dc_with_clip (ctx->GetCairo());
 }
 
+HDC
+gfxWindowsSurface::GetDC()
+{
+    return cairo_win32_surface_get_dc (CairoSurface());
+}
+
+
 already_AddRefed<gfxImageSurface>
 gfxWindowsSurface::GetAsImageSurface()
 {
     if (!mSurfaceValid) {
         NS_WARNING ("GetImageSurface on an invalid (null) surface; who's calling this without checking for surface errors?");
         return nullptr;
     }
 
--- a/gfx/thebes/gfxWindowsSurface.h
+++ b/gfx/thebes/gfxWindowsSurface.h
@@ -6,32 +6,38 @@
 #ifndef GFX_WINDOWSSURFACE_H
 #define GFX_WINDOWSSURFACE_H
 
 #include "gfxASurface.h"
 #include "gfxImageSurface.h"
 
 /* include windows.h for the HWND and HDC definitions that we need. */
 #include <windows.h>
+
+struct IDirect3DSurface9;
+
 /* undefine LoadImage because our code uses that name */
 #undef LoadImage
 
 class gfxContext;
 
 class gfxWindowsSurface : public gfxASurface {
 public:
     enum {
         FLAG_TAKE_DC = (1 << 0),
         FLAG_FOR_PRINTING = (1 << 1),
         FLAG_IS_TRANSPARENT = (1 << 2)
     };
 
     gfxWindowsSurface(HWND wnd, uint32_t flags = 0);
     gfxWindowsSurface(HDC dc, uint32_t flags = 0);
 
+    // Create from a shared d3d9surface
+    gfxWindowsSurface(IDirect3DSurface9 *surface, uint32_t flags = 0);
+
     // Create a DIB surface
     gfxWindowsSurface(const gfxIntSize& size,
                       gfxImageFormat imageFormat = ImageFormatRGB24);
 
     // Create a DDB surface; dc may be nullptr to use the screen DC
     gfxWindowsSurface(HDC dc,
                       const gfxIntSize& size,
                       gfxImageFormat imageFormat = ImageFormatRGB24);
@@ -40,17 +46,17 @@ public:
 
     virtual already_AddRefed<gfxASurface> CreateSimilarSurface(gfxContentType aType,
                                                                const gfxIntSize& aSize);
 
     void InitWithDC(uint32_t flags);
 
     virtual ~gfxWindowsSurface();
 
-    HDC GetDC() { return mDC; }
+    HDC GetDC();
 
     HDC GetDCWithClip(gfxContext *);
 
     already_AddRefed<gfxImageSurface> GetAsImageSurface();
 
     already_AddRefed<gfxWindowsSurface> OptimizeToDDB(HDC dc,
                                                       const gfxIntSize& size,
                                                       gfxImageFormat format);
--- a/layout/media/symbols.def.in
+++ b/layout/media/symbols.def.in
@@ -471,16 +471,17 @@ MOZ_XML_StopParser
 _moz_cairo_transform
 _moz_cairo_translate
 _moz_cairo_user_to_device
 _moz_cairo_user_to_device_distance
 _moz_cairo_win32_font_face_create_for_logfontw_hfont
 _moz_cairo_win32_printing_surface_create
 _moz_cairo_win32_scaled_font_select_font
 _moz_cairo_win32_surface_create
+_moz_cairo_win32_surface_create_with_d3dsurface9
 _moz_cairo_win32_surface_create_with_ddb
 _moz_cairo_win32_surface_create_with_dib
 _moz_cairo_win32_surface_get_dc
 _moz_cairo_win32_surface_get_image
 #ifdef MOZ_TREE_PIXMAN
 _moz_pixman_image_composite32
 _moz_pixman_image_create_bits
 _moz_pixman_image_set_transform