Backout bug 781731.
authorMs2ger <ms2ger@gmail.com>
Mon, 27 Aug 2012 12:27:40 +0200
changeset 105589 a8f183cf4b38272152dac2a43819592406ec54a6
parent 105588 cd5eb6f6f4954a83fb37ec064b0c8e09d8750463
child 105590 8b22f48262d184975d3be62ad3078a7129f4a53c
push id55
push usershu@rfrn.org
push dateThu, 30 Aug 2012 01:33:09 +0000
bugs781731
milestone17.0a1
Backout bug 781731.
content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
gfx/2d/2D.h
gfx/2d/Blur.cpp
gfx/2d/Blur.h
gfx/2d/DrawTargetCairo.cpp
gfx/2d/DrawTargetCairo.h
gfx/thebes/gfxPlatform.cpp
--- a/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
+++ b/content/canvas/src/nsCanvasRenderingContext2DAzure.cpp
@@ -282,18 +282,17 @@ public:
     if (mSigma > SIGMA_MAX) {
       mSigma = SIGMA_MAX;
     }
       
     Matrix transform = mCtx->mTarget->GetTransform();
 
     mTempRect = mgfx::Rect(0, 0, ctx->mWidth, ctx->mHeight);
 
-    static const gfxFloat GAUSSIAN_SCALE_FACTOR = (3 * sqrt(2 * M_PI) / 4) * 1.5;
-    int32_t blurRadius = (int32_t) floor(mSigma * GAUSSIAN_SCALE_FACTOR + 0.5);
+    Float blurRadius = mSigma * 3;
 
     // We need to enlarge and possibly offset our temporary surface
     // so that things outside of the canvas may cast shadows.
     mTempRect.Inflate(Margin(blurRadius + NS_MAX<Float>(state.shadowOffset.x, 0),
                              blurRadius + NS_MAX<Float>(state.shadowOffset.y, 0),
                              blurRadius + NS_MAX<Float>(-state.shadowOffset.x, 0),
                              blurRadius + NS_MAX<Float>(-state.shadowOffset.y, 0)));
 
@@ -301,31 +300,24 @@ public:
       // We actually include the bounds of the shadow blur, this makes it
       // easier to execute the actual blur on hardware, and shouldn't affect
       // the amount of pixels that need to be touched.
       aBounds->Inflate(Margin(blurRadius, blurRadius,
                               blurRadius, blurRadius));
       mTempRect = mTempRect.Intersect(*aBounds);
     }
 
-    // Nothing to draw
-    if (mTempRect.IsEmpty()) {
-      mTarget = ctx->mTarget;
-      mCtx = nullptr;
-      return;
-    }
-
     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, mSigma);
+      mCtx->mTarget->CreateSimilarDrawTarget(IntSize(int32_t(mTempRect.width), int32_t(mTempRect.height)),
+                                             FORMAT_B8G8R8A8);
 
     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);
@@ -3105,28 +3097,27 @@ struct NS_STACK_CLASS nsCanvasBidiProces
       if (!glyphBuf.size()) {
         // This may happen for glyph runs for a 0 size font.
         continue;
       }
 
       buffer.mGlyphs = &glyphBuf.front();
       buffer.mNumGlyphs = glyphBuf.size();
 
