OSDN Git Service

Allow "opaque" flag to be updated. DO NOT MERGE
authorAndy McFadden <fadden@android.com>
Thu, 30 Jan 2014 01:17:11 +0000 (17:17 -0800)
committerCraig Mautner <cmautner@google.com>
Tue, 18 Feb 2014 23:55:42 +0000 (15:55 -0800)
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
libs/gui/SurfaceComposerClient.cpp
services/surfaceflinger/Layer.cpp
services/surfaceflinger/Layer.h
services/surfaceflinger/SurfaceFlinger.cpp

index bf4bf03..5584fb1 100644 (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()
index aafc4d2..2246f5f 100644 (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;
index 61af51f..fcc9d78 100644 (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],
index ef4a7e9..ea65ded 100644 (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;
index c00b034..86be6c3 100644 (file)
@@ -1379,7 +1379,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()) {
@@ -1624,7 +1624,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
@@ -1868,7 +1868,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;
         }