Bug 1019492 - Stop creating a Thebes backed gfxContext in gfxQuartzNativeDrawing. r=mattwoodrow
authorMarkus Stange <mstange@themasta.com>
Wed, 04 Jun 2014 14:44:25 +0200
changeset 206921 adfd943ff73ea467bcbd60acb6426a5e25bb77c7
parent 206920 cb6938a8c0f9a1f3954318672c31588117612138
child 206922 28bb18a1306b27d590aea0ec0bf6b8ed7a5c3cc8
push id494
push userraliiev@mozilla.com
push dateMon, 25 Aug 2014 18:42:16 +0000
treeherdermozilla-release@a3cc3e46b571 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmattwoodrow
bugs1019492
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 1019492 - Stop creating a Thebes backed gfxContext in gfxQuartzNativeDrawing. r=mattwoodrow
gfx/thebes/gfxQuartzNativeDrawing.cpp
gfx/thebes/gfxQuartzNativeDrawing.h
--- a/gfx/thebes/gfxQuartzNativeDrawing.cpp
+++ b/gfx/thebes/gfxQuartzNativeDrawing.cpp
@@ -3,170 +3,87 @@
  * 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 "gfxQuartzNativeDrawing.h"
 #include "gfxQuartzSurface.h"
 #include "gfxPlatform.h"
 #include "cairo-quartz.h"
 
-// see cairo-quartz-surface.c for the complete list of these
-enum {
-    kPrivateCGCompositeSourceOver = 2
-};
-
 using namespace mozilla::gfx;
 using namespace mozilla;
 
-// private Quartz routine needed here
-extern "C" {
-    CG_EXTERN void CGContextSetCompositeOperation(CGContextRef, int);
-}
-
 gfxQuartzNativeDrawing::gfxQuartzNativeDrawing(gfxContext* ctx,
                                                const gfxRect& nativeRect,
                                                gfxFloat aBackingScale)
