Bug 950371 - Convert the Cocoa widget consumers of imgIContainer::GetFrame to act on a Moz2D SourceSurface instead of a Thebes gfxASurface. r=mattwoodrow,mstange
authorJonathan Watt <jwatt@jwatt.org>
Fri, 21 Feb 2014 19:07:42 +0000
changeset 187131 97a62f515945228702daa2f1dc45f1d3b564f867
parent 187130 625a7848187ae2cf10097a73d5615ec7e26bdbd3
child 187132 ad851c771c047ad2f8f3db0745ef94284b9dc4af
push id3503
push userraliiev@mozilla.com
push dateMon, 28 Apr 2014 18:51:11 +0000
treeherdermozilla-beta@c95ac01e332e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow, mstange
bugs950371
milestone30.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 950371 - Convert the Cocoa widget consumers of imgIContainer::GetFrame to act on a Moz2D SourceSurface instead of a Thebes gfxASurface. r=mattwoodrow,mstange
widget/cocoa/nsClipboard.mm
widget/cocoa/nsCocoaUtils.h
widget/cocoa/nsCocoaUtils.mm
widget/cocoa/nsMenuItemIconX.mm
--- a/widget/cocoa/nsClipboard.mm
+++ b/widget/cocoa/nsClipboard.mm
@@ -3,32 +3,37 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifdef MOZ_LOGGING
 #define FORCE_PR_LOG
 #endif
 #include "prlog.h"
 
+#include "gfxPlatform.h"
 #include "nsCOMPtr.h"
 #include "nsClipboard.h"
 #include "nsString.h"
 #include "nsISupportsPrimitives.h"
 #include "nsXPIDLString.h"
 #include "nsPrimitiveHelpers.h"
 #include "nsMemory.h"
 #include "nsIFile.h"
 #include "nsStringStream.h"
 #include "nsDragService.h"
 #include "nsEscape.h"
 #include "nsPrintfCString.h"
 #include "nsObjCExceptions.h"
 #include "imgIContainer.h"
 #include "nsCocoaUtils.h"
 
+using mozilla::gfx::DataSourceSurface;
+using mozilla::gfx::SourceSurface;
+using mozilla::RefPtr;
+
 // Screenshots use the (undocumented) png pasteboard type.
 #define IMAGE_PASTEBOARD_TYPES NSTIFFPboardType, @"Apple PNG pasteboard type", nil
 
 #ifdef PR_LOGGING
 extern PRLogModuleInfo* sCocoaLog;
 #endif
 
 extern void EnsureLogInitialized();
@@ -426,28 +431,30 @@ nsClipboard::PasteboardDictFromTransfera
       ptrPrimitive->GetData(getter_AddRefs(primitiveData));
 
       nsCOMPtr<imgIContainer> image(do_QueryInterface(primitiveData));
       if (!image) {
         NS_WARNING("Image isn't an imgIContainer in transferable");
         continue;
       }
 
-      nsRefPtr<gfxASurface> surface =
+      nsRefPtr<gfxASurface> thebesSurface =
         image->GetFrame(imgIContainer::FRAME_CURRENT,
                         imgIContainer::FLAG_SYNC_DECODE);
+      if (!thebesSurface) {
+        continue;
+      }
+      RefPtr<SourceSurface> surface =
+        gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(
+          gfxPlatform::GetPlatform()->ScreenReferenceDrawTarget(), thebesSurface);
       if (!surface) {
         continue;
       }
-      nsRefPtr<gfxImageSurface> frame(surface->GetAsReadableARGB32ImageSurface());
-      if (!frame) {
-        continue;
-      }
       CGImageRef imageRef = NULL;