-      Rect bounds(mBoundingBox.x, mBoundingBox.y, mBoundingBox.width, mBoundingBox.height);
       if (mOp == nsCanvasRenderingContext2DAzure::TEXT_DRAW_OPERATION_FILL) {
-        AdjustedTarget(mCtx, &bounds)->
+        AdjustedTarget(mCtx)->
           FillGlyphs(scaledFont, buffer,
                      CanvasGeneralPattern().
                        ForStyle(mCtx, nsCanvasRenderingContext2DAzure::STYLE_FILL, mCtx->mTarget),
                      DrawOptions(mState->globalAlpha, mCtx->UsedOperation()));
       } else if (mOp == nsCanvasRenderingContext2DAzure::TEXT_DRAW_OPERATION_STROKE) {
         RefPtr<Path> path = scaledFont->GetPathForGlyphs(buffer, mCtx->mTarget);
 
         const ContextState& state = *mState;
-        AdjustedTarget(mCtx, &bounds)->
+        AdjustedTarget(mCtx)->
           Stroke(path, CanvasGeneralPattern().
                    ForStyle(mCtx, nsCanvasRenderingContext2DAzure::STYLE_STROKE, mCtx->mTarget),
                  StrokeOptions(state.lineWidth, state.lineJoin,
                                state.lineCap, state.miterLimit,
                                state.dash.Length(),
                                state.dash.Elements(),
                                state.dashOffset),
                  DrawOptions(state.globalAlpha, mCtx->UsedOperation()));
--- a/gfx/2d/2D.h
+++ b/gfx/2d/2D.h
@@ -723,31 +723,16 @@ 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,
-                           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.
    * ID2D1SimplifiedGeometrySink requires the fill mode
    * to be set before calling BeginFigure().
    */
   virtual TemporaryRef<PathBuilder> CreatePathBuilder(FillRule aFillRule = FILL_WINDING) const = 0;
 
--- a/gfx/2d/Blur.cpp
+++ b/gfx/2d/Blur.cpp
@@ -325,18 +325,17 @@ RoundUpToMultipleOf4(int32_t aVal)
 
 AlphaBoxBlur::AlphaBoxBlur(const Rect& aRect,
                            const IntSize& aSpreadRadius,
                            const IntSize& aBlurRadius,
                            const Rect* aDirtyRect,
                            const Rect* aSkipRect)
  : mSpreadRadius(aSpreadRadius),
    mBlurRadius(aBlurRadius),
-   mData(nullptr),
-   mFreeData(true)
+   mData(nullptr)
 {
   Rect rect(aRect);
   rect.Inflate(Size(aBlurRadius + aSpreadRadius));
   rect.RoundOut();
 
   if (aDirtyRect) {
     // If we get passed a dirty rect from layout, we can minimize the
     // shadow size and make painting faster.
@@ -380,35 +379,19 @@ AlphaBoxBlur::AlphaBoxBlur(const Rect& a
                                sizeof(unsigned char);
     if (size.isValid()) {
       mData = static_cast<unsigned char*>(malloc(size.value()));
       memset(mData, 0, size.value());
     }
   }
 }
 
-AlphaBoxBlur::AlphaBoxBlur(uint8_t* aData,
-                           const Rect& aRect,
-                           int32_t aStride,
-                           float aSigma)
-  : mSpreadRadius(),
-    mBlurRadius(CalculateBlurRadius(Point(aSigma, aSigma))),
-    mData(aData),
-    mFreeData(false),
-    mStride(aStride),
-    mRect(aRect.x, aRect.y, aRect.width, aRect.height)
-{
-}
-
-
 AlphaBoxBlur::~AlphaBoxBlur()
 {
-  if (mFreeData) {
-    delete mData;
-  }
+  free(mData);
 }
 
 unsigned char*
 AlphaBoxBlur::GetData()
 {
   return mData;
 }
 
--- a/gfx/2d/Blur.h
+++ b/gfx/2d/Blur.h
@@ -52,21 +52,16 @@ public:
    *   speed reasons. It is safe to pass nullptr here.
    */
   AlphaBoxBlur(const Rect& aRect,
                const IntSize& aSpreadRadius,
                const IntSize& aBlurRadius,
                const Rect* aDirtyRect,
                const Rect* aSkipRect);
 
-  AlphaBoxBlur(uint8_t* aData,
-               const Rect& aRect,
-               int32_t aStride,
-               float aSigma);
-
   ~AlphaBoxBlur();
 
   /**
    * Return the pointer to memory allocated by the constructor for the 8-bit
    * alpha surface you need to be blurred. After you draw to this surface, call
    * Blur(), below, to have its contents blurred.
    */
   unsigned char* GetData();
@@ -135,22 +130,17 @@ private:
   /**
    * The blur radius, in pixels.
    */
   IntSize mBlurRadius;
 
   /**
    * A pointer to the backing 8-bit alpha surface.
    */
-  uint8_t* mData;
-
-  /**
-   * True if we need to dispose the data.
-   */
-  bool mFreeData;
+  unsigned char* mData;
 
   /**
    * The stride of the data contained in mData.
    */
   int32_t mStride;
 
   /**
    * Whether mDirtyRect contains valid data.
--- a/gfx/2d/DrawTargetCairo.cpp
+++ b/gfx/2d/DrawTargetCairo.cpp
@@ -6,17 +6,16 @@
 #include "DrawTargetCairo.h"
 
 #include "SourceSurfaceCairo.h"
 #include "PathCairo.h"
 #include "HelpersCairo.h"
 #include "ScaledFontBase.h"
 
 #include "cairo.h"
-#include "cairo-tee.h"
 #include <string.h>
 
 #include "Blur.h"
 #include "Logging.h"
 #include "Tools.h"
 
 #ifdef CAIRO_HAS_QUARTZ_SURFACE
 #include "cairo-quartz.h"
@@ -383,75 +382,96 @@ DrawTargetCairo::DrawSurfaceWithShadow(S
                                        const Point &aOffset,
                                        Float aSigma,
                                        CompositionOp aOperator)
 {
   if (aSurface->GetType() != SURFACE_CAIRO) {
     return;
   }
 
+  WillChange();
+
   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_surface_t* surf;
+  Rect extents(0, 0, width, height);
 
-  // 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;
+  AlphaBoxBlur blur(extents, IntSize(0, 0),
+                    AlphaBoxBlur::CalculateBlurRadius(Point(aSigma, aSigma)),
+                    nullptr, nullptr);
+  if (!blur.GetData()) {
+    return;
   }
 
-  WillChange();
+  IntSize blursize = blur.GetSize();
+  cairo_surface_t* blursurf = cairo_image_surface_create_for_data(blur.GetData(),
+                                                                  CAIRO_FORMAT_A8,
+                                                                  blursize.width,
+                                                                  blursize.height,
+                                                                  blur.GetStride());
+
   ClearSurfaceForUnboundedSource(aOperator);
   
+  // Draw the source surface into the surface we're going to blur.
+  SourceSurfaceCairo* source = static_cast<SourceSurfaceCairo*>(aSurface);
+  cairo_surface_t* surf = source->GetSurface();
+  cairo_pattern_t* pat = cairo_pattern_create_for_surface(surf);
+  cairo_pattern_set_extend(pat, CAIRO_EXTEND_PAD);
+
+  cairo_t* ctx = cairo_create(blursurf);
+
+  cairo_set_source(ctx, pat);
+
+  IntRect blurrect = blur.GetRect();
+  cairo_new_path(ctx);
+  cairo_rectangle(ctx, blurrect.x, blurrect.y, blurrect.width, blurrect.height);
+  cairo_clip(ctx);
+  cairo_paint(ctx);
+
+  cairo_destroy(ctx);
+
+  // Blur the result, then use that blurred result as a mask to draw the shadow
+  // colour to the surface.
+  blur.Blur();
   cairo_save(mContext);
   cairo_set_operator(mContext, GfxOpToCairoOp(aOperator));
   cairo_identity_matrix(mContext);
   cairo_translate(mContext, aDest.x, aDest.y);
 
   if (OperatorAffectsUncoveredAreas(aOperator) ||
       aOperator == OP_SOURCE){
     cairo_push_group(mContext);
       cairo_set_source_rgba(mContext, aColor.r, aColor.g, aColor.b, aColor.a);
       cairo_mask_surface(mContext, blursurf, aOffset.x, aOffset.y);
+    cairo_pop_group_to_source(mContext);
+    cairo_paint(mContext);
 
-      // Now that the shadow has been drawn, we can draw the surface on top.
-      cairo_set_source_surface(mContext, surf, 0, 0);
+    // Now that the shadow has been drawn, we can draw the surface on top.
+    cairo_push_group(mContext);
       cairo_new_path(mContext);
       cairo_rectangle(mContext, 0, 0, width, height);
+      cairo_set_source(mContext, pat);
       cairo_fill(mContext);
     cairo_pop_group_to_source(mContext);
-    cairo_paint(mContext);
   } else {
     cairo_set_source_rgba(mContext, aColor.r, aColor.g, aColor.b, aColor.a);
     cairo_mask_surface(mContext, blursurf, aOffset.x, aOffset.y);
 
     // Now that the shadow has been drawn, we can draw the surface on top.
-    cairo_set_source_surface(mContext, surf, 0, 0);
+    cairo_set_source(mContext, pat);
     cairo_new_path(mContext);
     cairo_rectangle(mContext, 0, 0, width, height);
-    cairo_fill(mContext);
+    cairo_clip(mContext);
   }
 
+  cairo_paint(mContext);
+
   cairo_restore(mContext);
+
+  cairo_pattern_destroy(pat);
+  cairo_surface_destroy(blursurf);
 }
 
 void
 DrawTargetCairo::DrawPattern(const Pattern& aPattern,
                              const StrokeOptions& aStrokeOptions,
                              const DrawOptions& aOptions,
                              DrawPatternType aDrawType)
 {
@@ -796,59 +816,16 @@ DrawTargetCairo::InitAlreadyReferenced(c
   mContext = cairo_create(aSurface);
   mSurface = aSurface;
   mSize = aSize;
   mFormat = CairoContentToGfxFormat(cairo_surface_get_content(aSurface));
 
   return true;
 }
 
-TemporaryRef<DrawTarget>
-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;
-  }
-
-  cairo_surface_t* tee = cairo_tee_surface_create(blursurf);
-  cairo_surface_destroy(blursurf);
-  if (cairo_surface_status(tee)) {
-    cairo_surface_destroy(similar);
-    return nullptr;
-  }
-
-  cairo_tee_surface_add(tee, similar);
-  cairo_surface_destroy(similar);
-
-  RefPtr<DrawTargetCairo> target = new DrawTargetCairo();
-  target->InitAlreadyReferenced(tee, aSize);
-  return target;
-}
-
 bool
 DrawTargetCairo::Init(cairo_surface_t* aSurface, const IntSize& aSize)
 {
   cairo_surface_reference(aSurface);
   return InitAlreadyReferenced(aSurface, aSize);
 }
 
 void *
--- a/gfx/2d/DrawTargetCairo.h
+++ b/gfx/2d/DrawTargetCairo.h
@@ -110,19 +110,16 @@ public:
                                                             const IntSize &aSize,
                                                             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,
-                           float aSigma) const;
 
   virtual TemporaryRef<GradientStops>
     CreateGradientStops(GradientStop *aStops,
                         uint32_t aNumStops,
                         ExtendMode aExtendMode = EXTEND_CLAMP) const;
 
   virtual void *GetNativeSurface(NativeSurfaceType aType);
 
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -530,31 +530,18 @@ gfxPlatform::GetSourceSurfaceForSurface(
     surf.mFormat = format;
     surf.mType = NATIVE_SURFACE_D3D10_TEXTURE;
     surf.mSurface = static_cast<gfxD2DSurface*>(aSurface)->GetTexture();
     mozilla::gfx::DrawTarget *dt = static_cast<mozilla::gfx::DrawTarget*>(aSurface->GetData(&kDrawTarget));
     if (dt) {
       dt->Flush();
     }
     srcBuffer = aTarget->CreateSourceSurfaceFromNativeSurface(surf);
-  } else
+  }
 #endif
-  if (aSurface->CairoSurface()) {
-    // If this is an xlib cairo surface we don't want to fetch it into memory
-    // because this is a major slow down.
-    NativeSurface surf;
-    surf.mFormat = format;
-    surf.mType = NATIVE_SURFACE_CAIRO_SURFACE;
-    surf.mSurface = aSurface->CairoSurface();
-    srcBuffer = aTarget->CreateSourceSurfaceFromNativeSurface(surf);
-
-    // It's cheap enough to make a new one so we won't keep it around and
-    // keeping it creates a cycle.
-    return srcBuffer;
-  }
 
   if (!srcBuffer) {
     nsRefPtr<gfxImageSurface> imgSurface = aSurface->GetAsImageSurface();
 
     bool isWin32ImageSurf = imgSurface &&
                             aSurface->GetType() == gfxASurface::SurfaceTypeWin32;
 
     if (!imgSurface) {