latch transparent region hint only when we get a new frame

since the transparent region hint really depends on the
content of the window containing the SurfaceView
(it's calculated by the view hierarchy based on
overlapping views), it makes sense to latch it only when
the content of the window (the app) changes.

This should help fixing drawing artifacts when changing the
layout of a window containing a SurfaceView.

Bug: 8511430
Change-Id: Ic3aa668495293cb4d82a2cd7dcf3b6a337287678
This commit is contained in:
Mathias Agopian 2013-04-02 18:30:32 -07:00
parent 128fcea1c6
commit 2ca79399b9
5 changed files with 28 additions and 7 deletions

View File

@ -108,6 +108,10 @@ public:
inline Region& operator += (const Point& pt); 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 */ /* various ways to access the rectangle list */

View File

@ -239,6 +239,10 @@ void Region::set(uint32_t w, uint32_t h)
mStorage.add(Rect(w,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) void Region::addRectUnchecked(int l, int t, int r, int b)

View File

@ -881,8 +881,7 @@ bool Layer::setMatrix(const layer_state_t::matrix22_t& matrix) {
return true; return true;
} }
bool Layer::setTransparentRegionHint(const Region& transparent) { bool Layer::setTransparentRegionHint(const Region& transparent) {
mCurrentState.sequence++; mCurrentState.requestedTransparentRegion = transparent;
mCurrentState.transparentRegion = transparent;
setTransactionFlags(eTransactionNeeded); setTransactionFlags(eTransactionNeeded);
return true; return true;
} }
@ -1008,7 +1007,6 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions)
swap(bufWidth, bufHeight); swap(bufWidth, bufHeight);
} }
bool isFixedSize = item.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE; bool isFixedSize = item.mScalingMode != NATIVE_WINDOW_SCALING_MODE_FREEZE;
if (front.active != front.requested) { if (front.active != front.requested) {
@ -1061,6 +1059,17 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions)
return true; 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; return false;
} }
}; };
@ -1168,7 +1177,7 @@ void Layer::dump(String8& result, char* buffer, size_t SIZE) const
getTypeId(), this, getName().string()); getTypeId(), this, getName().string());
result.append(buffer); result.append(buffer);
s.transparentRegion.dump(result, "transparentRegion"); s.activeTransparentRegion.dump(result, "transparentRegion");
visibleRegion.dump(result, "visibleRegion"); visibleRegion.dump(result, "visibleRegion");
sp<Client> client(mClientRef.promote()); sp<Client> client(mClientRef.promote());

View File

@ -103,7 +103,11 @@ public:
uint8_t reserved[2]; uint8_t reserved[2];
int32_t sequence; // changes when visible regions can change int32_t sequence; // changes when visible regions can change
Transform transform; 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 { class LayerMesh {

View File

@ -1360,14 +1360,14 @@ void SurfaceFlinger::computeVisibleRegions(
if (tr.transformed()) { if (tr.transformed()) {
if (tr.preserveRects()) { if (tr.preserveRects()) {
// transform the transparent region // transform the transparent region
transparentRegion = tr.transform(s.transparentRegion); transparentRegion = tr.transform(s.activeTransparentRegion);
} else { } else {
// transformation too complex, can't do the // transformation too complex, can't do the
// transparent region optimization. // transparent region optimization.
transparentRegion.clear(); transparentRegion.clear();
} }
} else { } else {
transparentRegion = s.transparentRegion; transparentRegion = s.activeTransparentRegion;
} }
} }