Bug 1051592 - Clip DrawTargetCairo's context to the surface bound to prevent massive mask allocations within cairo. r=jrmuizel
☠☠ backed out by 9443cda3374e ☠ ☠
authorMatt Woodrow <mwoodrow@mozilla.com>
Fri, 15 Aug 2014 14:23:22 +1200
changeset 199629 028c43cd12a5
parent 199628 f9c51223ffc9
child 199630 64c414de6db5
push id47701
push usermwoodrow@mozilla.com
push date2014-08-15 02:25 +0000
treeherdermozilla-inbound@76d4e6230498 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs1051592
milestone34.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1051592 - Clip DrawTargetCairo's context to the surface bound to prevent massive mask allocations within cairo. r=jrmuizel
gfx/2d/DrawTargetCairo.cpp
--- a/gfx/2d/DrawTargetCairo.cpp
+++ b/gfx/2d/DrawTargetCairo.cpp
@@ -63,17 +63,24 @@ public:
   AutoPrepareForDrawing(DrawTargetCairo* dt, cairo_t* ctx, const Path* path)
     : mCtx(ctx)
   {
     dt->PrepareForDrawing(ctx, path);
     cairo_save(mCtx);
     MOZ_ASSERT(cairo_status(mCtx) || dt->GetTransform() == GetTransform());
   }
 
-  ~AutoPrepareForDrawing() { cairo_restore(mCtx); }
+  ~AutoPrepareForDrawing()
+  {
+    cairo_restore(mCtx);
+    cairo_status_t status = cairo_status(mCtx);
+    if (status) {
+      gfxWarning() << "DrawTargetCairo context in error state: " << cairo_status_to_string(status) << "(" << status << ")";
+    }
+  }
 
 private:
 #ifdef DEBUG
   Matrix GetTransform()
   {
     cairo_matrix_t mat;
     cairo_get_matrix(mCtx, &mat);
     return Matrix(mat.xx, mat.yx, mat.xy, mat.yy, mat.x0, mat.y0);
@@ -1285,16 +1292,23 @@ DrawTargetCairo::CreateSimilarDrawTarget
 bool
 DrawTargetCairo::InitAlreadyReferenced(cairo_surface_t* aSurface, const IntSize& aSize, SurfaceFormat* aFormat)
 {
   mContext = cairo_create(aSurface);
   mSurface = aSurface;
   mSize = aSize;
   mFormat = aFormat ? *aFormat : CairoContentToGfxFormat(cairo_surface_get_content(aSurface));
 
+  // Cairo image surface have a bug where they will allocate a mask surface (for clipping)
+  // the size of the clip extents, and don't take the surface extents into account.
+  // Add a manual clip to the surface extents to prevent this.
+  cairo_new_path(mContext);
+  cairo_rectangle(mContext, 0, 0, mSize.width, mSize.height);
+  cairo_clip(mContext);
+
   if (mFormat == SurfaceFormat::B8G8R8A8 ||
       mFormat == SurfaceFormat::R8G8B8A8) {
     SetPermitSubpixelAA(false);
   } else {
     SetPermitSubpixelAA(true);
   }
 
   return true;