From 4125a4ffaf374ca9c0773f256998557d3325343e Mon Sep 17 00:00:00 2001 From: Andy McFadden Date: Wed, 29 Jan 2014 17:17:11 -0800 Subject: [PATCH] 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 --- include/private/gui/LayerState.h | 7 ++++++- libs/gui/SurfaceComposerClient.cpp | 7 ++++++- services/surfaceflinger/Layer.cpp | 22 +++++++++++----------- services/surfaceflinger/Layer.h | 7 +++++-- services/surfaceflinger/SurfaceFlinger.cpp | 8 +++++--- 5 files changed, 33 insertions(+), 18 deletions(-) diff --git a/include/private/gui/LayerState.h b/include/private/gui/LayerState.h index bf4bf034f..5584fb172 100644 --- a/include/private/gui/LayerState.h +++ b/include/private/gui/LayerState.h @@ -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() diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index aafc4d255..2246f5f9b 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -309,7 +309,12 @@ status_t Composer::setFlags(const sp& 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; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 61af51faf..fcc9d789d 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -64,7 +64,6 @@ Layer::Layer(SurfaceFlinger* flinger, const sp& 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, 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& 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 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], diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index ef4a7e918..ea65ded52 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -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; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index af3185237..40ca8ebf9 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -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& 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; }