Allow "opaque" flag to be updated

Moves the "opaque layer" from Layer to Layer::State.  This allows
it to be updated as part of a transaction.

Bug 12387406

Change-Id: I0a114ce6adf77cd12fb08f96e0691b76c475768d
This commit is contained in:
Andy McFadden 2014-01-29 17:17:11 -08:00
parent a9d5701b03
commit 4125a4ffaf
5 changed files with 33 additions and 18 deletions

View File

@ -30,11 +30,15 @@ namespace android {
class Parcel; class Parcel;
class ISurfaceComposerClient; class ISurfaceComposerClient;
/*
* Used to communicate layer information between SurfaceFlinger and its clients.
*/
struct layer_state_t { struct layer_state_t {
enum { enum {
eLayerHidden = 0x01, eLayerHidden = 0x01, // SURFACE_HIDDEN in SurfaceControl.java
eLayerOpaque = 0x02, // SURFACE_OPAQUE
}; };
enum { enum {
@ -47,6 +51,7 @@ struct layer_state_t {
eVisibilityChanged = 0x00000040, eVisibilityChanged = 0x00000040,
eLayerStackChanged = 0x00000080, eLayerStackChanged = 0x00000080,
eCropChanged = 0x00000100, eCropChanged = 0x00000100,
eOpacityChanged = 0x00000200,
}; };
layer_state_t() layer_state_t()

View File

@ -309,7 +309,12 @@ status_t Composer::setFlags(const sp<SurfaceComposerClient>& client,
layer_state_t* s = getLayerStateLocked(client, id); layer_state_t* s = getLayerStateLocked(client, id);
if (!s) if (!s)
return BAD_INDEX; return BAD_INDEX;
s->what |= layer_state_t::eVisibilityChanged; if (mask & layer_state_t::eLayerOpaque) {
s->what |= layer_state_t::eOpacityChanged;
}
if (mask & layer_state_t::eLayerHidden) {
s->what |= layer_state_t::eVisibilityChanged;
}
s->flags &= ~mask; s->flags &= ~mask;
s->flags |= (flags & mask); s->flags |= (flags & mask);
s->mask |= mask; s->mask |= mask;

View File

@ -64,7 +64,6 @@ Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client,
mName("unnamed"), mName("unnamed"),
mDebug(false), mDebug(false),
mFormat(PIXEL_FORMAT_NONE), mFormat(PIXEL_FORMAT_NONE),
mOpaqueLayer(true),
mTransactionFlags(0), mTransactionFlags(0),
mQueuedFrames(0), mQueuedFrames(0),
mCurrentTransform(0), mCurrentTransform(0),
@ -86,7 +85,9 @@ Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client,
uint32_t layerFlags = 0; uint32_t layerFlags = 0;
if (flags & ISurfaceComposerClient::eHidden) if (flags & ISurfaceComposerClient::eHidden)
layerFlags = layer_state_t::eLayerHidden; layerFlags |= layer_state_t::eLayerHidden;
if (flags & ISurfaceComposerClient::eOpaque)
layerFlags |= layer_state_t::eLayerOpaque;
if (flags & ISurfaceComposerClient::eNonPremultiplied) if (flags & ISurfaceComposerClient::eNonPremultiplied)
mPremultipliedAlpha = false; mPremultipliedAlpha = false;
@ -189,7 +190,6 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h,
mSecure = (flags & ISurfaceComposerClient::eSecure) ? true : false; mSecure = (flags & ISurfaceComposerClient::eSecure) ? true : false;
mProtectedByApp = (flags & ISurfaceComposerClient::eProtectedByApp) ? true : false; mProtectedByApp = (flags & ISurfaceComposerClient::eProtectedByApp) ? true : false;
mOpaqueLayer = (flags & ISurfaceComposerClient::eOpaque);
mCurrentOpacity = getOpacityForFormat(format); mCurrentOpacity = getOpacityForFormat(format);
mSurfaceFlingerConsumer->setDefaultBufferSize(w, h); mSurfaceFlingerConsumer->setDefaultBufferSize(w, h);
@ -352,7 +352,7 @@ void Layer::setGeometry(
// this gives us only the "orientation" component of the transform // this gives us only the "orientation" component of the transform
const State& s(getDrawingState()); const State& s(getDrawingState());
if (!isOpaque() || s.alpha != 0xFF) { if (!isOpaque(s) || s.alpha != 0xFF) {
layer.setBlending(mPremultipliedAlpha ? layer.setBlending(mPremultipliedAlpha ?
HWC_BLENDING_PREMULT : HWC_BLENDING_PREMULT :
HWC_BLENDING_COVERAGE); HWC_BLENDING_COVERAGE);
@ -596,7 +596,7 @@ void Layer::drawWithOpenGL(
texCoords[3] = vec2(right, 1.0f - top); texCoords[3] = vec2(right, 1.0f - top);
RenderEngine& engine(mFlinger->getRenderEngine()); RenderEngine& engine(mFlinger->getRenderEngine());
engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(), s.alpha); engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), s.alpha);
engine.drawMesh(mMesh); engine.drawMesh(mMesh);
engine.disableBlending(); engine.disableBlending();
} }
@ -656,7 +656,7 @@ void Layer::computeGeometry(const sp<const DisplayDevice>& hw, Mesh& mesh) const
} }
} }
bool Layer::isOpaque() const bool Layer::isOpaque(const Layer::State& s) const
{ {
// if we don't have a buffer yet, we're translucent regardless of the // if we don't have a buffer yet, we're translucent regardless of the
// layer's opaque flag. // layer's opaque flag.
@ -666,7 +666,7 @@ bool Layer::isOpaque() const
// if the layer has the opaque flag, then we're always opaque, // if the layer has the opaque flag, then we're always opaque,
// otherwise we use the current buffer's format. // otherwise we use the current buffer's format.
return mOpaqueLayer || mCurrentOpacity; return ((s.flags & layer_state_t::eLayerOpaque) != 0) || mCurrentOpacity;
} }
bool Layer::isProtected() const bool Layer::isProtected() const
@ -954,7 +954,8 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions)
} }
// Capture the old state of the layer for comparisons later // Capture the old state of the layer for comparisons later
const bool oldOpacity = isOpaque(); const State& s(getDrawingState());
const bool oldOpacity = isOpaque(s);
sp<GraphicBuffer> oldActiveBuffer = mActiveBuffer; sp<GraphicBuffer> oldActiveBuffer = mActiveBuffer;
struct Reject : public SurfaceFlingerConsumer::BufferRejecter { struct Reject : public SurfaceFlingerConsumer::BufferRejecter {
@ -1122,12 +1123,11 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions)
} }
mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format); mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format);
if (oldOpacity != isOpaque()) { if (oldOpacity != isOpaque(s)) {
recomputeVisibleRegions = true; recomputeVisibleRegions = true;
} }
// FIXME: postedRegion should be dirty & bounds // FIXME: postedRegion should be dirty & bounds
const Layer::State& s(getDrawingState());
Region dirtyRegion(Rect(s.active.w, s.active.h)); Region dirtyRegion(Rect(s.active.w, s.active.h));
// transform the dirty region to window-manager space // transform the dirty region to window-manager space
@ -1188,7 +1188,7 @@ void Layer::dump(String8& result, Colorizer& colorizer) const
s.layerStack, s.z, s.transform.tx(), s.transform.ty(), s.active.w, s.active.h, s.layerStack, s.z, s.transform.tx(), s.transform.ty(), s.active.w, s.active.h,
s.active.crop.left, s.active.crop.top, s.active.crop.left, s.active.crop.top,
s.active.crop.right, s.active.crop.bottom, s.active.crop.right, s.active.crop.bottom,
isOpaque(), contentDirty, isOpaque(s), contentDirty,
s.alpha, s.flags, s.alpha, s.flags,
s.transform[0][0], s.transform[0][1], s.transform[0][0], s.transform[0][1],
s.transform[1][0], s.transform[1][1], s.transform[1][0], s.transform[1][1],