-    : mContext(ctx)
-    , mNativeRect(nativeRect)
-    , mBackingScale(aBackingScale)
+  : mContext(ctx)
+  , mNativeRect(nativeRect)
+  , mBackingScale(aBackingScale)
+  , mCGContext(nullptr)
 {
-    mNativeRect.RoundOut();
+  mNativeRect.RoundOut();
 }
 
 CGContextRef
 gfxQuartzNativeDrawing::BeginNativeDrawing()
 {
-    NS_ASSERTION(!mQuartzSurface, "BeginNativeDrawing called when drawing already in progress");
-
-    gfxPoint deviceOffset;
-    nsRefPtr<gfxASurface> surf;
-
-    if (!mContext->IsCairo()) {
-      DrawTarget *dt = mContext->GetDrawTarget();
-      if (dt->GetType() == BackendType::COREGRAPHICS) {
-        if (dt->IsDualDrawTarget()) {
-          IntSize backingSize(NSToIntFloor(mNativeRect.width * mBackingScale),
-                              NSToIntFloor(mNativeRect.height * mBackingScale));
-
-         if (backingSize.IsEmpty())
-            return nullptr;
-
-          mDrawTarget = Factory::CreateDrawTarget(BackendType::COREGRAPHICS, backingSize, SurfaceFormat::B8G8R8A8);
-
-          Matrix transform;
-          transform.Scale(mBackingScale, mBackingScale);
-          transform.Translate(-mNativeRect.x, -mNativeRect.y);
-
-          mDrawTarget->SetTransform(transform);
-          dt = mDrawTarget;
-        }
-
-        mCGContext = mBorrowedContext.Init(dt);
-        MOZ_ASSERT(mCGContext);
-        return mCGContext;
-      }
-      surf = gfxPlatform::GetPlatform()->GetThebesSurfaceForDrawTarget(dt);
-    } else {
-      surf = mContext->CurrentSurface(&deviceOffset.x, &deviceOffset.y);
-    }
-    if (!surf || surf->CairoStatus())
-        return nullptr;
+  NS_ASSERTION(!mCGContext, "BeginNativeDrawing called when drawing already in progress");
 
-    // if this is a native Quartz surface, we don't have to redirect
-    // rendering to our own CGContextRef; in most cases, we are able to
-    // use the CGContextRef from the surface directly.  we can extend
-    // this to support offscreen drawing fairly easily in the future.
-    if (surf->GetType() == gfxSurfaceType::Quartz &&
-        (surf->GetContentType() == gfxContentType::COLOR ||
-         (surf->GetContentType() == gfxContentType::COLOR_ALPHA))) {
-        mQuartzSurface = static_cast<gfxQuartzSurface*>(surf.get());
-        mSurfaceContext = mContext;
-
-        // grab the CGContextRef
-        mCGContext = cairo_quartz_get_cg_context_with_clip(mSurfaceContext->GetCairo());
-        if (!mCGContext)
-            return nullptr;
-
-        gfxMatrix m = mContext->CurrentMatrix();
-        CGContextTranslateCTM(mCGContext, deviceOffset.x, deviceOffset.y);
-
-        // I -think- that this context will always have an identity
-        // transform (since we don't maintain a transform on it in
-        // cairo-land, and instead push/pop as needed)
-
-        gfxFloat x0 = m.x0;
-        gfxFloat y0 = m.y0;
+  if (mContext->IsCairo()) {
+    // We're past that now. Any callers that still supply a Cairo context
+    // don't deserve native theming.
+    NS_WARNING("gfxQuartzNativeDrawing being used with a gfxContext that is not backed by a DrawTarget");
+    return nullptr;
+  }
 
-        // We round x0/y0 if we don't have a scale, because otherwise things get
-        // rendered badly
-        // XXX how should we be rounding x0/y0?
-        if (!m.HasNonTranslationOrFlip()) {
-            x0 = floor(x0 + 0.5);
-            y0 = floor(y0 + 0.5);
-        }
-
-        CGContextConcatCTM(mCGContext, CGAffineTransformMake(m.xx, m.yx,
-                                                             m.xy, m.yy,
-                                                             x0, y0));
+  DrawTarget *dt = mContext->GetDrawTarget();
+  if (dt->GetType() != BackendType::COREGRAPHICS || dt->IsDualDrawTarget()) {
+    IntSize backingSize(NSToIntFloor(mNativeRect.width * mBackingScale),
+                        NSToIntFloor(mNativeRect.height * mBackingScale));
 
-        // bug 382049 - need to explicity set the composite operation to sourceOver
-        CGContextSetCompositeOperation(mCGContext, kPrivateCGCompositeSourceOver);
-    } else {
-        nsIntSize backingSize(NSToIntFloor(mNativeRect.width * mBackingScale),
-                              NSToIntFloor(mNativeRect.height * mBackingScale));
-        mQuartzSurface = new gfxQuartzSurface(backingSize,
-                                              gfxImageFormat::ARGB32);
-        if (mQuartzSurface->CairoStatus())
-            return nullptr;
-        mSurfaceContext = new gfxContext(mQuartzSurface);
-
-        // grab the CGContextRef
-        mCGContext = cairo_quartz_get_cg_context_with_clip(mSurfaceContext->GetCairo());
-        CGContextScaleCTM(mCGContext, mBackingScale, mBackingScale);
-        CGContextTranslateCTM(mCGContext, -mNativeRect.X(), -mNativeRect.Y());
+    if (backingSize.IsEmpty()) {
+      return nullptr;
     }
 
-    return mCGContext;
+    mDrawTarget = Factory::CreateDrawTarget(BackendType::COREGRAPHICS, backingSize, SurfaceFormat::B8G8R8A8);
+
+    Matrix transform;
+    transform.Scale(mBackingScale, mBackingScale);
+    transform.Translate(-mNativeRect.x, -mNativeRect.y);
+
+    mDrawTarget->SetTransform(transform);
+    dt = mDrawTarget;
+  }
+
+  mCGContext = mBorrowedContext.Init(dt);
+  MOZ_ASSERT(mCGContext);
+  return mCGContext;
 }
 
 void
 gfxQuartzNativeDrawing::EndNativeDrawing()
 {
-    NS_ASSERTION(mCGContext, "EndNativeDrawing called without BeginNativeDrawing");
+  NS_ASSERTION(mCGContext, "EndNativeDrawing called without BeginNativeDrawing");
+  MOZ_ASSERT(!mContext->IsCairo(), "BeginNativeDrawing succeeded with cairo context?");
 
-    if (mBorrowedContext.cg) {
-        MOZ_ASSERT(!mContext->IsCairo());
-        mBorrowedContext.Finish();
-        if (mDrawTarget) {
-          DrawTarget *dest = mContext->GetDrawTarget();
-          RefPtr<SourceSurface> source = mDrawTarget->Snapshot();
+  mBorrowedContext.Finish();
+  if (mDrawTarget) {
+    DrawTarget *dest = mContext->GetDrawTarget();
+    RefPtr<SourceSurface> source = mDrawTarget->Snapshot();
+
+    IntSize backingSize(NSToIntFloor(mNativeRect.width * mBackingScale),
+                        NSToIntFloor(mNativeRect.height * mBackingScale));
 
-          IntSize backingSize(NSToIntFloor(mNativeRect.width * mBackingScale),
-                              NSToIntFloor(mNativeRect.height * mBackingScale));
+    Matrix oldTransform = dest->GetTransform();
+    Matrix newTransform = oldTransform;
+    newTransform.Translate(mNativeRect.x, mNativeRect.y);
+    newTransform.Scale(1.0f / mBackingScale, 1.0f / mBackingScale);
 
-          Matrix oldTransform = dest->GetTransform();
-          Matrix newTransform = oldTransform;
-          newTransform.Translate(mNativeRect.x, mNativeRect.y);
-          newTransform.Scale(1.0f / mBackingScale, 1.0f / mBackingScale);
+    dest->SetTransform(newTransform);
 
-          dest->SetTransform(newTransform);
-
-          dest->DrawSurface(source,
-                            gfx::Rect(0, 0, backingSize.width, backingSize.height),
-                            gfx::Rect(0, 0, backingSize.width, backingSize.height));
+    dest->DrawSurface(source,
+                      gfx::Rect(0, 0, backingSize.width, backingSize.height),
+                      gfx::Rect(0, 0, backingSize.width, backingSize.height));
 
 
-          dest->SetTransform(oldTransform);
-        }
-        return;
-    }
-
-    cairo_quartz_finish_cg_context_with_clip(mSurfaceContext->GetCairo());
-    mQuartzSurface->MarkDirty();
-    if (mSurfaceContext != mContext) {
-        gfxContextMatrixAutoSaveRestore save(mContext);
-
-        // Copy back to destination
-        mContext->Translate(mNativeRect.TopLeft());
-        mContext->Scale(1.0f / mBackingScale, 1.0f / mBackingScale);
-        mContext->DrawSurface(mQuartzSurface, mQuartzSurface->GetSize());
-    }
+    dest->SetTransform(oldTransform);
+  }
 }
--- a/gfx/thebes/gfxQuartzNativeDrawing.h
+++ b/gfx/thebes/gfxQuartzNativeDrawing.h
@@ -53,25 +53,20 @@ public:
     /* Marks the end of native drawing */
     void EndNativeDrawing();
 
 private:
     // don't allow copying via construction or assignment
     gfxQuartzNativeDrawing(const gfxQuartzNativeDrawing&) MOZ_DELETE;
     const gfxQuartzNativeDrawing& operator=(const gfxQuartzNativeDrawing&) MOZ_DELETE;
 
-
     // Final destination context
     nsRefPtr<gfxContext> mContext;
     mozilla::RefPtr<mozilla::gfx::DrawTarget> mDrawTarget;
     mozilla::gfx::BorrowedCGContext mBorrowedContext;
-    // context that draws to mQuartzSurface; can be different from mContext
-    // if mContext is not drawing to Quartz
-    nsRefPtr<gfxContext> mSurfaceContext;
     gfxRect mNativeRect;
     gfxFloat mBackingScale;
 
     // saved state
-    nsRefPtr<gfxQuartzSurface> mQuartzSurface;
     CGContextRef mCGContext;
 };
 
 #endif