diff --git a/include/ui/Rect.h b/include/ui/Rect.h index 916928766..6cf64eb63 100644 --- a/include/ui/Rect.h +++ b/include/ui/Rect.h @@ -160,6 +160,10 @@ public: // the input. Rect transform(uint32_t xform, int32_t width, int32_t height) const; + // this calculates (Region(*this) - exclude).bounds() efficiently + Rect reduce(const Rect& exclude) const; + + // for backward compatibility inline int32_t width() const { return getWidth(); } inline int32_t height() const { return getHeight(); } diff --git a/libs/ui/Rect.cpp b/libs/ui/Rect.cpp index 365ea13f8..b480f3a62 100644 --- a/libs/ui/Rect.cpp +++ b/libs/ui/Rect.cpp @@ -107,4 +107,35 @@ Rect Rect::transform(uint32_t xform, int32_t width, int32_t height) const { return result; } +Rect Rect::reduce(const Rect& exclude) const { + Rect result; + + uint32_t mask = 0; + mask |= (exclude.left > left) ? 1 : 0; + mask |= (exclude.top > top) ? 2 : 0; + mask |= (exclude.right < right) ? 4 : 0; + mask |= (exclude.bottom < bottom) ? 8 : 0; + + if (mask == 0) { + // crop entirely covers us + result.clear(); + } else { + result = *this; + if (!(mask & (mask - 1))) { + // power-of-2, i.e.: just one bit is set + if (mask & 1) { + result.right = exclude.left; + } else if (mask & 2) { + result.bottom = exclude.top; + } else if (mask & 4) { + result.left = exclude.right; + } else if (mask & 8) { + result.top = exclude.bottom; + } + } + } + + return result; +} + }; // namespace android diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 07f9b8b98..c15dfd538 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -270,6 +270,16 @@ uint32_t Layer::getContentTransform() const { return mCurrentTransform; } +static Rect reduce(const Rect& win, const Region& exclude) { + if (CC_LIKELY(exclude.isEmpty())) { + return win; + } + if (exclude.isRect()) { + return win.reduce(exclude.getBounds()); + } + return Region(win).subtract(exclude).getBounds(); +} + Rect Layer::computeBounds() const { const Layer::State& s(drawingState()); Rect win(s.active.w, s.active.h); @@ -277,8 +287,7 @@ Rect Layer::computeBounds() const { win.intersect(s.active.crop, &win); } // subtract the transparent region and snap to the bounds - win = Region(win).subtract(s.activeTransparentRegion).getBounds(); - return win; + return reduce(win, s.activeTransparentRegion); } Rect Layer::computeCrop(const sp& hw) const { @@ -312,6 +321,9 @@ Rect Layer::computeCrop(const sp& hw) const { // window's bounds activeCrop.intersect(Rect(s.active.w, s.active.h), &activeCrop); + // subtract the transparent region and snap to the bounds + activeCrop = reduce(activeCrop, s.activeTransparentRegion); + if (!activeCrop.isEmpty()) { // Transform the window crop to match the buffer coordinate system, // which means using the inverse of the current transform set on the @@ -669,7 +681,7 @@ void Layer::computeGeometry(const sp& hw, LayerMesh* mesh) win.intersect(s.active.crop, &win); } // subtract the transparent region and snap to the bounds - win = Region(win).subtract(s.activeTransparentRegion).getBounds(); + win = reduce(win, s.activeTransparentRegion); if (mesh) { tr.transform(mesh->mVertices[0], win.left, win.top); tr.transform(mesh->mVertices[1], win.left, win.bottom);