[Mirror Layers] Added clone function to layers (1/4)
Added a cloning function to each layer in preparation for mirroring
Test: Nothing to test yet since no calls
Bug: 131622422
Change-Id: Iba0692b75c4d99841de48f40ed55b3dbccf2b9b9
diff --git a/services/surfaceflinger/BufferLayer.cpp b/services/surfaceflinger/BufferLayer.cpp
index fba235d..d189846 100644
--- a/services/surfaceflinger/BufferLayer.cpp
+++ b/services/surfaceflinger/BufferLayer.cpp
@@ -58,7 +58,7 @@
BufferLayer::BufferLayer(const LayerCreationArgs& args)
: Layer(args),
- mTextureName(args.flinger->getNewTexture()),
+ mTextureName(args.textureName),
mCompositionLayer{mFlinger->getCompositionEngine().createLayer(
compositionengine::LayerCreationArgs{this})} {
ALOGV("Creating Layer %s", args.name.string());
@@ -70,7 +70,13 @@
}
BufferLayer::~BufferLayer() {
- mFlinger->deleteTextureAsync(mTextureName);
+ if (!isClone()) {
+ // The original layer and the clone layer share the same texture. Therefore, only one of
+ // the layers, in this case the original layer, needs to handle the deletion. The original
+ // layer and the clone should be removed at the same time so there shouldn't be any issue
+ // with the clone layer trying to use the deleted texture.
+ mFlinger->deleteTextureAsync(mTextureName);
+ }
const int32_t layerID = getSequence();
mFlinger->mTimeStats->onDestroy(layerID);
mFlinger->mFrameTracer->onDestroy(layerID);
@@ -722,6 +728,15 @@
mBufferInfo.mTransform, filteringEnabled);
}
+void BufferLayer::setInitialValuesForClone(const sp<Layer>& clonedFrom) {
+ Layer::setInitialValuesForClone(clonedFrom);
+
+ sp<BufferLayer> bufferClonedFrom = static_cast<BufferLayer*>(clonedFrom.get());
+ mPremultipliedAlpha = bufferClonedFrom->mPremultipliedAlpha;
+ mPotentialCursor = bufferClonedFrom->mPotentialCursor;
+ mProtectedByApp = bufferClonedFrom->mProtectedByApp;
+}
+
} // namespace android
#if defined(__gl_h_)
diff --git a/services/surfaceflinger/BufferLayer.h b/services/surfaceflinger/BufferLayer.h
index f0a30e3..b2c0618 100644
--- a/services/surfaceflinger/BufferLayer.h
+++ b/services/surfaceflinger/BufferLayer.h
@@ -194,6 +194,7 @@
bool mRefreshPending{false};
ui::Dataspace translateDataspace(ui::Dataspace dataspace);
+ void setInitialValuesForClone(const sp<Layer>& clonedFrom);
private:
// Returns true if this layer requires filtering
diff --git a/services/surfaceflinger/BufferQueueLayer.cpp b/services/surfaceflinger/BufferQueueLayer.cpp
index fcabedf..eb13f65 100644
--- a/services/surfaceflinger/BufferQueueLayer.cpp
+++ b/services/surfaceflinger/BufferQueueLayer.cpp
@@ -461,12 +461,7 @@
sp<IGraphicBufferConsumer> consumer;
BufferQueue::createBufferQueue(&producer, &consumer, true);
mProducer = new MonitoredProducer(producer, mFlinger, this);
- {
- // Grab the SF state lock during this since it's the only safe way to access RenderEngine
- Mutex::Autolock lock(mFlinger->mStateLock);
- mConsumer =
- new BufferLayerConsumer(consumer, mFlinger->getRenderEngine(), mTextureName, this);
- }
+ mConsumer = new BufferLayerConsumer(consumer, mFlinger->getRenderEngine(), mTextureName, this);
mConsumer->setConsumerUsageBits(getEffectiveUsage(0));
mConsumer->setContentsChangedListener(this);
mConsumer->setName(mName);
@@ -476,7 +471,7 @@
mProducer->setMaxDequeuedBufferCount(2);
}
- if (const auto display = mFlinger->getDefaultDisplayDevice()) {
+ if (const auto display = mFlinger->getDefaultDisplayDeviceLocked()) {
updateTransformHint(display);
}
}
@@ -531,4 +526,15 @@
mBufferInfo.mTransformToDisplayInverse = mConsumer->getTransformToDisplayInverse();
}
+sp<Layer> BufferQueueLayer::createClone() {
+ const String8 name = mName + " (Mirror)";
+ LayerCreationArgs args =
+ LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, 0, LayerMetadata());
+ args.textureName = mTextureName;
+ sp<BufferQueueLayer> layer = new BufferQueueLayer(args);
+ layer->setInitialValuesForClone(this);
+
+ return layer;
+}
+
} // namespace android
diff --git a/services/surfaceflinger/BufferQueueLayer.h b/services/surfaceflinger/BufferQueueLayer.h
index 9374741..36dff15 100644
--- a/services/surfaceflinger/BufferQueueLayer.h
+++ b/services/surfaceflinger/BufferQueueLayer.h
@@ -31,6 +31,7 @@
*/
class BufferQueueLayer : public BufferLayer, public BufferLayerConsumer::ContentsChangedListener {
public:
+ // Only call while mStateLock is held
explicit BufferQueueLayer(const LayerCreationArgs&);
~BufferQueueLayer() override;
@@ -81,6 +82,7 @@
status_t updateFrameNumber(nsecs_t latchTime) override;
void latchPerFrameState(compositionengine::LayerFECompositionState&) const override;
+ sp<Layer> createClone() override;
// -----------------------------------------------------------------------
// Interface implementation for BufferLayerConsumer::ContentsChangedListener
diff --git a/services/surfaceflinger/BufferStateLayer.cpp b/services/surfaceflinger/BufferStateLayer.cpp
index ad05bc8..30fdbe1 100644
--- a/services/surfaceflinger/BufferStateLayer.cpp
+++ b/services/surfaceflinger/BufferStateLayer.cpp
@@ -48,10 +48,17 @@
: BufferLayer(args), mHwcSlotGenerator(new HwcSlotGenerator()) {
mOverrideScalingMode = NATIVE_WINDOW_SCALING_MODE_SCALE_TO_WINDOW;
mCurrentState.dataspace = ui::Dataspace::V0_SRGB;
+ if (const auto display = args.displayDevice) {
+ updateTransformHint(display);
+ }
}
BufferStateLayer::~BufferStateLayer() {
- if (mBufferInfo.mBuffer != nullptr) {
+ // The original layer and the clone layer share the same texture and buffer. Therefore, only
+ // one of the layers, in this case the original layer, needs to handle the deletion. The
+ // original layer and the clone should be removed at the same time so there shouldn't be any
+ // issue with the clone layer trying to use the texture.
+ if (mBufferInfo.mBuffer != nullptr && !isClone()) {
// Ensure that mBuffer is uncached from RenderEngine here, as
// RenderEngine may have been using the buffer as an external texture
// after the client uncached the buffer.
@@ -545,14 +552,6 @@
mFrameNumber++;
}
-void BufferStateLayer::onFirstRef() {
- BufferLayer::onFirstRef();
-
- if (const auto display = mFlinger->getDefaultDisplayDevice()) {
- updateTransformHint(display);
- }
-}
-
void BufferStateLayer::HwcSlotGenerator::bufferErased(const client_cache_t& clientCacheId) {
std::lock_guard lock(mMutex);
if (!clientCacheId.isValid()) {
@@ -668,4 +667,14 @@
return s.crop;
}
+sp<Layer> BufferStateLayer::createClone() {
+ const String8 name = mName + " (Mirror)";
+ LayerCreationArgs args =
+ LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, 0, LayerMetadata());
+ args.textureName = mTextureName;
+ sp<BufferStateLayer> layer = new BufferStateLayer(args);
+ layer->mHwcSlotGenerator = mHwcSlotGenerator;
+ layer->setInitialValuesForClone(this);
+ return layer;
+}
} // namespace android
diff --git a/services/surfaceflinger/BufferStateLayer.h b/services/surfaceflinger/BufferStateLayer.h
index 52063fc..e951ccf 100644
--- a/services/surfaceflinger/BufferStateLayer.h
+++ b/services/surfaceflinger/BufferStateLayer.h
@@ -124,13 +124,13 @@
status_t updateFrameNumber(nsecs_t latchTime) override;
void latchPerFrameState(compositionengine::LayerFECompositionState&) const override;
+ sp<Layer> createClone() override;
// Crop that applies to the buffer
Rect computeCrop(const State& s);
private:
friend class SlotGenerationTest;
- void onFirstRef() override;
bool willPresentCurrentTransaction() const;
static const std::array<float, 16> IDENTITY_MATRIX;
diff --git a/services/surfaceflinger/ColorLayer.cpp b/services/surfaceflinger/ColorLayer.cpp
index 99805d9..5b62054 100644
--- a/services/surfaceflinger/ColorLayer.cpp
+++ b/services/surfaceflinger/ColorLayer.cpp
@@ -107,6 +107,14 @@
return mDrawingState.dataspace;
}
+sp<Layer> ColorLayer::createClone() {
+ String8 name = mName + " (Mirror)";
+ sp<ColorLayer> layer = new ColorLayer(
+ LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, 0, LayerMetadata()));
+ layer->setInitialValuesForClone(this);
+ return layer;
+}
+
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/services/surfaceflinger/ColorLayer.h b/services/surfaceflinger/ColorLayer.h
index 16921df..634a800 100644
--- a/services/surfaceflinger/ColorLayer.h
+++ b/services/surfaceflinger/ColorLayer.h
@@ -50,6 +50,8 @@
compositionengine::LayerFE::ClientCompositionTargetSettings&) override;
std::shared_ptr<compositionengine::Layer> mCompositionLayer;
+
+ sp<Layer> createClone() override;
};
} // namespace android
diff --git a/services/surfaceflinger/ContainerLayer.cpp b/services/surfaceflinger/ContainerLayer.cpp
index 4a11303..cb50d9f 100644
--- a/services/surfaceflinger/ContainerLayer.cpp
+++ b/services/surfaceflinger/ContainerLayer.cpp
@@ -30,4 +30,11 @@
return false;
}
+sp<Layer> ContainerLayer::createClone() {
+ String8 name = mName + " (Mirror)";
+ sp<ContainerLayer> layer = new ContainerLayer(
+ LayerCreationArgs(mFlinger.get(), nullptr, name, 0, 0, 0, LayerMetadata()));
+ layer->setInitialValuesForClone(this);
+ return layer;
+}
} // namespace android
diff --git a/services/surfaceflinger/ContainerLayer.h b/services/surfaceflinger/ContainerLayer.h
index c3624f6..b48d471 100644
--- a/services/surfaceflinger/ContainerLayer.h
+++ b/services/surfaceflinger/ContainerLayer.h
@@ -32,6 +32,9 @@
bool isVisible() const override;
bool isCreatedFromMainThread() const override { return true; }
+
+protected:
+ sp<Layer> createClone() override;
};
} // namespace android
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index ba948cf..52a09b3 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -2015,6 +2015,15 @@
return outputLayer->getState().visibleRegion;
}
+void Layer::setInitialValuesForClone(const sp<Layer>& clonedFrom) {
+ // copy drawing state from cloned layer
+ mDrawingState = clonedFrom->mDrawingState;
+ mClonedFrom = clonedFrom;
+
+ // TODO: (b/140756730) Ignore input for now since InputDispatcher doesn't support multiple
+ // InputWindows per client token yet.
+ mDrawingState.inputInfo.token = nullptr;
+}
// ---------------------------------------------------------------------------
}; // namespace android
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 8771ccd..96970ac 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -91,6 +91,8 @@
LayerMetadata metadata;
pid_t callingPid;
uid_t callingUid;
+ sp<const DisplayDevice> displayDevice;
+ uint32_t textureName;
};
class Layer : public compositionengine::LayerFE {
@@ -465,6 +467,13 @@
virtual Rect getCrop(const Layer::State& s) const { return s.crop_legacy; }
virtual bool needsFiltering(const sp<const DisplayDevice>&) const { return false; }
+protected:
+ virtual sp<Layer> createClone() = 0;
+ sp<Layer> getClonedFrom() { return mClonedFrom != nullptr ? mClonedFrom.promote() : nullptr; }
+
+ bool isClone() { return getClonedFrom() != nullptr; }
+ virtual void setInitialValuesForClone(const sp<Layer>& clonedFrom);
+
public:
/*
* compositionengine::LayerFE overrides
@@ -912,6 +921,12 @@
// to help debugging.
pid_t mCallingPid;
uid_t mCallingUid;
+
+ // The current layer is a clone of mClonedFrom. This means that this layer will update it's
+ // properties based on mClonedFrom. When mClonedFrom latches a new buffer for BufferLayers,
+ // this layer will update it's buffer. When mClonedFrom updates it's drawing state, children,
+ // and relatives, this layer will update as well.
+ wp<Layer> mClonedFrom;
};
} // namespace android
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 41afb5d..e3cf84a 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -3532,8 +3532,18 @@
break;
}
- sp<BufferQueueLayer> layer = getFactory().createBufferQueueLayer(
- LayerCreationArgs(this, client, name, w, h, flags, std::move(metadata)));
+ sp<BufferQueueLayer> layer;
+ LayerCreationArgs args =
+ LayerCreationArgs(this, client, name, w, h, flags, std::move(metadata));
+ args.textureName = getNewTexture();
+ {
+ // Grab the SF state lock during this since it's the only safe way to access
+ // RenderEngine when creating a BufferLayerConsumer
+ // TODO: Check if this lock is still needed here
+ Mutex::Autolock lock(mStateLock);
+ layer = getFactory().createBufferQueueLayer(args);
+ }
+
status_t err = layer->setDefaultBufferProperties(w, h, format);
if (err == NO_ERROR) {
*handle = layer->getHandle();
@@ -3549,8 +3559,11 @@
uint32_t w, uint32_t h, uint32_t flags,
LayerMetadata metadata, sp<IBinder>* handle,
sp<Layer>* outLayer) {
- sp<BufferStateLayer> layer = getFactory().createBufferStateLayer(
- LayerCreationArgs(this, client, name, w, h, flags, std::move(metadata)));
+ LayerCreationArgs args =
+ LayerCreationArgs(this, client, name, w, h, flags, std::move(metadata));
+ args.displayDevice = getDefaultDisplayDevice();
+ args.textureName = getNewTexture();
+ sp<BufferStateLayer> layer = getFactory().createBufferStateLayer(args);
*handle = layer->getHandle();
*outLayer = layer;
diff --git a/services/surfaceflinger/tests/unittests/CompositionTest.cpp b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
index 20dfed6..f29e2dd 100644
--- a/services/surfaceflinger/tests/unittests/CompositionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/CompositionTest.cpp
@@ -883,11 +883,14 @@
FlingerLayerType layer =
Base::template createLayerWithFactory<BufferQueueLayer>(test, [test]() {
- return new BufferQueueLayer(
- LayerCreationArgs(test->mFlinger.mFlinger.get(), sp<Client>(),
- String8("test-layer"), LayerProperties::WIDTH,
- LayerProperties::HEIGHT,
- LayerProperties::LAYER_FLAGS, LayerMetadata()));
+ sp<Client> client;
+ String8 name("test-layer");
+ LayerCreationArgs args =
+ LayerCreationArgs(test->mFlinger.mFlinger.get(), client, name,
+ LayerProperties::WIDTH, LayerProperties::HEIGHT,
+ LayerProperties::LAYER_FLAGS, LayerMetadata());
+ args.textureName = test->mFlinger.mutableTexturePool().back();
+ return new BufferQueueLayer(args);
});
LayerProperties::setupLayerState(test, layer);