diff options
25 files changed, 929 insertions, 478 deletions
diff --git a/include/gui/ISurfaceComposer.h b/include/gui/ISurfaceComposer.h index 824e5c4dea..ff04e2f276 100644 --- a/include/gui/ISurfaceComposer.h +++ b/include/gui/ISurfaceComposer.h @@ -157,7 +157,7 @@ public: virtual status_t captureScreen(const sp<IBinder>& display, const sp<IGraphicBufferProducer>& producer, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - uint32_t minLayerZ, uint32_t maxLayerZ, + int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, Rotation rotation = eRotateNone) = 0; 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 183b42d9c3..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 @@ -142,7 +143,7 @@ public: status_t show(const sp<IBinder>& id); status_t setFlags(const sp<IBinder>& id, uint32_t flags, uint32_t mask); status_t setTransparentRegionHint(const sp<IBinder>& id, const Region& transparent); - status_t setLayer(const sp<IBinder>& id, uint32_t layer); + status_t setLayer(const sp<IBinder>& id, int32_t layer); status_t setLayerInfo(const sp<IBinder>& id, uint32_t type, uint32_t appid); status_t setAlpha(const sp<IBinder>& id, float alpha=1.0f); status_t setMatrix(const sp<IBinder>& id, float dsdx, float dtdx, float dsdy, float dtdy); @@ -213,12 +214,12 @@ public: const sp<IBinder>& display, const sp<IGraphicBufferProducer>& producer, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - uint32_t minLayerZ, uint32_t maxLayerZ, + int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform); static status_t captureToBuffer( const sp<IBinder>& display, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - uint32_t minLayerZ, uint32_t maxLayerZ, + int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, uint32_t rotation, sp<GraphicBuffer>* outbuffer); @@ -242,11 +243,11 @@ public: bool useIdentityTransform); status_t update(const sp<IBinder>& display, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - uint32_t minLayerZ, uint32_t maxLayerZ, + int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform); status_t update(const sp<IBinder>& display, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - uint32_t minLayerZ, uint32_t maxLayerZ, + int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, uint32_t rotation); sp<CpuConsumer> getCpuConsumer() const; diff --git a/include/gui/SurfaceControl.h b/include/gui/SurfaceControl.h index 456bde40f3..62217ad107 100644 --- a/include/gui/SurfaceControl.h +++ b/include/gui/SurfaceControl.h @@ -61,7 +61,7 @@ public: void disconnect(); status_t setLayerStack(uint32_t layerStack); - status_t setLayer(uint32_t layer); + status_t setLayer(int32_t layer); status_t setLayerInfo(uint32_t type, uint32_t appid); status_t setPosition(float x, float y); status_t setSize(uint32_t w, uint32_t h); diff --git a/include/private/gui/LayerState.h b/include/private/gui/LayerState.h index b6487517a8..b3481d6465 100644 --- a/include/private/gui/LayerState.h +++ b/include/private/gui/LayerState.h @@ -84,7 +84,7 @@ struct layer_state_t { uint32_t what; float x; float y; - uint32_t z; + int32_t z; uint32_t w; uint32_t h; uint32_t layerStack; diff --git a/libs/gui/ISurfaceComposer.cpp b/libs/gui/ISurfaceComposer.cpp index fa2f59abb0..74c3bedf98 100644 --- a/libs/gui/ISurfaceComposer.cpp +++ b/libs/gui/ISurfaceComposer.cpp @@ -104,7 +104,7 @@ public: virtual status_t captureScreen(const sp<IBinder>& display, const sp<IGraphicBufferProducer>& producer, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - uint32_t minLayerZ, uint32_t maxLayerZ, + int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, ISurfaceComposer::Rotation rotation) { @@ -115,8 +115,8 @@ public: data.write(sourceCrop); data.writeUint32(reqWidth); data.writeUint32(reqHeight); - data.writeUint32(minLayerZ); - data.writeUint32(maxLayerZ); + data.writeInt32(minLayerZ); + data.writeInt32(maxLayerZ); data.writeInt32(static_cast<int32_t>(useIdentityTransform)); data.writeInt32(static_cast<int32_t>(rotation)); remote()->transact(BnSurfaceComposer::CAPTURE_SCREEN, data, &reply); @@ -544,8 +544,8 @@ status_t BnSurfaceComposer::onTransact( data.read(sourceCrop); uint32_t reqWidth = data.readUint32(); uint32_t reqHeight = data.readUint32(); - uint32_t minLayerZ = data.readUint32(); - uint32_t maxLayerZ = data.readUint32(); + int32_t minLayerZ = data.readInt32(); + int32_t maxLayerZ = data.readInt32(); bool useIdentityTransform = static_cast<bool>(data.readInt32()); int32_t rotation = data.readInt32(); 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/LayerState.cpp b/libs/gui/LayerState.cpp index 3949186f2b..16bf324298 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -28,7 +28,7 @@ status_t layer_state_t::write(Parcel& output) const output.writeUint32(what); output.writeFloat(x); output.writeFloat(y); - output.writeUint32(z); + output.writeInt32(z); output.writeUint32(w); output.writeUint32(h); output.writeUint32(layerStack); @@ -54,7 +54,7 @@ status_t layer_state_t::read(const Parcel& input) what = input.readUint32(); x = input.readFloat(); y = input.readFloat(); - z = input.readUint32(); + z = input.readInt32(); w = input.readUint32(); h = input.readUint32(); layerStack = input.readUint32(); diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 3346a83f3a..c2be6eb751 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -148,7 +148,7 @@ public: status_t setSize(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id, uint32_t w, uint32_t h); status_t setLayer(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id, - uint32_t z); + int32_t z); status_t setLayerInfo(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id, uint32_t type, uint32_t appid); status_t setFlags(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id, @@ -327,7 +327,7 @@ status_t Composer::setSize(const sp<SurfaceComposerClient>& client, } status_t Composer::setLayer(const sp<SurfaceComposerClient>& client, - const sp<IBinder>& id, uint32_t z) { + const sp<IBinder>& id, int32_t z) { Mutex::Autolock _l(mLock); layer_state_t* s = getLayerStateLocked(client, id); if (!s) @@ -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) { @@ -714,7 +720,7 @@ status_t SurfaceComposerClient::setSize(const sp<IBinder>& id, uint32_t w, uint3 return getComposer().setSize(this, id, w, h); } -status_t SurfaceComposerClient::setLayer(const sp<IBinder>& id, uint32_t z) { +status_t SurfaceComposerClient::setLayer(const sp<IBinder>& id, int32_t z) { return getComposer().setLayer(this, id, z); } @@ -871,7 +877,7 @@ status_t ScreenshotClient::capture( const sp<IBinder>& display, const sp<IGraphicBufferProducer>& producer, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - uint32_t minLayerZ, uint32_t maxLayerZ, bool useIdentityTransform) { + int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform) { sp<ISurfaceComposer> s(ComposerService::getComposerService()); if (s == NULL) return NO_INIT; return s->captureScreen(display, producer, sourceCrop, @@ -880,7 +886,7 @@ status_t ScreenshotClient::capture( status_t ScreenshotClient::captureToBuffer(const sp<IBinder>& display, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - uint32_t minLayerZ, uint32_t maxLayerZ, bool useIdentityTransform, + int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, uint32_t rotation, sp<GraphicBuffer>* outBuffer) { sp<ISurfaceComposer> s(ComposerService::getComposerService()); @@ -926,7 +932,7 @@ sp<CpuConsumer> ScreenshotClient::getCpuConsumer() const { status_t ScreenshotClient::update(const sp<IBinder>& display, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - uint32_t minLayerZ, uint32_t maxLayerZ, + int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, uint32_t rotation) { sp<ISurfaceComposer> s(ComposerService::getComposerService()); if (s == NULL) return NO_INIT; @@ -953,7 +959,7 @@ status_t ScreenshotClient::update(const sp<IBinder>& display, status_t ScreenshotClient::update(const sp<IBinder>& display, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - uint32_t minLayerZ, uint32_t maxLayerZ, + int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform) { return ScreenshotClient::update(display, sourceCrop, reqWidth, reqHeight, @@ -962,14 +968,16 @@ status_t ScreenshotClient::update(const sp<IBinder>& display, status_t ScreenshotClient::update(const sp<IBinder>& display, Rect sourceCrop, bool useIdentityTransform) { - return ScreenshotClient::update(display, sourceCrop, 0, 0, 0, -1U, + return ScreenshotClient::update(display, sourceCrop, 0, 0, + INT32_MIN, INT32_MAX, useIdentityTransform, ISurfaceComposer::eRotateNone); } status_t ScreenshotClient::update(const sp<IBinder>& display, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, bool useIdentityTransform) { return ScreenshotClient::update(display, sourceCrop, reqWidth, reqHeight, - 0, -1U, useIdentityTransform, ISurfaceComposer::eRotateNone); + INT32_MIN, INT32_MAX, + useIdentityTransform, ISurfaceComposer::eRotateNone); } void ScreenshotClient::release() { diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp index b47e434561..c82f6a7812 100644 --- a/libs/gui/SurfaceControl.cpp +++ b/libs/gui/SurfaceControl.cpp @@ -102,7 +102,7 @@ status_t SurfaceControl::setLayerStack(uint32_t layerStack) { if (err < 0) return err; return mClient->setLayerStack(mHandle, layerStack); } -status_t SurfaceControl::setLayer(uint32_t layer) { +status_t SurfaceControl::setLayer(int32_t layer) { status_t err = validate(); if (err < 0) return err; return mClient->setLayer(mHandle, layer); diff --git a/libs/gui/tests/Surface_test.cpp b/libs/gui/tests/Surface_test.cpp index e40b4eb075..7b78175333 100644 --- a/libs/gui/tests/Surface_test.cpp +++ b/libs/gui/tests/Surface_test.cpp @@ -398,7 +398,7 @@ public: status_t captureScreen(const sp<IBinder>& /*display*/, const sp<IGraphicBufferProducer>& /*producer*/, Rect /*sourceCrop*/, uint32_t /*reqWidth*/, uint32_t /*reqHeight*/, - uint32_t /*minLayerZ*/, uint32_t /*maxLayerZ*/, + int32_t /*minLayerZ*/, int32_t /*maxLayerZ*/, bool /*useIdentityTransform*/, Rotation /*rotation*/) override { return NO_ERROR; } status_t clearAnimationFrameStats() override { return NO_ERROR; } diff --git a/services/surfaceflinger/Android.mk b/services/surfaceflinger/Android.mk index fcc9241202..1cd921569f 100644 --- a/services/surfaceflinger/Android.mk +++ b/services/surfaceflinger/Android.mk @@ -15,6 +15,7 @@ LOCAL_SRC_FILES := \ Layer.cpp \ LayerDim.cpp \ LayerRejecter.cpp \ + LayerVector.cpp \ MessageQueue.cpp \ MonitoredProducer.cpp \ SurfaceFlingerConsumer.cpp \ 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 b388448da7..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 @@ -482,7 +550,7 @@ gfx::FloatRect Layer::computeCrop(const sp<const DisplayDevice>& hw) const { } #ifdef USE_HWC2 -void Layer::setGeometry(const sp<const DisplayDevice>& displayDevice) +void Layer::setGeometry(const sp<const DisplayDevice>& displayDevice, uint32_t z) #else void Layer::setGeometry( const sp<const DisplayDevice>& hw, @@ -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(); @@ -602,9 +672,9 @@ void Layer::setGeometry( "%s (%d)", mName.string(), s.alpha, to_string(error).c_str(), static_cast<int32_t>(error)); - error = hwcLayer->setZOrder(s.z); + error = hwcLayer->setZOrder(z); ALOGE_IF(error != HWC2::Error::None, "[%s] Failed to set Z %u: %s (%d)", - mName.string(), s.z, to_string(error).c_str(), + mName.string(), z, to_string(error).c_str(), static_cast<int32_t>(error)); #else if (!frame.intersect(hw->getViewport(), &frame)) { @@ -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 SurfaceFlinger::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,7 +1647,19 @@ bool Layer::setPosition(float x, float y, bool immediate) { return true; } -bool Layer::setLayer(uint32_t z) { +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; mCurrentState.sequence++; @@ -1594,6 +1668,7 @@ bool Layer::setLayer(uint32_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 1654a512bd..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" @@ -109,7 +110,7 @@ public: struct State { Geometry active; Geometry requested; - uint32_t z; + int32_t z; uint32_t layerStack; #ifdef USE_HWC2 float alpha; @@ -154,7 +155,7 @@ public: // modify current state bool setPosition(float x, float y, bool immediate); - bool setLayer(uint32_t z); + bool setLayer(int32_t z); bool setSize(uint32_t w, uint32_t h); #ifdef USE_HWC2 bool setAlpha(float alpha); @@ -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; @@ -234,7 +244,7 @@ public: // ----------------------------------------------------------------------- #ifdef USE_HWC2 - void setGeometry(const sp<const DisplayDevice>& displayDevice); + void setGeometry(const sp<const DisplayDevice>& displayDevice, uint32_t z); void forceClientComposition(int32_t hwcId); void setPerFrameData(const sp<const DisplayDevice>& displayDevice); @@ -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 new file mode 100644 index 0000000000..7ba6ad3bfa --- /dev/null +++ b/services/surfaceflinger/LayerVector.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "LayerVector.h" +#include "Layer.h" + +namespace android { +LayerVector::LayerVector(const LayerVector& rhs) : SortedVector<sp<Layer>>(rhs) { +} + +int LayerVector::do_compare(const void* lhs, const void* rhs) const +{ + // sort layers per layer-stack, then by z-order and finally by sequence + const auto& l = *reinterpret_cast<const sp<Layer>*>(lhs); + const auto& r = *reinterpret_cast<const sp<Layer>*>(rhs); + + uint32_t ls = l->getCurrentState().layerStack; + uint32_t rs = r->getCurrentState().layerStack; + if (ls != rs) + return ls - rs; + + uint32_t lz = l->getCurrentState().z; + uint32_t rz = r->getCurrentState().z; + if (lz != rz) + return lz - rz; + + return l->sequence - r->sequence; +} + +void LayerVector::traverseInZOrder(const std::function<void(Layer*)>& consume) const { + 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--) { + (*this)[i]->traverseInReverseZOrder(consume); + } +} +} // namespace android diff --git a/services/surfaceflinger/LayerVector.h b/services/surfaceflinger/LayerVector.h new file mode 100644 index 0000000000..7dfa4a0350 --- /dev/null +++ b/services/surfaceflinger/LayerVector.h @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2016 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef ANDROID_SURFACE_FLINGER_LAYER_VECTOR_H +#define ANDROID_SURFACE_FLINGER_LAYER_VECTOR_H + +#include <utils/SortedVector.h> +#include <utils/RefBase.h> + +#include <functional> + +namespace android { +class Layer; + +/* + * Used by the top-level SurfaceFlinger state and individual layers + * to track layers they own sorted according to Z-order. Provides traversal + * functions for traversing all owned layers, and their descendents. + */ +class LayerVector : public SortedVector<sp<Layer>> { +public: + LayerVector() = default; + LayerVector(const LayerVector& rhs); + // Sorts layer by layer-stack, Z order, and finally creation order (sequence). + int do_compare(const void* lhs, const void* rhs) const override; + + void traverseInReverseZOrder(const std::function<void(Layer*)>& consume) const; + void traverseInZOrder(const std::function<void(Layer*)>& consume) const; +}; +} + +#endif /* ANDROID_SURFACE_FLINGER_LAYER_VECTOR_H_ */ diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 5f25ef5dc7..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"); @@ -1211,13 +1214,12 @@ void SurfaceFlinger::preComposition(nsecs_t refreshStartTime) ALOGV("preComposition"); bool needExtraInvalidate = false; - const LayerVector& layers(mDrawingState.layersSortedByZ); - const size_t count = layers.size(); - for (size_t i=0 ; i<count ; i++) { - if (layers[i]->onPreComposition(refreshStartTime)) { + mDrawingState.traverseInZOrder([&](Layer* layer) { + if (layer->onPreComposition(refreshStartTime)) { needExtraInvalidate = true; } - } + }); + if (needExtraInvalidate) { signalLayerUpdate(); } @@ -1258,18 +1260,14 @@ void SurfaceFlinger::postComposition() } else { retireFenceTime = &displayFenceTime; } - - const LayerVector& layers(mDrawingState.layersSortedByZ); - const size_t count = layers.size(); - for (size_t i=0 ; i<count ; i++) { - bool frameLatched = - layers[i]->onPostComposition(glCompositionDoneFenceTime, - *presentFenceTime, *retireFenceTime); + mDrawingState.traverseInZOrder([&](Layer* layer) { + bool frameLatched = layer->onPostComposition(glCompositionDoneFenceTime, + *presentFenceTime, *retireFenceTime); if (frameLatched) { - recordBufferingStats(layers[i]->getName().string(), - layers[i]->getOccupancyHistory(false)); + recordBufferingStats(layer->getName().string(), + layer->getOccupancyHistory(false)); } - } + }); if (displayFence->isValid()) { if (mPrimaryDispSync.addPresentFence(displayFence)) { @@ -1332,7 +1330,6 @@ void SurfaceFlinger::rebuildLayerStacks() { mVisibleRegionsDirty = false; invalidateHwcGeometry(); - const LayerVector& layers(mDrawingState.layersSortedByZ); for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) { Region opaqueRegion; Region dirtyRegion; @@ -1341,15 +1338,12 @@ void SurfaceFlinger::rebuildLayerStacks() { const Transform& tr(displayDevice->getTransform()); const Rect bounds(displayDevice->getBounds()); if (displayDevice->isDisplayOn()) { - SurfaceFlinger::computeVisibleRegions(layers, + computeVisibleRegions( displayDevice->getLayerStack(), dirtyRegion, opaqueRegion); - const size_t count = layers.size(); - for (size_t i=0 ; i<count ; i++) { - const sp<Layer>& layer(layers[i]); - const Layer::State& s(layer->getDrawingState()); - if (s.layerStack == displayDevice->getLayerStack()) { + mDrawingState.traverseInZOrder([&](Layer* layer) { + if (layer->getLayerStack() == displayDevice->getLayerStack()) { Region drawRegion(tr.transform( layer->visibleNonTransparentRegion)); drawRegion.andSelf(bounds); @@ -1362,7 +1356,7 @@ void SurfaceFlinger::rebuildLayerStacks() { nullptr); } } - } + }); } displayDevice->setVisibleLayersSortedByZ(layersSortedByZ); displayDevice->undefinedRegion.set(bounds); @@ -1416,7 +1410,8 @@ void SurfaceFlinger::setUpHWComposer() { const Vector<sp<Layer>>& currentLayers( displayDevice->getVisibleLayersSortedByZ()); bool foundLayerWithoutHwc = false; - for (auto& layer : currentLayers) { + for (size_t i = 0; i < currentLayers.size(); i++) { + const auto& layer = currentLayers[i]; if (!layer->hasHwcLayer(hwcId)) { auto hwcLayer = mHwc->createLayer(hwcId); if (hwcLayer) { @@ -1428,7 +1423,7 @@ void SurfaceFlinger::setUpHWComposer() { } } - layer->setGeometry(displayDevice); + layer->setGeometry(displayDevice, i); if (mDebugDisableHWC || mDebugRegion) { layer->forceClientComposition(hwcId); } @@ -1567,13 +1562,10 @@ void SurfaceFlinger::handleTransaction(uint32_t transactionFlags) void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) { - const LayerVector& currentLayers(mCurrentState.layersSortedByZ); - const size_t count = currentLayers.size(); - // Notify all layers of available frames - for (size_t i = 0; i < count; ++i) { - currentLayers[i]->notifyAvailableFrames(); - } + mCurrentState.traverseInZOrder([](Layer* layer) { + layer->notifyAvailableFrames(); + }); /* * Traversal of the children @@ -1581,15 +1573,14 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) */ if (transactionFlags & eTraversalNeeded) { - for (size_t i=0 ; i<count ; i++) { - const sp<Layer>& layer(currentLayers[i]); + mCurrentState.traverseInZOrder([&](Layer* layer) { uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded); - if (!trFlags) continue; + if (!trFlags) return; const uint32_t flags = layer->doTransaction(0); if (flags & Layer::eVisibleRegion) mVisibleRegionsDirty = true; - } + }); } /* @@ -1782,13 +1773,13 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) // sp<const DisplayDevice> disp; uint32_t currentlayerStack = 0; - for (size_t i=0; i<count; i++) { + bool first = true; + mCurrentState.traverseInZOrder([&](Layer* layer) { // 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). - const sp<Layer>& layer(currentLayers[i]); - uint32_t layerStack = layer->getDrawingState().layerStack; - if (i==0 || currentlayerStack != layerStack) { + uint32_t layerStack = layer->getLayerStack(); + if (first || currentlayerStack != layerStack) { currentlayerStack = layerStack; // figure out if this layerstack is mirrored // (more than one display) if so, pick the default display, @@ -1816,7 +1807,9 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) disp = getDefaultDisplayDevice(); } layer->updateTransformHint(disp); - } + + first = false; + }); } @@ -1824,9 +1817,9 @@ 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; } @@ -1835,20 +1828,17 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) if (mLayersRemoved) { mLayersRemoved = false; mVisibleRegionsDirty = true; - const size_t count = layers.size(); - for (size_t i=0 ; i<count ; i++) { - const sp<Layer>& layer(layers[i]); - if (currentLayers.indexOf(layer) < 0) { + mDrawingState.traverseInZOrder([&](Layer* layer) { + 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); } - } + }); } commitTransaction(); @@ -1874,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(); } @@ -1887,13 +1877,15 @@ void SurfaceFlinger::commitTransaction() mAnimCompositionPending = mAnimTransactionPending; mDrawingState = mCurrentState; + mDrawingState.traverseInZOrder([](Layer* layer) { + layer->commitChildList(); + }); mTransactionPending = false; mAnimTransactionPending = false; mTransactionCV.broadcast(); } -void SurfaceFlinger::computeVisibleRegions( - const LayerVector& currentLayers, uint32_t layerStack, +void SurfaceFlinger::computeVisibleRegions(uint32_t layerStack, Region& outDirtyRegion, Region& outOpaqueRegion) { ATRACE_CALL(); @@ -1905,16 +1897,13 @@ void SurfaceFlinger::computeVisibleRegions( outDirtyRegion.clear(); - size_t i = currentLayers.size(); - while (i--) { - const sp<Layer>& layer = currentLayers[i]; - + mDrawingState.traverseInReverseZOrder([&](Layer* layer) { // start with the whole surface at its current location const Layer::State& s(layer->getDrawingState()); // only consider the layers on the given layer stack - if (s.layerStack != layerStack) - continue; + if (layer->getLayerStack() != layerStack) + return; /* * opaqueRegion: area of a surface that is fully opaque. @@ -1949,12 +1938,12 @@ void SurfaceFlinger::computeVisibleRegions( // 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); @@ -1966,7 +1955,7 @@ void SurfaceFlinger::computeVisibleRegions( } // 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 @@ -2023,7 +2012,7 @@ void SurfaceFlinger::computeVisibleRegions( layer->setCoveredRegion(coveredRegion); layer->setVisibleNonTransparentRegion( visibleRegion.subtract(transparentRegion)); - } + }); outOpaqueRegion = aboveOpaqueLayers; } @@ -2045,7 +2034,6 @@ bool SurfaceFlinger::handlePageFlip() nsecs_t latchTime = systemTime(); bool visibleRegions = false; - const LayerVector& layers(mDrawingState.layersSortedByZ); bool frameQueued = false; // Store the set of layers that need updates. This set must not change as @@ -2057,24 +2045,23 @@ bool SurfaceFlinger::handlePageFlip() // 3.) Layer 1 is latched. // Display is now waiting on Layer 1's frame, which is behind layer 0's // second frame. But layer 0's second frame could be waiting on display. - for (size_t i = 0, count = layers.size(); i<count ; i++) { - const sp<Layer>& layer(layers[i]); + mDrawingState.traverseInZOrder([&](Layer* layer) { if (layer->hasQueuedFrame()) { frameQueued = true; if (layer->shouldPresentNow(mPrimaryDispSync)) { - mLayersWithQueuedFrames.push_back(layer.get()); + mLayersWithQueuedFrames.push_back(layer); } else { layer->useEmptyDamage(); } } else { layer->useEmptyDamage(); } - } + }); + 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; @@ -2296,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 @@ -2322,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() { @@ -2504,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) { @@ -2543,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) @@ -2571,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)", @@ -2603,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; } @@ -2891,12 +2909,9 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args) void SurfaceFlinger::listLayersLocked(const Vector<String16>& /* args */, size_t& /* index */, String8& result) const { - const LayerVector& currentLayers = mCurrentState.layersSortedByZ; - const size_t count = currentLayers.size(); - for (size_t i=0 ; i<count ; i++) { - const sp<Layer>& layer(currentLayers[i]); + mCurrentState.traverseInZOrder([&](Layer* layer) { result.appendFormat("%s\n", layer->getName().string()); - } + }); } void SurfaceFlinger::dumpStatsLocked(const Vector<String16>& args, size_t& index, @@ -2915,14 +2930,11 @@ void SurfaceFlinger::dumpStatsLocked(const Vector<String16>& args, size_t& index if (name.isEmpty()) { mAnimFrameTracker.dumpStats(result); } else { - const LayerVector& currentLayers = mCurrentState.layersSortedByZ; - const size_t count = currentLayers.size(); - for (size_t i=0 ; i<count ; i++) { - const sp<Layer>& layer(currentLayers[i]); + mCurrentState.traverseInZOrder([&](Layer* layer) { if (name == layer->getName()) { layer->dumpFrameStats(result); } - } + }); } } @@ -2935,14 +2947,11 @@ void SurfaceFlinger::clearStatsLocked(const Vector<String16>& args, size_t& inde index++; } - const LayerVector& currentLayers = mCurrentState.layersSortedByZ; - const size_t count = currentLayers.size(); - for (size_t i=0 ; i<count ; i++) { - const sp<Layer>& layer(currentLayers[i]); + mCurrentState.traverseInZOrder([&](Layer* layer) { if (name.isEmpty() || (name == layer->getName())) { layer->clearFrameStats(); } - } + }); mAnimFrameTracker.clearStats(); } @@ -2950,12 +2959,9 @@ void SurfaceFlinger::clearStatsLocked(const Vector<String16>& args, size_t& inde // This should only be called from the main thread. Otherwise it would need // the lock and should use mCurrentState rather than mDrawingState. void SurfaceFlinger::logFrameStats() { - const LayerVector& drawingLayers = mDrawingState.layersSortedByZ; - const size_t count = drawingLayers.size(); - for (size_t i=0 ; i<count ; i++) { - const sp<Layer>& layer(drawingLayers[i]); + mDrawingState.traverseInZOrder([&](Layer* layer) { layer->logFrameStats(); - } + }); mAnimFrameTracker.logAndResetStats(String8("<win-anim>")); } @@ -3112,15 +3118,12 @@ 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); - for (size_t i=0 ; i<count ; i++) { - const sp<Layer>& layer(currentLayers[i]); + mCurrentState.traverseInZOrder([&](Layer* layer) { layer->dump(result, colorizer); - } + }); /* * Dump Display state @@ -3198,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"); } @@ -3582,7 +3584,7 @@ public: status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display, const sp<IGraphicBufferProducer>& producer, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - uint32_t minLayerZ, uint32_t maxLayerZ, + int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, ISurfaceComposer::Rotation rotation) { if (CC_UNLIKELY(display == 0)) @@ -3633,7 +3635,7 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display, const sp<IBinder>& display, const sp<IGraphicBufferProducer>& producer, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - uint32_t minLayerZ, uint32_t maxLayerZ, + int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, Transform::orientation_flags rotation, bool isLocalScreenshot) @@ -3682,7 +3684,7 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display, void SurfaceFlinger::renderScreenImplLocked( const sp<const DisplayDevice>& hw, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - uint32_t minLayerZ, uint32_t maxLayerZ, + int32_t minLayerZ, int32_t maxLayerZ, bool yswap, bool useIdentityTransform, Transform::orientation_flags rotation) { ATRACE_CALL(); @@ -3726,20 +3728,24 @@ void SurfaceFlinger::renderScreenImplLocked( // redraw the screen entirely... engine.clearWithColor(0, 0, 0, 1); - const LayerVector& layers( mDrawingState.layersSortedByZ ); - const size_t count = layers.size(); - for (size_t i=0 ; i<count ; ++i) { - const sp<Layer>& layer(layers[i]); + // 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(); @@ -3750,7 +3756,7 @@ status_t SurfaceFlinger::captureScreenImplLocked( const sp<const DisplayDevice>& hw, const sp<IGraphicBufferProducer>& producer, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - uint32_t minLayerZ, uint32_t maxLayerZ, + int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, Transform::orientation_flags rotation, bool isLocalScreenshot) { @@ -3774,16 +3780,16 @@ status_t SurfaceFlinger::captureScreenImplLocked( reqHeight = (!reqHeight) ? hw_h : reqHeight; bool secureLayerIsVisible = false; - const LayerVector& layers(mDrawingState.layersSortedByZ); - const size_t count = layers.size(); - for (size_t i = 0 ; i < count ; ++i) { - const sp<Layer>& layer(layers[i]); + 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) { @@ -3911,7 +3917,7 @@ status_t SurfaceFlinger::captureScreenImplLocked( } void SurfaceFlinger::checkScreenshot(size_t w, size_t s, size_t h, void const* vaddr, - const sp<const DisplayDevice>& hw, uint32_t minLayerZ, uint32_t maxLayerZ) { + const sp<const DisplayDevice>& hw, int32_t minLayerZ, int32_t maxLayerZ) { if (DEBUG_SCREENSHOTS) { for (size_t y=0 ; y<h ; y++) { uint32_t const * p = (uint32_t const *)vaddr + y*s; @@ -3922,49 +3928,32 @@ 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()); - const LayerVector& layers( mDrawingState.layersSortedByZ ); - const size_t count = layers.size(); - for (size_t i=0 ; i<count ; ++i) { - const sp<Layer>& layer(layers[i]); + + size_t i = 0; + 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++; + }); + } } } } // --------------------------------------------------------------------------- -SurfaceFlinger::LayerVector::LayerVector() { -} - -SurfaceFlinger::LayerVector::LayerVector(const LayerVector& rhs) - : SortedVector<sp<Layer> >(rhs) { +void SurfaceFlinger::State::traverseInZOrder(const std::function<void(Layer*)>& consume) const { + layersSortedByZ.traverseInZOrder(consume); } -int SurfaceFlinger::LayerVector::do_compare(const void* lhs, - const void* rhs) const -{ - // sort layers per layer-stack, then by z-order and finally by sequence - const sp<Layer>& l(*reinterpret_cast<const sp<Layer>*>(lhs)); - const sp<Layer>& r(*reinterpret_cast<const sp<Layer>*>(rhs)); - - uint32_t ls = l->getCurrentState().layerStack; - uint32_t rs = r->getCurrentState().layerStack; - if (ls != rs) - return ls - rs; - - uint32_t lz = l->getCurrentState().z; - uint32_t rz = r->getCurrentState().z; - if (lz != rz) - return lz - rz; - - return l->sequence - r->sequence; +void SurfaceFlinger::State::traverseInReverseZOrder(const std::function<void(Layer*)>& consume) const { + layersSortedByZ.traverseInReverseZOrder(consume); } }; // namespace android diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index f7f9ef54ea..4f3ee7433d 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -55,6 +55,7 @@ #include "DisplayDevice.h" #include "DispSync.h" #include "FrameTracker.h" +#include "LayerVector.h" #include "MessageQueue.h" #include "SurfaceInterceptor.h" @@ -168,16 +169,13 @@ private: * Internal data structures */ - class LayerVector : public SortedVector< sp<Layer> > { + class State { public: - LayerVector(); - LayerVector(const LayerVector& rhs); - virtual int do_compare(const void* lhs, const void* rhs) const; - }; - - struct State { LayerVector layersSortedByZ; DefaultKeyedVector< wp<IBinder>, DisplayDeviceState> displays; + + void traverseInZOrder(const std::function<void(Layer*)>& consume) const; + void traverseInReverseZOrder(const std::function<void(Layer*)>& consume) const; }; /* ------------------------------------------------------------------------ @@ -206,7 +204,7 @@ private: virtual status_t captureScreen(const sp<IBinder>& display, const sp<IGraphicBufferProducer>& producer, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - uint32_t minLayerZ, uint32_t maxLayerZ, + int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, ISurfaceComposer::Rotation rotation); virtual status_t getDisplayStats(const sp<IBinder>& display, DisplayStatInfo* stats); @@ -295,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, @@ -322,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 @@ -333,14 +333,14 @@ private: void renderScreenImplLocked( const sp<const DisplayDevice>& hw, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - uint32_t minLayerZ, uint32_t maxLayerZ, + int32_t minLayerZ, int32_t maxLayerZ, bool yswap, bool useIdentityTransform, Transform::orientation_flags rotation); status_t captureScreenImplLocked( const sp<const DisplayDevice>& hw, const sp<IGraphicBufferProducer>& producer, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - uint32_t minLayerZ, uint32_t maxLayerZ, + int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, Transform::orientation_flags rotation, bool isLocalScreenshot); @@ -397,8 +397,7 @@ private: * Compositing */ void invalidateHwcGeometry(); - static void computeVisibleRegions( - const LayerVector& currentLayers, uint32_t layerStack, + void computeVisibleRegions(uint32_t layerStack, Region& dirtyRegion, Region& opaqueRegion); void preComposition(nsecs_t refreshStartTime); @@ -426,6 +425,7 @@ private: void enableHardwareVsync(); void resyncToHardwareVsync(bool makeAvailable); void disableHardwareVsync(bool makeUnavailable); + public: void resyncWithRateLimit(); private: @@ -441,7 +441,7 @@ private: void appendSfConfigString(String8& result) const; void checkScreenshot(size_t w, size_t s, size_t h, void const* vaddr, const sp<const DisplayDevice>& hw, - uint32_t minLayerZ, uint32_t maxLayerZ); + int32_t minLayerZ, int32_t maxLayerZ); void logFrameStats(); @@ -467,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; @@ -568,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 fcf0185953..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"); @@ -1126,13 +1129,12 @@ void SurfaceFlinger::doDebugFlashRegions() void SurfaceFlinger::preComposition(nsecs_t refreshStartTime) { bool needExtraInvalidate = false; - const LayerVector& layers(mDrawingState.layersSortedByZ); - const size_t count = layers.size(); - for (size_t i=0 ; i<count ; i++) { - if (layers[i]->onPreComposition(refreshStartTime)) { + mDrawingState.traverseInZOrder([&](Layer* layer) { + if (layer->onPreComposition(refreshStartTime)) { needExtraInvalidate = true; } - } + }); + if (needExtraInvalidate) { signalLayerUpdate(); } @@ -1159,16 +1161,15 @@ void SurfaceFlinger::postComposition() mDisplayTimeline.push(retireFenceTime); mDisplayTimeline.updateSignalTimes(); - const LayerVector& layers(mDrawingState.layersSortedByZ); - const size_t count = layers.size(); - for (size_t i=0 ; i<count ; i++) { - bool frameLatched = layers[i]->onPostComposition( - glCompositionDoneFenceTime, presentFenceTime, retireFenceTime); + mDrawingState.traverseInZOrder([&](Layer* layer) { + bool frameLatched = layer->onPostComposition(glCompositionDoneFenceTime, + presentFenceTime, retireFenceTime); + if (frameLatched) { - recordBufferingStats(layers[i]->getName().string(), - layers[i]->getOccupancyHistory(false)); + recordBufferingStats(layer->getName().string(), + layer->getOccupancyHistory(false)); } - } + }); if (displayFence->isValid()) { if (mPrimaryDispSync.addPresentFence(displayFence)) { @@ -1226,7 +1227,6 @@ void SurfaceFlinger::rebuildLayerStacks() { mVisibleRegionsDirty = false; invalidateHwcGeometry(); - const LayerVector& layers(mDrawingState.layersSortedByZ); for (size_t dpy=0 ; dpy<mDisplays.size() ; dpy++) { Region opaqueRegion; Region dirtyRegion; @@ -1235,14 +1235,11 @@ void SurfaceFlinger::rebuildLayerStacks() { const Transform& tr(hw->getTransform()); const Rect bounds(hw->getBounds()); if (hw->isDisplayOn()) { - SurfaceFlinger::computeVisibleRegions(layers, - hw->getLayerStack(), dirtyRegion, opaqueRegion); - - const size_t count = layers.size(); - for (size_t i=0 ; i<count ; i++) { - const sp<Layer>& layer(layers[i]); - const Layer::State& s(layer->getDrawingState()); - if (s.layerStack == hw->getLayerStack()) { + computeVisibleRegions(hw->getLayerStack(), dirtyRegion, + opaqueRegion); + + mDrawingState.traverseInZOrder([&](Layer* layer) { + if (layer->getLayerStack() == hw->getLayerStack()) { Region drawRegion(tr.transform( layer->visibleNonTransparentRegion)); drawRegion.andSelf(bounds); @@ -1250,7 +1247,7 @@ void SurfaceFlinger::rebuildLayerStacks() { layersSortedByZ.add(layer); } } - } + }); } hw->setVisibleLayersSortedByZ(layersSortedByZ); hw->undefinedRegion.set(bounds); @@ -1473,13 +1470,10 @@ void SurfaceFlinger::handleTransaction(uint32_t transactionFlags) void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) { - const LayerVector& currentLayers(mCurrentState.layersSortedByZ); - const size_t count = currentLayers.size(); - // Notify all layers of available frames - for (size_t i = 0; i < count; ++i) { - currentLayers[i]->notifyAvailableFrames(); - } + mCurrentState.traverseInZOrder([](Layer* layer) { + layer->notifyAvailableFrames(); + }); /* * Traversal of the children @@ -1487,15 +1481,14 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) */ if (transactionFlags & eTraversalNeeded) { - for (size_t i=0 ; i<count ; i++) { - const sp<Layer>& layer(currentLayers[i]); + mCurrentState.traverseInZOrder([&](Layer* layer) { uint32_t trFlags = layer->getTransactionFlags(eTransactionNeeded); - if (!trFlags) continue; + if (!trFlags) return; const uint32_t flags = layer->doTransaction(0); if (flags & Layer::eVisibleRegion) mVisibleRegionsDirty = true; - } + }); } /* @@ -1682,13 +1675,13 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) // sp<const DisplayDevice> disp; uint32_t currentlayerStack = 0; - for (size_t i=0; i<count; i++) { + bool first = true; + mCurrentState.traverseInZOrder([&](Layer* layer) { // 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). - const sp<Layer>& layer(currentLayers[i]); - uint32_t layerStack = layer->getDrawingState().layerStack; - if (i==0 || currentlayerStack != layerStack) { + uint32_t layerStack = layer->getLayerStack(); + if (first || currentlayerStack != layerStack) { currentlayerStack = layerStack; // figure out if this layerstack is mirrored // (more than one display) if so, pick the default display, @@ -1716,7 +1709,9 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) disp = getDefaultDisplayDevice(); } layer->updateTransformHint(disp); - } + + first = false; + }); } @@ -1724,9 +1719,9 @@ 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; } @@ -1735,20 +1730,17 @@ void SurfaceFlinger::handleTransactionLocked(uint32_t transactionFlags) if (mLayersRemoved) { mLayersRemoved = false; mVisibleRegionsDirty = true; - const size_t count = layers.size(); - for (size_t i=0 ; i<count ; i++) { - const sp<Layer>& layer(layers[i]); - if (currentLayers.indexOf(layer) < 0) { + mDrawingState.traverseInZOrder([&](Layer* layer) { + 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); } - } + }); } commitTransaction(); @@ -1786,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(); } @@ -1799,13 +1791,15 @@ void SurfaceFlinger::commitTransaction() mAnimCompositionPending = mAnimTransactionPending; mDrawingState = mCurrentState; + mDrawingState.traverseInZOrder([](Layer* layer) { + layer->commitChildList(); + }); mTransactionPending = false; mAnimTransactionPending = false; mTransactionCV.broadcast(); } -void SurfaceFlinger::computeVisibleRegions( - const LayerVector& currentLayers, uint32_t layerStack, +void SurfaceFlinger::computeVisibleRegions(uint32_t layerStack, Region& outDirtyRegion, Region& outOpaqueRegion) { ATRACE_CALL(); @@ -1816,16 +1810,13 @@ void SurfaceFlinger::computeVisibleRegions( outDirtyRegion.clear(); - size_t i = currentLayers.size(); - while (i--) { - const sp<Layer>& layer = currentLayers[i]; - + mDrawingState.traverseInReverseZOrder([&](Layer* layer) { // start with the whole surface at its current location const Layer::State& s(layer->getDrawingState()); // only consider the layers on the given layer stack - if (s.layerStack != layerStack) - continue; + if (layer->getLayerStack() != layerStack) + return; /* * opaqueRegion: area of a surface that is fully opaque. @@ -1860,12 +1851,12 @@ void SurfaceFlinger::computeVisibleRegions( // 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); @@ -1877,7 +1868,7 @@ void SurfaceFlinger::computeVisibleRegions( } // 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 @@ -1934,7 +1925,7 @@ void SurfaceFlinger::computeVisibleRegions( layer->setCoveredRegion(coveredRegion); layer->setVisibleNonTransparentRegion( visibleRegion.subtract(transparentRegion)); - } + }); outOpaqueRegion = aboveOpaqueLayers; } @@ -1955,7 +1946,6 @@ bool SurfaceFlinger::handlePageFlip() Region dirtyRegion; bool visibleRegions = false; - const LayerVector& layers(mDrawingState.layersSortedByZ); bool frameQueued = false; // Store the set of layers that need updates. This set must not change as @@ -1968,25 +1958,23 @@ bool SurfaceFlinger::handlePageFlip() // Display is now waiting on Layer 1's frame, which is behind layer 0's // second frame. But layer 0's second frame could be waiting on display. Vector<Layer*> layersWithQueuedFrames; - for (size_t i = 0, count = layers.size(); i<count ; i++) { - const sp<Layer>& layer(layers[i]); + mDrawingState.traverseInZOrder([&](Layer* layer) { if (layer->hasQueuedFrame()) { frameQueued = true; if (layer->shouldPresentNow(mPrimaryDispSync)) { - layersWithQueuedFrames.push_back(layer.get()); + layersWithQueuedFrames.push_back(layer); } else { layer->useEmptyDamage(); } } else { layer->useEmptyDamage(); } - } + }); for (size_t i = 0, count = layersWithQueuedFrames.size() ; i<count ; i++) { 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; @@ -2202,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 @@ -2228,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() { @@ -2410,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) { @@ -2449,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) @@ -2477,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)", @@ -2509,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; } @@ -2797,12 +2816,9 @@ status_t SurfaceFlinger::dump(int fd, const Vector<String16>& args) void SurfaceFlinger::listLayersLocked(const Vector<String16>& /* args */, size_t& /* index */, String8& result) const { - const LayerVector& currentLayers = mCurrentState.layersSortedByZ; - const size_t count = currentLayers.size(); - for (size_t i=0 ; i<count ; i++) { - const sp<Layer>& layer(currentLayers[i]); + mCurrentState.traverseInZOrder([&](Layer* layer) { result.appendFormat("%s\n", layer->getName().string()); - } + }); } void SurfaceFlinger::dumpStatsLocked(const Vector<String16>& args, size_t& index, @@ -2821,14 +2837,11 @@ void SurfaceFlinger::dumpStatsLocked(const Vector<String16>& args, size_t& index if (name.isEmpty()) { mAnimFrameTracker.dumpStats(result); } else { - const LayerVector& currentLayers = mCurrentState.layersSortedByZ; - const size_t count = currentLayers.size(); - for (size_t i=0 ; i<count ; i++) { - const sp<Layer>& layer(currentLayers[i]); + mCurrentState.traverseInZOrder([&](Layer* layer) { if (name == layer->getName()) { layer->dumpFrameStats(result); } - } + }); } } @@ -2841,14 +2854,11 @@ void SurfaceFlinger::clearStatsLocked(const Vector<String16>& args, size_t& inde index++; } - const LayerVector& currentLayers = mCurrentState.layersSortedByZ; - const size_t count = currentLayers.size(); - for (size_t i=0 ; i<count ; i++) { - const sp<Layer>& layer(currentLayers[i]); + mCurrentState.traverseInZOrder([&](Layer* layer) { if (name.isEmpty() || (name == layer->getName())) { layer->clearFrameStats(); } - } + }); mAnimFrameTracker.clearStats(); } @@ -2856,12 +2866,9 @@ void SurfaceFlinger::clearStatsLocked(const Vector<String16>& args, size_t& inde // This should only be called from the main thread. Otherwise it would need // the lock and should use mCurrentState rather than mDrawingState. void SurfaceFlinger::logFrameStats() { - const LayerVector& drawingLayers = mDrawingState.layersSortedByZ; - const size_t count = drawingLayers.size(); - for (size_t i=0 ; i<count ; i++) { - const sp<Layer>& layer(drawingLayers[i]); + mDrawingState.traverseInZOrder([&](Layer* layer) { layer->logFrameStats(); - } + }); mAnimFrameTracker.logAndResetStats(String8("<win-anim>")); } @@ -3015,15 +3022,12 @@ 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); - for (size_t i=0 ; i<count ; i++) { - const sp<Layer>& layer(currentLayers[i]); + mCurrentState.traverseInZOrder([&](Layer* layer) { layer->dump(result, colorizer); - } + }); /* * Dump Display state @@ -3459,7 +3463,7 @@ public: status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display, const sp<IGraphicBufferProducer>& producer, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - uint32_t minLayerZ, uint32_t maxLayerZ, + int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, ISurfaceComposer::Rotation rotation) { if (CC_UNLIKELY(display == 0)) @@ -3500,7 +3504,7 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display, sp<IGraphicBufferProducer> producer; Rect sourceCrop; uint32_t reqWidth, reqHeight; - uint32_t minLayerZ,maxLayerZ; + int32_t minLayerZ,maxLayerZ; bool useIdentityTransform; Transform::orientation_flags rotation; status_t result; @@ -3510,7 +3514,7 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display, const sp<IBinder>& display, const sp<IGraphicBufferProducer>& producer, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - uint32_t minLayerZ, uint32_t maxLayerZ, + int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, Transform::orientation_flags rotation, bool isLocalScreenshot) @@ -3559,7 +3563,7 @@ status_t SurfaceFlinger::captureScreen(const sp<IBinder>& display, void SurfaceFlinger::renderScreenImplLocked( const sp<const DisplayDevice>& hw, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - uint32_t minLayerZ, uint32_t maxLayerZ, + int32_t minLayerZ, int32_t maxLayerZ, bool yswap, bool useIdentityTransform, Transform::orientation_flags rotation) { ATRACE_CALL(); @@ -3603,20 +3607,24 @@ void SurfaceFlinger::renderScreenImplLocked( // redraw the screen entirely... engine.clearWithColor(0, 0, 0, 1); - const LayerVector& layers( mDrawingState.layersSortedByZ ); - const size_t count = layers.size(); - for (size_t i=0 ; i<count ; ++i) { - const sp<Layer>& layer(layers[i]); + // 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 @@ -3629,7 +3637,7 @@ status_t SurfaceFlinger::captureScreenImplLocked( const sp<const DisplayDevice>& hw, const sp<IGraphicBufferProducer>& producer, Rect sourceCrop, uint32_t reqWidth, uint32_t reqHeight, - uint32_t minLayerZ, uint32_t maxLayerZ, + int32_t minLayerZ, int32_t maxLayerZ, bool useIdentityTransform, Transform::orientation_flags rotation, bool isLocalScreenshot) { @@ -3653,16 +3661,16 @@ status_t SurfaceFlinger::captureScreenImplLocked( reqHeight = (!reqHeight) ? hw_h : reqHeight; bool secureLayerIsVisible = false; - const LayerVector& layers(mDrawingState.layersSortedByZ); - const size_t count = layers.size(); - for (size_t i = 0 ; i < count ; ++i) { - const sp<Layer>& layer(layers[i]); + 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) { @@ -3782,7 +3790,7 @@ status_t SurfaceFlinger::captureScreenImplLocked( } void SurfaceFlinger::checkScreenshot(size_t w, size_t s, size_t h, void const* vaddr, - const sp<const DisplayDevice>& hw, uint32_t minLayerZ, uint32_t maxLayerZ) { + const sp<const DisplayDevice>& hw, int32_t minLayerZ, int32_t maxLayerZ) { if (DEBUG_SCREENSHOTS) { for (size_t y=0 ; y<h ; y++) { uint32_t const * p = (uint32_t const *)vaddr + y*s; @@ -3793,49 +3801,31 @@ 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()); - const LayerVector& layers( mDrawingState.layersSortedByZ ); - const size_t count = layers.size(); - for (size_t i=0 ; i<count ; ++i) { - const sp<Layer>& layer(layers[i]); + size_t i = 0; + 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++; + }); + } } } } // --------------------------------------------------------------------------- -SurfaceFlinger::LayerVector::LayerVector() { -} - -SurfaceFlinger::LayerVector::LayerVector(const LayerVector& rhs) - : SortedVector<sp<Layer> >(rhs) { +void SurfaceFlinger::State::traverseInZOrder(const std::function<void(Layer*)>& consume) const { + layersSortedByZ.traverseInZOrder(consume); } -int SurfaceFlinger::LayerVector::do_compare(const void* lhs, - const void* rhs) const -{ - // sort layers per layer-stack, then by z-order and finally by sequence - const sp<Layer>& l(*reinterpret_cast<const sp<Layer>*>(lhs)); - const sp<Layer>& r(*reinterpret_cast<const sp<Layer>*>(rhs)); - - uint32_t ls = l->getCurrentState().layerStack; - uint32_t rs = r->getCurrentState().layerStack; - if (ls != rs) - return ls - rs; - - uint32_t lz = l->getCurrentState().z; - uint32_t rz = r->getCurrentState().z; - if (lz != rz) - return lz - rz; - - return l->sequence - r->sequence; +void SurfaceFlinger::State::traverseInReverseZOrder(const std::function<void(Layer*)>& consume) const { + layersSortedByZ.traverseInReverseZOrder(consume); } }; // namespace android 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); + } +} } |