Bug 1034593 - Prevent clips with huge extents to be passed to a cairo context from CanvasRenderingContext2D. r=jrmuizel, a=sledru
authorNicolas Silva <nsilva@mozilla.com>
Fri, 18 Jul 2014 04:15:00 -0400
changeset 209169 589fd10b25751e0a6e5eda5b719994a88ee947b2
parent 209168 7da62c51fa9742e1f9590b5a0363199c04271d48
child 209170 ea0e9e117349d70184a4736f7c05eeecb813cdba
push id494
push userraliiev@mozilla.com
push dateMon, 25 Aug 2014 18:42:16 +0000
treeherdermozilla-release@a3cc3e46b571 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel, sledru
bugs1034593
milestone32.0a2
Bug 1034593 - Prevent clips with huge extents to be passed to a cairo context from CanvasRenderingContext2D. r=jrmuizel, a=sledru
content/canvas/src/CanvasRenderingContext2D.cpp
--- a/content/canvas/src/CanvasRenderingContext2D.cpp
+++ b/content/canvas/src/CanvasRenderingContext2D.cpp
@@ -958,16 +958,25 @@ CanvasRenderingContext2D::EnsureTarget()
 
     gCanvasAzureMemoryUsed += mWidth * mHeight * 4;
     JSContext* context = nsContentUtils::GetCurrentJSContext();
     if (context) {
       JS_updateMallocCounter(context, mWidth * mHeight * 4);
     }
 
     mTarget->ClearRect(mgfx::Rect(Point(0, 0), Size(mWidth, mHeight)));
+    if (mTarget->GetType() == mgfx::BackendType::CAIRO) {
+      // Cairo doesn't play well with huge clips. When given a very big clip it
+      // will try to allocate big mask surface without taking the target
+      // size into account which can cause OOM. See bug 1034593.
+      // This limits the clip extents to the size of the canvas.
+      // A fix in Cairo would probably be preferable, but requires somewhat
+      // invasive changes.
+      mTarget->PushClipRect(mgfx::Rect(Point(0, 0), Size(mWidth, mHeight)));
+    }
     // Force a full layer transaction since we didn't have a layer before
     // and now we might need one.
     if (mCanvasElement) {
       mCanvasElement->InvalidateCanvas();
     }
     // Calling Redraw() tells our invalidation machinery that the entire
     // canvas is already invalid, which can speed up future drawing.
     Redraw();
@@ -1045,16 +1054,21 @@ CanvasRenderingContext2D::InitializeWith
   mTarget = gfxPlatform::GetPlatform()->
     CreateDrawTargetForSurface(surface, IntSize(width, height));
 
   if (!mTarget) {
     EnsureErrorTarget();
     mTarget = sErrorTarget;
   }
 
+  if (mTarget->GetType() == mgfx::BackendType::CAIRO) {
+    // Cf comment in EnsureTarget
+    mTarget->PushClipRect(mgfx::Rect(Point(0, 0), Size(mWidth, mHeight)));
+  }
+
   return NS_OK;
 }
 
 NS_IMETHODIMP
 CanvasRenderingContext2D::SetIsOpaque(bool isOpaque)
 {
   if (isOpaque != mOpaque) {
     mOpaque = isOpaque;