Bug 590294, part 7: Add APIs for recording the resolution at which ThebesLayers were painted and for requesting resolution-scaled drawing for basic layers. r=roc sr=vlad
authorChris Jones <jones.chris.g@gmail.com>
Fri, 03 Sep 2010 15:10:46 -0500
changeset 54082 3467965f4d9f4e10d7c49a596e7715f5d5ff5bdb
parent 54081 0b90c6b07933ff2cb7e56be41eb5e82516513592
child 54083 8321155e8dad2fb39353be91023c23f85600f215
push idunknown
push userunknown
push dateunknown
reviewersroc, vlad
bugs590294
milestone2.0b6pre
Bug 590294, part 7: Add APIs for recording the resolution at which ThebesLayers were painted and for requesting resolution-scaled drawing for basic layers. r=roc sr=vlad
gfx/layers/Layers.h
gfx/layers/basic/BasicLayers.cpp
gfx/layers/basic/BasicLayers.h
gfx/layers/ipc/PLayers.ipdl
gfx/layers/ipc/ShadowLayers.h
gfx/layers/ipc/ShadowLayersParent.cpp
--- a/gfx/layers/Layers.h
+++ b/gfx/layers/Layers.h
@@ -723,29 +723,50 @@ public:
    * will need to be repainted. This area is removed from the valid
    * region.
    */
   virtual void InvalidateRegion(const nsIntRegion& aRegion) = 0;
 
   /**
    * Can be used anytime
    */
-  const nsIntRegion& GetValidRegion() { return mValidRegion; }
+  const nsIntRegion& GetValidRegion() const { return mValidRegion; }
+  float GetXResolution() const { return mXResolution; }
+  float GetYResolution() const { return mYResolution; }
 
   virtual ThebesLayer* AsThebesLayer() { return this; }
 
   MOZ_LAYER_DECL_NAME("ThebesLayer", TYPE_THEBES)
 
 protected:
   ThebesLayer(LayerManager* aManager, void* aImplData)
-    : Layer(aManager, aImplData) {}
+    : Layer(aManager, aImplData)
+    , mValidRegion()
+    , mXResolution(1.0)
+    , mYResolution(1.0)
+  {}
 
   virtual nsACString& PrintInfo(nsACString& aTo, const char* aPrefix);
 
   nsIntRegion mValidRegion;
