diff options
author | 2016-10-24 16:27:39 -0700 | |
---|---|---|
committer | 2017-01-24 13:04:43 -0800 | |
commit | 1f0a16a5d7cd00ba7fda82e7d315afa1fd1303b9 (patch) | |
tree | 28a321d2992c122a17079f523f6e2bacfc5c1123 | |
parent | 2047fae0cfed99c425dc7333f31d309e5b8ee1ba (diff) |
SurfaceFlinger and libgui: Support for child layers.
Add support for parenting Layers in a tree. Layers
follow scene-graph style rules, that is to say:
1. A child is cropped to the final bounds of the parent.
2. A child inherits the parent's transform (including position)
3. A child's Z ordering is relative to the parent and bounded between
the parents siblings.
4. A childs lifetime is bounded by it's parents lifetime.
Test: New tests in Transaction_test plus manual testing with later branches.
Change-Id: I96f8ad863665b9a70b6f845561344c297b7e6eff
-rw-r--r-- | include/gui/ISurfaceComposerClient.h | 1 | ||||
-rw-r--r-- | include/gui/SurfaceComposerClient.h | 3 | ||||
-rw-r--r-- | libs/gui/ISurfaceComposerClient.cpp | 11 | ||||
-rw-r--r-- | libs/gui/SurfaceComposerClient.cpp | 10 | ||||
-rw-r--r-- | services/surfaceflinger/Client.cpp | 21 | ||||
-rw-r--r-- | services/surfaceflinger/Client.h | 1 | ||||
-rw-r--r-- | services/surfaceflinger/Layer.cpp | 274 | ||||
-rw-r--r-- | services/surfaceflinger/Layer.h | 46 | ||||
-rw-r--r-- | services/surfaceflinger/LayerDim.cpp | 2 | ||||
-rw-r--r-- | services/surfaceflinger/LayerVector.cpp | 7 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 197 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 12 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger_hwc1.cpp | 189 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceInterceptor.cpp | 8 | ||||
-rw-r--r-- | services/surfaceflinger/tests/Android.mk | 1 | ||||
-rw-r--r-- | services/surfaceflinger/tests/Transaction_test.cpp | 119 |
16 files changed, 680 insertions, 222 deletions
diff --git a/include/gui/ISurfaceComposerClient.h b/include/gui/ISurfaceComposerClient.h index 4a4efb631a..0a4d35dca5 100644 --- a/include/gui/ISurfaceComposerClient.h +++ b/include/gui/ISurfaceComposerClient.h @@ -60,6 +60,7 @@ public: virtual status_t createSurface( const String8& name, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, + const sp<IBinder>& parent, sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp) = 0; diff --git a/include/gui/SurfaceComposerClient.h b/include/gui/SurfaceComposerClient.h index 4356a58c51..789dc7c932 100644 --- a/include/gui/SurfaceComposerClient.h +++ b/include/gui/SurfaceComposerClient.h @@ -105,7 +105,8 @@ public: uint32_t w, // width in pixel uint32_t h, // height in pixel PixelFormat format, // pixel-format desired - uint32_t flags = 0 // usage flags + uint32_t flags = 0, // usage flags + SurfaceControl* parent = nullptr // parent ); //! Create a virtual display diff --git a/libs/gui/ISurfaceComposerClient.cpp b/libs/gui/ISurfaceComposerClient.cpp index 47cb0473e8..b2036dcadb 100644 --- a/libs/gui/ISurfaceComposerClient.cpp +++ b/libs/gui/ISurfaceComposerClient.cpp @@ -56,7 +56,7 @@ public: virtual status_t createSurface(const String8& name, uint32_t width, uint32_t height, PixelFormat format, uint32_t flags, - sp<IBinder>* handle, + const sp<IBinder>& parent, sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp) { Parcel data, reply; data.writeInterfaceToken(ISurfaceComposerClient::getInterfaceDescriptor()); @@ -65,6 +65,9 @@ public: data.writeUint32(height); data.writeInt32(static_cast<int32_t>(format)); data.writeUint32(flags); + if (parent != nullptr) { + data.writeStrongBinder(parent); + } remote()->transact(CREATE_SURFACE, data, &reply); *handle = reply.readStrongBinder(); *gbp = interface_cast<IGraphicBufferProducer>(reply.readStrongBinder()); @@ -145,10 +148,14 @@ status_t BnSurfaceComposerClient::onTransact( uint32_t height = data.readUint32(); PixelFormat format = static_cast<PixelFormat>(data.readInt32()); uint32_t createFlags = data.readUint32(); + sp<IBinder> parent = nullptr; + if (data.dataAvail() > 0) { + parent = data.readStrongBinder(); + } sp<IBinder> handle; sp<IGraphicBufferProducer> gbp; status_t result = createSurface(name, width, height, format, - createFlags, &handle, &gbp); + createFlags, parent, &handle, &gbp); reply->writeStrongBinder(handle); reply->writeStrongBinder(IInterface::asBinder(gbp)); reply->writeInt32(result); diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 540dbd9238..c2be6eb751 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -610,13 +610,19 @@ sp<SurfaceControl> SurfaceComposerClient::createSurface( uint32_t w, uint32_t h, PixelFormat format, - uint32_t flags) + uint32_t flags, + SurfaceControl* parent) { sp<SurfaceControl> sur; if (mStatus == NO_ERROR) { sp<IBinder> handle; + sp<IBinder> parentHandle; sp<IGraphicBufferProducer> gbp; - status_t err = mClient->createSurface(name, w, h, format, flags, + + if (parent != nullptr) { + parentHandle = parent->getHandle(); + } + status_t err = mClient->createSurface(name, w, h, format, flags, parentHandle, &handle, &gbp); ALOGE_IF(err, "SurfaceComposerClient::createSurface error %s", strerror(-err)); if (err == NO_ERROR) { diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp index e14a59b46d..7e04fda6de 100644 --- a/services/surfaceflinger/Client.cpp +++ b/services/surfaceflinger/Client.cpp @@ -106,14 +106,22 @@ status_t Client::onTransact( status_t Client::createSurface( const String8& name, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, + const sp<IBinder>& parentHandle, sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp) { + sp<Layer> parent = nullptr; + if (parentHandle != nullptr) { + parent = getLayerUser(parentHandle); + if (parent == nullptr) { + return NAME_NOT_FOUND; + } + } + /* * createSurface must be called from the GL thread so that it can * have access to the GL context. */ - class MessageCreateLayer : public MessageBase { SurfaceFlinger* flinger; Client* client; @@ -124,26 +132,29 @@ status_t Client::createSurface( uint32_t w, h; PixelFormat format; uint32_t flags; + sp<Layer>* parent; public: MessageCreateLayer(SurfaceFlinger* flinger, const String8& name, Client* client, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, sp<IBinder>* handle, - sp<IGraphicBufferProducer>* gbp) + sp<IGraphicBufferProducer>* gbp, + sp<Layer>* parent) : flinger(flinger), client(client), handle(handle), gbp(gbp), result(NO_ERROR), - name(name), w(w), h(h), format(format), flags(flags) { + name(name), w(w), h(h), format(format), flags(flags), + parent(parent) { } status_t getResult() const { return result; } virtual bool handler() { result = flinger->createLayer(name, client, w, h, format, flags, - handle, gbp); + handle, gbp, parent); return true; } }; sp<MessageBase> msg = new MessageCreateLayer(mFlinger.get(), - name, this, w, h, format, flags, handle, gbp); + name, this, w, h, format, flags, handle, gbp, &parent); mFlinger->postMessageSync(msg); return static_cast<MessageCreateLayer*>( msg.get() )->getResult(); } diff --git a/services/surfaceflinger/Client.h b/services/surfaceflinger/Client.h index 9c7d05042a..2a9825c687 100644 --- a/services/surfaceflinger/Client.h +++ b/services/surfaceflinger/Client.h @@ -55,6 +55,7 @@ private: virtual status_t createSurface( const String8& name, uint32_t w, uint32_t h,PixelFormat format, uint32_t flags, + const sp<IBinder>& parent, sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp); diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index 5b61c2511b..6fd9cd75b3 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -280,6 +280,9 @@ void Layer::onSidebandStreamChanged() { // it's removed from the drawing state list) void Layer::onRemoved() { mSurfaceFlingerConsumer->abandon(); + for (const auto& child : mCurrentChildren) { + child->onRemoved(); + } } // --------------------------------------------------------------------------- @@ -362,6 +365,40 @@ static Rect reduce(const Rect& win, const Region& exclude) { return Region(win).subtract(exclude).getBounds(); } +Rect Layer::computeScreenBounds(bool reduceTransparentRegion) const { + const Layer::State& s(getDrawingState()); + Rect win(s.active.w, s.active.h); + + if (!s.crop.isEmpty()) { + win.intersect(s.crop, &win); + } + + Transform t = getTransform(); + win = t.transform(win); + + const sp<Layer>& p = getParent(); + // Now we need to calculate the parent bounds, so we can clip ourselves to those. + // When calculating the parent bounds for purposes of clipping, + // we don't need to constrain the parent to its transparent region. + // The transparent region is an optimization based on the + // buffer contents of the layer, but does not affect the space allocated to + // it by policy, and thus children should be allowed to extend into the + // parent's transparent region. In fact one of the main uses, is to reduce + // buffer allocation size in cases where a child window sits behind a main window + // (by marking the hole in the parent window as a transparent region) + if (p != nullptr) { + Rect bounds = p->computeScreenBounds(false); + bounds.intersect(win, &win); + } + + if (reduceTransparentRegion) { + auto const screenTransparentRegion = t.transform(s.activeTransparentRegion); + win = reduce(win, screenTransparentRegion); + } + + return win; +} + Rect Layer::computeBounds() const { const Layer::State& s(getDrawingState()); return computeBounds(s.activeTransparentRegion); @@ -374,15 +411,25 @@ Rect Layer::computeBounds(const Region& activeTransparentRegion) const { if (!s.crop.isEmpty()) { win.intersect(s.crop, &win); } + + Rect bounds = win; + const auto& p = getParent(); + if (p != nullptr) { + bounds = p->computeScreenBounds(); + } + + Transform t = getTransform(); + if (p != nullptr) { + win = t.transform(win); + win.intersect(bounds, &win); + win = t.inverse().transform(win); + } + // subtract the transparent region and snap to the bounds return reduce(win, activeTransparentRegion); } -gfx::FloatRect Layer::computeCrop(const sp<const DisplayDevice>& hw) const { - // the content crop is the area of the content that gets scaled to the - // layer's size. - gfx::FloatRect crop = getContentCrop().toFloatRect(); - +Rect Layer::computeInitialCrop(const sp<const DisplayDevice>& hw) const { // the crop is the area of the window that gets cropped, but not // scaled in any ways. const State& s(getDrawingState()); @@ -399,7 +446,8 @@ gfx::FloatRect Layer::computeCrop(const sp<const DisplayDevice>& hw) const { activeCrop = s.crop; } - activeCrop = s.active.transform.transform(activeCrop); + Transform t = getTransform(); + activeCrop = t.transform(activeCrop); if (!activeCrop.intersect(hw->getViewport(), &activeCrop)) { activeCrop.clear(); } @@ -408,7 +456,27 @@ gfx::FloatRect Layer::computeCrop(const sp<const DisplayDevice>& hw) const { activeCrop.clear(); } } - activeCrop = s.active.transform.inverse().transform(activeCrop); + return activeCrop; +} + +gfx::FloatRect Layer::computeCrop(const sp<const DisplayDevice>& hw) const { + // the content crop is the area of the content that gets scaled to the + // layer's size. This is in buffer space. + gfx::FloatRect crop = getContentCrop().toFloatRect(); + + // In addition there is a WM-specified crop we pull from our drawing state. + const State& s(getDrawingState()); + + // Screen space to make reduction to parent crop clearer. + Rect activeCrop = computeInitialCrop(hw); + const auto& p = getParent(); + if (p != nullptr) { + auto parentCrop = p->computeInitialCrop(hw); + activeCrop.intersect(parentCrop, &activeCrop); + } + Transform t = getTransform(); + // Back to layer space to work with the content crop. + activeCrop = t.inverse().transform(activeCrop); // This needs to be here as transform.transform(Rect) computes the // transformed rect and then takes the bounding box of the result before @@ -535,9 +603,10 @@ void Layer::setGeometry( // apply the layer's transform, followed by the display's global transform // here we're guaranteed that the layer's transform preserves rects Region activeTransparentRegion(s.activeTransparentRegion); + Transform t = getTransform(); if (!s.crop.isEmpty()) { Rect activeCrop(s.crop); - activeCrop = s.active.transform.transform(activeCrop); + activeCrop = t.transform(activeCrop); #ifdef USE_HWC2 if(!activeCrop.intersect(displayDevice->getViewport(), &activeCrop)) { #else @@ -545,7 +614,7 @@ void Layer::setGeometry( #endif activeCrop.clear(); } - activeCrop = s.active.transform.inverse().transform(activeCrop, true); + activeCrop = t.inverse().transform(activeCrop, true); // This needs to be here as transform.transform(Rect) computes the // transformed rect and then takes the bounding box of the result before // returning. This means @@ -564,7 +633,8 @@ void Layer::setGeometry( activeTransparentRegion.orSelf(Rect(activeCrop.right, activeCrop.top, s.active.w, activeCrop.bottom)); } - Rect frame(s.active.transform.transform(computeBounds(activeTransparentRegion))); + + Rect frame(t.transform(computeBounds(activeTransparentRegion))); if (!s.finalCrop.isEmpty()) { if(!frame.intersect(s.finalCrop, &frame)) { frame.clear(); @@ -625,7 +695,7 @@ void Layer::setGeometry( */ const Transform bufferOrientation(mCurrentTransform); - Transform transform(tr * s.active.transform * bufferOrientation); + Transform transform(tr * t * bufferOrientation); if (mSurfaceFlingerConsumer->getTransformToDisplayInverse()) { /* @@ -811,7 +881,7 @@ void Layer::updateCursorPosition(const sp<const DisplayDevice>& displayDevice) { } // Subtract the transparent region and snap to the bounds Rect bounds = reduce(win, s.activeTransparentRegion); - Rect frame(s.active.transform.transform(bounds)); + Rect frame(getTransform().transform(bounds)); frame.intersect(displayDevice->getViewport(), &frame); if (!s.finalCrop.isEmpty()) { frame.intersect(s.finalCrop, &frame); @@ -860,7 +930,7 @@ Rect Layer::getPosition( } // subtract the transparent region and snap to the bounds Rect bounds = reduce(win, s.activeTransparentRegion); - Rect frame(s.active.transform.transform(bounds)); + Rect frame(getTransform().transform(bounds)); frame.intersect(hw->getViewport(), &frame); if (!s.finalCrop.isEmpty()) { frame.intersect(s.finalCrop, &frame); @@ -903,15 +973,14 @@ void Layer::onDraw(const sp<const DisplayDevice>& hw, const Region& clip, // figure out if there is something below us Region under; - const LayerVector& drawingLayers( - mFlinger->mDrawingState.layersSortedByZ); - const size_t count = drawingLayers.size(); - for (size_t i=0 ; i<count ; ++i) { - const sp<Layer>& layer(drawingLayers[i]); - if (layer.get() == static_cast<Layer const*>(this)) - break; + bool finished = false; + mFlinger->mDrawingState.layersSortedByZ.traverseInZOrder([&](Layer* layer) { + if (finished || layer == static_cast<Layer const*>(this)) { + finished = true; + return; + } under.orSelf( hw->getTransform().transform(layer->visibleRegion) ); - } + }); // if not everything below us is covered, we plug the holes! Region holes(clip.subtract(under)); if (!holes.isEmpty()) { @@ -1023,12 +1092,13 @@ void Layer::drawWithOpenGL(const sp<const DisplayDevice>& hw, */ Rect win(computeBounds()); + Transform t = getTransform(); if (!s.finalCrop.isEmpty()) { - win = s.active.transform.transform(win); + win = t.transform(win); if (!win.intersect(s.finalCrop, &win)) { win.clear(); } - win = s.active.transform.inverse().transform(win); + win = t.inverse().transform(win); if (!win.intersect(computeBounds(), &win)) { win.clear(); } @@ -1228,25 +1298,21 @@ void Layer::computeGeometry(const sp<const DisplayDevice>& hw, Mesh& mesh, bool useIdentityTransform) const { const Layer::State& s(getDrawingState()); - const Transform tr(hw->getTransform()); + const Transform hwTransform(hw->getTransform()); const uint32_t hw_h = hw->getHeight(); - Rect win(s.active.w, s.active.h); - if (!s.crop.isEmpty()) { - win.intersect(s.crop, &win); - } - // subtract the transparent region and snap to the bounds - win = reduce(win, s.activeTransparentRegion); + Rect win = computeBounds(); vec2 lt = vec2(win.left, win.top); vec2 lb = vec2(win.left, win.bottom); vec2 rb = vec2(win.right, win.bottom); vec2 rt = vec2(win.right, win.top); + Transform layerTransform = getTransform(); if (!useIdentityTransform) { - lt = s.active.transform.transform(lt); - lb = s.active.transform.transform(lb); - rb = s.active.transform.transform(rb); - rt = s.active.transform.transform(rt); + lt = layerTransform.transform(lt); + lb = layerTransform.transform(lb); + rb = layerTransform.transform(rb); + rt = layerTransform.transform(rt); } if (!s.finalCrop.isEmpty()) { @@ -1257,10 +1323,10 @@ void Layer::computeGeometry(const sp<const DisplayDevice>& hw, Mesh& mesh, } Mesh::VertexArray<vec2> position(mesh.getPositionArray<vec2>()); - position[0] = tr.transform(lt); - position[1] = tr.transform(lb); - position[2] = tr.transform(rb); - position[3] = tr.transform(rt); + position[0] = hwTransform.transform(lt); + position[1] = hwTransform.transform(lb); + position[2] = hwTransform.transform(rb); + position[3] = hwTransform.transform(rt); for (size_t i=0 ; i<4 ; i++) { position[i].y = hw_h - position[i].y; } @@ -1542,11 +1608,7 @@ uint32_t Layer::doTransaction(uint32_t flags) { // that transactions for layers depending on this layer's frames becoming // visible are not blocked if (c.flags & layer_state_t::eLayerHidden) { - Mutex::Autolock lock(mLocalSyncPointMutex); - for (auto& point : mLocalSyncPoints) { - point->setFrameAvailable(); - } - mLocalSyncPoints.clear(); + clearSyncPoints(); } // Commit the transaction @@ -1585,6 +1647,18 @@ bool Layer::setPosition(float x, float y, bool immediate) { return true; } +bool Layer::setChildLayer(const sp<Layer>& childLayer, int32_t z) { + ssize_t idx = mCurrentChildren.indexOf(childLayer); + if (idx < 0) { + return false; + } + if (childLayer->setLayer(z)) { + mCurrentChildren.removeAt(idx); + mCurrentChildren.add(childLayer); + } + return true; +} + bool Layer::setLayer(int32_t z) { if (mCurrentState.z == z) return false; @@ -1594,6 +1668,7 @@ bool Layer::setLayer(int32_t z) { setTransactionFlags(eTransactionNeeded); return true; } + bool Layer::setSize(uint32_t w, uint32_t h) { if (mCurrentState.requested.w == w && mCurrentState.requested.h == h) return false; @@ -1699,6 +1774,14 @@ bool Layer::setDataSpace(android_dataspace dataSpace) { return true; } +uint32_t Layer::getLayerStack() const { + auto p = getParent(); + if (p == nullptr) { + return getDrawingState().layerStack; + } + return p->getLayerStack(); +} + void Layer::deferTransactionUntil(const sp<IBinder>& handle, uint64_t frameNumber) { mCurrentState.handle = handle; @@ -1827,13 +1910,22 @@ void Layer::releasePendingBuffer(nsecs_t dequeueReadyTime) { } #endif +bool Layer::isHiddenByPolicy() const { + const Layer::State& s(mDrawingState); + const auto& parent = getParent(); + if (parent != nullptr && parent->isHiddenByPolicy()) { + return true; + } + return s.flags & layer_state_t::eLayerHidden; +} + bool Layer::isVisible() const { const Layer::State& s(mDrawingState); #ifdef USE_HWC2 - return !(s.flags & layer_state_t::eLayerHidden) && s.alpha > 0.0f + return !(isHiddenByPolicy()) && s.alpha > 0.0f && (mActiveBuffer != NULL || mSidebandStream != NULL); #else - return !(s.flags & layer_state_t::eLayerHidden) && s.alpha + return !(isHiddenByPolicy()) && s.alpha && (mActiveBuffer != NULL || mSidebandStream != NULL); #endif } @@ -1878,7 +1970,7 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) recomputeVisibleRegions = true; const State& s(getDrawingState()); - return s.active.transform.transform(Region(Rect(s.active.w, s.active.h))); + return getTransform().transform(Region(Rect(s.active.w, s.active.h))); } Region outDirtyRegion; @@ -2067,7 +2159,7 @@ Region Layer::latchBuffer(bool& recomputeVisibleRegions, nsecs_t latchTime) Region dirtyRegion(Rect(s.active.w, s.active.h)); // transform the dirty region to window-manager space - outDirtyRegion = (s.active.transform.transform(dirtyRegion)); + outDirtyRegion = (getTransform().transform(dirtyRegion)); return outDirtyRegion; } @@ -2130,7 +2222,9 @@ void Layer::dump(String8& result, Colorizer& colorizer) const "alpha=0x%02x, flags=0x%08x, tr=[%.2f, %.2f][%.2f, %.2f]\n" #endif " client=%p\n", - s.layerStack, s.z, s.active.transform.tx(), s.active.transform.ty(), s.active.w, s.active.h, + getLayerStack(), s.z, + s.active.transform.tx(), s.active.transform.ty(), + s.active.w, s.active.h, s.crop.left, s.crop.top, s.crop.right, s.crop.bottom, s.finalCrop.left, s.finalCrop.top, @@ -2263,6 +2357,90 @@ bool Layer::getTransformToDisplayInverse() const { return mSurfaceFlingerConsumer->getTransformToDisplayInverse(); } +void Layer::addChild(const sp<Layer>& layer) { + mCurrentChildren.add(layer); + layer->setParent(this); +} + +ssize_t Layer::removeChild(const sp<Layer>& layer) { + layer->setParent(nullptr); + return mCurrentChildren.remove(layer); +} + +void Layer::setParent(const sp<Layer>& layer) { + mParent = layer; +} + +void Layer::clearSyncPoints() { + for (const auto& child : mCurrentChildren) { + child->clearSyncPoints(); + } + + Mutex::Autolock lock(mLocalSyncPointMutex); + for (auto& point : mLocalSyncPoints) { + point->setFrameAvailable(); + } + mLocalSyncPoints.clear(); +} + +int32_t Layer::getZ() const { + return mDrawingState.z; +} + +/** + * Negatively signed children are before 'this' in Z-order. + */ +void Layer::traverseInZOrder(const std::function<void(Layer*)>& exec) { + size_t i = 0; + for (; i < mDrawingChildren.size(); i++) { + const auto& child = mDrawingChildren[i]; + if (child->getZ() >= 0) + break; + child->traverseInZOrder(exec); + } + exec(this); + for (; i < mDrawingChildren.size(); i++) { + const auto& child = mDrawingChildren[i]; + child->traverseInZOrder(exec); + } +} + +/** + * Positively signed children are before 'this' in reverse Z-order. + */ +void Layer::traverseInReverseZOrder(const std::function<void(Layer*)>& exec) { + int32_t i = 0; + for (i = mDrawingChildren.size()-1; i>=0; i--) { + const auto& child = mDrawingChildren[i]; + if (child->getZ() < 0) { + break; + } + child->traverseInReverseZOrder(exec); + } + exec(this); + for (; i>=0; i--) { + const auto& child = mDrawingChildren[i]; + child->traverseInReverseZOrder(exec); + } +} + +Transform Layer::getTransform() const { + Transform t; + const auto& p = getParent(); + if (p != nullptr) { + t = p->getTransform(); + } + return t * getDrawingState().active.transform; +} + +void Layer::commitChildList() { + for (size_t i = 0; i < mCurrentChildren.size(); i++) { + const auto& child = mCurrentChildren[i]; + child->commitChildList(); + } + mDrawingChildren = mCurrentChildren; +} + // --------------------------------------------------------------------------- }; // namespace android diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index 3959341f4a..bf224ae4d8 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -42,6 +42,7 @@ #include "FrameTracker.h" #include "Client.h" +#include "LayerVector.h" #include "MonitoredProducer.h" #include "SurfaceFlinger.h" #include "SurfaceFlingerConsumer.h" @@ -168,6 +169,7 @@ public: bool setFinalCrop(const Rect& crop); bool setLayerStack(uint32_t layerStack); bool setDataSpace(android_dataspace dataSpace); + uint32_t getLayerStack() const; void deferTransactionUntil(const sp<IBinder>& handle, uint64_t frameNumber); bool setOverrideScalingMode(int32_t overrideScalingMode); @@ -219,6 +221,14 @@ public: virtual bool isVisible() const; /* + * isHiddenByPolicy - true if this layer has been forced invisible. + * just because this is false, doesn't mean isVisible() is true. + * For example if this layer has no active buffer, it may not be hidden by + * policy, but it still can not be visible. + */ + virtual bool isHiddenByPolicy() const; + + /* * isFixedSize - true if content has a fixed size */ virtual bool isFixedSize() const; @@ -422,6 +432,26 @@ public: bool getTransformToDisplayInverse() const; + Transform getTransform() const; + + void traverseInReverseZOrder(const std::function<void(Layer*)>& exec); + void traverseInZOrder(const std::function<void(Layer*)>& exec); + + void addChild(const sp<Layer>& layer); + // Returns index if removed, or negative value otherwise + // for symmetry with Vector::remove + ssize_t removeChild(const sp<Layer>& layer); + sp<Layer> getParent() const { return mParent.promote(); } + bool hasParent() const { return getParent() != nullptr; } + + Rect computeScreenBounds(bool reduceTransparentRegion = true) const; + bool setChildLayer(const sp<Layer>& childLayer, int32_t z); + + // Copy the current list of children to the drawing state. Called by + // SurfaceFlinger to complete a transaction. + void commitChildList(); + + int32_t getZ() const; protected: // constant sp<SurfaceFlinger> mFlinger; @@ -462,7 +492,12 @@ private: bool needsFiltering(const sp<const DisplayDevice>& hw) const; uint32_t getEffectiveUsage(uint32_t usage) const; + gfx::FloatRect computeCrop(const sp<const DisplayDevice>& hw) const; + // Compute the initial crop as specified by parent layers and the SurfaceControl + // for this layer. Does not include buffer crop from the IGraphicBufferProducer + // client, as that should not affect child clipping. Returns in screen space. + Rect computeInitialCrop(const sp<const DisplayDevice>& hw) const; bool isCropped() const; static bool getOpacityForFormat(uint32_t format); @@ -478,6 +513,8 @@ private: // Loads the corresponding system property once per process static bool latchUnsignaledBuffers(); + void setParent(const sp<Layer>& layer); + // ----------------------------------------------------------------------- class SyncPoint @@ -532,6 +569,8 @@ private: void popPendingState(State* stateToCommit); bool applyPendingStates(State* stateToCommit); + void clearSyncPoints(); + // Returns mCurrentScaling mode (originating from the // Client) or mOverrideScalingMode mode (originating from // the Surface Controller) if set. @@ -662,6 +701,13 @@ private: bool mAutoRefresh; bool mFreezePositionUpdates; + + // Child list about to be committed/used for editing. + LayerVector mCurrentChildren; + // Child list used for rendering. + LayerVector mDrawingChildren; + + wp<Layer> mParent; }; // --------------------------------------------------------------------------- diff --git a/services/surfaceflinger/LayerDim.cpp b/services/surfaceflinger/LayerDim.cpp index 4d5b3dbdf3..daebf8abcd 100644 --- a/services/surfaceflinger/LayerDim.cpp +++ b/services/surfaceflinger/LayerDim.cpp @@ -59,7 +59,7 @@ void LayerDim::onDraw(const sp<const DisplayDevice>& hw, bool LayerDim::isVisible() const { const Layer::State& s(getDrawingState()); - return !(s.flags & layer_state_t::eLayerHidden) && s.alpha; + return !isHiddenByPolicy() && s.alpha; } diff --git a/services/surfaceflinger/LayerVector.cpp b/services/surfaceflinger/LayerVector.cpp index 6ac4b14df1..7ba6ad3bfa 100644 --- a/services/surfaceflinger/LayerVector.cpp +++ b/services/surfaceflinger/LayerVector.cpp @@ -41,15 +41,14 @@ int LayerVector::do_compare(const void* lhs, const void* rhs) const } void LayerVector::traverseInZOrder(const std::function<void(Layer*)>& consume) const { - const size_t n = size(); - for (size_t i = 0; i < n; i++) { - consume((*this)[i].get()); + for (size_t i = 0; i < size(); i++) { + (*this)[i]->traverseInZOrder(consume); } } void LayerVector::traverseInReverseZOrder(const std::function<void(Layer*)>& consume) const { for (auto i = static_cast<int64_t>(size()) - 1; i >= 0; i--) { - consume((*this)[i].get()); + (*this)[i]->traverseInReverseZOrder(consume); } } } // namespace android diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 510a3e1c95..3480d83d28 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -69,6 +69,7 @@ #include "EventControlThread.h" #include "EventThread.h" #include "Layer.h" +#include "LayerVector.h" #include "LayerDim.h" #include "SurfaceFlinger.h" @@ -133,6 +134,7 @@ SurfaceFlinger::SurfaceFlinger() mTransactionPending(false), mAnimTransactionPending(false), mLayersRemoved(false), + mLayersAdded(false), mRepaintEverything(0), mRenderEngine(NULL), mBootTime(systemTime()), @@ -158,7 +160,8 @@ SurfaceFlinger::SurfaceFlinger() mHasPoweredOff(false), mFrameBuckets(), mTotalTime(0), - mLastSwapTime(0) + mLastSwapTime(0), + mNumLayers(0) { ALOGI("SurfaceFlinger is starting"); @@ -1340,8 +1343,7 @@ void SurfaceFlinger::rebuildLayerStacks() { opaqueRegion); mDrawingState.traverseInZOrder([&](Layer* layer) { - const Layer::State& s(layer->getDrawingState()); - if (s.layerStack == displayDevice->getLayerStack()) { + if (layer->getLayerStack() == displayDevice->getLayerStack()) { Region drawRegion(tr.transform( layer->visibleNonTransparentRegion)); drawRegion.andSelf(bounds); @@ -1409,7 +1411,7 @@ void SurfaceFlinger::setUpHWComposer() { displayDevice->getVisibleLayersSortedByZ()); bool foundLayerWithoutHwc = false; for (size_t i = 0; i < currentLayers.size(); i++) { - auto const& layer = currentLayers[i]; + const auto& layer = currentLayers[i]; if (!layer->hasHwcLayer(hwcId)) { auto hwcLayer = mHwc->createLayer(hwcId); if (hwcLayer) { @@ -1560,8 +1562,6 @@ void SurfaceFlinger::handleTransaction(uint32_t transactionFlags) void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) { - const LayerVector& currentLayers(mCurrentState.layersSortedByZ); - // Notify all layers of available frames mCurrentState.traverseInZOrder([](Layer* layer) { layer->notifyAvailableFrames(); @@ -1778,7 +1778,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) // NOTE: we rely on the fact that layers are sorted by // layerStack first (so we don't have to traverse the list // of displays for every layer). - uint32_t layerStack = layer->getDrawingState().layerStack; + uint32_t layerStack = layer->getLayerStack(); if (first || currentlayerStack != layerStack) { currentlayerStack = layerStack; // figure out if this layerstack is mirrored @@ -1816,9 +1816,10 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) /* * Perform our own transaction if needed */ - const LayerVector& layers(mDrawingState.layersSortedByZ); - if (currentLayers.size() > layers.size()) { - // layers have been added + + if (mLayersAdded) { + mLayersAdded = false; + // Layers have been added. mVisibleRegionsDirty = true; } @@ -1828,15 +1829,14 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) mLayersRemoved = false; mVisibleRegionsDirty = true; mDrawingState.traverseInZOrder([&](Layer* layer) { - if (currentLayers.indexOf(layer) < 0) { + if (mLayersPendingRemoval.indexOf(layer) >= 0) { // this layer is not visible anymore // TODO: we could traverse the tree from front to back and // compute the actual visible region // TODO: we could cache the transformed region - const Layer::State& s(layer->getDrawingState()); - Region visibleReg = s.active.transform.transform( - Region(Rect(s.active.w, s.active.h))); - invalidateLayerStack(s.layerStack, visibleReg); + Region visibleReg; + visibleReg.set(layer->computeScreenBounds()); + invalidateLayerStack(layer->getLayerStack(), visibleReg); } }); } @@ -1864,10 +1864,10 @@ void SurfaceFlinger::commitTransaction() { if (!mLayersPendingRemoval.isEmpty()) { // Notify removed layers now that they can't be drawn from - for (size_t i = 0; i < mLayersPendingRemoval.size(); i++) { - recordBufferingStats(mLayersPendingRemoval[i]->getName().string(), - mLayersPendingRemoval[i]->getOccupancyHistory(true)); - mLayersPendingRemoval[i]->onRemoved(); + for (const auto& l : mLayersPendingRemoval) { + recordBufferingStats(l->getName().string(), + l->getOccupancyHistory(true)); + l->onRemoved(); } mLayersPendingRemoval.clear(); } @@ -1877,6 +1877,9 @@ void SurfaceFlinger::commitTransaction() mAnimCompositionPending = mAnimTransactionPending; mDrawingState = mCurrentState; + mDrawingState.traverseInZOrder([](Layer* layer) { + layer->commitChildList(); + }); mTransactionPending = false; mAnimTransactionPending = false; mTransactionCV.broadcast(); @@ -1899,7 +1902,7 @@ void SurfaceFlinger::computeVisibleRegions(uint32_t layerStack, const Layer::State& s(layer->getDrawingState()); // only consider the layers on the given layer stack - if (s.layerStack != layerStack) + if (layer->getLayerStack() != layerStack) return; /* @@ -1935,12 +1938,12 @@ void SurfaceFlinger::computeVisibleRegions(uint32_t layerStack, // handle hidden surfaces by setting the visible region to empty if (CC_LIKELY(layer->isVisible())) { const bool translucent = !layer->isOpaque(s); - Rect bounds(s.active.transform.transform(layer->computeBounds())); + Rect bounds(layer->computeScreenBounds()); visibleRegion.set(bounds); + Transform tr = layer->getTransform(); if (!visibleRegion.isEmpty()) { // Remove the transparent area from the visible region if (translucent) { - const Transform tr(s.active.transform); if (tr.preserveRects()) { // transform the transparent region transparentRegion = tr.transform(s.activeTransparentRegion); @@ -1952,7 +1955,7 @@ void SurfaceFlinger::computeVisibleRegions(uint32_t layerStack, } // compute the opaque region - const int32_t layerOrientation = s.active.transform.getOrientation(); + const int32_t layerOrientation = tr.getOrientation(); if (s.alpha == 1.0f && !translucent && ((layerOrientation & Transform::ROT_INVALID) == false)) { // the opaque region is the layer's footprint @@ -2058,8 +2061,7 @@ bool SurfaceFlinger::handlePageFlip() for (auto& layer : mLayersWithQueuedFrames) { const Region dirty(layer->latchBuffer(visibleRegions, latchTime)); layer->useSurfaceDamage(); - const Layer::State& s(layer->getDrawingState()); - invalidateLayerStack(s.layerStack, dirty); + invalidateLayerStack(layer->getLayerStack(), dirty); } mVisibleRegionsDirty |= visibleRegions; @@ -2281,16 +2283,23 @@ void SurfaceFlinger::drawWormhole(const sp<const DisplayDevice>& displayDevice, status_t SurfaceFlinger::addClientLayer(const sp<Client>& client, const sp<IBinder>& handle, const sp<IGraphicBufferProducer>& gbc, - const sp<Layer>& lbc) + const sp<Layer>& lbc, + const sp<Layer>& parent) { // add this layer to the current state list { Mutex::Autolock _l(mStateLock); - if (mCurrentState.layersSortedByZ.size() >= MAX_LAYERS) { + if (mNumLayers >= MAX_LAYERS) { return NO_MEMORY; } - mCurrentState.layersSortedByZ.add(lbc); + if (parent == nullptr) { + mCurrentState.layersSortedByZ.add(lbc); + } else { + parent->addChild(lbc); + } mGraphicBufferProducerList.add(IInterface::asBinder(gbc)); + mLayersAdded = true; + mNumLayers++; } // attach this layer to the client @@ -2307,14 +2316,22 @@ status_t SurfaceFlinger::removeLayer(const wp<Layer>& weakLayer) { return NO_ERROR; } - ssize_t index = mCurrentState.layersSortedByZ.remove(layer); - if (index >= 0) { - mLayersPendingRemoval.push(layer); - mLayersRemoved = true; - setTransactionFlags(eTransactionNeeded); - return NO_ERROR; + const auto& p = layer->getParent(); + const ssize_t index = (p != nullptr) ? p->removeChild(layer) : + mCurrentState.layersSortedByZ.remove(layer); + + if (index < 0) { + ALOGE("Failed to find layer (%s) in layer parent (%s).", + layer->getName().string(), + (p != nullptr) ? p->getName().string() : "no-parent"); + return BAD_VALUE; } - return status_t(index); + + mLayersPendingRemoval.add(layer); + mLayersRemoved = true; + mNumLayers--; + setTransactionFlags(eTransactionNeeded); + return NO_ERROR; } uint32_t SurfaceFlinger::peekTransactionFlags() { @@ -2489,13 +2506,20 @@ uint32_t SurfaceFlinger::setClientStateLocked( } if (what & layer_state_t::eLayerChanged) { // NOTE: index needs to be calculated before we update the state - ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer); - if (layer->setLayer(s.z) && idx >= 0) { - mCurrentState.layersSortedByZ.removeAt(idx); - mCurrentState.layersSortedByZ.add(layer); - // we need traversal (state changed) - // AND transaction (list changed) - flags |= eTransactionNeeded|eTraversalNeeded; + const auto& p = layer->getParent(); + if (p == nullptr) { + ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer); + if (layer->setLayer(s.z) && idx >= 0) { + mCurrentState.layersSortedByZ.removeAt(idx); + mCurrentState.layersSortedByZ.add(layer); + // we need traversal (state changed) + // AND transaction (list changed) + flags |= eTransactionNeeded|eTraversalNeeded; + } + } else { + if (p->setChildLayer(layer, s.z)) { + flags |= eTransactionNeeded|eTraversalNeeded; + } } } if (what & layer_state_t::eSizeChanged) { @@ -2528,9 +2552,17 @@ uint32_t SurfaceFlinger::setClientStateLocked( flags |= eTraversalNeeded; } if (what & layer_state_t::eLayerStackChanged) { - // NOTE: index needs to be calculated before we update the state ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer); - if (layer->setLayerStack(s.layerStack) && idx >= 0) { + // We only allow setting layer stacks for top level layers, + // everything else inherits layer stack from its parent. + if (layer->hasParent()) { + ALOGE("Attempt to set layer stack on layer with parent (%s) is invalid", + layer->getName().string()); + } else if (idx < 0) { + ALOGE("Attempt to set layer stack on layer without parent (%s) that " + "that also does not appear in the top level layer list. Something" + " has gone wrong.", layer->getName().string()); + } else if (layer->setLayerStack(s.layerStack)) { mCurrentState.layersSortedByZ.removeAt(idx); mCurrentState.layersSortedByZ.add(layer); // we need traversal (state changed) @@ -2556,7 +2588,8 @@ status_t SurfaceFlinger::createLayer( const String8& name, const sp<Client>& client, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, - sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp) + sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, + sp<Layer>* parent) { if (int32_t(w|h) < 0) { ALOGE("createLayer() failed, w or h is negative (w=%d, h=%d)", @@ -2588,7 +2621,7 @@ status_t SurfaceFlinger::createLayer( return result; } - result = addClientLayer(client, *handle, *gbp, layer); + result = addClientLayer(client, *handle, *gbp, layer, *parent); if (result != NO_ERROR) { return result; } @@ -3085,10 +3118,8 @@ void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index, /* * Dump the visible layer list */ - const LayerVector& currentLayers = mCurrentState.layersSortedByZ; - const size_t count = currentLayers.size(); colorizer.bold(result); - result.appendFormat("Visible layers (count = %zu)\n", count); + result.appendFormat("Visible layers (count = %zu)\n", mNumLayers); colorizer.reset(result); mCurrentState.traverseInZOrder([&](Layer* layer) { layer->dump(result, colorizer); @@ -3170,10 +3201,9 @@ void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index, result.appendFormat("Display %d HWC layers:\n", hwcId); Layer::miniDumpHeader(result); - for (size_t l = 0; l < count; l++) { - const sp<Layer>& layer(currentLayers[l]); + mCurrentState.traverseInZOrder([&](Layer* layer) { layer->miniDump(result, hwcId); - } + }); result.append("\n"); } @@ -3698,18 +3728,25 @@ void SurfaceFlinger::renderScreenImplLocked( // redraw the screen entirely... engine.clearWithColor(0, 0, 0, 1); - mDrawingState.traverseInZOrder([&](Layer* layer) { + // We loop through the first level of layers without traversing, + // as we need to interpret min/max layer Z in the top level Z space. + for (const auto& layer : mDrawingState.layersSortedByZ) { + if (layer->getLayerStack() != hw->getLayerStack()) { + continue; + } const Layer::State& state(layer->getDrawingState()); - if (state.layerStack == hw->getLayerStack()) { - if (state.z >= minLayerZ && state.z <= maxLayerZ) { - if (layer->isVisible()) { - if (filtering) layer->setFiltering(true); - layer->draw(hw, useIdentityTransform); - if (filtering) layer->setFiltering(false); - } - } + if (state.z < minLayerZ || state.z > maxLayerZ) { + continue; } - }); + layer->traverseInZOrder([&](Layer* layer) { + if (!layer->isVisible()) { + return; + } + if (filtering) layer->setFiltering(true); + layer->draw(hw, useIdentityTransform); + if (filtering) layer->setFiltering(false); + }); + } hw->setViewportAndProjection(); } @@ -3743,14 +3780,17 @@ status_t SurfaceFlinger::captureScreenImplLocked( reqHeight = (!reqHeight) ? hw_h : reqHeight; bool secureLayerIsVisible = false; - mDrawingState.traverseInZOrder([&](Layer* layer) { + for (const auto& layer : mDrawingState.layersSortedByZ) { const Layer::State& state(layer->getDrawingState()); - if (state.layerStack == hw->getLayerStack() && state.z >= minLayerZ && - state.z <= maxLayerZ && layer->isVisible() && - layer->isSecure()) { - secureLayerIsVisible = true; + if ((layer->getLayerStack() != hw->getLayerStack()) || + (state.z < minLayerZ || state.z > maxLayerZ)) { + continue; } - }); + layer->traverseInZOrder([&](Layer *layer) { + secureLayerIsVisible = secureLayerIsVisible || (layer->isVisible() && + layer->isSecure()); + }); + } if (!isLocalScreenshot && secureLayerIsVisible) { ALOGW("FB is protected: PERMISSION_DENIED"); @@ -3888,18 +3928,21 @@ void SurfaceFlinger::checkScreenshot(size_t w, size_t s, size_t h, void const* v ALOGE("*** we just took a black screenshot ***\n" "requested minz=%d, maxz=%d, layerStack=%d", minLayerZ, maxLayerZ, hw->getLayerStack()); + size_t i = 0; - mDrawingState.traverseInZOrder([&](Layer* layer) { + for (const auto& layer : mDrawingState.layersSortedByZ) { const Layer::State& state(layer->getDrawingState()); - const bool visible = (state.layerStack == hw->getLayerStack()) - && (state.z >= minLayerZ && state.z <= maxLayerZ) - && (layer->isVisible()); - ALOGE("%c index=%zu, name=%s, layerStack=%d, z=%d, visible=%d, flags=%x, alpha=%.3f", - visible ? '+' : '-', - i, layer->getName().string(), state.layerStack, state.z, + if (layer->getLayerStack() == hw->getLayerStack() && state.z >= minLayerZ && + state.z <= maxLayerZ) { + layer->traverseInZOrder([&](Layer* layer) { + ALOGE("%c index=%zu, name=%s, layerStack=%d, z=%d, visible=%d, flags=%x, alpha=%.3f", + layer->isVisible() ? '+' : '-', + i, layer->getName().string(), layer->getLayerStack(), state.z, layer->isVisible(), state.flags, state.alpha); - i++; - }); + i++; + }); + } + } } } diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index d573f1a94a..4f3ee7433d 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -293,7 +293,8 @@ private: */ status_t createLayer(const String8& name, const sp<Client>& client, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, - sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp); + sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, + sp<Layer>* parent); status_t createNormalLayer(const sp<Client>& client, const String8& name, uint32_t w, uint32_t h, uint32_t flags, PixelFormat& format, @@ -320,7 +321,8 @@ private: status_t addClientLayer(const sp<Client>& client, const sp<IBinder>& handle, const sp<IGraphicBufferProducer>& gbc, - const sp<Layer>& lbc); + const sp<Layer>& lbc, + const sp<Layer>& parent); /* ------------------------------------------------------------------------ * Boot animation, on/off animations and screen capture @@ -423,6 +425,7 @@ private: void enableHardwareVsync(); void resyncToHardwareVsync(bool makeAvailable); void disableHardwareVsync(bool makeUnavailable); + public: void resyncWithRateLimit(); private: @@ -464,11 +467,12 @@ private: Condition mTransactionCV; bool mTransactionPending; bool mAnimTransactionPending; - Vector< sp<Layer> > mLayersPendingRemoval; + SortedVector< sp<Layer> > mLayersPendingRemoval; SortedVector< wp<IBinder> > mGraphicBufferProducerList; // protected by mStateLock (but we could use another lock) bool mLayersRemoved; + bool mLayersAdded; // access must be protected by mInvalidateLock volatile int32_t mRepaintEverything; @@ -565,6 +569,8 @@ private: nsecs_t mTotalTime; std::atomic<nsecs_t> mLastSwapTime; + size_t mNumLayers; + // Double- vs. triple-buffering stats struct BufferingStats { BufferingStats() diff --git a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp index 5bfc10bb32..1976d2e739 100644 --- a/services/surfaceflinger/SurfaceFlinger_hwc1.cpp +++ b/services/surfaceflinger/SurfaceFlinger_hwc1.cpp @@ -72,6 +72,7 @@ #include "EventControlThread.h" #include "EventThread.h" #include "Layer.h" +#include "LayerVector.h" #include "LayerDim.h" #include "SurfaceFlinger.h" @@ -136,6 +137,7 @@ SurfaceFlinger::SurfaceFlinger() mTransactionPending(false), mAnimTransactionPending(false), mLayersRemoved(false), + mLayersAdded(false), mRepaintEverything(0), mRenderEngine(NULL), mBootTime(systemTime()), @@ -161,7 +163,8 @@ SurfaceFlinger::SurfaceFlinger() mHasPoweredOff(false), mFrameBuckets(), mTotalTime(0), - mLastSwapTime(0) + mLastSwapTime(0), + mNumLayers(0) { ALOGI("SurfaceFlinger is starting"); @@ -1236,8 +1239,7 @@ void SurfaceFlinger::rebuildLayerStacks() { opaqueRegion); mDrawingState.traverseInZOrder([&](Layer* layer) { - const Layer::State& s(layer->getDrawingState()); - if (s.layerStack == hw->getLayerStack()) { + if (layer->getLayerStack() == hw->getLayerStack()) { Region drawRegion(tr.transform( layer->visibleNonTransparentRegion)); drawRegion.andSelf(bounds); @@ -1468,8 +1470,6 @@ void SurfaceFlinger::handleTransaction(uint32_t transactionFlags) void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) { - const LayerVector& currentLayers(mCurrentState.layersSortedByZ); - // Notify all layers of available frames mCurrentState.traverseInZOrder([](Layer* layer) { layer->notifyAvailableFrames(); @@ -1680,7 +1680,7 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) // NOTE: we rely on the fact that layers are sorted by // layerStack first (so we don't have to traverse the list // of displays for every layer). - uint32_t layerStack = layer->getDrawingState().layerStack; + uint32_t layerStack = layer->getLayerStack(); if (first || currentlayerStack != layerStack) { currentlayerStack = layerStack; // figure out if this layerstack is mirrored @@ -1718,9 +1718,10 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) /* * Perform our own transaction if needed */ - const LayerVector& layers(mDrawingState.layersSortedByZ); - if (currentLayers.size() > layers.size()) { - // layers have been added + + if (mLayersAdded) { + mLayersAdded = false; + // Layers have been added. mVisibleRegionsDirty = true; } @@ -1730,15 +1731,14 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) mLayersRemoved = false; mVisibleRegionsDirty = true; mDrawingState.traverseInZOrder([&](Layer* layer) { - if (currentLayers.indexOf(layer) < 0) { + if (mLayersPendingRemoval.indexOf(layer) >= 0) { // this layer is not visible anymore // TODO: we could traverse the tree from front to back and // compute the actual visible region // TODO: we could cache the transformed region - const Layer::State& s(layer->getDrawingState()); - Region visibleReg = s.active.transform.transform( - Region(Rect(s.active.w, s.active.h))); - invalidateLayerStack(s.layerStack, visibleReg); + Region visibleReg; + visibleReg.set(layer->computeScreenBounds()); + invalidateLayerStack(layer->getLayerStack(), visibleReg); } }); } @@ -1778,10 +1778,10 @@ void SurfaceFlinger::commitTransaction() { if (!mLayersPendingRemoval.isEmpty()) { // Notify removed layers now that they can't be drawn from - for (size_t i = 0; i < mLayersPendingRemoval.size(); i++) { - recordBufferingStats(mLayersPendingRemoval[i]->getName().string(), - mLayersPendingRemoval[i]->getOccupancyHistory(true)); - mLayersPendingRemoval[i]->onRemoved(); + for (const auto& l : mLayersPendingRemoval) { + recordBufferingStats(l->getName().string(), + l->getOccupancyHistory(true)); + l->onRemoved(); } mLayersPendingRemoval.clear(); } @@ -1791,6 +1791,9 @@ void SurfaceFlinger::commitTransaction() mAnimCompositionPending = mAnimTransactionPending; mDrawingState = mCurrentState; + mDrawingState.traverseInZOrder([](Layer* layer) { + layer->commitChildList(); + }); mTransactionPending = false; mAnimTransactionPending = false; mTransactionCV.broadcast(); @@ -1812,7 +1815,7 @@ void SurfaceFlinger::computeVisibleRegions(uint32_t layerStack, const Layer::State& s(layer->getDrawingState()); // only consider the layers on the given layer stack - if (s.layerStack != layerStack) + if (layer->getLayerStack() != layerStack) return; /* @@ -1848,12 +1851,12 @@ void SurfaceFlinger::computeVisibleRegions(uint32_t layerStack, // handle hidden surfaces by setting the visible region to empty if (CC_LIKELY(layer->isVisible())) { const bool translucent = !layer->isOpaque(s); - Rect bounds(s.active.transform.transform(layer->computeBounds())); + Rect bounds(layer->computeScreenBounds()); visibleRegion.set(bounds); + Transform tr = layer->getTransform(); if (!visibleRegion.isEmpty()) { // Remove the transparent area from the visible region if (translucent) { - const Transform tr(s.active.transform); if (tr.preserveRects()) { // transform the transparent region transparentRegion = tr.transform(s.activeTransparentRegion); @@ -1865,7 +1868,7 @@ void SurfaceFlinger::computeVisibleRegions(uint32_t layerStack, } // compute the opaque region - const int32_t layerOrientation = s.active.transform.getOrientation(); + const int32_t layerOrientation = tr.getOrientation(); if (s.alpha==255 && !translucent && ((layerOrientation & Transform::ROT_INVALID) == false)) { // the opaque region is the layer's footprint @@ -1971,8 +1974,7 @@ bool SurfaceFlinger::handlePageFlip() Layer* layer = layersWithQueuedFrames[i]; const Region dirty(layer->latchBuffer(visibleRegions, latchTime)); layer->useSurfaceDamage(); - const Layer::State& s(layer->getDrawingState()); - invalidateLayerStack(s.layerStack, dirty); + invalidateLayerStack(layer->getLayerStack(), dirty); } mVisibleRegionsDirty |= visibleRegions; @@ -2188,16 +2190,23 @@ void SurfaceFlinger::drawWormhole(const sp<const DisplayDevice>& hw, const Regio status_t SurfaceFlinger::addClientLayer(const sp<Client>& client, const sp<IBinder>& handle, const sp<IGraphicBufferProducer>& gbc, - const sp<Layer>& lbc) + const sp<Layer>& lbc, + const sp<Layer>& parent) { // add this layer to the current state list { Mutex::Autolock _l(mStateLock); - if (mCurrentState.layersSortedByZ.size() >= MAX_LAYERS) { + if (mNumLayers >= MAX_LAYERS) { return NO_MEMORY; } - mCurrentState.layersSortedByZ.add(lbc); + if (parent == nullptr) { + mCurrentState.layersSortedByZ.add(lbc); + } else { + parent->addChild(lbc); + } mGraphicBufferProducerList.add(IInterface::asBinder(gbc)); + mLayersAdded = true; + mNumLayers++; } // attach this layer to the client @@ -2214,14 +2223,22 @@ status_t SurfaceFlinger::removeLayer(const wp<Layer>& weakLayer) { return NO_ERROR; } - ssize_t index = mCurrentState.layersSortedByZ.remove(layer); - if (index >= 0) { - mLayersPendingRemoval.push(layer); - mLayersRemoved = true; - setTransactionFlags(eTransactionNeeded); - return NO_ERROR; + const auto& p = layer->getParent(); + const ssize_t index = (p != nullptr) ? p->removeChild(layer) : + mCurrentState.layersSortedByZ.remove(layer); + + if (index < 0) { + ALOGE("Failed to find layer (%s) in layer parent (%s).", + layer->getName().string(), + (p != nullptr) ? p->getName().string() : "no-parent"); + return BAD_VALUE; } - return status_t(index); + + mLayersPendingRemoval.add(layer); + mLayersRemoved = true; + mNumLayers--; + setTransactionFlags(eTransactionNeeded); + return NO_ERROR; } uint32_t SurfaceFlinger::peekTransactionFlags() { @@ -2396,13 +2413,20 @@ uint32_t SurfaceFlinger::setClientStateLocked( } if (what & layer_state_t::eLayerChanged) { // NOTE: index needs to be calculated before we update the state - ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer); - if (layer->setLayer(s.z) && idx >= 0) { - mCurrentState.layersSortedByZ.removeAt(idx); - mCurrentState.layersSortedByZ.add(layer); - // we need traversal (state changed) - // AND transaction (list changed) - flags |= eTransactionNeeded|eTraversalNeeded; + const auto& p = layer->getParent(); + if (p == nullptr) { + ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer); + if (layer->setLayer(s.z) && idx >= 0) { + mCurrentState.layersSortedByZ.removeAt(idx); + mCurrentState.layersSortedByZ.add(layer); + // we need traversal (state changed) + // AND transaction (list changed) + flags |= eTransactionNeeded|eTraversalNeeded; + } + } else { + if (p->setChildLayer(layer, s.z)) { + flags |= eTransactionNeeded|eTraversalNeeded; + } } } if (what & layer_state_t::eSizeChanged) { @@ -2435,9 +2459,17 @@ uint32_t SurfaceFlinger::setClientStateLocked( flags |= eTraversalNeeded; } if (what & layer_state_t::eLayerStackChanged) { - // NOTE: index needs to be calculated before we update the state ssize_t idx = mCurrentState.layersSortedByZ.indexOf(layer); - if (layer->setLayerStack(s.layerStack) && idx >= 0) { + // We only allow setting layer stacks for top level layers, + // everything else inherits layer stack from its parent. + if (layer->hasParent()) { + ALOGE("Attempt to set layer stack on layer with parent (%s) is invalid", + layer->getName().string()); + } else if (idx < 0) { + ALOGE("Attempt to set layer stack on layer without parent (%s) that " + "that also does not appear in the top level layer list. Something" + " has gone wrong.", layer->getName().string()); + } else if (layer->setLayerStack(s.layerStack)) { mCurrentState.layersSortedByZ.removeAt(idx); mCurrentState.layersSortedByZ.add(layer); // we need traversal (state changed) @@ -2463,7 +2495,8 @@ status_t SurfaceFlinger::createLayer( const String8& name, const sp<Client>& client, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, - sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp) + sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp, + sp<Layer>* parent) { if (int32_t(w|h) < 0) { ALOGE("createLayer() failed, w or h is negative (w=%d, h=%d)", @@ -2495,7 +2528,7 @@ status_t SurfaceFlinger::createLayer( return result; } - result = addClientLayer(client, *handle, *gbp, layer); + result = addClientLayer(client, *handle, *gbp, layer, *parent); if (result != NO_ERROR) { return result; } @@ -2989,10 +3022,8 @@ void SurfaceFlinger::dumpAllLocked(const Vector<String16>& args, size_t& index, /* * Dump the visible layer list */ - const LayerVector& currentLayers = mCurrentState.layersSortedByZ; - const size_t count = currentLayers.size(); colorizer.bold(result); - result.appendFormat("Visible layers (count = %zu)\n", count); + result.appendFormat("Visible layers (count = %zu)\n", mNumLayers); colorizer.reset(result); mCurrentState.traverseInZOrder([&](Layer* layer) { layer->dump(result, colorizer); @@ -3576,18 +3607,25 @@ void SurfaceFlinger::renderScreenImplLocked( // redraw the screen entirely... engine.clearWithColor(0, 0, 0, 1); - mDrawingState.traverseInZOrder([&](Layer* layer) { + // We loop through the first level of layers without traversing, + // as we need to interpret min/max layer Z in the top level Z space. + for (const auto& layer : mDrawingState.layersSortedByZ) { + if (layer->getLayerStack() != hw->getLayerStack()) { + continue; + } const Layer::State& state(layer->getDrawingState()); - if (state.layerStack == hw->getLayerStack()) { - if (state.z >= minLayerZ && state.z <= maxLayerZ) { - if (layer->isVisible()) { - if (filtering) layer->setFiltering(true); - layer->draw(hw, useIdentityTransform); - if (filtering) layer->setFiltering(false); - } - } + if (state.z < minLayerZ || state.z > maxLayerZ) { + continue; } - }); + layer->traverseInZOrder([&](Layer* layer) { + if (!layer->isVisible()) { + return; + } + if (filtering) layer->setFiltering(true); + layer->draw(hw, useIdentityTransform); + if (filtering) layer->setFiltering(false); + }); + } // compositionComplete is needed for older driver hw->compositionComplete(); @@ -3623,14 +3661,17 @@ status_t SurfaceFlinger::captureScreenImplLocked( reqHeight = (!reqHeight) ? hw_h : reqHeight; bool secureLayerIsVisible = false; - mDrawingState.traverseInZOrder([&](Layer* layer) { + for (const auto& layer : mDrawingState.layersSortedByZ) { const Layer::State& state(layer->getDrawingState()); - if (state.layerStack == hw->getLayerStack() && state.z >= minLayerZ && - state.z <= maxLayerZ && layer->isVisible() && - layer->isSecure()) { - secureLayerIsVisible = true; + if ((layer->getLayerStack() != hw->getLayerStack()) || + (state.z < minLayerZ || state.z > maxLayerZ)) { + continue; } - }); + layer->traverseInZOrder([&](Layer *layer) { + secureLayerIsVisible = secureLayerIsVisible || (layer->isVisible() && + layer->isSecure()); + }); + } if (!isLocalScreenshot && secureLayerIsVisible) { ALOGW("FB is protected: PERMISSION_DENIED"); @@ -3761,17 +3802,19 @@ void SurfaceFlinger::checkScreenshot(size_t w, size_t s, size_t h, void const* v "requested minz=%d, maxz=%d, layerStack=%d", minLayerZ, maxLayerZ, hw->getLayerStack()); size_t i = 0; - mDrawingState.traverseInZOrder([&](Layer* layer) { + for (const auto& layer : mDrawingState.layersSortedByZ) { const Layer::State& state(layer->getDrawingState()); - const bool visible = (state.layerStack == hw->getLayerStack()) - && (state.z >= minLayerZ && state.z <= maxLayerZ) - && (layer->isVisible()); - ALOGE("%c index=%zu, name=%s, layerStack=%d, z=%d, visible=%d, flags=%x, alpha=%x", - visible ? '+' : '-', - i, layer->getName().string(), state.layerStack, state.z, + if (layer->getLayerStack() == hw->getLayerStack() && state.z >= minLayerZ && + state.z <= maxLayerZ) { + layer->traverseInZOrder([&](Layer* layer) { + ALOGE("%c index=%zu, name=%s, layerStack=%d, z=%d, visible=%d, flags=%x, alpha=%x", + layer->isVisible() ? '+' : '-', + i, layer->getName().string(), layer->getLayerStack(), state.z, layer->isVisible(), state.flags, state.alpha); - i++; - }); + i++; + }); + } + } } } diff --git a/services/surfaceflinger/SurfaceInterceptor.cpp b/services/surfaceflinger/SurfaceInterceptor.cpp index 60bc7f37ae..2d6472a8ef 100644 --- a/services/surfaceflinger/SurfaceInterceptor.cpp +++ b/services/surfaceflinger/SurfaceInterceptor.cpp @@ -74,9 +74,11 @@ void SurfaceInterceptor::saveExistingDisplaysLocked( void SurfaceInterceptor::saveExistingSurfacesLocked(const SortedVector<sp<Layer>>& layers) { ATRACE_CALL(); - for (const auto& layer : layers) { - addSurfaceCreationLocked(createTraceIncrementLocked(), layer); - addInitialSurfaceStateLocked(createTraceIncrementLocked(), layer); + for (const auto& l : layers) { + l->traverseInZOrder([this](Layer* layer) { + addSurfaceCreationLocked(createTraceIncrementLocked(), layer); + addInitialSurfaceStateLocked(createTraceIncrementLocked(), layer); + }); } } diff --git a/services/surfaceflinger/tests/Android.mk b/services/surfaceflinger/tests/Android.mk index 4f1a8e6e61..f93d91881a 100644 --- a/services/surfaceflinger/tests/Android.mk +++ b/services/surfaceflinger/tests/Android.mk @@ -20,6 +20,7 @@ LOCAL_SHARED_LIBRARIES := \ libprotobuf-cpp-full \ libui \ libutils \ + liblog LOCAL_STATIC_LIBRARIES := libtrace_proto diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index 79cd245bf5..d9f1438026 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -84,6 +84,18 @@ public: } } + void expectFGColor(uint32_t x, uint32_t y) { + checkPixel(x, y, 195, 63, 63); + } + + void expectBGColor(uint32_t x, uint32_t y) { + checkPixel(x, y, 63, 63, 195); + } + + void expectChildColor(uint32_t x, uint32_t y) { + checkPixel(x, y, 200, 200, 200); + } + private: ScreenCapture(const sp<CpuConsumer>& cc) : mCC(cc) { @@ -140,14 +152,14 @@ protected: mComposerClient->setDisplayLayerStack(display, 0); - ASSERT_EQ(NO_ERROR, mBGSurfaceControl->setLayer(INT_MAX-2)); + ASSERT_EQ(NO_ERROR, mBGSurfaceControl->setLayer(INT32_MAX-2)); ASSERT_EQ(NO_ERROR, mBGSurfaceControl->show()); - ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setLayer(INT_MAX-1)); + ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setLayer(INT32_MAX-1)); ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setPosition(64, 64)); ASSERT_EQ(NO_ERROR, mFGSurfaceControl->show()); - ASSERT_EQ(NO_ERROR, mSyncSurfaceControl->setLayer(INT_MAX-1)); + ASSERT_EQ(NO_ERROR, mSyncSurfaceControl->setLayer(INT32_MAX-1)); ASSERT_EQ(NO_ERROR, mSyncSurfaceControl->setPosition(displayWidth-2, displayHeight-2)); ASSERT_EQ(NO_ERROR, mSyncSurfaceControl->show()); @@ -517,4 +529,105 @@ TEST_F(LayerUpdateTest, DeferredTransactionTest) { } } +class ChildLayerTest : public LayerUpdateTest { +protected: + void SetUp() override { + LayerUpdateTest::SetUp(); + mChild = mComposerClient->createSurface( + String8("Child surface"), + 10, 10, PIXEL_FORMAT_RGBA_8888, + 0, mFGSurfaceControl.get()); + fillSurfaceRGBA8(mChild, 200, 200, 200); + + { + SCOPED_TRACE("before anything"); + ScreenCapture::captureScreen(&mCapture); + mCapture->expectChildColor(64, 64); + } + } + void TearDown() override { + LayerUpdateTest::TearDown(); + mChild = 0; + } + + sp<SurfaceControl> mChild; + sp<ScreenCapture> mCapture; +}; + +TEST_F(ChildLayerTest, ChildLayerPositioning) { + SurfaceComposerClient::openGlobalTransaction(); + mChild->show(); + mChild->setPosition(10, 10); + mFGSurfaceControl->setPosition(64, 64); + SurfaceComposerClient::closeGlobalTransaction(true); + + { + ScreenCapture::captureScreen(&mCapture); + // Top left of foreground must now be visible + mCapture->expectFGColor(64, 64); + // But 10 pixels in we should see the child surface + mCapture->expectChildColor(74, 74); + // And 10 more pixels we should be back to the foreground surface + mCapture->expectFGColor(84, 84); + } + + SurfaceComposerClient::openGlobalTransaction(); + ASSERT_EQ(NO_ERROR, mFGSurfaceControl->setPosition(0, 0)); + SurfaceComposerClient::closeGlobalTransaction(true); + + { + ScreenCapture::captureScreen(&mCapture); + // Top left of foreground should now be at 0, 0 + mCapture->expectFGColor(0, 0); + // But 10 pixels in we should see the child surface + mCapture->expectChildColor(10, 10); + // And 10 more pixels we should be back to the foreground surface + mCapture->expectFGColor(20, 20); + } +} + +TEST_F(ChildLayerTest, ChildLayerConstraints) { + SurfaceComposerClient::openGlobalTransaction(); + mChild->show(); + mFGSurfaceControl->setPosition(0, 0); + mChild->setPosition(63, 63); + SurfaceComposerClient::closeGlobalTransaction(true); + + { + ScreenCapture::captureScreen(&mCapture); + mCapture->expectFGColor(0, 0); + // Last pixel in foreground should now be the child. + mCapture->expectChildColor(63, 63); + // But the child should be constrained and the next pixel + // must be the background + mCapture->expectBGColor(64, 64); + } +} + +TEST_F(ChildLayerTest, ChildLayerScaling) { + SurfaceComposerClient::openGlobalTransaction(); + mFGSurfaceControl->setPosition(0, 0); + SurfaceComposerClient::closeGlobalTransaction(true); + + // Find the boundary between the parent and child + { + ScreenCapture::captureScreen(&mCapture); + mCapture->expectChildColor(9, 9); + mCapture->expectFGColor(10, 10); + } + + SurfaceComposerClient::openGlobalTransaction(); + mFGSurfaceControl->setMatrix(2.0, 0, 0, 2.0); + SurfaceComposerClient::closeGlobalTransaction(true); + + // The boundary should be twice as far from the origin now. + // The pixels from the last test should all be child now + { + ScreenCapture::captureScreen(&mCapture); + mCapture->expectChildColor(9, 9); + mCapture->expectChildColor(10, 10); + mCapture->expectChildColor(19, 19); + mCapture->expectFGColor(20, 20); + } +} } |