diff options
-rw-r--r-- | include/gui/SurfaceComposerClient.h | 2 | ||||
-rw-r--r-- | include/gui/SurfaceControl.h | 21 | ||||
-rw-r--r-- | include/private/gui/LayerState.h | 5 | ||||
-rw-r--r-- | libs/gui/LayerState.cpp | 2 | ||||
-rw-r--r-- | libs/gui/SurfaceComposerClient.cpp | 21 | ||||
-rw-r--r-- | libs/gui/SurfaceControl.cpp | 8 | ||||
-rw-r--r-- | services/surfaceflinger/Layer.cpp | 105 | ||||
-rw-r--r-- | services/surfaceflinger/Layer.h | 12 | ||||
-rw-r--r-- | services/surfaceflinger/LayerVector.cpp | 12 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 5 | ||||
-rw-r--r-- | services/surfaceflinger/tests/Transaction_test.cpp | 43 |
11 files changed, 218 insertions, 18 deletions
diff --git a/include/gui/SurfaceComposerClient.h b/include/gui/SurfaceComposerClient.h index 394425a328..ec310cf6f9 100644 --- a/include/gui/SurfaceComposerClient.h +++ b/include/gui/SurfaceComposerClient.h @@ -146,6 +146,8 @@ public: 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, int32_t layer); + status_t setRelativeLayer(const sp<IBinder>& id, + const sp<IBinder>& relativeTo, int32_t layer); status_t setAlpha(const sp<IBinder>& id, float alpha=1.0f); status_t setMatrix(const sp<IBinder>& id, float dsdx, float dtdx, float dtdy, float dsdy); status_t setPosition(const sp<IBinder>& id, float x, float y); diff --git a/include/gui/SurfaceControl.h b/include/gui/SurfaceControl.h index 3cff7df260..712a323337 100644 --- a/include/gui/SurfaceControl.h +++ b/include/gui/SurfaceControl.h @@ -62,6 +62,27 @@ public: status_t setLayerStack(uint32_t layerStack); status_t setLayer(int32_t layer); + + // Sets a Z order relative to the Surface specified by "relativeTo" but + // without becoming a full child of the relative. Z-ordering works exactly + // as if it were a child however. + // + // As a nod to sanity, only non-child surfaces may have a relative Z-order. + // + // This overrides any previous and is overriden by any future calls + // to setLayer. + // + // If the relative dissapears, the Surface will have no layer and be + // invisible, until the next time set(Relative)Layer is called. + // + // TODO: This is probably a hack. Currently it exists only to work around + // some framework usage of the hidden APPLICATION_MEDIA_OVERLAY window type + // which allows inserting a window between a SurfaceView and it's main application + // window. However, since we are using child windows for the SurfaceView, but not using + // child windows elsewhere in O, the WindowManager can't set the layer appropriately. + // This is only used by the "TvInputService" and following the port of ViewRootImpl + // to child surfaces, we can then port this and remove this method. + status_t setRelativeLayer(const sp<IBinder>& relativeTo, int32_t layer); status_t setPosition(float x, float y); status_t setSize(uint32_t w, uint32_t h); status_t hide(); diff --git a/include/private/gui/LayerState.h b/include/private/gui/LayerState.h index 20f51a57ce..307c764702 100644 --- a/include/private/gui/LayerState.h +++ b/include/private/gui/LayerState.h @@ -58,7 +58,8 @@ struct layer_state_t { eOverrideScalingModeChanged = 0x00000800, eGeometryAppliesWithResize = 0x00001000, eReparentChildren = 0x00002000, - eDetachChildren = 0x00004000 + eDetachChildren = 0x00004000, + eRelativeLayerChanged = 0x00008000 }; layer_state_t() @@ -104,6 +105,8 @@ struct layer_state_t { sp<IGraphicBufferProducer> barrierGbp; + sp<IBinder> relativeLayerHandle; + // non POD must be last. see write/read Region transparentRegion; }; diff --git a/libs/gui/LayerState.cpp b/libs/gui/LayerState.cpp index 2461cba152..9b06e63610 100644 --- a/libs/gui/LayerState.cpp +++ b/libs/gui/LayerState.cpp @@ -44,6 +44,7 @@ status_t layer_state_t::write(Parcel& output) const output.writeUint64(frameNumber); output.writeInt32(overrideScalingMode); output.writeStrongBinder(IInterface::asBinder(barrierGbp)); + output.writeStrongBinder(relativeLayerHandle); output.write(transparentRegion); return NO_ERROR; } @@ -75,6 +76,7 @@ status_t layer_state_t::read(const Parcel& input) overrideScalingMode = input.readInt32(); barrierGbp = interface_cast<IGraphicBufferProducer>(input.readStrongBinder()); + relativeLayerHandle = input.readStrongBinder(); input.read(transparentRegion); return NO_ERROR; } diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 56c7586041..8c8384399c 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -149,6 +149,8 @@ public: uint32_t w, uint32_t h); status_t setLayer(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id, int32_t z); + status_t setRelativeLayer(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id, + const sp<IBinder>& relativeTo, int32_t z); status_t setFlags(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id, uint32_t flags, uint32_t mask); status_t setTransparentRegionHint( @@ -343,6 +345,20 @@ status_t Composer::setLayer(const sp<SurfaceComposerClient>& client, return NO_ERROR; } +status_t Composer::setRelativeLayer(const sp<SurfaceComposerClient>& client, + const sp<IBinder>& id, const sp<IBinder>& relativeTo, + int32_t z) { + Mutex::Autolock _l(mLock); + layer_state_t* s = getLayerStateLocked(client, id); + if (!s) { + return BAD_INDEX; + } + s->what |= layer_state_t::eRelativeLayerChanged; + s->relativeLayerHandle = relativeTo; + s->z = z; + return NO_ERROR; +} + status_t Composer::setFlags(const sp<SurfaceComposerClient>& client, const sp<IBinder>& id, uint32_t flags, uint32_t mask) { @@ -760,6 +776,11 @@ status_t SurfaceComposerClient::setLayer(const sp<IBinder>& id, int32_t z) { return getComposer().setLayer(this, id, z); } +status_t SurfaceComposerClient::setRelativeLayer(const sp<IBinder>& id, + const sp<IBinder>& relativeTo, int32_t z) { + return getComposer().setRelativeLayer(this, id, relativeTo, z); +} + status_t SurfaceComposerClient::hide(const sp<IBinder>& id) { return getComposer().setFlags(this, id, layer_state_t::eLayerHidden, diff --git a/libs/gui/SurfaceControl.cpp b/libs/gui/SurfaceControl.cpp index 7a68f1174a..bf8a815fe6 100644 --- a/libs/gui/SurfaceControl.cpp +++ b/libs/gui/SurfaceControl.cpp @@ -102,11 +102,19 @@ status_t SurfaceControl::setLayerStack(uint32_t layerStack) { if (err < 0) return err; return mClient->setLayerStack(mHandle, layerStack); } + status_t SurfaceControl::setLayer(int32_t layer) { status_t err = validate(); if (err < 0) return err; return mClient->setLayer(mHandle, layer); } + +status_t SurfaceControl::setRelativeLayer(const sp<IBinder>& relativeTo, int32_t layer) { + status_t err = validate(); + if (err < 0) return err; + return mClient->setRelativeLayer(mHandle, relativeTo, layer); +} + status_t SurfaceControl::setPosition(float x, float y) { status_t err = validate(); if (err < 0) return err; diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp index c211c7b4ed..b10d437fea 100644 --- a/services/surfaceflinger/Layer.cpp +++ b/services/surfaceflinger/Layer.cpp @@ -1719,10 +1719,55 @@ bool Layer::setLayer(int32_t z) { mCurrentState.sequence++; mCurrentState.z = z; mCurrentState.modified = true; + + // Discard all relative layering. + if (mCurrentState.zOrderRelativeOf != nullptr) { + sp<Layer> strongRelative = mCurrentState.zOrderRelativeOf.promote(); + if (strongRelative != nullptr) { + strongRelative->removeZOrderRelative(this); + } + mCurrentState.zOrderRelativeOf = nullptr; + } setTransactionFlags(eTransactionNeeded); return true; } +void Layer::removeZOrderRelative(const wp<Layer>& relative) { + mCurrentState.zOrderRelatives.remove(relative); + mCurrentState.sequence++; + mCurrentState.modified = true; + setTransactionFlags(eTransactionNeeded); +} + +void Layer::addZOrderRelative(const wp<Layer>& relative) { + mCurrentState.zOrderRelatives.add(relative); + mCurrentState.modified = true; + mCurrentState.sequence++; + setTransactionFlags(eTransactionNeeded); +} + +bool Layer::setRelativeLayer(const sp<IBinder>& relativeToHandle, int32_t z) { + sp<Handle> handle = static_cast<Handle*>(relativeToHandle.get()); + if (handle == nullptr) { + return false; + } + sp<Layer> relative = handle->owner.promote(); + if (relative == nullptr) { + return false; + } + + mCurrentState.sequence++; + mCurrentState.modified = true; + mCurrentState.z = z; + + mCurrentState.zOrderRelativeOf = relative; + relative->addZOrderRelative(this); + + setTransactionFlags(eTransactionNeeded); + + return true; +} + bool Layer::setSize(uint32_t w, uint32_t h) { if (mCurrentState.requested.w == w && mCurrentState.requested.h == h) return false; @@ -2506,40 +2551,70 @@ int32_t Layer::getZ() const { return mDrawingState.z; } +LayerVector Layer::makeTraversalList() { + if (mDrawingState.zOrderRelatives.size() == 0) { + return mDrawingChildren; + } + LayerVector traverse; + + for (const wp<Layer>& weakRelative : mDrawingState.zOrderRelatives) { + sp<Layer> strongRelative = weakRelative.promote(); + if (strongRelative != nullptr) { + traverse.add(strongRelative); + } else { + // We need to erase from current state instead of drawing + // state so we don't overwrite when copying + // the current state to the drawing state. + mCurrentState.zOrderRelatives.remove(weakRelative); + } + } + + for (const sp<Layer>& child : mDrawingChildren) { + traverse.add(child); + } + + return traverse; +} + /** - * Negatively signed children are before 'this' in Z-order. + * Negatively signed relatives are before 'this' in Z-order. */ void Layer::traverseInZOrder(const std::function<void(Layer*)>& exec) { + LayerVector list = makeTraversalList(); + size_t i = 0; - for (; i < mDrawingChildren.size(); i++) { - const auto& child = mDrawingChildren[i]; - if (child->getZ() >= 0) + for (; i < list.size(); i++) { + const auto& relative = list[i]; + if (relative->getZ() >= 0) { break; - child->traverseInZOrder(exec); + } + relative->traverseInZOrder(exec); } exec(this); - for (; i < mDrawingChildren.size(); i++) { - const auto& child = mDrawingChildren[i]; - child->traverseInZOrder(exec); + for (; i < list.size(); i++) { + const auto& relative = list[i]; + relative->traverseInZOrder(exec); } } /** - * Positively signed children are before 'this' in reverse Z-order. + * Positively signed relatives are before 'this' in reverse Z-order. */ void Layer::traverseInReverseZOrder(const std::function<void(Layer*)>& exec) { + LayerVector list = makeTraversalList(); + int32_t i = 0; - for (i = mDrawingChildren.size()-1; i>=0; i--) { - const auto& child = mDrawingChildren[i]; - if (child->getZ() < 0) { + for (i = list.size()-1; i>=0; i--) { + const auto& relative = list[i]; + if (relative->getZ() < 0) { break; } - child->traverseInReverseZOrder(exec); + relative->traverseInReverseZOrder(exec); } exec(this); for (; i>=0; i--) { - const auto& child = mDrawingChildren[i]; - child->traverseInReverseZOrder(exec); + const auto& relative = list[i]; + relative->traverseInReverseZOrder(exec); } } diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h index e21be8b032..a5224ecb4b 100644 --- a/services/surfaceflinger/Layer.h +++ b/services/surfaceflinger/Layer.h @@ -151,6 +151,12 @@ public: uint32_t appId; uint32_t type; + + // If non-null, a Surface this Surface's Z-order is interpreted relative to. + wp<Layer> zOrderRelativeOf; + + // A list of surfaces whose Z-order is interpreted relative to ours. + SortedVector<wp<Layer>> zOrderRelatives; }; // ----------------------------------------------------------------------- @@ -173,6 +179,8 @@ public: bool setFinalCrop(const Rect& crop, bool immediate); bool setLayer(int32_t z); + bool setRelativeLayer(const sp<IBinder>& relativeToHandle, int32_t relativeZ); + bool setSize(uint32_t w, uint32_t h); #ifdef USE_HWC2 bool setAlpha(float alpha); @@ -549,6 +557,10 @@ private: void setParent(const sp<Layer>& layer); + LayerVector makeTraversalList(); + void addZOrderRelative(const wp<Layer>& relative); + void removeZOrderRelative(const wp<Layer>& relative); + // ----------------------------------------------------------------------- class SyncPoint diff --git a/services/surfaceflinger/LayerVector.cpp b/services/surfaceflinger/LayerVector.cpp index 7ba6ad3bfa..90e6395ea1 100644 --- a/services/surfaceflinger/LayerVector.cpp +++ b/services/surfaceflinger/LayerVector.cpp @@ -42,13 +42,21 @@ int LayerVector::do_compare(const void* lhs, const void* rhs) const void LayerVector::traverseInZOrder(const std::function<void(Layer*)>& consume) const { for (size_t i = 0; i < size(); i++) { - (*this)[i]->traverseInZOrder(consume); + const auto& layer = (*this)[i]; + if (layer->getDrawingState().zOrderRelativeOf != nullptr) { + continue; + } + layer->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); + const auto& layer = (*this)[i]; + if (layer->getDrawingState().zOrderRelativeOf != nullptr) { + continue; + } + layer->traverseInReverseZOrder(consume); } } } // namespace android diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 26baaaecb2..dcb24e4e35 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -2820,6 +2820,11 @@ uint32_t SurfaceFlinger::setClientStateLocked( } } } + if (what & layer_state_t::eRelativeLayerChanged) { + if (layer->setRelativeLayer(s.relativeLayerHandle, s.z)) { + flags |= eTransactionNeeded|eTraversalNeeded; + } + } if (what & layer_state_t::eSizeChanged) { if (layer->setSize(s.w, s.h)) { flags |= eTraversalNeeded; diff --git a/services/surfaceflinger/tests/Transaction_test.cpp b/services/surfaceflinger/tests/Transaction_test.cpp index a46ba48026..441fc7e092 100644 --- a/services/surfaceflinger/tests/Transaction_test.cpp +++ b/services/surfaceflinger/tests/Transaction_test.cpp @@ -662,6 +662,49 @@ TEST_F(LayerUpdateTest, DeferredTransactionTest) { } } +TEST_F(LayerUpdateTest, LayerSetRelativeLayerWorks) { + sp<ScreenCapture> sc; + { + SCOPED_TRACE("before adding relative surface"); + ScreenCapture::captureScreen(&sc); + sc->expectBGColor(24, 24); + sc->expectFGColor(75, 75); + sc->expectBGColor(145, 145); + } + + auto relativeSurfaceControl = mComposerClient->createSurface( + String8("Test Surface"), 64, 64, PIXEL_FORMAT_RGBA_8888, 0); + fillSurfaceRGBA8(relativeSurfaceControl, 255, 177, 177); + waitForPostedBuffers(); + + // Now we stack the surface above the foreground surface and make sure it is visible. + SurfaceComposerClient::openGlobalTransaction(); + relativeSurfaceControl->setPosition(64, 64); + relativeSurfaceControl->show(); + relativeSurfaceControl->setRelativeLayer(mFGSurfaceControl->getHandle(), 1); + SurfaceComposerClient::closeGlobalTransaction(true); + + + { + SCOPED_TRACE("after adding relative surface"); + ScreenCapture::captureScreen(&sc); + // our relative surface should be visible now. + sc->checkPixel(75, 75, 255, 177, 177); + } + + // A call to setLayer will override a call to setRelativeLayer + SurfaceComposerClient::openGlobalTransaction(); + relativeSurfaceControl->setLayer(0); + SurfaceComposerClient::closeGlobalTransaction(); + + { + SCOPED_TRACE("after set layer"); + ScreenCapture::captureScreen(&sc); + // now the FG surface should be visible again. + sc->expectFGColor(75, 75); + } +} + class ChildLayerTest : public LayerUpdateTest { protected: void SetUp() override { |