Bug 711063 - Part 11: Allow using Azure for content drawing with D3D10 layers. r=jrmuizel
authorBas Schouten <bschouten@mozilla.com>
Thu, 05 Jan 2012 08:17:52 +0100
changeset 85077 590333161e6f014f67fc61b096e86aa6a851a186
parent 85076 2d3b8d36d9b22dfcac9c10d228abd9d9de89f1d1
child 85078 2c1e788aea4eae6e68f325d95e9b5f626e2239fd
push id805
push userakeybl@mozilla.com
push dateWed, 01 Feb 2012 18:17:35 +0000
treeherdermozilla-aurora@6fb3bf232436 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjrmuizel
bugs711063
milestone12.0a1
Bug 711063 - Part 11: Allow using Azure for content drawing with D3D10 layers. r=jrmuizel
gfx/layers/d3d10/ThebesLayerD3D10.cpp
gfx/layers/d3d10/ThebesLayerD3D10.h
gfx/thebes/gfxPlatform.cpp
gfx/thebes/gfxPlatform.h
--- a/gfx/layers/d3d10/ThebesLayerD3D10.cpp
+++ b/gfx/layers/d3d10/ThebesLayerD3D10.cpp
@@ -49,16 +49,21 @@
 #endif
 
 #include "../d3d9/Nv3DVUtils.h"
 #include "gfxTeeSurface.h"
 #include "gfxUtils.h"
 #include "ReadbackLayer.h"
 #include "ReadbackProcessor.h"
 
