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 ISurfaceComposerClient;
/*
* Used to communicate layer information between SurfaceFlinger and its clients.
*/
struct layer_state_t {
enum {
eLayerHidden = 0x01,
eLayerHidden = 0x01, // SURFACE_HIDDEN in SurfaceControl.java
eLayerOpaque = 0x02, // SURFACE_OPAQUE
};
enum {
@ -47,6 +51,7 @@ struct layer_state_t {
eVisibilityChanged = 0x00000040,
eLayerStackChanged = 0x00000080,
eCropChanged = 0x00000100,
eOpacityChanged = 0x00000200,
};
layer_state_t()

View File

@ -309,7 +309,12 @@ status_t Composer::setFlags(const sp<SurfaceComposerClient>& client,
layer_state_t* s = getLayerStateLocked(client, id);
if (!s)
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 |= (flags & mask);
s->mask |= mask;

View File

@ -64,7 +64,6 @@ Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client,
mName("unnamed"),
mDebug(false),
mFormat(PIXEL_FORMAT_NONE),
mOpaqueLayer(true),
mTransactionFlags(0),
mQueuedFrames(0),
mCurrentTransform(0),
@ -86,7 +85,9 @@ Layer::Layer(SurfaceFlinger* flinger, const sp<Client>& client,
uint32_t layerFlags = 0;
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)
mPremultipliedAlpha = false;
@ -189,7 +190,6 @@ status_t Layer::setBuffers( uint32_t w, uint32_t h,
mSecure = (flags & ISurfaceComposerClient::eSecure) ? true : false;
mProtectedByApp = (flags & ISurfaceComposerClient::eProtectedByApp) ? true : false;
mOpaqueLayer = (flags & ISurfaceComposerClient::eOpaque);
mCurrentOpacity = getOpacityForFormat(format);
mSurfaceFlingerConsumer->setDefaultBufferSize(w, h);
@ -352,7 +352,7 @@ void Layer::setGeometry(
// this gives us only the "orientation" component of the transform
const State& s(getDrawingState());
if (!isOpaque() || s.alpha != 0xFF) {
if (!isOpaque(s) || s.alpha != 0xFF) {
layer.setBlending(mPremultipliedAlpha ?
HWC_BLENDING_PREMULT :
HWC_BLENDING_COVERAGE);
@ -596,7 +596,7 @@ void Layer::drawWithOpenGL(
texCoords[3] = vec2(right, 1.0f - top);
RenderEngine& engine(mFlinger->getRenderEngine());
engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(), s.alpha);
engine.setupLayerBlending(mPremultipliedAlpha, isOpaque(s), s.alpha);
engine.drawMesh(mMesh);
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
// layer's opaque flag.
@ -666,7 +666,7 @@ bool Layer::isOpaque() const
// if the layer has the opaque flag, then we're always opaque,
// otherwise we use the current buffer's format.
return mOpaqueLayer || mCurrentOpacity;
return ((s.flags & layer_state_t::eLayerOpaque) != 0) || mCurrentOpacity;
}
bool Layer::isProtected() const
@ -954,7 +954,8 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions)
}
// 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;
struct Reject : public SurfaceFlingerConsumer::BufferRejecter {
@ -1122,12 +1123,11 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions)
}
mCurrentOpacity = getOpacityForFormat(mActiveBuffer->format);
if (oldOpacity != isOpaque()) {
if (oldOpacity != isOpaque(s)) {
recomputeVisibleRegions = true;
}
// FIXME: postedRegion should be dirty & bounds
const Layer::State& s(getDrawingState());
Region dirtyRegion(Rect(s.active.w, s.active.h));
// 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.active.crop.left, s.active.crop.top,
s.active.crop.right, s.active.crop.bottom,
isOpaque(), contentDirty,
isOpaque(s), contentDirty,
s.alpha, s.flags,
s.transform[0][0], s.transform[0][1],
s.transform[1][0], s.transform[1][1],

View File

@ -149,8 +149,12 @@ public:
/*
* 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
@ -335,7 +339,6 @@ private:
String8 mName;
mutable bool mDebug;
PixelFormat mFormat;
bool mOpaqueLayer;
// these are protected by an external lock
State mCurrentState;

View File

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