gfx/cairo/win32-ddb-dib.patch

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

michael@0 1 b=455513; add optional flag to allow converting a DDB to a DIB internally, if the surface is every used as a source; r=jmuizelaar
michael@0 2
michael@0 3 If a DDB is used as a source for an operation that can't be handled
michael@0 4 natively by GDI, we end up needing to take a really slow path (creating a
michael@0 5 temporary surface for acquire_source) for each operation. If we convert
michael@0 6 the DDB to a DIB, we then end up having a real image buffer and can hand
michael@0 7 things off to pixman directly.
michael@0 8
michael@0 9 This isn't the default mode because I'm not sure if there are cases where a
michael@0 10 DDB is explicitly needed (e.g. for printing), and it would change
michael@0 11 current cairo behaviour. It might become the default at some point in the
michael@0 12 future.
michael@0 13
michael@0 14 diff --git a/gfx/cairo/cairo/src/cairo-win32-private.h b/gfx/cairo/cairo/src/cairo-win32-private.h
michael@0 15 --- a/gfx/cairo/cairo/src/cairo-win32-private.h
michael@0 16 +++ b/gfx/cairo/cairo/src/cairo-win32-private.h
michael@0 17 @@ -117,6 +117,9 @@
michael@0 18
michael@0 19 /* Whether we can use the CHECKJPEGFORMAT escape function */
michael@0 20 CAIRO_WIN32_SURFACE_CAN_CHECK_PNG = (1<<8),
michael@0 21 +
michael@0 22 + /* if this DDB surface can be converted to a DIB if necessary */
michael@0 23 + CAIRO_WIN32_SURFACE_CAN_CONVERT_TO_DIB = (1<<9),
michael@0 24 };
michael@0 25
michael@0 26 cairo_status_t
michael@0 27 diff --git a/gfx/cairo/cairo/src/cairo-win32-surface.c b/gfx/cairo/cairo/src/cairo-win32-surface.c
michael@0 28 --- a/gfx/cairo/cairo/src/cairo-win32-surface.c
michael@0 29 +++ b/gfx/cairo/cairo/src/cairo-win32-surface.c
michael@0 30 @@ -560,6 +560,56 @@
michael@0 31 return CAIRO_STATUS_SUCCESS;
michael@0 32 }
michael@0 33
michael@0 34 +static void
michael@0 35 +_cairo_win32_convert_ddb_to_dib (cairo_win32_surface_t *surface)
michael@0 36 +{
michael@0 37 + cairo_win32_surface_t *new_surface;
michael@0 38 + int width = surface->extents.width;
michael@0 39 + int height = surface->extents.height;
michael@0 40 +
michael@0 41 + BOOL ok;
michael@0 42 + HBITMAP oldbitmap;
michael@0 43 +
michael@0 44 + new_surface = (cairo_win32_surface_t*)
michael@0 45 + _cairo_win32_surface_create_for_dc (surface->dc,
michael@0 46 + surface->format,
michael@0 47 + width,
michael@0 48 + height);
michael@0 49 +
michael@0 50 + if (new_surface->base.status)
michael@0 51 + return;
michael@0 52 +
michael@0 53 + /* DDB can't be 32bpp, so BitBlt is safe */
michael@0 54 + ok = BitBlt (new_surface->dc,
michael@0 55 + 0, 0, width, height,
michael@0 56 + surface->dc,
michael@0 57 + 0, 0, SRCCOPY);
michael@0 58 +
michael@0 59 + if (!ok)
michael@0 60 + goto out;
michael@0 61 +
michael@0 62 + /* Now swap around new_surface and surface's internal bitmap
michael@0 63 + * pointers. */
michael@0 64 + DeleteDC (new_surface->dc);
michael@0 65 + new_surface->dc = NULL;
michael@0 66 +
michael@0 67 + oldbitmap = SelectObject (surface->dc, new_surface->bitmap);
michael@0 68 + DeleteObject (oldbitmap);
michael@0 69 +
michael@0 70 + surface->image = new_surface->image;
michael@0 71 + surface->is_dib = new_surface->is_dib;
michael@0 72 + surface->bitmap = new_surface->bitmap;
michael@0 73 +
michael@0 74 + new_surface->bitmap = NULL;
michael@0 75 + new_surface->image = NULL;
michael@0 76 +
michael@0 77 + /* Finally update flags */
michael@0 78 + surface->flags = _cairo_win32_flags_for_dc (surface->dc);
michael@0 79 +
michael@0 80 + out:
michael@0 81 + cairo_surface_destroy ((cairo_surface_t*)new_surface);
michael@0 82 +}
michael@0 83 +
michael@0 84 static cairo_status_t
michael@0 85 _cairo_win32_surface_acquire_source_image (void *abstract_surface,
michael@0 86 cairo_image_surface_t **image_out,
michael@0 87 @@ -568,6 +618,17 @@
michael@0 88 cairo_win32_surface_t *surface = abstract_surface;
michael@0 89 cairo_win32_surface_t *local = NULL;
michael@0 90 cairo_status_t status;
michael@0 91 +
michael@0 92 + if (!surface->image && !surface->is_dib && surface->bitmap &&
michael@0 93 + (surface->flags & CAIRO_WIN32_SURFACE_CAN_CONVERT_TO_DIB) != 0)
michael@0 94 + {
michael@0 95 + /* This is a DDB, and we're being asked to use it as a source for
michael@0 96 + * something that we couldn't support natively. So turn it into
michael@0 97 + * a DIB, so that we have an equivalent image surface, as long
michael@0 98 + * as we're allowed to via flags.
michael@0 99 + */
michael@0 100 + _cairo_win32_convert_ddb_to_dib (surface);
michael@0 101 + }
michael@0 102
michael@0 103 if (surface->image) {
michael@0 104 *image_out = (cairo_image_surface_t *)surface->image;
michael@0 105 @@ -2133,3 +2194,61 @@
michael@0 106 free(rd);
michael@0 107 fflush (stderr);
michael@0 108 }
michael@0 109 +
michael@0 110 +/**
michael@0 111 + * cairo_win32_surface_set_can_convert_to_dib
michael@0 112 + * @surface: a #cairo_surface_t
michael@0 113 + * @can_convert: a #cairo_bool_t indicating whether this surface can
michael@0 114 + * be coverted to a DIB if necessary
michael@0 115 + *
michael@0 116 + * A DDB surface with this flag set can be converted to a DIB if it's
michael@0 117 + * used as a source in a way that GDI can't natively handle; for
michael@0 118 + * example, drawing a RGB24 DDB onto an ARGB32 DIB. Doing this
michael@0 119 + * conversion results in a significant speed optimization, because we
michael@0 120 + * can call on pixman to perform the operation natively, instead of
michael@0 121 + * reading the data from the DC each time.
michael@0 122 + *
michael@0 123 + * Return value: %CAIRO_STATUS_SUCCESS if the flag was successfully
michael@0 124 + * changed, or an error otherwise.
michael@0 125 + *
michael@0 126 + */
michael@0 127 +cairo_status_t
michael@0 128 +cairo_win32_surface_set_can_convert_to_dib (cairo_surface_t *asurface, cairo_bool_t can_convert)
michael@0 129 +{
michael@0 130 + cairo_win32_surface_t *surface = (cairo_win32_surface_t*) asurface;
michael@0 131 + if (surface->base.type != CAIRO_SURFACE_TYPE_WIN32)
michael@0 132 + return CAIRO_STATUS_SURFACE_TYPE_MISMATCH;
michael@0 133 +
michael@0 134 + if (surface->bitmap) {
michael@0 135 + if (can_convert)
michael@0 136 + surface->flags |= CAIRO_WIN32_SURFACE_CAN_CONVERT_TO_DIB;
michael@0 137 + else
michael@0 138 + surface->flags &= ~CAIRO_WIN32_SURFACE_CAN_CONVERT_TO_DIB;
michael@0 139 + }
michael@0 140 +
michael@0 141 + return CAIRO_STATUS_SUCCESS;
michael@0 142 +}
michael@0 143 +
michael@0 144 +/**
michael@0 145 + * cairo_win32_surface_get_can_convert_to_dib
michael@0 146 + * @surface: a #cairo_surface_t
michael@0 147 + * @can_convert: a #cairo_bool_t* that receives the return value
michael@0 148 + *
michael@0 149 + * Returns the value of the flag indicating whether the surface can be
michael@0 150 + * converted to a DIB if necessary, as set by
michael@0 151 + * cairo_win32_surface_set_can_convert_to_dib.
michael@0 152 + *
michael@0 153 + * Return value: %CAIRO_STATUS_SUCCESS if the flag was successfully
michael@0 154 + * retreived, or an error otherwise.
michael@0 155 + *
michael@0 156 + */
michael@0 157 +cairo_status_t
michael@0 158 +cairo_win32_surface_get_can_convert_to_dib (cairo_surface_t *asurface, cairo_bool_t *can_convert)
michael@0 159 +{
michael@0 160 + cairo_win32_surface_t *surface = (cairo_win32_surface_t*) asurface;
michael@0 161 + if (surface->base.type != CAIRO_SURFACE_TYPE_WIN32)
michael@0 162 + return CAIRO_STATUS_SURFACE_TYPE_MISMATCH;
michael@0 163 +
michael@0 164 + *can_convert = ((surface->flags & CAIRO_WIN32_SURFACE_CAN_CONVERT_TO_DIB) != 0);
michael@0 165 + return CAIRO_STATUS_SUCCESS;
michael@0 166 +}
michael@0 167 diff --git a/gfx/cairo/cairo/src/cairo-win32.h b/gfx/cairo/cairo/src/cairo-win32.h
michael@0 168 --- a/gfx/cairo/cairo/src/cairo-win32.h
michael@0 169 +++ b/gfx/cairo/cairo/src/cairo-win32.h
michael@0 170 @@ -68,6 +68,12 @@ cairo_win32_surface_get_dc (cairo_surface_t *surface);
michael@0 171 cairo_public cairo_surface_t *
michael@0 172 cairo_win32_surface_get_image (cairo_surface_t *surface);
michael@0 173
michael@0 174 +cairo_public cairo_status_t
michael@0 175 +cairo_win32_surface_set_can_convert_to_dib (cairo_surface_t *surface, cairo_bool_t can_convert);
michael@0 176 +
michael@0 177 +cairo_public cairo_status_t
michael@0 178 +cairo_win32_surface_get_can_convert_to_dib (cairo_surface_t *surface, cairo_bool_t *can_convert);
michael@0 179 +
michael@0 180 #if CAIRO_HAS_WIN32_FONT
michael@0 181

mercurial