Bug 781731 - Use a similar surface for non-blurred shadows to improve performance. r=joe
authorAnthony Jones <ajones@mozilla.com>
Sun, 02 Sep 2012 19:07:06 -0400
changeset 104132 6c66c399738180c890c19903da1e2b4f0b110dea
parent 104131 07c5d694b7f3c618de1e8f6ab1fa41a9a58a853a
child 104133 1272677b5816bedb28fa2f97dab65d29bf5f2f8b
child 104150 059f341beaad5f8595bccf02281b6ad645d02382
push id14344
push userryanvm@gmail.com
push dateSun, 02 Sep 2012 23:06:51 +0000
treeherdermozilla-inbound@6c66c3997381 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjoe
bugs781731
milestone18.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 781731 - Use a similar surface for non-blurred shadows to improve performance. r=joe
content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
gfx/2d/2D.h
gfx/2d/DrawTargetCairo.cpp
gfx/2d/DrawTargetCairo.h
--- a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
@@ -308,17 +308,17 @@ public:
 
     mTempRect.ScaleRoundOut(1.0f);
 
     transform._31 -= mTempRect.x;
     transform._32 -= mTempRect.y;
       
     mTarget =
       mCtx->mTarget->CreateShadowDrawTarget(IntSize(int32_t(mTempRect.width), int32_t(mTempRect.height)),
-                                             FORMAT_B8G8R8A8);
+                                             FORMAT_B8G8R8A8, mSigma);
 
     if (!mTarget) {
       // XXX - Deal with the situation where our temp size is too big to
       // fit in a texture.
       mTarget = ctx->mTarget;
       mCtx = nullptr;
     } else {
       mTarget->SetTransform(transform);
--- a/gfx/2d/2D.h
+++ b/gfx/2d/2D.h
@@ -724,19 +724,25 @@ public:
   /*
    * Create a DrawTarget whose snapshot is optimized for use with this DrawTarget.
    */
   virtual TemporaryRef<DrawTarget>
     CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const = 0;
 
   /*
    * Create a draw target optimized for drawing a shadow.
+   *
+   * Note that aSigma is the blur radius that must be used when we draw the
+   * shadow. Also note that this doesn't affect the size of the allocated
+   * surface, the caller is still responsible for including the shadow area in
+   * its size.
    */
   virtual TemporaryRef<DrawTarget>
-    CreateShadowDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const
+    CreateShadowDrawTarget(const IntSize &aSize, SurfaceFormat aFormat,
+                           float aSigma) const
   {
     return CreateSimilarDrawTarget(aSize, aFormat);
   }
 
   /*
    * Create a path builder with the specified fillmode.
    *
    * We need the fill mode up front because of Direct2D.
--- a/gfx/2d/DrawTargetCairo.cpp
+++ b/gfx/2d/DrawTargetCairo.cpp
@@ -388,26 +388,36 @@ DrawTargetCairo::DrawSurfaceWithShadow(S
     return;
   }
 
   Float width = aSurface->GetSize().width;
   Float height = aSurface->GetSize().height;
  
   SourceSurfaceCairo* source = static_cast<SourceSurfaceCairo*>(aSurface);
   cairo_surface_t* sourcesurf = source->GetSurface();
-  cairo_surface_t* blursurf = cairo_tee_surface_index(sourcesurf, 0);
-  cairo_surface_t* surf = cairo_tee_surface_index(sourcesurf, 1);
- 
-  MOZ_ASSERT(cairo_surface_get_type(blursurf) == CAIRO_SURFACE_TYPE_IMAGE);
-  Rect extents(0, 0, width, height);
-  AlphaBoxBlur blur(cairo_image_surface_get_data(blursurf),
-                    extents,
-                    cairo_image_surface_get_stride(blursurf),
-                    aSigma);
-  blur.Blur();
+  cairo_surface_t* blursurf;
+  cairo_surface_t* surf;
+
+  // We only use the A8 surface for blurred shadows. Unblurred shadows can just
+  // use the RGBA surface directly.
+  if (cairo_surface_get_type(sourcesurf) == CAIRO_SURFACE_TYPE_TEE) {
+    blursurf = cairo_tee_surface_index(sourcesurf, 0);
+    surf = cairo_tee_surface_index(sourcesurf, 1);
+
+    MOZ_ASSERT(cairo_surface_get_type(blursurf) == CAIRO_SURFACE_TYPE_IMAGE);
+    Rect extents(0, 0, width, height);
+    AlphaBoxBlur blur(cairo_image_surface_get_data(blursurf),
+                      extents,
+                      cairo_image_surface_get_stride(blursurf),
+                      aSigma);
+    blur.Blur();
+  } else {
+    blursurf = sourcesurf;
+    surf = sourcesurf;
+  }
 
   WillChange();
   ClearSurfaceForUnboundedSource(aOperator);
   
   cairo_save(mContext);
   cairo_set_operator(mContext, GfxOpToCairoOp(aOperator));
   cairo_identity_matrix(mContext);
   cairo_translate(mContext, aDest.x, aDest.y);
@@ -787,26 +797,35 @@ DrawTargetCairo::InitAlreadyReferenced(c
   mSurface = aSurface;
   mSize = aSize;
   mFormat = CairoContentToGfxFormat(cairo_surface_get_content(aSurface));
 
   return true;
 }
 
 TemporaryRef<DrawTarget>
-DrawTargetCairo::CreateShadowDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const
+DrawTargetCairo::CreateShadowDrawTarget(const IntSize &aSize, SurfaceFormat aFormat,
+                                        float aSigma) const
 {
   cairo_surface_t* similar = cairo_surface_create_similar(cairo_get_target(mContext),
                                                           GfxFormatToCairoContent(aFormat),
                                                           aSize.width, aSize.height);
 
   if (cairo_surface_status(similar)) {
     return nullptr;
   }
 
+  // If we don't have a blur then we can use the RGBA mask and keep all the
+  // operations in graphics memory.
+  if (aSigma == 0.0F) {
+    RefPtr<DrawTargetCairo> target = new DrawTargetCairo();
+    target->InitAlreadyReferenced(similar, aSize);
+    return target;
+  }
+
   cairo_surface_t* blursurf = cairo_image_surface_create(CAIRO_FORMAT_A8,
                                                          aSize.width,
                                                          aSize.height);
 
   if (cairo_surface_status(blursurf)) {
     return nullptr;
   }
 
--- a/gfx/2d/DrawTargetCairo.h
+++ b/gfx/2d/DrawTargetCairo.h
@@ -111,17 +111,18 @@ public:
                                                             int32_t aStride,
                                                             SurfaceFormat aFormat) const;
   virtual TemporaryRef<SourceSurface> OptimizeSourceSurface(SourceSurface *aSurface) const;
   virtual TemporaryRef<SourceSurface>
     CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const;
   virtual TemporaryRef<DrawTarget>
     CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const;
   virtual TemporaryRef<DrawTarget>
-    CreateShadowDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const;
+    CreateShadowDrawTarget(const IntSize &aSize, SurfaceFormat aFormat,
+                           float aSigma) const;
 
   virtual TemporaryRef<GradientStops>
     CreateGradientStops(GradientStop *aStops,
                         uint32_t aNumStops,
                         ExtendMode aExtendMode = EXTEND_CLAMP) const;
 
   virtual void *GetNativeSurface(NativeSurfaceType aType);