+#include "mozilla/Preferences.h"
+#include "mozilla/gfx/2D.h"
+
+using namespace mozilla::gfx;
+
 namespace mozilla {
 namespace layers {
 
 ThebesLayerD3D10::ThebesLayerD3D10(LayerManagerD3D10 *aManager)
   : ThebesLayer(aManager, NULL)
   , LayerD3D10(aManager)
   , mCurrentSurfaceMode(SURFACE_OPAQUE)
 {
@@ -184,17 +189,18 @@ ThebesLayerD3D10::Validate(ReadbackProce
   if (mVisibleRegion.IsEmpty()) {
     return;
   }
 
   nsIntRect newTextureRect = mVisibleRegion.GetBounds();
 
   SurfaceMode mode = GetSurfaceMode();
   if (mode == SURFACE_COMPONENT_ALPHA &&
-      (!mParent || !mParent->SupportsComponentAlphaChildren())) {
+      (gfxPlatform::UseAzureContentDrawing() ||
+       !mParent || !mParent->SupportsComponentAlphaChildren())) {
     mode = SURFACE_SINGLE_CHANNEL_ALPHA;
   }
   // If we have a transform that requires resampling of our texture, then
   // we need to make sure we don't sample pixels that haven't been drawn.
   // We clamp sample coordinates to the texture rect, but when the visible region
   // doesn't fill the entire texture rect we need to make sure we draw all the
   // pixels in the texture rect anyway in case they get sampled.
   nsIntRegion neededRegion = mVisibleRegion;
@@ -347,29 +353,31 @@ ThebesLayerD3D10::VerifyContentType(Surf
     }
   }
 }
 
 static void
 FillSurface(gfxASurface* aSurface, const nsIntRegion& aRegion,
             const nsIntPoint& aOffset, const gfxRGBA& aColor)
 {
-  nsRefPtr<gfxContext> ctx = new gfxContext(aSurface);
-  ctx->Translate(-gfxPoint(aOffset.x, aOffset.y));
-  gfxUtils::PathFromRegion(ctx, aRegion);
-  ctx->SetColor(aColor);
-  ctx->Fill();
+  if (aSurface) {
+    nsRefPtr<gfxContext> ctx = new gfxContext(aSurface);
+    ctx->Translate(-gfxPoint(aOffset.x, aOffset.y));
+    gfxUtils::PathFromRegion(ctx, aRegion);
+    ctx->SetColor(aColor);
+    ctx->Fill();
+  }
 }
 
 void
 ThebesLayerD3D10::DrawRegion(nsIntRegion &aRegion, SurfaceMode aMode)
 {
   nsIntRect visibleRect = mVisibleRegion.GetBounds();
 
-  if (!mD2DSurface) {
+  if (!mD2DSurface && !mDrawTarget) {
     return;
   }
 
   nsRefPtr<gfxASurface> destinationSurface;
   
   if (aMode == SURFACE_COMPONENT_ALPHA) {
     FillSurface(mD2DSurface, aRegion, visibleRect.TopLeft(), gfxRGBA(0.0, 0.0, 0.0, 1.0));
     FillSurface(mD2DSurfaceOnWhite, aRegion, visibleRect.TopLeft(), gfxRGBA(1.0, 1.0, 1.0, 1.0));
@@ -378,34 +386,45 @@ ThebesLayerD3D10::DrawRegion(nsIntRegion
     // Using this surface as a source will likely go horribly wrong, since
     // only the onBlack surface will really be used, so alpha information will
     // be incorrect.
     destinationSurface->SetAllowUseAsSource(false);
   } else {
     destinationSurface = mD2DSurface;
   }
 
-  nsRefPtr<gfxContext> context = new gfxContext(destinationSurface);
+  nsRefPtr<gfxContext> context;
+
+  if (mDrawTarget) {
+    context = new gfxContext(mDrawTarget);
+  } else {
+    context = new gfxContext(destinationSurface);
+  }
 
   nsIntRegionRectIterator iter(aRegion);
   context->Translate(gfxPoint(-visibleRect.x, -visibleRect.y));
   context->NewPath();
   const nsIntRect *iterRect;
   while ((iterRect = iter.Next())) {
     context->Rectangle(gfxRect(iterRect->x, iterRect->y, iterRect->width, iterRect->height));      
+    if (mDrawTarget) {
+      mDrawTarget->ClearRect(Rect(iterRect->x, iterRect->y, iterRect->width, iterRect->height));
+    }
   }
   context->Clip();
 
-  if (aMode == SURFACE_SINGLE_CHANNEL_ALPHA) {
+  if (!mDrawTarget && aMode == SURFACE_SINGLE_CHANNEL_ALPHA) {
     context->SetOperator(gfxContext::OPERATOR_CLEAR);
     context->Paint();
     context->SetOperator(gfxContext::OPERATOR_OVER);
   }
 
-  mD2DSurface->SetSubpixelAntialiasingEnabled(!(mContentFlags & CONTENT_COMPONENT_ALPHA));
+  if (mD2DSurface) {
+    mD2DSurface->SetSubpixelAntialiasingEnabled(!(mContentFlags & CONTENT_COMPONENT_ALPHA));
+  }
 
   LayerManagerD3D10::CallbackInfo cbInfo = mD3DManager->GetCallbackInfo();
   cbInfo.Callback(this, context, aRegion, nsIntRegion(), cbInfo.CallbackData);
 }
 
 void
 ThebesLayerD3D10::CreateNewTextures(const gfxIntSize &aSize, SurfaceMode aMode)
 {
@@ -428,25 +447,35 @@ ThebesLayerD3D10::CreateNewTextures(cons
     }
 
     hr = device()->CreateShaderResourceView(mTexture, NULL, getter_AddRefs(mSRView));
 
     if (FAILED(hr)) {
       NS_WARNING("Failed to create shader resource view for ThebesLayerD3D10.");
     }
 
-    mD2DSurface = new gfxD2DSurface(mTexture, aMode != SURFACE_SINGLE_CHANNEL_ALPHA ?
-      gfxASurface::CONTENT_COLOR : gfxASurface::CONTENT_COLOR_ALPHA);
+    if (!gfxPlatform::UseAzureContentDrawing()) {
+      mD2DSurface = new gfxD2DSurface(mTexture, aMode != SURFACE_SINGLE_CHANNEL_ALPHA ?
+                                                gfxASurface::CONTENT_COLOR : gfxASurface::CONTENT_COLOR_ALPHA);
 
-    if (!mD2DSurface || mD2DSurface->CairoStatus()) {
-      NS_WARNING("Failed to create surface for ThebesLayerD3D10.");
-      mD2DSurface = nsnull;
-      return;
+      if (!mD2DSurface || mD2DSurface->CairoStatus()) {
+        NS_WARNING("Failed to create surface for ThebesLayerD3D10.");
+        mD2DSurface = NULL;
+        return;
+      }
+    } else {
+      mDrawTarget = Factory::CreateDrawTargetForD3D10Texture(mTexture, aMode != SURFACE_SINGLE_CHANNEL_ALPHA ?
+        FORMAT_B8G8R8X8 : FORMAT_B8G8R8A8);
+
+      if (!mDrawTarget) {
+        NS_WARNING("Failed to create DrawTarget for ThebesLayerD3D10.");
+        mDrawTarget = nsnull;
+        return;
+      }
     }
-
   }
 
   if (aMode == SURFACE_COMPONENT_ALPHA && !mTextureOnWhite) {
     hr = device()->CreateTexture2D(&desc, NULL, getter_AddRefs(mTextureOnWhite));
 
     if (FAILED(hr)) {
       NS_WARNING("Failed to create new texture for ThebesLayerD3D10!");
       return;
--- a/gfx/layers/d3d10/ThebesLayerD3D10.h
+++ b/gfx/layers/d3d10/ThebesLayerD3D10.h
@@ -81,16 +81,18 @@ private:
   SurfaceMode mCurrentSurfaceMode;
 
   /* Checks if our D2D surface has the right content type */
   void VerifyContentType(SurfaceMode aMode);
 
   /* This contains the thebes surface */
   nsRefPtr<gfxASurface> mD2DSurface;
 
+  mozilla::RefPtr<mozilla::gfx::DrawTarget> mDrawTarget;
+
   /* This contains the thebes surface for our render-on-white texture */
   nsRefPtr<gfxASurface> mD2DSurfaceOnWhite;
 
   /* Have a region of our layer drawn */
   void DrawRegion(nsIntRegion &aRegion, SurfaceMode aMode);
 
   /* Create a new texture */
   void CreateNewTextures(const gfxIntSize &aSize, SurfaceMode aMode);
--- a/gfx/thebes/gfxPlatform.cpp
+++ b/gfx/thebes/gfxPlatform.cpp
@@ -971,16 +971,31 @@ gfxPlatform::AppendPrefLang(eFontPrefLan
     }
     
     if (i == aLen) {
         aPrefLangs[aLen] = aAddLang;
         aLen++;
     }
 }
 
+bool
+gfxPlatform::UseAzureContentDrawing()
+{
+  static bool sAzureContentDrawingEnabled;
+  static bool sAzureContentDrawingPrefCached = false;
+
+  if (!sAzureContentDrawingPrefCached) {
+    sAzureContentDrawingPrefCached = true;
+    mozilla::Preferences::AddBoolVarCache(&sAzureContentDrawingEnabled, 
+                                          "gfx.content.azure.enabled");
+  }
+
+  return sAzureContentDrawingEnabled;
+}
+
 eCMSMode
 gfxPlatform::GetCMSMode()
 {
     if (gCMSInitialized == false) {
         gCMSInitialized = true;
         nsresult rv;
 
         PRInt32 mode;
--- a/gfx/thebes/gfxPlatform.h
+++ b/gfx/thebes/gfxPlatform.h
@@ -351,16 +351,19 @@ public:
     // map a Unicode range (based on char code) to a font language for Preferences
     static eFontPrefLang GetFontPrefLangFor(PRUint8 aUnicodeRange);
 
     // returns true if a pref lang is CJK
     static bool IsLangCJK(eFontPrefLang aLang);
     
     // helper method to add a pref lang to an array, if not already in array
     static void AppendPrefLang(eFontPrefLang aPrefLangs[], PRUint32& aLen, eFontPrefLang aAddLang);
+
+    // helper method to indicate if we want to use Azure content drawing
+    static bool UseAzureContentDrawing();
     
     /**
      * Are we going to try color management?
      */
     static eCMSMode GetCMSMode();
 
     /**
      * Determines the rendering intent for color management.