diff options
-rw-r--r-- | libs/gui/ISurfaceComposerClient.cpp | 11 | ||||
-rw-r--r-- | libs/gui/SurfaceComposerClient.cpp | 14 | ||||
-rw-r--r-- | libs/gui/include/gui/ISurfaceComposerClient.h | 2 | ||||
-rw-r--r-- | libs/gui/include/gui/SurfaceComposerClient.h | 11 | ||||
-rw-r--r-- | services/surfaceflinger/Client.cpp | 4 | ||||
-rw-r--r-- | services/surfaceflinger/Client.h | 2 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.cpp | 29 | ||||
-rw-r--r-- | services/surfaceflinger/SurfaceFlinger.h | 3 | ||||
-rw-r--r-- | services/surfaceflinger/tests/Android.bp | 1 | ||||
-rw-r--r-- | services/surfaceflinger/tests/MirrorLayer_test.cpp | 226 |
10 files changed, 302 insertions, 1 deletions
diff --git a/libs/gui/ISurfaceComposerClient.cpp b/libs/gui/ISurfaceComposerClient.cpp index 129558bd15..b98e48b52a 100644 --- a/libs/gui/ISurfaceComposerClient.cpp +++ b/libs/gui/ISurfaceComposerClient.cpp @@ -34,7 +34,8 @@ enum class Tag : uint32_t { CREATE_WITH_SURFACE_PARENT, CLEAR_LAYER_FRAME_STATS, GET_LAYER_FRAME_STATS, - LAST = GET_LAYER_FRAME_STATS, + MIRROR_SURFACE, + LAST = MIRROR_SURFACE, }; } // Anonymous namespace @@ -80,6 +81,12 @@ public: &ISurfaceComposerClient::getLayerFrameStats)>(Tag::GET_LAYER_FRAME_STATS, handle, outStats); } + + status_t mirrorSurface(const sp<IBinder>& mirrorFromHandle, sp<IBinder>* outHandle) override { + return callRemote<decltype(&ISurfaceComposerClient::mirrorSurface)>(Tag::MIRROR_SURFACE, + mirrorFromHandle, + outHandle); + } }; // Out-of-line virtual method definition to trigger vtable emission in this @@ -105,6 +112,8 @@ status_t BnSurfaceComposerClient::onTransact(uint32_t code, const Parcel& data, return callLocal(data, reply, &ISurfaceComposerClient::clearLayerFrameStats); case Tag::GET_LAYER_FRAME_STATS: return callLocal(data, reply, &ISurfaceComposerClient::getLayerFrameStats); + case Tag::MIRROR_SURFACE: + return callLocal(data, reply, &ISurfaceComposerClient::mirrorSurface); } } diff --git a/libs/gui/SurfaceComposerClient.cpp b/libs/gui/SurfaceComposerClient.cpp index 547e5f1be2..7b256f5c02 100644 --- a/libs/gui/SurfaceComposerClient.cpp +++ b/libs/gui/SurfaceComposerClient.cpp @@ -1505,6 +1505,20 @@ status_t SurfaceComposerClient::createSurfaceChecked(const String8& name, uint32 return err; } +sp<SurfaceControl> SurfaceComposerClient::mirrorSurface(SurfaceControl* mirrorFromSurface) { + if (mirrorFromSurface == nullptr) { + return nullptr; + } + + sp<IBinder> handle; + sp<IBinder> mirrorFromHandle = mirrorFromSurface->getHandle(); + status_t err = mClient->mirrorSurface(mirrorFromHandle, &handle); + if (err == NO_ERROR) { + return new SurfaceControl(this, handle, nullptr, true /* owned */); + } + return nullptr; +} + status_t SurfaceComposerClient::clearLayerFrameStats(const sp<IBinder>& token) const { if (mStatus != NO_ERROR) { return mStatus; diff --git a/libs/gui/include/gui/ISurfaceComposerClient.h b/libs/gui/include/gui/ISurfaceComposerClient.h index 32ac9e8928..5fe7ca5344 100644 --- a/libs/gui/include/gui/ISurfaceComposerClient.h +++ b/libs/gui/include/gui/ISurfaceComposerClient.h @@ -76,6 +76,8 @@ public: * Requires ACCESS_SURFACE_FLINGER permission */ virtual status_t getLayerFrameStats(const sp<IBinder>& handle, FrameStats* outStats) const = 0; + + virtual status_t mirrorSurface(const sp<IBinder>& mirrorFromHandle, sp<IBinder>* outHandle) = 0; }; class BnSurfaceComposerClient : public SafeBnInterface<ISurfaceComposerClient> { diff --git a/libs/gui/include/gui/SurfaceComposerClient.h b/libs/gui/include/gui/SurfaceComposerClient.h index 15287e2cb6..6676be4837 100644 --- a/libs/gui/include/gui/SurfaceComposerClient.h +++ b/libs/gui/include/gui/SurfaceComposerClient.h @@ -245,6 +245,17 @@ public: LayerMetadata metadata = LayerMetadata() // metadata ); + // Creates a mirrored hierarchy for the mirrorFromSurface. This returns a SurfaceControl + // which is a parent of the root of the mirrored hierarchy. + // + // Real Hierarchy Mirror + // SC (value that's returned) + // | + // A A' + // | | + // B B' + sp<SurfaceControl> mirrorSurface(SurfaceControl* mirrorFromSurface); + //! Create a virtual display static sp<IBinder> createDisplay(const String8& displayName, bool secure); diff --git a/services/surfaceflinger/Client.cpp b/services/surfaceflinger/Client.cpp index 6bfd302b5c..c7ed9b0412 100644 --- a/services/surfaceflinger/Client.cpp +++ b/services/surfaceflinger/Client.cpp @@ -106,6 +106,10 @@ status_t Client::createWithSurfaceParent(const String8& name, uint32_t w, uint32 nullptr, layer); } +status_t Client::mirrorSurface(const sp<IBinder>& mirrorFromHandle, sp<IBinder>* outHandle) { + return mFlinger->mirrorLayer(this, mirrorFromHandle, outHandle); +} + status_t Client::clearLayerFrameStats(const sp<IBinder>& handle) const { sp<Layer> layer = getLayerUser(handle); if (layer == nullptr) { diff --git a/services/surfaceflinger/Client.h b/services/surfaceflinger/Client.h index 74e48188d6..7d7cef8c50 100644 --- a/services/surfaceflinger/Client.h +++ b/services/surfaceflinger/Client.h @@ -62,6 +62,8 @@ private: LayerMetadata metadata, sp<IBinder>* handle, sp<IGraphicBufferProducer>* gbp); + status_t mirrorSurface(const sp<IBinder>& mirrorFromHandle, sp<IBinder>* handle); + virtual status_t clearLayerFrameStats(const sp<IBinder>& handle) const; virtual status_t getLayerFrameStats(const sp<IBinder>& handle, FrameStats* outStats) const; diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp index 86e73c2481..a9fad1e21b 100644 --- a/services/surfaceflinger/SurfaceFlinger.cpp +++ b/services/surfaceflinger/SurfaceFlinger.cpp @@ -3388,6 +3388,35 @@ uint32_t SurfaceFlinger::addInputWindowCommands(const InputWindowCommands& input return flags; } +status_t SurfaceFlinger::mirrorLayer(const sp<Client>& client, const sp<IBinder>& mirrorFromHandle, + sp<IBinder>* outHandle) { + if (!mirrorFromHandle) { + return NAME_NOT_FOUND; + } + + sp<Layer> mirrorLayer; + sp<Layer> mirrorFrom; + String8 uniqueName = getUniqueLayerName(String8("MirrorRoot")); + + { + Mutex::Autolock _l(mStateLock); + mirrorFrom = fromHandle(mirrorFromHandle); + if (!mirrorFrom) { + return NAME_NOT_FOUND; + } + + status_t result = createContainerLayer(client, uniqueName, -1, -1, 0, LayerMetadata(), + outHandle, &mirrorLayer); + if (result != NO_ERROR) { + return result; + } + + mirrorLayer->mClonedChild = mirrorFrom->createClone(); + } + + return addClientLayer(client, *outHandle, nullptr, mirrorLayer, nullptr, nullptr, false); +} + status_t SurfaceFlinger::createLayer(const String8& name, const sp<Client>& client, uint32_t w, uint32_t h, PixelFormat format, uint32_t flags, LayerMetadata metadata, sp<IBinder>* handle, diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h index 2ea8f78c66..a9a4276592 100644 --- a/services/surfaceflinger/SurfaceFlinger.h +++ b/services/surfaceflinger/SurfaceFlinger.h @@ -623,6 +623,9 @@ private: uint32_t h, uint32_t flags, LayerMetadata metadata, sp<IBinder>* outHandle, sp<Layer>* outLayer); + status_t mirrorLayer(const sp<Client>& client, const sp<IBinder>& mirrorFromHandle, + sp<IBinder>* outHandle); + String8 getUniqueLayerName(const String8& name); // called when all clients have released all their references to diff --git a/services/surfaceflinger/tests/Android.bp b/services/surfaceflinger/tests/Android.bp index f422939abd..d021fc2859 100644 --- a/services/surfaceflinger/tests/Android.bp +++ b/services/surfaceflinger/tests/Android.bp @@ -28,6 +28,7 @@ cc_test { "LayerTypeAndRenderTypeTransaction_test.cpp", "LayerTypeTransaction_test.cpp", "LayerUpdate_test.cpp", + "MirrorLayer_test.cpp", "MultiDisplayLayerBounds_test.cpp", "RelativeZ_test.cpp", "SetGeometry_test.cpp", diff --git a/services/surfaceflinger/tests/MirrorLayer_test.cpp b/services/surfaceflinger/tests/MirrorLayer_test.cpp new file mode 100644 index 0000000000..0bcac1a880 --- /dev/null +++ b/services/surfaceflinger/tests/MirrorLayer_test.cpp @@ -0,0 +1,226 @@ +/* + * Copyright (C) 2019 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 "LayerTransactionTest.h" + +namespace android { + +class MirrorLayerTest : public LayerTransactionTest { +protected: + virtual void SetUp() { + LayerTransactionTest::SetUp(); + ASSERT_EQ(NO_ERROR, mClient->initCheck()); + + const auto display = SurfaceComposerClient::getInternalDisplayToken(); + ASSERT_FALSE(display == nullptr); + + mParentLayer = createColorLayer("Parent layer", Color::RED); + mChildLayer = createColorLayer("Child layer", Color::GREEN, mParentLayer.get()); + asTransaction([&](Transaction& t) { + t.setDisplayLayerStack(display, 0); + t.setLayer(mParentLayer, INT32_MAX - 2).show(mParentLayer); + t.setCrop_legacy(mChildLayer, Rect(0, 0, 400, 400)).show(mChildLayer); + t.setPosition(mChildLayer, 50, 50); + t.setFlags(mParentLayer, layer_state_t::eLayerOpaque, layer_state_t::eLayerOpaque); + t.setFlags(mChildLayer, layer_state_t::eLayerOpaque, layer_state_t::eLayerOpaque); + }); + } + + virtual void TearDown() { + LayerTransactionTest::TearDown(); + mParentLayer = 0; + mChildLayer = 0; + } + + sp<SurfaceControl> mParentLayer; + sp<SurfaceControl> mChildLayer; +}; + +TEST_F(MirrorLayerTest, MirrorColorLayer) { + sp<SurfaceControl> grandchild = + createColorLayer("Grandchild layer", Color::BLUE, mChildLayer.get()); + Transaction() + .setFlags(grandchild, layer_state_t::eLayerOpaque, layer_state_t::eLayerOpaque) + .setCrop_legacy(grandchild, Rect(0, 0, 200, 200)) + .show(grandchild) + .apply(); + + // Mirror mChildLayer + sp<SurfaceControl> mirrorLayer = mClient->mirrorSurface(mChildLayer.get()); + ASSERT_NE(mirrorLayer, nullptr); + + // Add mirrorLayer as child of mParentLayer so it's shown on the display + Transaction() + .reparent(mirrorLayer, mParentLayer->getHandle()) + .setPosition(mirrorLayer, 500, 500) + .show(mirrorLayer) + .apply(); + + { + SCOPED_TRACE("Initial Mirror"); + auto shot = screenshot(); + // Grandchild mirror + shot->expectColor(Rect(550, 550, 750, 750), Color::BLUE); + // Child mirror + shot->expectColor(Rect(750, 750, 950, 950), Color::GREEN); + } + + // Set color to white on grandchild layer. + Transaction().setColor(grandchild, half3{1, 1, 1}).apply(); + { + SCOPED_TRACE("Updated Grandchild Layer Color"); + auto shot = screenshot(); + // Grandchild mirror + shot->expectColor(Rect(550, 550, 750, 750), Color::WHITE); + // Child mirror + shot->expectColor(Rect(750, 750, 950, 950), Color::GREEN); + } + + // Set color to black on child layer. + Transaction().setColor(mChildLayer, half3{0, 0, 0}).apply(); + { + SCOPED_TRACE("Updated Child Layer Color"); + auto shot = screenshot(); + // Grandchild mirror + shot->expectColor(Rect(550, 550, 750, 750), Color::WHITE); + // Child mirror + shot->expectColor(Rect(750, 750, 950, 950), Color::BLACK); + } + + // Remove grandchild layer + Transaction().reparent(grandchild, nullptr).apply(); + { + SCOPED_TRACE("Removed Grandchild Layer"); + auto shot = screenshot(); + // Grandchild mirror + shot->expectColor(Rect(550, 550, 750, 750), Color::BLACK); + // Child mirror + shot->expectColor(Rect(750, 750, 950, 950), Color::BLACK); + } + + // Remove child layer + Transaction().reparent(mChildLayer, nullptr).apply(); + { + SCOPED_TRACE("Removed Child Layer"); + auto shot = screenshot(); + // Grandchild mirror + shot->expectColor(Rect(550, 550, 750, 750), Color::RED); + // Child mirror + shot->expectColor(Rect(750, 750, 950, 950), Color::RED); + } + + // Add grandchild layer to offscreen layer + Transaction().reparent(grandchild, mChildLayer->getHandle()).apply(); + { + SCOPED_TRACE("Added Grandchild Layer"); + auto shot = screenshot(); + // Grandchild mirror + shot->expectColor(Rect(550, 550, 750, 750), Color::RED); + // Child mirror + shot->expectColor(Rect(750, 750, 950, 950), Color::RED); + } + + // Add child layer + Transaction().reparent(mChildLayer, mParentLayer->getHandle()).apply(); + { + SCOPED_TRACE("Added Child Layer"); + auto shot = screenshot(); + // Grandchild mirror + shot->expectColor(Rect(550, 550, 750, 750), Color::WHITE); + // Child mirror + shot->expectColor(Rect(750, 750, 950, 950), Color::BLACK); + } +} + +TEST_F(MirrorLayerTest, MirrorBufferLayer) { + sp<SurfaceControl> bufferQueueLayer = + createLayer("BufferQueueLayer", 200, 200, 0, mChildLayer.get()); + fillBufferQueueLayerColor(bufferQueueLayer, Color::BLUE, 200, 200); + Transaction().show(bufferQueueLayer).apply(); + + sp<SurfaceControl> mirrorLayer = mClient->mirrorSurface(mChildLayer.get()); + Transaction() + .reparent(mirrorLayer, mParentLayer->getHandle()) + .setPosition(mirrorLayer, 500, 500) + .show(mirrorLayer) + .apply(); + + { + SCOPED_TRACE("Initial Mirror BufferQueueLayer"); + auto shot = screenshot(); + // Buffer mirror + shot->expectColor(Rect(550, 550, 750, 750), Color::BLUE); + // Child mirror + shot->expectColor(Rect(750, 750, 950, 950), Color::GREEN); + } + + fillBufferQueueLayerColor(bufferQueueLayer, Color::WHITE, 200, 200); + { + SCOPED_TRACE("Update BufferQueueLayer"); + auto shot = screenshot(); + // Buffer mirror + shot->expectColor(Rect(550, 550, 750, 750), Color::WHITE); + // Child mirror + shot->expectColor(Rect(750, 750, 950, 950), Color::GREEN); + } + + Transaction().reparent(bufferQueueLayer, nullptr).apply(); + { + SCOPED_TRACE("Removed BufferQueueLayer"); + auto shot = screenshot(); + // Buffer mirror + shot->expectColor(Rect(550, 550, 750, 750), Color::GREEN); + // Child mirror + shot->expectColor(Rect(750, 750, 950, 950), Color::GREEN); + } + + sp<SurfaceControl> bufferStateLayer = + createLayer("BufferStateLayer", 200, 200, ISurfaceComposerClient::eFXSurfaceBufferState, + mChildLayer.get()); + fillBufferStateLayerColor(bufferStateLayer, Color::BLUE, 200, 200); + Transaction().setFrame(bufferStateLayer, Rect(0, 0, 200, 200)).show(bufferStateLayer).apply(); + + { + SCOPED_TRACE("Initial Mirror BufferStateLayer"); + auto shot = screenshot(); + // Buffer mirror + shot->expectColor(Rect(550, 550, 750, 750), Color::BLUE); + // Child mirror + shot->expectColor(Rect(750, 750, 950, 950), Color::GREEN); + } + + fillBufferStateLayerColor(bufferStateLayer, Color::WHITE, 200, 200); + { + SCOPED_TRACE("Update BufferStateLayer"); + auto shot = screenshot(); + // Buffer mirror + shot->expectColor(Rect(550, 550, 750, 750), Color::WHITE); + // Child mirror + shot->expectColor(Rect(750, 750, 950, 950), Color::GREEN); + } + + Transaction().reparent(bufferStateLayer, nullptr).apply(); + { + SCOPED_TRACE("Removed BufferStateLayer"); + auto shot = screenshot(); + // Buffer mirror + shot->expectColor(Rect(550, 550, 750, 750), Color::GREEN); + // Child mirror + shot->expectColor(Rect(750, 750, 950, 950), Color::GREEN); + } +} + +} // namespace android |