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 #include +#include #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; };