-      nsresult rv = nsCocoaUtils::CreateCGImageFromSurface(frame, &imageRef);
+      nsresult rv = nsCocoaUtils::CreateCGImageFromSurface(surface, &imageRef);
       if (NS_FAILED(rv) || !imageRef) {
         continue;
       }
       
       // Convert the CGImageRef to TIFF data.
       CFMutableDataRef tiffData = CFDataCreateMutable(kCFAllocatorDefault, 0);
       CGImageDestinationRef destRef = CGImageDestinationCreateWithData(tiffData,
                                                                        CFSTR("public.tiff"),
--- a/widget/cocoa/nsCocoaUtils.h
+++ b/widget/cocoa/nsCocoaUtils.h
@@ -21,16 +21,22 @@
 // Declare the backingScaleFactor method that we want to call
 // on NSView/Window/Screen objects, if they recognize it.
 @interface NSObject (BackingScaleFactorCategory)
 - (CGFloat)backingScaleFactor;
 @end
 
 class nsIWidget;
 
+namespace mozilla {
+namespace gfx {
+class SourceSurface;
+}
+}
+
 // Used to retain a Cocoa object for the remainder of a method's execution.
 class nsAutoRetainCocoaObject {
 public:
 nsAutoRetainCocoaObject(id anObject)
 {
   mObject = NS_OBJC_TRY_EXPR_ABORT([anObject retain]);
 }
 ~nsAutoRetainCocoaObject()
@@ -97,17 +103,19 @@ struct KeyBindingsCommand
 - (void)doCommandBySelector:(SEL)aSelector;
 
 - (void)insertText:(id)aString;
 
 @end // NativeKeyBindingsRecorder
 
 class nsCocoaUtils
 {
-  public:
+  typedef mozilla::gfx::SourceSurface SourceSurface;
+
+public:
 
   // Get the backing scale factor from an object that supports this selector
   // (NSView/Window/Screen, on 10.7 or later), returning 1.0 if not supported
   static CGFloat
   GetBackingScaleFactor(id aObject)
   {
     if (HiDPIEnabled() &&
         [aObject respondsToSelector:@selector(backingScaleFactor)]) {
@@ -221,17 +229,18 @@ class nsCocoaUtils
   
   /** Creates a <code>CGImageRef</code> from a frame contained in an <code>imgIContainer</code>.
       Copies the pixel data from the indicated frame of the <code>imgIContainer</code> into a new <code>CGImageRef</code>.
       The caller owns the <code>CGImageRef</code>. 
       @param aFrame the frame to convert
       @param aResult the resulting CGImageRef
       @return NS_OK if the conversion worked, NS_ERROR_FAILURE otherwise
    */
-  static nsresult CreateCGImageFromSurface(gfxImageSurface *aFrame, CGImageRef *aResult);
+  static nsresult CreateCGImageFromSurface(SourceSurface* aSurface,
+                                           CGImageRef* aResult);
   
   /** Creates a Cocoa <code>NSImage</code> from a <code>CGImageRef</code>.
       Copies the pixel data from the <code>CGImageRef</code> into a new <code>NSImage</code>.
       The caller owns the <code>NSImage</code>. 
       @param aInputImage the image to convert
       @param aResult the resulting NSImage
       @return NS_OK if the conversion worked, NS_ERROR_FAILURE otherwise
    */
--- a/widget/cocoa/nsCocoaUtils.mm
+++ b/widget/cocoa/nsCocoaUtils.mm
@@ -1,34 +1,41 @@
 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "gfxImageSurface.h"
+#include "gfxPlatform.h"
 #include "nsCocoaUtils.h"
 #include "nsChildView.h"
 #include "nsMenuBarX.h"
 #include "nsCocoaWindow.h"
 #include "nsCOMPtr.h"
 #include "nsIInterfaceRequestorUtils.h"
 #include "nsIAppShellService.h"
 #include "nsIXULWindow.h"
 #include "nsIBaseWindow.h"
 #include "nsIServiceManager.h"
 #include "nsMenuUtilsX.h"
 #include "nsToolkit.h"
 #include "nsCRT.h"
+#include "mozilla/gfx/2D.h"
 #include "mozilla/MiscEvents.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/TextEvents.h"
 
 using namespace mozilla;
 using namespace mozilla::widget;
 
+using mozilla::gfx::DataSourceSurface;
+using mozilla::gfx::IntSize;
+using mozilla::gfx::SurfaceFormat;
+using mozilla::gfx::SourceSurface;
+
 static float
 MenuBarScreenHeight()
 {
   NS_OBJC_BEGIN_TRY_ABORT_BLOCK_RETURN;
 
   NSArray* allScreens = [NSScreen screens];
   if ([allScreens count]) {
     return [[allScreens objectAtIndex:0] frame].size.height;
@@ -253,39 +260,56 @@ void nsCocoaUtils::CleanUpAfterNativeApp
   if (!mainWindow)
     hiddenWindowMenuBar->Paint();
   else
     [WindowDelegate paintMenubarForWindow:mainWindow];
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
-nsresult nsCocoaUtils::CreateCGImageFromSurface(gfxImageSurface *aFrame, CGImageRef *aResult)
+void data_ss_release_callback(void *aDataSourceSurface,
+                              const void *data,
+                              size_t size)
 {
+  if (aDataSourceSurface) {
+    static_cast<DataSourceSurface*>(aDataSourceSurface)->Release();
+  }
+}
 
-  int32_t width = aFrame->Width();
-  int32_t stride = aFrame->Stride();
-  int32_t height = aFrame->Height();
-  if ((stride % 4 != 0) || (height < 1) || (width < 1)) {
+nsresult nsCocoaUtils::CreateCGImageFromSurface(SourceSurface* aSurface,
+                                                CGImageRef* aResult)
+{
+  RefPtr<DataSourceSurface> dataSurface = aSurface->GetDataSurface();
+
+  MOZ_ASSERT(dataSurface->GetFormat() ==  SurfaceFormat::B8G8R8A8,
+             "We assume B8G8R8A8 when calling CGImageCreate");
+
+  int32_t width = dataSurface->GetSize().width;
+  int32_t height = dataSurface->GetSize().height;
+  if (height < 1 || width < 1) {
     return NS_ERROR_FAILURE;
   }
 
+  DataSourceSurface::MappedSurface map;
+  dataSurface->Map(DataSourceSurface::MapType::READ, &map);
+  NS_ENSURE_TRUE(map.mData, NS_ERROR_FAILURE);
+
   // Create a CGImageRef with the bits from the image, taking into account
   // the alpha ordering and endianness of the machine so we don't have to
   // touch the bits ourselves.
-  CGDataProviderRef dataProvider = ::CGDataProviderCreateWithData(NULL,
-                                                                  aFrame->Data(),
-                                                                  stride * height,
-                                                                  NULL);
+  CGDataProviderRef dataProvider = ::CGDataProviderCreateWithData(dataSurface.forget().drop(),
+                                                                  map.mData,
+                                                                  map.mStride * height,
+                                                                  data_ss_release_callback);
   CGColorSpaceRef colorSpace = ::CGColorSpaceCreateWithName(kCGColorSpaceGenericRGB);
   *aResult = ::CGImageCreate(width,
                              height,
                              8,
                              32,
-                             stride,
+                             map.mStride,
                              colorSpace,
                              kCGBitmapByteOrder32Host | kCGImageAlphaPremultipliedFirst,
                              dataProvider,
                              NULL,
                              0,
                              kCGRenderingIntentDefault);
   ::CGColorSpaceRelease(colorSpace);
   ::CGDataProviderRelease(dataProvider);
@@ -343,50 +367,59 @@ nsresult nsCocoaUtils::CreateNSImageFrom
   [offscreenRep release];
   return NS_OK;
 
   NS_OBJC_END_TRY_ABORT_BLOCK_NSRESULT;
 }
 
 nsresult nsCocoaUtils::CreateNSImageFromImageContainer(imgIContainer *aImage, uint32_t aWhichFrame, NSImage **aResult, CGFloat scaleFactor)
 {
-  nsRefPtr<gfxImageSurface> frame;
+  RefPtr<SourceSurface> surface;
   int32_t width = 0, height = 0;
   aImage->GetWidth(&width);
   aImage->GetHeight(&height);
 
   // Render a vector image at the correct resolution on a retina display
   if (aImage->GetType() == imgIContainer::TYPE_VECTOR && scaleFactor != 1.0f) {
     int scaledWidth = (int)ceilf(width * scaleFactor);
     int scaledHeight = (int)ceilf(height * scaleFactor);
 
-    frame = new gfxImageSurface(gfxIntSize(scaledWidth, scaledHeight), gfxImageFormat::ARGB32);
+    nsRefPtr<gfxImageSurface> frame =
+      new gfxImageSurface(gfxIntSize(scaledWidth, scaledHeight), gfxImageFormat::ARGB32);
     NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
 
     nsRefPtr<gfxContext> context = new gfxContext(frame);
     NS_ENSURE_TRUE(context, NS_ERROR_FAILURE);
 
     aImage->Draw(context, GraphicsFilter::FILTER_NEAREST, gfxMatrix(),
       gfxRect(0.0f, 0.0f, scaledWidth, scaledHeight),
       nsIntRect(0, 0, width, height),
       nsIntSize(scaledWidth, scaledHeight),
       nullptr, aWhichFrame, imgIContainer::FLAG_SYNC_DECODE);
+
+    surface =
+      gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(nullptr, frame);
+  } else {
+    nsRefPtr<gfxASurface> thebesSurface =
+      aImage->GetFrame(aWhichFrame, imgIContainer::FLAG_SYNC_DECODE);
+    NS_ENSURE_TRUE(thebesSurface, NS_ERROR_FAILURE);
+
+    nsRefPtr<gfxImageSurface> thebesImageSurface =
+      thebesSurface->GetAsReadableARGB32ImageSurface();
+    NS_ENSURE_TRUE(thebesImageSurface, NS_ERROR_FAILURE);
+
+    surface =
+      gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(nullptr,
+                                                             thebesImageSurface);
   }
 
-  else {
-    nsRefPtr<gfxASurface> surface =
-      aImage->GetFrame(aWhichFrame, imgIContainer::FLAG_SYNC_DECODE);
-    NS_ENSURE_TRUE(surface, NS_ERROR_FAILURE);
-
-    frame = surface->GetAsReadableARGB32ImageSurface();
-    NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
-  }
+  NS_ENSURE_TRUE(surface, NS_ERROR_FAILURE);
 
   CGImageRef imageRef = NULL;
-  nsresult rv = nsCocoaUtils::CreateCGImageFromSurface(frame, &imageRef);
+  nsresult rv = nsCocoaUtils::CreateCGImageFromSurface(surface, &imageRef);
   if (NS_FAILED(rv) || !imageRef) {
     return NS_ERROR_FAILURE;
   }
 
   rv = nsCocoaUtils::CreateNSImageFromCGImage(imageRef, aResult);
   if (NS_FAILED(rv) || !aResult) {
     return NS_ERROR_FAILURE;
   }
--- a/widget/cocoa/nsMenuItemIconX.mm
+++ b/widget/cocoa/nsMenuItemIconX.mm
@@ -32,20 +32,24 @@
 #include "nsIDOMRect.h"
 #include "nsThreadUtils.h"
 #include "nsToolkit.h"
 #include "nsNetUtil.h"
 #include "imgLoader.h"
 #include "imgRequestProxy.h"
 #include "nsMenuItemX.h"
 #include "gfxImageSurface.h"
+#include "gfxPlatform.h"
 #include "imgIContainer.h"
 #include "nsCocoaUtils.h"
 #include "nsContentUtils.h"
 
+using mozilla::gfx::SourceSurface;
+using mozilla::RefPtr;
+
 static const uint32_t kIconWidth = 16;
 static const uint32_t kIconHeight = 16;
 static const uint32_t kIconBitsPerComponent = 8;
 static const uint32_t kIconComponents = 4;
 static const uint32_t kIconBitsPerPixel = kIconBitsPerComponent *
                                           kIconComponents;
 static const uint32_t kIconBytesPerRow = kIconWidth * kIconBitsPerPixel / 8;
 static const uint32_t kIconBytes = kIconBytesPerRow * kIconHeight;
@@ -379,28 +383,30 @@ nsMenuItemIconX::OnStopFrame(imgIRequest
     [mNativeMenuItem setImage:nil];
     return NS_ERROR_FAILURE;
   }
 
   if (mImageRegionRect.IsEmpty()) {
     mImageRegionRect.SetRect(0, 0, origWidth, origHeight);
   }
   
-  nsRefPtr<gfxASurface> surface =
+  nsRefPtr<gfxASurface> thebesSurface =
     imageContainer->GetFrame(imgIContainer::FRAME_CURRENT,
                              imgIContainer::FLAG_NONE);
-  if (!surface) {
+  if (!thebesSurface) {
     [mNativeMenuItem setImage:nil];
     return NS_ERROR_FAILURE;
   }
-  nsRefPtr<gfxImageSurface> frame(surface->GetAsReadableARGB32ImageSurface());
-  NS_ENSURE_TRUE(frame, NS_ERROR_FAILURE);
+  RefPtr<SourceSurface> surface =
+    gfxPlatform::GetPlatform()->GetSourceSurfaceForSurface(nullptr,
+                                                           thebesSurface);
+  NS_ENSURE_TRUE(surface, NS_ERROR_FAILURE);
 
   CGImageRef origImage = NULL;
-  nsresult rv = nsCocoaUtils::CreateCGImageFromSurface(frame, &origImage);
+  nsresult rv = nsCocoaUtils::CreateCGImageFromSurface(surface, &origImage);
   if (NS_FAILED(rv) || !origImage) {
     [mNativeMenuItem setImage:nil];
     return NS_ERROR_FAILURE;
   }
 
   bool createSubImage = !(mImageRegionRect.x == 0 && mImageRegionRect.y == 0 &&
                             mImageRegionRect.width == origWidth && mImageRegionRect.height == origHeight);