View File

@ -149,8 +149,12 @@ public:
/* /*
* isOpaque - true if this surface is opaque * isOpaque - true if this surface is opaque
*
* This takes into account the buffer format (i.e. whether or not the
* pixel format includes an alpha channel) and the "opaque" flag set
* on the layer. It does not examine the current plane alpha value.
*/ */
virtual bool isOpaque() const; virtual bool isOpaque(const Layer::State& s) const;
/* /*
* isSecure - true if this surface is secure, that is if it prevents * isSecure - true if this surface is secure, that is if it prevents
@ -335,7 +339,6 @@ private:
String8 mName; String8 mName;
mutable bool mDebug; mutable bool mDebug;
PixelFormat mFormat; PixelFormat mFormat;
bool mOpaqueLayer;
// these are protected by an external lock // these are protected by an external lock
State mCurrentState; State mCurrentState;

View File

@ -1380,7 +1380,7 @@ void SurfaceFlinger::computeVisibleRegions(
// handle hidden surfaces by setting the visible region to empty // handle hidden surfaces by setting the visible region to empty
if (CC_LIKELY(layer->isVisible())) { if (CC_LIKELY(layer->isVisible())) {
const bool translucent = !layer->isOpaque(); const bool translucent = !layer->isOpaque(s);
Rect bounds(s.transform.transform(layer->computeBounds())); Rect bounds(s.transform.transform(layer->computeBounds()));
visibleRegion.set(bounds); visibleRegion.set(bounds);
if (!visibleRegion.isEmpty()) { if (!visibleRegion.isEmpty()) {
@ -1629,7 +1629,7 @@ void SurfaceFlinger::doComposeSurfaces(const sp<const DisplayDevice>& hw, const
const Layer::State& state(layer->getDrawingState()); const Layer::State& state(layer->getDrawingState());
if ((cur->getHints() & HWC_HINT_CLEAR_FB) if ((cur->getHints() & HWC_HINT_CLEAR_FB)
&& i && i
&& layer->isOpaque() && (state.alpha == 0xFF) && layer->isOpaque(state) && (state.alpha == 0xFF)
&& hasGlesComposition) { && hasGlesComposition) {
// never clear the very first layer since we're // never clear the very first layer since we're
// guaranteed the FB is already cleared // guaranteed the FB is already cleared
@ -1873,7 +1873,9 @@ uint32_t SurfaceFlinger::setClientStateLocked(
if (layer->setTransparentRegionHint(s.transparentRegion)) if (layer->setTransparentRegionHint(s.transparentRegion))
flags |= eTraversalNeeded; flags |= eTraversalNeeded;
} }
if (what & layer_state_t::eVisibilityChanged) { if ((what & layer_state_t::eVisibilityChanged) ||
(what & layer_state_t::eOpacityChanged)) {
// TODO: should we just use an eFlagsChanged for this?
if (layer->setFlags(s.flags, s.mask)) if (layer->setFlags(s.flags, s.mask))
flags |= eTraversalNeeded; flags |= eTraversalNeeded;
} }