Bug 1003707 - Pass surfaces sizes in to CreateSourceSurfaceFromNativeSurface instead of trying to extract it from cairo. r=Bas
authorMatt Woodrow <mwoodrow@mozilla.com>
Thu, 08 May 2014 11:23:44 +1200
changeset 201290 3b5fb4abaa3fe006cbcc34fa0bfcb940b1101c53
parent 201289 52f249e906ce34349523c2331c43150224d4db50
child 201291 9641ef44e561f974a9b888349a7770d3d3afc1cb
push id3741
push userasasaki@mozilla.com
push dateMon, 21 Jul 2014 20:25:18 +0000
treeherdermozilla-beta@4d6f46f5af68 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersBas
bugs1003707
milestone32.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 1003707 - Pass surfaces sizes in to CreateSourceSurfaceFromNativeSurface instead of trying to extract it from cairo. r=Bas
gfx/2d/2D.h
gfx/2d/DrawTargetCairo.cpp
gfx/2d/DrawTargetCairo.h
gfx/2d/Factory.cpp
gfx/layers/basic/BasicCompositor.cpp
gfx/layers/basic/MacIOSurfaceTextureHostBasic.cpp
gfx/layers/basic/MacIOSurfaceTextureHostBasic.h
gfx/layers/basic/TextureHostBasic.h
gfx/layers/basic/X11TextureSourceBasic.cpp
gfx/layers/basic/X11TextureSourceBasic.h
gfx/thebes/gfxASurface.cpp
gfx/thebes/gfxPlatform.cpp
gfx/thebes/gfxXlibNativeRenderer.cpp
--- a/gfx/2d/2D.h
+++ b/gfx/2d/2D.h
@@ -55,16 +55,17 @@ class SourceSurface;
 class DataSourceSurface;
 class DrawTarget;
 class DrawEventRecorder;
 class FilterNode;
 
 struct NativeSurface {
   NativeSurfaceType mType;
   SurfaceFormat mFormat;
+  gfx::IntSize mSize;
   void *mSurface;
 };
 
 struct NativeFont {
   NativeFontType mType;
   void *mFont;
 };
 
@@ -1029,20 +1030,16 @@ public:
   /* Make sure that the given dimensions don't overflow a 32-bit signed int
    * using 4 bytes per pixel; optionally, make sure that either dimension
    * doesn't exceed the given limit.
    */
   static bool CheckSurfaceSize(const IntSize &sz, int32_t limit = 0);
 
   static TemporaryRef<DrawTarget> CreateDrawTargetForCairoSurface(cairo_surface_t* aSurface, const IntSize& aSize, SurfaceFormat* aFormat = nullptr);
 
-  static TemporaryRef<SourceSurface>
-    CreateSourceSurfaceForCairoSurface(cairo_surface_t* aSurface,
-                                       SurfaceFormat aFormat);
-
   static TemporaryRef<DrawTarget>
     CreateDrawTarget(BackendType aBackend, const IntSize &aSize, SurfaceFormat aFormat);
 
   static TemporaryRef<DrawTarget>
     CreateRecordingDrawTarget(DrawEventRecorder *aRecorder, DrawTarget *aDT);
      
   static TemporaryRef<DrawTarget>
     CreateDrawTargetForData(BackendType aBackend, unsigned char* aData, const IntSize &aSize, int32_t aStride, SurfaceFormat aFormat);
--- a/gfx/2d/DrawTargetCairo.cpp
+++ b/gfx/2d/DrawTargetCairo.cpp
@@ -77,80 +77,16 @@ private:
 
   cairo_t* mCtx;
 };
 
 
 } // end anonymous namespace
 
 static bool
