diff --git a/include/ui/Region.h b/include/ui/Region.h index ffcd429ae..ce91f3b69 100644 --- a/include/ui/Region.h +++ b/include/ui/Region.h @@ -108,6 +108,10 @@ public: inline Region& operator += (const Point& pt); + // returns true if the regions share the same underlying storage + bool isTriviallyEqual(const Region& region) const; + + /* various ways to access the rectangle list */ diff --git a/libs/ui/Region.cpp b/libs/ui/Region.cpp index 488fba32c..bf01488ca 100644 --- a/libs/ui/Region.cpp +++ b/libs/ui/Region.cpp @@ -239,6 +239,10 @@ void Region::set(uint32_t w, uint32_t h) mStorage.add(Rect(w,h)); } +bool Region::isTriviallyEqual(const Region& region) const { + return begin() == region.begin(); +} + // ---------------------------------------------------------------------------- void Region::addRectUnchecked(int l, int t, int r, int b) diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index a4c613cb8..2302367bb 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -881,8 +881,7 @@ bool Layer::setMatrix(const layer_state_t::matrix22_t& matrix) { return true; } bool Layer::setTransparentRegionHint(const Region& transparent) { - mCurrentState.sequence++; - mCurrentState.transparentRegion = transparent; + mCurrentState.requestedTransparentRegion = transparent; setTransactionFlags(eTransactionNeeded); return true; } @@ -1008,7 +1007,6 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions) swap(bufWidth, bufHeight); } - bool isFixedSize = item.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE; if (front.active != front.requested) { @@ -1061,6 +1059,17 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions) return true; } } + + // if the transparent region has changed (this test is + // conservative, but that's fine, worst case we're doing + // a bit of extra work), we latch the new one and we + // trigger a visible-region recompute. + if (!front.activeTransparentRegion.isTriviallyEqual( + front.requestedTransparentRegion)) { + front.activeTransparentRegion = front.requestedTransparentRegion; + recomputeVisibleRegions = true; + } + return false; } }; @@ -1168,7 +1177,7 @@ void Layer::dump(String8& result, char* buffer, size_t SIZE) const getTypeId(), this, getName().string()); result.append(buffer); - s.transparentRegion.dump(result, "transparentRegion"); + s.activeTransparentRegion.dump(result, "transparentRegion"); visibleRegion.dump(result, "visibleRegion"); sp client(mClientRef.promote()); diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 6bca9413a..2765db1be 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -103,7 +103,11 @@ public: uint8_t reserved[2]; int32_t sequence; // changes when visible regions can change Transform transform; - Region transparentRegion; + // the transparentRegion hint is a bit special, it's latched only + // when we receive a buffer -- this is because it's "content" + // dependent. + Region activeTransparentRegion; + Region requestedTransparentRegion; }; class LayerMesh { diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 3ed8b1b2e..5c7cf0758 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -1360,14 +1360,14 @@ void SurfaceFlinger::computeVisibleRegions( if (tr.transformed()) { if (tr.preserveRects()) { // transform the transparent region - transparentRegion = tr.transform(s.transparentRegion); + transparentRegion = tr.transform(s.activeTransparentRegion); } else { // transformation too complex, can't do the // transparent region optimization. transparentRegion.clear(); } } else { - transparentRegion = s.transparentRegion; + transparentRegion = s.activeTransparentRegion; } }