b=434602; win32 create_similar should fall back to dib to avoid exausting vram; r=stuart
authorVladimir Vukicevic <vladimir@pobox.com>
Thu, 09 Oct 2008 14:49:15 -0700
changeset 20224 ab96d199ce9b55292835e2afc17d717d8dc6f022
parent 20223 3f9a436f49fe3dc134fe23ea49db5831a0a3e766
child 20225 60a855404ff85f9f4fdcedafa07b9b0b339b452b
push idunknown
push userunknown
push dateunknown
reviewersstuart
bugs434602
milestone1.9.1b2pre
b=434602; win32 create_similar should fall back to dib to avoid exausting vram; r=stuart
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
@@ -382,54 +382,46 @@ static cairo_surface_t *
 _cairo_win32_surface_create_similar_internal (void	    *abstract_src,
 					      cairo_content_t content,
 					      int	     width,
 					      int	     height,
 					      cairo_bool_t   force_dib)
 {
     cairo_win32_surface_t *src = abstract_src;
     cairo_format_t format = _cairo_format_from_content (content);
-    cairo_win32_surface_t *new_surf;
+    cairo_surface_t *new_surf = NULL;
 
     /* We force a DIB always if:
      * - we need alpha; or
      * - the parent is a DIB; or
      * - the parent is for printing (because we don't care about the bit depth at that point)
+     *
+     * We also might end up with a DIB even if a DDB is requested if DDB creation failed
+     * due to out of memory.
      */
     if (src->is_dib ||
 	(content & CAIRO_CONTENT_ALPHA) ||
 	src->base.backend->type == CAIRO_SURFACE_TYPE_WIN32_PRINTING)
     {
 	force_dib = TRUE;
     }
 
-    if (force_dib) {
-	new_surf = (cairo_win32_surface_t*)
-	    _cairo_win32_surface_create_for_dc (src->dc, format, width, height);
-    } else {
-	/* otherwise, create a ddb */
-	HBITMAP ddb = CreateCompatibleBitmap (src->dc, width, height);
-	HDC ddb_dc = CreateCompatibleDC (src->dc);
-	HBITMAP saved_dc_bitmap;
-
-	saved_dc_bitmap = SelectObject (ddb_dc, ddb);
+    if (!force_dib) {
+	/* try to create a ddb */
+	new_surf = cairo_win32_surface_create_with_ddb (src->dc, CAIRO_FORMAT_RGB24, width, height);
 
-	new_surf = (cairo_win32_surface_t*) cairo_win32_surface_create (ddb_dc);
-	if (new_surf->base.status == CAIRO_STATUS_SUCCESS) {
-	    new_surf->bitmap = ddb;
-	    new_surf->saved_dc_bitmap = saved_dc_bitmap;
-	    new_surf->is_dib = FALSE;
-	} else {
-	    SelectObject (ddb_dc, saved_dc_bitmap);
-	    DeleteDC (ddb_dc);
-	    DeleteObject (ddb);
-	}
+	if (new_surf->status != CAIRO_STATUS_SUCCESS)
+	    new_surf = NULL;
     }
 
-    return (cairo_surface_t*) new_surf;
+    if (new_surf == NULL) {
+	new_surf = _cairo_win32_surface_create_for_dc (src->dc, format, width, height);
+    }
+
+    return new_surf;
 }
 
 cairo_surface_t *
 _cairo_win32_surface_create_similar (void	    *abstract_src,
 				     cairo_content_t content,
 				     int	     width,
 				     int	     height)
 {
@@ -1826,30 +1818,29 @@ cairo_win32_surface_create_with_ddb (HDC
 	screen_dc = GetDC (NULL);
 	hdc = screen_dc;
     } else {
 	screen_dc = NULL;
     }
 
     ddb_dc = CreateCompatibleDC (hdc);
     if (ddb_dc == NULL) {
-	_cairo_win32_print_gdi_error("CreateCompatibleDC");
 	new_surf = (cairo_win32_surface_t*) _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 	goto FINISH;
     }
 
     ddb = CreateCompatibleBitmap (hdc, width, height);
     if (ddb == NULL) {
 	DeleteDC (ddb_dc);
 
 	/* Note that if an app actually does hit this out of memory
 	 * condition, it's going to have lots of other issues, as
-	 * video memory is probably exhausted.
+	 * video memory is probably exhausted.  However, it can often
+	 * continue using DIBs instead of DDBs.
 	 */
-	_cairo_win32_print_gdi_error("CreateCompatibleBitmap");
 	new_surf = (cairo_win32_surface_t*) _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 	goto FINISH;
     }
 
     saved_dc_bitmap = SelectObject (ddb_dc, ddb);
 
     new_surf = (cairo_win32_surface_t*) cairo_win32_surface_create (ddb_dc);
     new_surf->bitmap = ddb;