-GetCairoSurfaceSize(cairo_surface_t* surface, IntSize& size)
-{
-  switch (cairo_surface_get_type(surface))
-  {
-    case CAIRO_SURFACE_TYPE_IMAGE:
-    {
-      size.width = cairo_image_surface_get_width(surface);
-      size.height = cairo_image_surface_get_height(surface);
-      return true;
-    }
-
-#ifdef CAIRO_HAS_XLIB_SURFACE
-    case CAIRO_SURFACE_TYPE_XLIB:
-    {
-      size.width = cairo_xlib_surface_get_width(surface);
-      size.height = cairo_xlib_surface_get_height(surface);
-      return true;
-    }
-#endif
-
-#ifdef CAIRO_HAS_QUARTZ_SURFACE
-    case CAIRO_SURFACE_TYPE_QUARTZ:
-    {
-      CGContextRef cgc = cairo_quartz_surface_get_cg_context(surface);
-
-      // It's valid to call these CGBitmapContext functions on non-bitmap
-      // contexts; they'll just return 0 in that case.
-      size.width = CGBitmapContextGetWidth(cgc);
-      size.height = CGBitmapContextGetHeight(cgc);
-      return true;
-    }
-#endif
-#ifdef CAIRO_HAS_WIN32_SURFACE
-#ifdef MOZ2D_HAS_MOZ_CAIRO
-    case CAIRO_SURFACE_TYPE_WIN32:
-    case CAIRO_SURFACE_TYPE_WIN32_PRINTING:
-    {
-      size.width = cairo_win32_surface_get_width(surface);
-      size.height = cairo_win32_surface_get_height(surface);
-      return true;
-    }
-#else
-    case CAIRO_SURFACE_TYPE_WIN32:
-    {
-      cairo_surface_t *img = cairo_win32_surface_get_image(surface);
-
-      if (!img) {
-        // XXX - fix me
-        MOZ_ASSERT(false);
-        return true;
-      }
-      size.width = cairo_image_surface_get_width(img);
-      size.height = cairo_image_surface_get_height(img);
-      return true;
-    }
-#endif
-#endif
-
-    default:
-      return false;
-  }
-}
-
-static bool
 SupportsSelfCopy(cairo_surface_t* surface)
 {
   switch (cairo_surface_get_type(surface))
   {
 #ifdef CAIRO_HAS_QUARTZ_SURFACE
     case CAIRO_SURFACE_TYPE_QUARTZ:
       return true;
 #endif
@@ -1126,36 +1062,24 @@ DrawTargetCairo::OptimizeSourceSurface(S
 {
   return aSurface;
 }
 
 TemporaryRef<SourceSurface>
 DrawTargetCairo::CreateSourceSurfaceFromNativeSurface(const NativeSurface &aSurface) const
 {
   if (aSurface.mType == NativeSurfaceType::CAIRO_SURFACE) {
-    IntSize size;
-    cairo_surface_t* surf = static_cast<cairo_surface_t*>(aSurface.mSurface);
-    if (GetCairoSurfaceSize(surf, size)) {
-      RefPtr<SourceSurfaceCairo> source =
-        new SourceSurfaceCairo(surf, size, aSurface.mFormat);
-      return source;
+    if (aSurface.mSize.width <= 0 ||
+        aSurface.mSize.height <= 0) {
+      gfxWarning() << "Can't create a SourceSurface without a valid size";
+      return nullptr;
     }
-  }
-
-  return nullptr;
-}
-
-TemporaryRef<SourceSurface>
-DrawTargetCairo::CreateSourceSurfaceForCairoSurface(cairo_surface_t *aSurface,
-                                                    SurfaceFormat aFormat)
-{
-  IntSize size;
-  if (GetCairoSurfaceSize(aSurface, size)) {
+    cairo_surface_t* surf = static_cast<cairo_surface_t*>(aSurface.mSurface);
     RefPtr<SourceSurfaceCairo> source =
-      new SourceSurfaceCairo(aSurface, size, aFormat);
+      new SourceSurfaceCairo(surf, aSurface.mSize, aSurface.mFormat);
     return source;
   }
 
   return nullptr;
 }
 
 TemporaryRef<DrawTarget>
 DrawTargetCairo::CreateSimilarDrawTarget(const IntSize &aSize, SurfaceFormat aFormat) const
--- a/gfx/2d/DrawTargetCairo.h
+++ b/gfx/2d/DrawTargetCairo.h
@@ -164,20 +164,16 @@ public:
 
   // Call to set up aContext for drawing (with the current transform, etc).
   // Pass the path you're going to be using if you have one.
   // Implicitly calls WillChange(aPath).
   void PrepareForDrawing(cairo_t* aContext, const Path* aPath = nullptr);
 
   static cairo_surface_t *GetDummySurface();
 
-  static TemporaryRef<SourceSurface>
-      CreateSourceSurfaceForCairoSurface(cairo_surface_t* aSurface,
-                                         SurfaceFormat aFormat);
-
 private: // methods
   // Init cairo surface without doing a cairo_surface_reference() call.
   bool InitAlreadyReferenced(cairo_surface_t* aSurface, const IntSize& aSize, SurfaceFormat* aFormat = nullptr);
   enum DrawPatternType { DRAW_FILL, DRAW_STROKE };
   void DrawPattern(const Pattern& aPattern,
                    const StrokeOptions& aStrokeOptions,
                    const DrawOptions& aOptions,
                    DrawPatternType aDrawType,
--- a/gfx/2d/Factory.cpp
+++ b/gfx/2d/Factory.cpp
@@ -632,28 +632,16 @@ Factory::CreateDrawTargetForCairoSurface
   if (mRecorder && retVal) {
     RefPtr<DrawTarget> recordDT = new DrawTargetRecording(mRecorder, retVal, true);
     return recordDT;
   }
 #endif
   return retVal;
 }
 
-TemporaryRef<SourceSurface>
-Factory::CreateSourceSurfaceForCairoSurface(cairo_surface_t* aSurface,
-                                            SurfaceFormat aFormat)
-{
-  RefPtr<SourceSurface> retVal;
-
-#ifdef USE_CAIRO
-  retVal = DrawTargetCairo::CreateSourceSurfaceForCairoSurface(aSurface, aFormat);
-#endif
-  return retVal;
-}
-
 #ifdef XP_MACOSX
 TemporaryRef<DrawTarget>
 Factory::CreateDrawTargetForCairoCGContext(CGContextRef cg, const IntSize& aSize)
 {
   RefPtr<DrawTarget> retVal;
 
   RefPtr<DrawTargetCG> newTarget = new DrawTargetCG();
 
--- a/gfx/layers/basic/BasicCompositor.cpp
+++ b/gfx/layers/basic/BasicCompositor.cpp
@@ -27,17 +27,17 @@ namespace layers {
 
 class DataTextureSourceBasic : public DataTextureSource
                              , public TextureSourceBasic
 {
 public:
 
   virtual TextureSourceBasic* AsSourceBasic() MOZ_OVERRIDE { return this; }
 
-  virtual gfx::SourceSurface* GetSurface() MOZ_OVERRIDE { return mSurface; }
+  virtual gfx::SourceSurface* GetSurface(DrawTarget* aTarget) MOZ_OVERRIDE { return mSurface; }
 
   SurfaceFormat GetFormat() const MOZ_OVERRIDE
   {
     return mSurface->GetFormat();
   }
 
   virtual IntSize GetSize() const MOZ_OVERRIDE
   {
@@ -288,17 +288,17 @@ BasicCompositor::DrawQuad(const gfx::Rec
 
   newTransform.Translate(-offset.x, -offset.y);
   buffer->SetTransform(newTransform);
 
   RefPtr<SourceSurface> sourceMask;
   Matrix maskTransform;
   if (aEffectChain.mSecondaryEffects[EffectTypes::MASK]) {
     EffectMask *effectMask = static_cast<EffectMask*>(aEffectChain.mSecondaryEffects[EffectTypes::MASK].get());
-    sourceMask = effectMask->mMaskTexture->AsSourceBasic()->GetSurface();
+    sourceMask = effectMask->mMaskTexture->AsSourceBasic()->GetSurface(dest);
     MOZ_ASSERT(effectMask->mMaskTransform.Is2D(), "How did we end up with a 3D transform here?!");
     MOZ_ASSERT(!effectMask->mIs3D);
     maskTransform = effectMask->mMaskTransform.As2D();
     maskTransform.Translate(-offset.x, -offset.y);
   }
 
   switch (aEffectChain.mPrimaryEffect->mType) {
     case EffectTypes::SOLID_COLOR: {
@@ -310,17 +310,17 @@ BasicCompositor::DrawQuad(const gfx::Rec
       break;
     }
     case EffectTypes::RGB: {
       TexturedEffect* texturedEffect =
           static_cast<TexturedEffect*>(aEffectChain.mPrimaryEffect.get());
       TextureSourceBasic* source = texturedEffect->mTexture->AsSourceBasic();
 
       DrawSurfaceWithTextureCoords(dest, aRect,
-                                   source->GetSurface(),
+                                   source->GetSurface(dest),
                                    texturedEffect->mTextureCoords,
                                    texturedEffect->mFilter,
                                    aOpacity, sourceMask, &maskTransform);
       break;
     }
     case EffectTypes::YCBCR: {
       NS_RUNTIMEABORT("Can't (easily) support component alpha with BasicCompositor!");
       break;
--- a/gfx/layers/basic/MacIOSurfaceTextureHostBasic.cpp
+++ b/gfx/layers/basic/MacIOSurfaceTextureHostBasic.cpp
@@ -41,17 +41,17 @@ MacIOSurfaceTextureHostBasic::MacIOSurfa
   : TextureHost(aFlags)
 {
   mSurface = MacIOSurface::LookupSurface(aDescriptor.surface(),
                                          aDescriptor.scaleFactor(),
                                          aDescriptor.hasAlpha());
 }
 
 gfx::SourceSurface*
-MacIOSurfaceTextureSourceBasic::GetSurface()
+MacIOSurfaceTextureSourceBasic::GetSurface(gfx::DrawTarget* aTarget)
 {
   if (!mSourceSurface) {
     mSourceSurface = mSurface->GetAsSurface();
   }
   return mSourceSurface;
 }
 
 void
--- a/gfx/layers/basic/MacIOSurfaceTextureHostBasic.h
+++ b/gfx/layers/basic/MacIOSurfaceTextureHostBasic.h
@@ -29,17 +29,17 @@ public:
   MacIOSurfaceTextureSourceBasic(BasicCompositor* aCompositor,
                                  MacIOSurface* aSurface);
   virtual ~MacIOSurfaceTextureSourceBasic();
 
   virtual TextureSourceBasic* AsSourceBasic() MOZ_OVERRIDE { return this; }
 
   virtual gfx::IntSize GetSize() const MOZ_OVERRIDE;
   virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE;
-  virtual gfx::SourceSurface* GetSurface() MOZ_OVERRIDE;
+  virtual gfx::SourceSurface* GetSurface(gfx::DrawTarget* aTarget) MOZ_OVERRIDE;
 
   virtual void DeallocateDeviceData() MOZ_OVERRIDE { }
 
   virtual void SetCompositor(Compositor* aCompositor) MOZ_OVERRIDE;
 
 protected:
   BasicCompositor* mCompositor;
   RefPtr<MacIOSurface> mSurface;
--- a/gfx/layers/basic/TextureHostBasic.h
+++ b/gfx/layers/basic/TextureHostBasic.h
@@ -17,15 +17,15 @@ namespace layers {
 
 /**
  * A texture source interface that can be used by the software Compositor.
  */
 class TextureSourceBasic
 {
 public:
   virtual ~TextureSourceBasic() {}
-  virtual gfx::SourceSurface* GetSurface() = 0;
+  virtual gfx::SourceSurface* GetSurface(gfx::DrawTarget* aTarget) = 0;
 };
 
 } // namespace layers
 } // namespace mozilla
 
 #endif // MOZILLA_GFX_TEXTUREHOSTBASIC_H_
--- a/gfx/layers/basic/X11TextureSourceBasic.cpp
+++ b/gfx/layers/basic/X11TextureSourceBasic.cpp
@@ -27,21 +27,25 @@ X11TextureSourceBasic::GetSize() const
 SurfaceFormat
 X11TextureSourceBasic::GetFormat() const
 {
   gfxContentType type = mSurface->GetContentType();
   return X11TextureSourceBasic::ContentTypeToSurfaceFormat(type);
 }
 
 SourceSurface*
-X11TextureSourceBasic::GetSurface()
+X11TextureSourceBasic::GetSurface(DrawTarget* aTarget)
 {
   if (!mSourceSurface) {
-    mSourceSurface =
-      Factory::CreateSourceSurfaceForCairoSurface(mSurface->CairoSurface(), GetFormat());
+    NativeSurface surf;
+    surf.mFormat = GetFormat();
+    surf.mType = NativeSurfaceType::CAIRO_SURFACE;
+    surf.mSurface = mSurface->CairoSurface();
+    surf.mSize = GetSize();
+    mSourceSurface = aTarget->CreateSourceSurfaceFromNativeSurface(surf);
   }
   return mSourceSurface;
 }
 
 void
 X11TextureSourceBasic::SetCompositor(Compositor* aCompositor)
 {
   MOZ_ASSERT(aCompositor->GetBackendType() == LayersBackend::LAYERS_BASIC);
@@ -57,9 +61,9 @@ X11TextureSourceBasic::ContentTypeToSurf
       return SurfaceFormat::B8G8R8X8;
     case gfxContentType::ALPHA:
       return SurfaceFormat::A8;
     case gfxContentType::COLOR_ALPHA:
       return SurfaceFormat::B8G8R8A8;
     default:
       return SurfaceFormat::UNKNOWN;
   }
-}
\ No newline at end of file
+}
--- a/gfx/layers/basic/X11TextureSourceBasic.h
+++ b/gfx/layers/basic/X11TextureSourceBasic.h
@@ -23,17 +23,17 @@ public:
   X11TextureSourceBasic(BasicCompositor* aCompositor, gfxXlibSurface* aSurface);
 
   virtual X11TextureSourceBasic* AsSourceBasic() MOZ_OVERRIDE { return this; }
 
   virtual gfx::IntSize GetSize() const MOZ_OVERRIDE;
 
   virtual gfx::SurfaceFormat GetFormat() const MOZ_OVERRIDE;
 
-  virtual gfx::SourceSurface* GetSurface() MOZ_OVERRIDE;
+  virtual gfx::SourceSurface* GetSurface(gfx::DrawTarget* aTarget) MOZ_OVERRIDE;
 
   virtual void DeallocateDeviceData() MOZ_OVERRIDE { }
 
   virtual void SetCompositor(Compositor* aCompositor);
 
   static gfx::SurfaceFormat ContentTypeToSurfaceFormat(gfxContentType aType);
 
 protected:
--- a/gfx/thebes/gfxASurface.cpp
+++ b/gfx/thebes/gfxASurface.cpp
@@ -7,16 +7,17 @@
 #include "nsMemory.h"
 #include "mozilla/ArrayUtils.h"
 #include "mozilla/Base64.h"
 #include "mozilla/CheckedInt.h"
 #include "mozilla/Attributes.h"
 #include "mozilla/MemoryReporting.h"
 #include "nsISupportsImpl.h"
 #include "mozilla/gfx/2D.h"
+#include "gfx2DGlue.h"
 
 #include "gfxASurface.h"
 #include "gfxContext.h"
 #include "gfxImageSurface.h"
 #include "gfxPlatform.h"
 #include "gfxRect.h"
 
 #include "cairo.h"
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -734,30 +734,32 @@ gfxPlatform::GetSourceSurfaceForSurface(
 
 #ifdef XP_WIN
   if (aSurface->GetType() == gfxSurfaceType::D2D &&
       format != SurfaceFormat::A8) {
     NativeSurface surf;
     surf.mFormat = format;
     surf.mType = NativeSurfaceType::D3D10_TEXTURE;
     surf.mSurface = static_cast<gfxD2DSurface*>(aSurface)->GetTexture();
+    surf.mSize = ToIntSize(aSurface->GetSize());
     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() && aTarget->GetType() == BackendType::CAIRO) {
     // 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 = NativeSurfaceType::CAIRO_SURFACE;
     surf.mSurface = aSurface->CairoSurface();
+    surf.mSize = ToIntSize(aSurface->GetSize());
     srcBuffer = aTarget->CreateSourceSurfaceFromNativeSurface(surf);
 
     if (srcBuffer) {
       // It's cheap enough to make a new one so we won't keep it around and
       // keeping it creates a cycle.
       return srcBuffer;
     }
   }
--- a/gfx/thebes/gfxXlibNativeRenderer.cpp
+++ b/gfx/thebes/gfxXlibNativeRenderer.cpp
@@ -570,28 +570,29 @@ gfxXlibNativeRenderer::Draw(gfxContext* 
         cairo_paint(tmpCtx);
         cairo_destroy(tmpCtx);
     }
 
     if (!DrawOntoTempSurface(tempXlibSurface, -drawingRect.TopLeft())) {
         cairo_surface_destroy(tempXlibSurface);
         return;
     }
-  
+
     SurfaceFormat moz2DFormat =
         cairo_surface_get_content(tempXlibSurface) == CAIRO_CONTENT_COLOR ?
             SurfaceFormat::B8G8R8A8 : SurfaceFormat::B8G8R8X8;
     if (method != eAlphaExtraction) {
         if (drawTarget) {
-            // It doesn't matter if moz2DFormat doesn't exactly match the format
-            // of tempXlibSurface, since this DrawTarget just wraps the cairo
-            // drawing.
+            NativeSurface native;
+            native.mFormat = moz2DFormat;
+            native.mType = NativeSurfaceType::CAIRO_SURFACE;
+            native.mSurface = tempXlibSurface;
+            native.mSize = ToIntSize(size);
             RefPtr<SourceSurface> sourceSurface =
-                Factory::CreateSourceSurfaceForCairoSurface(tempXlibSurface,
-                                                            moz2DFormat);
+                drawTarget->CreateSourceSurfaceFromNativeSurface(native);
             if (sourceSurface) {
                 drawTarget->DrawSurface(sourceSurface,
                     Rect(offset.x, offset.y, size.width, size.height),
                     Rect(0, 0, size.width, size.height));
             }
         } else {
             nsRefPtr<gfxASurface> tmpSurf = gfxASurface::Wrap(tempXlibSurface);
             ctx->SetSource(tmpSurf, offset);
@@ -617,19 +618,23 @@ gfxXlibNativeRenderer::Draw(gfxContext* 
         whiteImage->CairoStatus() == CAIRO_STATUS_SUCCESS) {
         if (!gfxAlphaRecovery::RecoverAlpha(blackImage, whiteImage)) {
             cairo_surface_destroy(tempXlibSurface);
             return;
         }
 
         gfxASurface* paintSurface = blackImage;
         if (drawTarget) {
+            NativeSurface native;
+            native.mFormat = moz2DFormat;
+            native.mType = NativeSurfaceType::CAIRO_SURFACE;
+            native.mSurface = tempXlibSurface;
+            native.mSize = ToIntSize(size);
             RefPtr<SourceSurface> sourceSurface =
-                Factory::CreateSourceSurfaceForCairoSurface(paintSurface->CairoSurface(),
-                                                            moz2DFormat);
+                drawTarget->CreateSourceSurfaceFromNativeSurface(native);
             if (sourceSurface) {
                 drawTarget->DrawSurface(sourceSurface,
                     Rect(offset.x, offset.y, size.width, size.height),
                     Rect(0, 0, size.width, size.height));
             }
         } else {
             ctx->SetSource(paintSurface, offset);
             ctx->Paint();