Bug 832383 - Add support for complex visible regions to HwcComposer2D. r=mwu
authorDiego Wilson <dwilson@codeaurora.org>
Mon, 29 Apr 2013 17:21:54 -0700
changeset 141869 5feac049908f2a910002c2ef98c8a237aea2870f
parent 141868 afb7995ef276f6e1209d6cb605163bd24dd34766
child 141870 f52a8c803f263f9ee6f850f465b86c13f14c8491
push id2579
push userakeybl@mozilla.com
push dateMon, 24 Jun 2013 18:52:47 +0000
treeherdermozilla-beta@b69b7de8a05a [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmwu
bugs832383
milestone23.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 832383 - Add support for complex visible regions to HwcComposer2D. r=mwu
widget/gonk/HwcComposer2D.cpp
widget/gonk/HwcComposer2D.h
--- a/widget/gonk/HwcComposer2D.cpp
+++ b/widget/gonk/HwcComposer2D.cpp
@@ -189,16 +189,62 @@ PrepareLayerRects(nsIntRect aVisible, co
     aVisibleRegionScreen->top  = visibleRectScreen.y;
     aVisibleRegionScreen->right  = visibleRectScreen.x + visibleRectScreen.width;
     aVisibleRegionScreen->bottom = visibleRectScreen.y + visibleRectScreen.height;
 
     return true;
 }
 
 /**
+ * Prepares hwc layer visible region required for hwc composition
+ *
+ * @param aVisible Input. Layer's unclipped visible region
+ *        The origin is the top-left corner of the layer
+ * @param aTransform Input. Layer's transformation matrix
+ *        It transforms from layer space to screen space
+ * @param aClip Input. A clipping rectangle.
+ *        The origin is the top-left corner of the screen
+ * @param aBufferRect Input. The layer's buffer bounds
+ *        The origin is the top-left corner of the layer
+ * @param aVisibleRegionScreen Output. Visible region in screen space.
+ *        The origin is the top-left corner of the screen
+ * @return true if the layer should be rendered.
+ *         false if the layer can be skipped
+ */
+static bool
+PrepareVisibleRegion(const nsIntRegion& aVisible,
+                     const gfxMatrix& aTransform,
+                     nsIntRect aClip, nsIntRect aBufferRect,
+                     RectVector* aVisibleRegionScreen) {
+
+    nsIntRegionRectIterator rect(aVisible);
+    bool isVisible = false;
+    while (const nsIntRect* visibleRect = rect.Next()) {
+        hwc_rect_t visibleRectScreen;
+        gfxRect screenRect;
+
+        screenRect.IntersectRect(gfxRect(*visibleRect), aBufferRect);
+        screenRect = aTransform.TransformBounds(screenRect);
+        screenRect.IntersectRect(screenRect, aClip);
+        screenRect.RoundIn();
+        if (screenRect.IsEmpty()) {
+            continue;
+        }
+        visibleRectScreen.left = screenRect.x;
+        visibleRectScreen.top  = screenRect.y;
+        visibleRectScreen.right  = screenRect.XMost();
+        visibleRectScreen.bottom = screenRect.YMost();
+        aVisibleRegionScreen->push_back(visibleRectScreen);
+        isVisible = true;
+    }
+
+    return isVisible;
+}
+
+/**
  * Calculates the layer's clipping rectangle
  *
  * @param aTransform Input. A transformation matrix
  *        It transforms the clip rect to screen space
  * @param aLayerClip Input. The layer's internal clipping rectangle.
  *        This may be NULL which means the layer has no internal clipping
  *        The origin is the top-left corner of the layer
  * @param aParentClip Input. The parent layer's rendering clipping rectangle
@@ -255,22 +301,16 @@ HwcComposer2D::PrepareLayerList(Layer* a
         LOGD("Layer is fully transparent so skip rendering");
         return true;
     }
     else if (opacity < 1) {
         LOGD("Layer has planar semitransparency which is unsupported");
         return false;
     }
 
-    if (visibleRegion.GetNumRects() > 1) {
-        // FIXME/bug 808339
-        LOGD("Layer has nontrivial visible region");
-        return false;
-    }
-
     nsIntRect clip;
     if (!CalculateClipRect(aParentTransform * aGLWorldTransform,
                            aLayer->GetEffectiveClipRect(),
                            aClip,
                            &clip))
     {
         LOGD("Clip rect is empty. Skip layer");
         return true;
@@ -380,18 +420,32 @@ HwcComposer2D::PrepareLayerList(Layer* a
             hwcLayer.transform = HWC_TRANSFORM_ROT_180;
             LOGD("Layer buffer rotated 180 degrees");
         } else {
             hwcLayer.transform = 0;
         }
 
         hwcLayer.transform |= state.YFlipped() ? HWC_TRANSFORM_FLIP_V : 0;
         hwc_region_t region;
-        region.numRects = 1;
-        region.rects = &(hwcLayer.displayFrame);
+        if (visibleRegion.GetNumRects() > 1) {
+            mVisibleRegions.push_back(RectVector());
+            RectVector* visibleRects = &(mVisibleRegions.back());
+            if(!PrepareVisibleRegion(visibleRegion,
+                                     transform * aGLWorldTransform,
+                                     clip,
+                                     bufferRect,
+                                     visibleRects)) {
+                return true;
+            }
+            region.numRects = visibleRects->size();
+            region.rects = &((*visibleRects)[0]);
+        } else {
+            region.numRects = 1;
+            region.rects = &(hwcLayer.displayFrame);
+        }
         hwcLayer.visibleRegionScreen = region;
     } else {
         hwcLayer.flags |= HWC_COLOR_FILL;
         ColorLayer* colorLayer = static_cast<ColorLayer*>(layerGL->GetLayer());
         hwcLayer.transform = colorLayer->GetColor().Packed();
     }
 
     mList->numHwLayers++;
@@ -407,16 +461,20 @@ HwcComposer2D::TryRender(Layer* aRoot,
         return false;
     }
 
     MOZ_ASSERT(Initialized());
     if (mList) {
         mList->numHwLayers = 0;
     }
 
+    // XXX: The clear() below means all rect vectors will be have to be
+    // reallocated. We may want to avoid this if possible
+    mVisibleRegions.clear();
+
     if (!PrepareLayerList(aRoot,
                           mScreenRect,
                           gfxMatrix(),
                           aGLWorldTransform))
     {
         LOGD("Render aborted. Nothing was drawn to the screen");
         return false;
     }
--- a/widget/gonk/HwcComposer2D.h
+++ b/widget/gonk/HwcComposer2D.h
@@ -15,24 +15,30 @@
  */
 
 #ifndef mozilla_HwcComposer2D
 #define mozilla_HwcComposer2D
 
 #include "Composer2D.h"
 #include "HWComposer.h"
 #include "Layers.h"
+#include <vector>
+#include <list>
 
 namespace mozilla {
 
 namespace layers {
 class ContainerLayer;
 class Layer;
 }
 
+//Holds a dynamically allocated vector of rectangles
+//used to decribe the complex visible region of a layer
+typedef std::vector<hwc_rect_t> RectVector;
+
 class HwcComposer2D : public android::HWComposer,
                       public mozilla::layers::Composer2D {
 public:
     HwcComposer2D();
     virtual ~HwcComposer2D();
 
     int Init(hwc_display_t aDisplay, hwc_surface_t aSurface);
 
@@ -49,13 +55,16 @@ private:
     bool ReallocLayerList();
     bool PrepareLayerList(layers::Layer* aContainer, const nsIntRect& aClip,
           const gfxMatrix& aParentTransform, const gfxMatrix& aGLWorldTransform);
 
     hwc_layer_list_t*       mList;
     nsIntRect               mScreenRect;
     int                     mMaxLayerCount;
     bool                    mColorFill;
+    //Holds all the dynamically allocated RectVectors needed
+    //to render the current frame
+    std::list<RectVector>   mVisibleRegions;
 };
 
 } // namespace mozilla
 
 #endif // mozilla_HwcComposer2D