gecko-dev/gfx/cairo/win32-d3dsurface9.patch

466 lines
15 KiB
Diff

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;
};