Bug 950371 - Convert the Cocoa widget consumers of imgIContainer::GetFrame to act on a Moz2D SourceSurface instead of a Thebes gfxASurface. r=mattwoodrow
☠☠ backed out by 147db60f2911 ☠ ☠
authorJonathan Watt <jwatt@jwatt.org>
Fri, 21 Feb 2014 08:42:12 +0000
changeset 170179 05a5f08f1278ab404c2b6faec5eac4dba22f7dba
parent 170178 c2f752b69b3accf8820e5e1bfb410b81687e37f1
child 170180 147db60f29113783f8b77e6c832ca89e988d3379
push id270
push userpvanderbeken@mozilla.com
push dateThu, 06 Mar 2014 09:24:21 +0000
reviewersmattwoodrow
bugs950371
milestone30.0a1
Bug 950371 - Convert the Cocoa widget consumers of imgIContainer::GetFrame to act on a Moz2D SourceSurface instead of a Thebes gfxASurface. r=mattwoodrow
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,47 @@ void nsCocoaUtils::CleanUpAfterNativeApp
   if (!mainWindow)
     hiddenWindowMenuBar->Paint();
   else
     [WindowDelegate paintMenubarForWindow:mainWindow];
 
   NS_OBJC_END_TRY_ABORT_BLOCK;
 }
 
-nsresult nsCocoaUtils::CreateCGImageFromSurface(gfxImageSurface *aFrame, CGImageRef *aResult)
+nsresult nsCocoaUtils::CreateCGImageFromSurface(SourceSurface* aSurface,
+                                                CGImageRef* aResult)
 {
+  RefPtr<DataSourceSurface> dataSurface = aSurface->GetDataSurface();
 
-  int32_t width = aFrame->Width();
-  int32_t stride = aFrame->Stride();
-  int32_t height = aFrame->Height();
-  if ((stride % 4 != 0) || (height < 1) || (width < 1)) {
+  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,
+                                                                  map.mData,
+                                                                  map.mStride * height,
                                                                   NULL);
   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 +358,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,23 @@
 #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;
+
 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 +382,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);