gfx/cairo/win32-d3dsurface9.patch
author Brian Hackett <bhackett1024@gmail.com>
Thu, 12 Dec 2013 13:10:54 -0800
changeset 176470 2e5ff561425490570383d57abf4eff21619c865f
parent 162237 951ceba4c9e61d3632275001ca7668c85e60b9c0
permissions -rw-r--r--
Bug 932982 - Trace type constraints and allow preserving jitcode in GCs without also marking all type information, r=billm, r=jandem

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 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,21 @@ cairo_dwrite_scaled_font_get_force_GDI_classic(cairo_scaled_font_t *dwrite_scale
 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 */
 
+struct IDirect3DSurface9;
+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;
 };