+  // Resolution values tell this to paint its content scaled by
+  // <aXResolution, aYResolution>, into a backing buffer with
+  // dimensions scaled the same.  A non-1.0 resolution also tells this
+  // to set scaling factors that compensate for the re-paint
+  // resolution when rendering itself to render targets
+  //
+  // Resolution doesn't affect the visible region, valid region, or
+  // re-painted regions at all.  It only affects how scalable thebes
+  // content is rasterized to device pixels.
+  //
+  // Setting the resolution isn't part of the public ThebesLayer API
+  // because it's backend-specific, and it doesn't necessarily make
+  // sense for all backends to fully support it.
+  float mXResolution;
+  float mYResolution;
 };
 
 /**
  * A Layer which other layers render into. It holds references to its
  * children.
  */
 class THEBES_API ContainerLayer : public Layer {
 public:
--- a/gfx/layers/basic/BasicLayers.cpp
+++ b/gfx/layers/basic/BasicLayers.cpp
@@ -859,17 +859,19 @@ MayHaveOverlappingOrTransparentLayers(La
 
   return PR_FALSE;
 }
 
 BasicLayerManager::BasicLayerManager(nsIWidget* aWidget) :
 #ifdef DEBUG
   mPhase(PHASE_NONE),
 #endif
-  mWidget(aWidget)
+  mXResolution(1.0)
+  , mYResolution(1.0)
+  , mWidget(aWidget)
   , mDoubleBuffering(BUFFER_NONE), mUsingDefaultTarget(PR_FALSE)
 {
   MOZ_COUNT_CTOR(BasicLayerManager);
   NS_ASSERTION(aWidget, "Must provide a widget");
 }
 
 BasicLayerManager::BasicLayerManager() :
 #ifdef DEBUG
@@ -1295,17 +1297,18 @@ public:
   {
     if (mBackBuffer)
       BasicManager()->ShadowLayerForwarder::DestroySharedSurface(mBackBuffer);
     MOZ_COUNT_DTOR(BasicShadowableThebesLayer);
   }
 
   virtual void FillSpecificAttributes(SpecificLayerAttributes& aAttrs)
   {
-    aAttrs = ThebesLayerAttributes(GetValidRegion());
+    aAttrs = ThebesLayerAttributes(GetValidRegion(),
+                                   mXResolution, mYResolution);
   }
 
   virtual Layer* AsLayer() { return this; }
   virtual ShadowableLayer* AsShadowableLayer() { return this; }
 
   virtual void SetBackBuffer(gfxSharedImageSurface* aBuffer)
   {
     mBackBuffer = aBuffer;
--- a/gfx/layers/basic/BasicLayers.h
+++ b/gfx/layers/basic/BasicLayers.h
@@ -113,16 +113,31 @@ public:
    */
   enum BufferMode {
     BUFFER_NONE,
     BUFFER_BUFFERED
   };
   void SetDefaultTarget(gfxContext* aContext, BufferMode aDoubleBuffering);
   gfxContext* GetDefaultTarget() { return mDefaultTarget; }
 
+  /**
+   * Set a target resolution for managed layers that are scalable.  It
+   * might make sense to call this outside of a transaction, but
+   * currently it's only allowed during the construction phase of
+   * transactions.
+   */
+  void SetResolution(float aXResolution, float aYResolution)
+  {
+    NS_ASSERTION(InConstruction(), "resolution must be set before drawing");
+    mXResolution = aXResolution;
+    mYResolution = aYResolution;
+  }
+  float XResolution() const { return mXResolution; }
+  float YResolution() const { return mYResolution; }
+
   nsIWidget* GetRetainerWidget() { return mWidget; }
   void ClearRetainerWidget() { mWidget = nsnull; }
 
   virtual void BeginTransaction();
   virtual void BeginTransactionWithTarget(gfxContext* aTarget);
   virtual void EndTransaction(DrawThebesLayerCallback aCallback,
                               void* aCallbackData);
 
@@ -179,16 +194,20 @@ private:
   void ClearLayer(Layer* aLayer);
 
   already_AddRefed<gfxContext> PushGroupWithCachedSurface(gfxContext *aTarget,
                                                           gfxASurface::gfxContentType aContent,
                                                           gfxPoint *aSavedOffset);
   void PopGroupWithCachedSurface(gfxContext *aTarget,
                                  const gfxPoint& aSavedOffset);
 
+  // Target resolution for scalable content.
+  float mXResolution;
+  float mYResolution;
+
   // Widget whose surface should be used as the basis for ThebesLayer
   // buffers.
   nsIWidget* mWidget;
   // The default context for BeginTransaction.
   nsRefPtr<gfxContext> mDefaultTarget;
   // The context to draw into.
   nsRefPtr<gfxContext> mTarget;
 
--- a/gfx/layers/ipc/PLayers.ipdl
+++ b/gfx/layers/ipc/PLayers.ipdl
@@ -102,17 +102,21 @@ struct CommonLayerAttributes {
   nsIntRegion visibleRegion;
   gfx3DMatrix transform;
   PRUint32 contentFlags;
   float opacity;
   bool useClipRect;
   nsIntRect clipRect;
 };
 
-struct ThebesLayerAttributes   { nsIntRegion validRegion; };
+struct ThebesLayerAttributes {
+  nsIntRegion validRegion;
+  float xResolution;
+  float yResolution;
+};
 struct ContainerLayerAttributes{ FrameMetrics metrics; };
 struct ColorLayerAttributes    { gfxRGBA color; };
 struct CanvasLayerAttributes   { GraphicsFilterType filter; };
 struct ImageLayerAttributes    { GraphicsFilterType filter; };
 
 union SpecificLayerAttributes {
   null_t;
   ThebesLayerAttributes;
--- a/gfx/layers/ipc/ShadowLayers.h
+++ b/gfx/layers/ipc/ShadowLayers.h
@@ -326,16 +326,26 @@ public:
   void SetValidRegion(const nsIntRegion& aRegion)
   {
     mValidRegion = aRegion;
     Mutated();
   }
 
   /**
    * CONSTRUCTION PHASE ONLY
+   */
+  void SetResolution(float aXResolution, float aYResolution)
+  {
+    mXResolution = aXResolution;
+    mYResolution = aYResolution;
+    Mutated();
+  }
+
+  /**
+   * CONSTRUCTION PHASE ONLY
    *
    * Publish the remote layer's back ThebesLayerBuffer to this shadow,
    * swapping out the old front ThebesLayerBuffer (the new back buffer
    * for the remote layer).
    *
    * XXX should the receiving process blit updates from the new front
    * buffer to the previous front buffer (new back buffer) while it has
    * access to the new front buffer?  Or is it better to fill the
--- a/gfx/layers/ipc/ShadowLayersParent.cpp
+++ b/gfx/layers/ipc/ShadowLayersParent.cpp
@@ -275,23 +275,29 @@ ShadowLayersParent::RecvUpdate(const nsT
       layer->SetTransform(common.transform());
 
       typedef SpecificLayerAttributes Specific;
       const SpecificLayerAttributes& specific = attrs.specific();
       switch (specific.type()) {
       case Specific::Tnull_t:
         break;
 
-      case Specific::TThebesLayerAttributes:
+      case Specific::TThebesLayerAttributes: {
         MOZ_LAYERS_LOG(("[ParentSide]   thebes layer"));
 
-        static_cast<ShadowThebesLayer*>(layer)->SetValidRegion(
-          specific.get_ThebesLayerAttributes().validRegion());
+        ShadowThebesLayer* thebesLayer =
+          static_cast<ShadowThebesLayer*>(layer);
+        const ThebesLayerAttributes& attrs =
+          specific.get_ThebesLayerAttributes();
+
+        thebesLayer->SetValidRegion(attrs.validRegion());
+        thebesLayer->SetResolution(attrs.xResolution(), attrs.yResolution());
+
         break;
-
+      }
       case Specific::TContainerLayerAttributes:
         MOZ_LAYERS_LOG(("[ParentSide]   container layer"));
 
         static_cast<ContainerLayer*>(layer)->SetFrameMetrics(
           specific.get_ContainerLayerAttributes().metrics());
         break;
 
       case Specific::TColorLayerAttributes: