Backout bug 629799 due to reftest permaorange causing a=CLOSED TREE
authorMarco Bonardo <mbonardo@mozilla.com>
Wed, 09 Feb 2011 19:16:29 +0100
changeset 62225 548c6fb45f53cc846e7327a6ee8d260d0a9f197f
parent 62224 62335c50673bca960c7542aab58f4f0950c01e21
child 62228 c99cefaa4c8e0cff713fd9ef3a30c5b11fc2eee3
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersCLOSED
bugs629799
milestone2.0b12pre
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
Backout bug 629799 due to reftest permaorange causing a=CLOSED TREE
dom/plugins/PluginInstanceChild.cpp
gfx/ipc/SharedDIBWin.cpp
gfx/thebes/gfxAlphaRecovery.h
gfx/thebes/gfxAlphaRecoverySSE2.cpp
gfx/thebes/gfxImageSurface.cpp
--- a/dom/plugins/PluginInstanceChild.cpp
+++ b/dom/plugins/PluginInstanceChild.cpp
@@ -2533,18 +2533,18 @@ PluginInstanceChild::UpdateWindowAttribu
         }
     }
 #endif // MAEMO
 #endif // MOZ_X11
 #ifdef XP_WIN
     HDC dc = NULL;
 
     if (curSurface) {
-        if (!SharedDIBSurface::IsSharedDIBSurface(curSurface))
-            NS_RUNTIMEABORT("Expected SharedDIBSurface!");
+        NS_ASSERTION(SharedDIBSurface::IsSharedDIBSurface(curSurface),
+                     "Expected (SharedDIB) image surface.");
 
         SharedDIBSurface* dibsurf = static_cast<SharedDIBSurface*>(curSurface.get());
         dc = dibsurf->GetHDC();
     }
     if (mWindow.window != dc) {
         mWindow.window = dc;
         needWindowUpdate = true;
     }
@@ -2755,110 +2755,56 @@ PluginInstanceChild::PaintRectToSurface(
         ctx->Fill();
     }
 }
 
 void
 PluginInstanceChild::PaintRectWithAlphaExtraction(const nsIntRect& aRect,
                                                   gfxASurface* aSurface)
 {
-    NS_ABORT_IF_FALSE(aSurface->GetContentType() == gfxASurface::CONTENT_COLOR_ALPHA,
-                      "Refusing to pointlessly recover alpha");
-
-    nsIntRect rect(aRect);
-    // If |aSurface| can be used to paint and can have alpha values
-    // recovered directly to it, do that to save a tmp surface and
-    // copy.
-    bool useSurfaceSubimageForBlack = false;
-    if (gfxASurface::SurfaceTypeImage == aSurface->GetType()) {
-        gfxImageSurface* surfaceAsImage =
-            static_cast<gfxImageSurface*>(aSurface);
-        useSurfaceSubimageForBlack =
-            (surfaceAsImage->Format() == gfxASurface::ImageFormatARGB32);
-        // If we're going to use a subimage, nudge the rect so that we
-        // can use optimal alpha recovery.  If we're not using a
-        // subimage, the temporaries should automatically get
-        // fast-path alpha recovery so we don't need to do anything.
-        if (useSurfaceSubimageForBlack) {
-            rect =
-                gfxAlphaRecovery::AlignRectForSubimageRecovery(aRect,
-                                                               surfaceAsImage);
+    // Paint onto black image
+    bool needImageSurface = true;
+    nsRefPtr<gfxImageSurface> blackImage;
+    gfxIntSize clipSize(aRect.width, aRect.height);
+    gfxPoint deviceOffset(-aRect.x, -aRect.y);
+    // Try to re-use existing image surface, and avoid one copy
+    if (aSurface->GetType() == gfxASurface::SurfaceTypeImage) {
+        gfxImageSurface *surface = static_cast<gfxImageSurface*>(aSurface);
+        if (surface->Format() == gfxASurface::ImageFormatARGB32) {
+            needImageSurface = false;
+            blackImage = surface->GetSubimage(GfxFromNsRect(aRect));
         }
     }
-
-    nsRefPtr<gfxImageSurface> whiteImage;
-    nsRefPtr<gfxImageSurface> blackImage;
-    gfxRect targetRect(rect.x, rect.y, rect.width, rect.height);
-    gfxIntSize targetSize(rect.width, rect.height);
-    gfxPoint deviceOffset = -targetRect.pos;
-
-    // We always use a temporary "white image"
-    whiteImage = new gfxImageSurface(targetSize, gfxASurface::ImageFormatRGB24);
-
-#ifdef XP_WIN
-    // On windows, we need an HDC and so can't paint directly to
-    // vanilla image surfaces.  Bifurcate this painting code so that
-    // we don't accidentally attempt that.
-    if (!SharedDIBSurface::IsSharedDIBSurface(aSurface))
-        NS_RUNTIMEABORT("Expected SharedDIBSurface!");
-
-    // Paint the plugin directly onto the target, with a white
-    // background and copy the result
-    PaintRectToSurface(rect, aSurface, gfxRGBA(1.0, 1.0, 1.0));
-    {
-        gfxRect copyRect(gfxPoint(0, 0), targetRect.size);
-        nsRefPtr<gfxContext> ctx = new gfxContext(whiteImage);
-        ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
-        ctx->SetSource(aSurface, deviceOffset);
-        ctx->Rectangle(copyRect);
-        ctx->Fill();
+    // otherwise create new helper surface
+    if (needImageSurface) {
+        blackImage = new gfxImageSurface(clipSize, gfxASurface::ImageFormatARGB32);
     }
 
-    // Paint the plugin directly onto the target, with a black
-    // background
-    PaintRectToSurface(rect, aSurface, gfxRGBA(0.0, 0.0, 0.0));
-
-    // Don't copy the result, just extract a subimage so that we can
-    // recover alpha directly into the target
-    gfxImageSurface *image = static_cast<gfxImageSurface*>(aSurface);
-    blackImage = image->GetSubimage(targetRect);
-
-#else
-    // Paint onto white background
+    // Paint to black image
+    blackImage->SetDeviceOffset(deviceOffset);
+    PaintRectToSurface(aRect, blackImage, gfxRGBA(0.0, 0.0, 0.0));
+
+    // Paint onto white image
+    nsRefPtr<gfxImageSurface> whiteImage =
+        new gfxImageSurface(clipSize, gfxASurface::ImageFormatRGB24);
+
     whiteImage->SetDeviceOffset(deviceOffset);
-    PaintRectToSurface(rect, whiteImage, gfxRGBA(1.0, 1.0, 1.0));
-
-    if (useSurfaceSubimageForBlack) {
-        gfxImageSurface *surface = static_cast<gfxImageSurface*>(aSurface);
-        blackImage = surface->GetSubimage(targetRect);
-    } else {
-        blackImage = new gfxImageSurface(targetSize,
-                                         gfxASurface::ImageFormatARGB32);
-    }
-
-    // Paint onto black background
-    blackImage->SetDeviceOffset(deviceOffset);
-    PaintRectToSurface(rect, blackImage, gfxRGBA(0.0, 0.0, 0.0));
-#endif
-
-    NS_ABORT_IF_FALSE(whiteImage && blackImage, "Didn't paint enough!");
-
-    // Extract alpha from black and white image and store to black
-    // image
-    if (!gfxAlphaRecovery::RecoverAlpha(blackImage, whiteImage)) {
+    PaintRectToSurface(aRect, whiteImage, gfxRGBA(1.0, 1.0, 1.0));
+
+    // Extract Alpha from black and white image and store to black Image
+    gfxRect rect(aRect.x, aRect.y, aRect.width, aRect.height);
+    if (!gfxAlphaRecovery::RecoverAlpha(blackImage, whiteImage, nsnull)) {
         return;
     }
 
-    // If we had to use a temporary black surface, copy the pixels
-    // with alpha back to the target
-    if (!useSurfaceSubimageForBlack) {
+    if (needImageSurface) {
         nsRefPtr<gfxContext> ctx = new gfxContext(aSurface);
         ctx->SetOperator(gfxContext::OPERATOR_SOURCE);
         ctx->SetSource(blackImage);
-        ctx->Rectangle(targetRect);
+        ctx->Rectangle(GfxFromNsRect(aRect));
         ctx->Fill();
     }
 }
 
 bool
 PluginInstanceChild::ShowPluginFrame()
 {
     if (mPendingPluginCall) {
--- a/gfx/ipc/SharedDIBWin.cpp
+++ b/gfx/ipc/SharedDIBWin.cpp
@@ -32,27 +32,23 @@
  * decision by deleting the provisions above and replace them with the notice
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "SharedDIBWin.h"
-#include "gfxAlphaRecovery.h"
 #include "nsMathUtils.h"
 #include "nsDebug.h"
 
 namespace mozilla {
 namespace gfx {
 
 static const PRUint32 kBytesPerPixel = 4;
-static const PRUint32 kByteAlign = 1 << gfxAlphaRecovery::GoodAlignmentLog2();
-static const PRUint32 kHeaderBytes =
-  (sizeof(BITMAPV4HEADER) + kByteAlign - 1) & ~(kByteAlign - 1);
 
 SharedDIBWin::SharedDIBWin() :
     mSharedHdc(nsnull)
   , mSharedBmp(nsnull)
   , mOldObj(nsnull)
 {
 }
 
@@ -139,33 +135,33 @@ SharedDIBWin::SetupBitmapHeader(PRUint32
   aHeader->bV4V4Compression = BI_BITFIELDS;
   aHeader->bV4RedMask       = 0x00FF0000;
   aHeader->bV4GreenMask     = 0x0000FF00;
   aHeader->bV4BlueMask      = 0x000000FF;
 
   if (aTransparent)
     aHeader->bV4AlphaMask     = 0xFF000000;
 
-  return (kHeaderBytes + (-aHeader->bV4Height * aHeader->bV4Width * kBytesPerPixel));
+  return (sizeof(BITMAPV4HEADER) + (-aHeader->bV4Height * aHeader->bV4Width * kBytesPerPixel));
 }
 
 nsresult
 SharedDIBWin::SetupSurface(HDC aHdc, BITMAPV4HEADER *aHdr)
 {
   mSharedHdc = ::CreateCompatibleDC(aHdc);
 
   if (!mSharedHdc)
     return NS_ERROR_FAILURE;
 
   mSharedBmp = ::CreateDIBSection(mSharedHdc,
                                   (BITMAPINFO*)aHdr,
                                   DIB_RGB_COLORS,
                                   &mBitmapBits,
                                   mShMem->handle(),
-                                  kHeaderBytes);
+                                  (unsigned long)sizeof(BITMAPV4HEADER));
   if (!mSharedBmp)
     return NS_ERROR_FAILURE;
 
   mOldObj = SelectObject(mSharedHdc, mSharedBmp);
 
   return NS_OK;
 }
 
--- a/gfx/thebes/gfxAlphaRecovery.h
+++ b/gfx/thebes/gfxAlphaRecovery.h
@@ -36,72 +36,43 @@
  * ***** END LICENSE BLOCK ***** */
 
 #ifndef _GFXALPHARECOVERY_H_
 #define _GFXALPHARECOVERY_H_
 
 #include "gfxContext.h"
 #include "gfxImageSurface.h"
 #include "mozilla/SSE.h"
-#include "nsRect.h"
 
 class THEBES_API gfxAlphaRecovery {
 public:
     struct Analysis {
         PRBool uniformColor;
         PRBool uniformAlpha;
         gfxFloat alpha;
         gfxFloat r, g, b;
     };
 
-    /**
-     * Some SIMD fast-paths only can be taken if the relative
-     * byte-alignment of images' pointers and strides meets certain
-     * criteria.  Aligning image pointers and strides by
-     * |GoodAlignmentLog2()| below will ensure that fast-paths aren't
-     * skipped because of misalignment.  Fast-paths may still be taken
-     * even if GoodAlignmentLog2() is not met, in some conditions.
-     */
-    static PRUint32 GoodAlignmentLog2() { return 4; /* for SSE2 */ }
-
     /* Given two surfaces of equal size with the same rendering, one onto a
      * black background and the other onto white, recovers alpha values from
      * the difference and sets the alpha values on the black surface.
      * The surfaces must have format RGB24 or ARGB32.
      * Returns PR_TRUE on success.
      */
     static PRBool RecoverAlpha (gfxImageSurface *blackSurface,
                                 const gfxImageSurface *whiteSurface,
                                 Analysis *analysis = nsnull);
 
 #ifdef MOZILLA_MAY_SUPPORT_SSE2
-    /* This does the same as the previous function, but uses SSE2
+    /* This does the save as the previous function, but uses SSE2
      * optimizations. Usually this should not be called directly.  Be sure to
      * check mozilla::supports_sse2() before calling this function.
      */
     static PRBool RecoverAlphaSSE2 (gfxImageSurface *blackSurface,
                                     const gfxImageSurface *whiteSurface);
-
-    /**
-     * A common use-case for alpha recovery is to paint into a
-     * temporary "white image", then paint onto a subrect of the
-     * surface, the "black image", into which alpha-recovered pixels
-     * are eventually to be written.  This function returns a rect
-     * aligned so that recovering alpha for that rect will hit SIMD
-     * fast-paths, if possible.  It's not always possible to align
-     * |aRect| so that fast-paths will be taken.
-     *
-     * The returned rect is always a superset of |aRect|.
-     */
-    static nsIntRect AlignRectForSubimageRecovery(const nsIntRect& aRect,
-                                                  gfxImageSurface* aSurface);
-#else
-    static nsIntRect AlignRectForSubimageRecovery(const nsIntRect& aRect,
-                                                  gfxImageSurface*)
-    { return aRect; }
 #endif
 
     /** from cairo-xlib-utils.c, modified */
     /**
      * Given the RGB data for two image surfaces, one a source image composited
      * with OVER onto a black background, and one a source image composited with 
      * OVER onto a white background, reconstruct the original image data into
      * black_data.
--- a/gfx/thebes/gfxAlphaRecoverySSE2.cpp
+++ b/gfx/thebes/gfxAlphaRecoverySSE2.cpp
@@ -155,104 +155,8 @@ gfxAlphaRecovery::RecoverAlphaSSE2(gfxIm
         blackData += blackSurf->Stride() - j * 4;
         whiteData += whiteSurf->Stride() - j * 4;
     }
 
     blackSurf->MarkDirty();
 
     return PR_TRUE;
 }
-
-static PRInt32
-ByteAlignment(PRInt32 aAlignToLog2, PRInt32 aX, PRInt32 aY=0, PRInt32 aStride=1)
-{
-    return (aX + aStride * aY) & ((1 << aAlignToLog2) - 1);
-}
-
-/*static*/ nsIntRect
-gfxAlphaRecovery::AlignRectForSubimageRecovery(const nsIntRect& aRect,
-                                               gfxImageSurface* aSurface)
-{
-    NS_ASSERTION(gfxASurface::ImageFormatARGB32 == aSurface->Format(),
-                 "Thebes grew support for non-ARGB32 COLOR_ALPHA?");
-    static const PRInt32 kByteAlignLog2 = GoodAlignmentLog2();
-    static const PRInt32 bpp = 4;
-    static const PRInt32 pixPerAlign = (1 << kByteAlignLog2) / bpp;
-    //
-    // We're going to create a subimage of the surface with size
-    // <sw,sh> for alpha recovery, and want a SIMD fast-path.  The
-    // rect <x,y, w,h> /needs/ to be redrawn, but it might not be
-    // properly aligned for SIMD.  So we want to find a rect <x',y',
-    // w',h'> that's a superset of what needs to be redrawn but is
-    // properly aligned.  Proper alignment is
-    //
-    //   BPP * (x' + y' * sw) \cong 0         (mod ALIGN)
-    //   BPP * w'             \cong BPP * sw  (mod ALIGN)
-    //
-    // (We assume the pixel at surface <0,0> is already ALIGN'd.)
-    // That rect (obviously) has to fit within the surface bounds, and
-    // we should also minimize the extra pixels redrawn only for
-    // alignment's sake.  So we also want
-    //
-    //  minimize <x',y', w',h'>
-    //   0 <= x' <= x
-    //   0 <= y' <= y
-    //   w <= w' <= sw
-    //   h <= h' <= sh
-    //
-    // This is a messy integer non-linear programming problem, except
-    // ... we can assume that ALIGN/BPP is a very small constant.  So,
-    // brute force is viable.  The algorithm below will find a
-    // solution if one exists, but isn't guaranteed to find the
-    // minimum solution.  (For SSE2, ALIGN/BPP = 4, so it'll do at
-    // most 64 iterations below).  In what's likely the common case,
-    // an already-aligned rectangle, it only needs 1 iteration.
-    //
-    // Is this alignment worth doing?  Recovering alpha will take work
-    // proportional to w*h (assuming alpha recovery computation isn't
-    // memory bound).  This analysis can lead to O(w+h) extra work
-    // (with small constants).  In exchange, we expect to shave off a
-    // ALIGN/BPP constant by using SIMD-ized alpha recovery.  So as
-    // w*h diverges from w+h, the win factor approaches ALIGN/BPP.  We
-    // only really care about the w*h >> w+h case anyway; others
-    // should be fast enough even with the overhead.  (Unless the cost
-    // of repainting the expanded rect is high, but in that case
-    // SIMD-ized alpha recovery won't make a difference so this code
-    // shouldn't be called.)
-    //
-    gfxIntSize surfaceSize = aSurface->GetSize();
-    const PRInt32 stride = bpp * surfaceSize.width;
-    if (stride != aSurface->Stride()) {
-        NS_WARNING("Unexpected stride, falling back on slow alpha recovery");
-        return aRect;
-    }
-
-    const PRInt32 x = aRect.x, y = aRect.y, w = aRect.width, h = aRect.height;
-    const PRInt32 sw = surfaceSize.width, sh = surfaceSize.height;
-    const PRInt32 strideAlign = ByteAlignment(kByteAlignLog2, stride);
-
-    PRInt32 dx, dy, dw;
-    // The outer two loops search for an aligned top-left pixel
-    for (dy = 0; (dy < pixPerAlign) && (y - dy >= 0) && (h + dy <= sh); ++dy) {
-        for (dx = 0; (dx < pixPerAlign) && (x - dx >= 0); ++dx) {
-            if (0 != ByteAlignment(kByteAlignLog2,
-                                   bpp * (x - dx), y - dy, stride)) {
-                continue;
-            }
-            // The inner searches for an aligned stride
-            for (dw = 0; (dw < pixPerAlign) && (w + dw + dx <= sw); ++dw) {
-                if (strideAlign == ByteAlignment(kByteAlignLog2,
-                                                 bpp * (w + dw + dx))) {
-                    goto FOUND_SOLUTION;
-                }
-            }
-        }
-    }
-
-    // Didn't find a solution.
-    return aRect;
-
-FOUND_SOLUTION:
-    nsIntRect solution = nsIntRect(x - dx, y - dy, w + dw + dx, h + dy);
-    NS_ABORT_IF_FALSE(nsIntRect(0,0, sw,sh).Contains(solution),
-                      "'Solution' extends outside surface bounds!");
-    return solution;
-}
--- a/gfx/thebes/gfxImageSurface.cpp
+++ b/gfx/thebes/gfxImageSurface.cpp
@@ -32,17 +32,16 @@
  * and other provisions required by the GPL or the LGPL. If you do not delete
  * the provisions above, a recipient may use your version of this file under
  * the terms of any one of the MPL, the GPL or the LGPL.
  *
  * ***** END LICENSE BLOCK ***** */
 
 #include "prmem.h"
 
-#include "gfxAlphaRecovery.h"
 #include "gfxImageSurface.h"
 
 #include "cairo.h"
 
 gfxImageSurface::gfxImageSurface()
   : mSize(0, 0),
     mOwnsData(PR_FALSE),
     mFormat(ImageFormatUnknown),
@@ -92,48 +91,29 @@ gfxImageSurface::InitWithData(unsigned c
     // cairo_image_surface_create_for_data can return a 'null' surface
     // in out of memory conditions. The gfxASurface::Init call checks
     // the surface it receives to see if there is an error with the
     // surface and handles it appropriately. That is why there is
     // no check here.
     Init(surface);
 }
 
-static void*
-TryAllocAlignedBytes(size_t aSize)
-{
-    // Use fallible allocators here
-#if defined(HAVE_POSIX_MEMALIGN) || defined(HAVE_JEMALLOC_POSIX_MEMALIGN)
-    void* ptr;
-    // Try to align for fast alpha recovery.  This should only help
-    // cairo too, can't hurt.
-    return moz_posix_memalign(&ptr,
-                              1 << gfxAlphaRecovery::GoodAlignmentLog2(),
-                              aSize) ?
-             nsnull : ptr;
-#else
-    // Oh well, hope that luck is with us in the allocator
-    return moz_malloc(aSize);
-#endif
-}
-
 gfxImageSurface::gfxImageSurface(const gfxIntSize& size, gfxImageFormat format) :
     mSize(size), mOwnsData(PR_FALSE), mData(nsnull), mFormat(format)
 {
     mStride = ComputeStride();
 
     if (!CheckSurfaceSize(size))
         return;
 
     // if we have a zero-sized surface, just leave mData nsnull
     if (mSize.height * mStride > 0) {
 
-        // This can fail to allocate memory aligned as we requested,
-        // or it can fail to allocate any memory at all.
-        mData = (unsigned char *) TryAllocAlignedBytes(mSize.height * mStride);
+        // Use the fallible allocator here
+        mData = (unsigned char *) moz_malloc(mSize.height * mStride);
         if (!mData)
             return;
         memset(mData, 0, mSize.height * mStride);
     }
 
     mOwnsData = PR_TRUE;
 
     cairo_surface_t *surface =