summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Alec Mouri <alecmouri@google.com> 2022-04-27 21:20:04 +0000
committer Alec Mouri <alecmouri@google.com> 2022-04-28 22:37:25 +0000
commit14d5b8632c365428cb5f69f119365dff86ecc77f (patch)
tree1d6a9ad0533f1ddaf18fbbf20ade5d35bc2a7a33
parentf18ac6cac6c38bfaf02068fe167d3936c70469bf (diff)
Propagate HDR information to screenshot animation.
The screenshot animation must know whether the screenshot contains HDR layers so that it can correctly inform SurfaceFlinger whether its layer can be dimmed. This is due to the interplay of the following: 1. Devices are now able to configure DisplayManager to send significantly lower SDR white points relative to display brightness to SurfaceFlinger when HDR is simultaneously on-screen. 2. AIDL composer is required to support per-layer dimming, so that SDR layers may be dimmed to preserve the relative luminance of HDR video content. 3. Because the screenshot does not contain an HDR transfer function, SurfaceFlinger will treat the layer as SDR, and attempt to dim it. 4. Screen rotations containing HDR layers must request SurfaceFlinger to present the rotated screenshot at display brightness, to override (3) above. Otherwise, HDR content captured in the screenshot will suddenly dim during the rotation animation. 5. Also due to (3), DisplayManager no longer thinks that there is HDR content on screen, so a prior patch treated layers that requested to to be dimmed to be reported as HDR (I1d1b0dcaf230300ca34b84ea407d0817feb2c664). Otherwise, the display brightness will decrease during the animation and ramp back up afterwards. 6. But because of (5), screenshots that only contained SDR layers were incorrectly treated as HDR, which caused the display brightness to ramp up during the animation. This patch fixes (6) by allowing for the screenshot animation to learn whether the screenshot contains HDR layers, and request dimming capabilities accordingly. Bug: 230068567 Test: screen rotation Change-Id: I6bbb2433f976e368bfe2c04e084e110cfb551c15
-rw-r--r--libs/gui/ScreenCaptureResults.cpp2
-rw-r--r--libs/gui/include/gui/ScreenCaptureResults.h1
-rw-r--r--services/surfaceflinger/SurfaceFlinger.cpp1
-rw-r--r--services/surfaceflinger/tests/ScreenCapture_test.cpp46
-rw-r--r--services/surfaceflinger/tests/TransactionTestHarnesses.h3
-rw-r--r--services/surfaceflinger/tests/utils/ScreenshotUtils.h12
6 files changed, 58 insertions, 7 deletions
diff --git a/libs/gui/ScreenCaptureResults.cpp b/libs/gui/ScreenCaptureResults.cpp
index e91f74f3d3..fe387064bc 100644
--- a/libs/gui/ScreenCaptureResults.cpp
+++ b/libs/gui/ScreenCaptureResults.cpp
@@ -36,6 +36,7 @@ status_t ScreenCaptureResults::writeToParcel(android::Parcel* parcel) const {
}
SAFE_PARCEL(parcel->writeBool, capturedSecureLayers);
+ SAFE_PARCEL(parcel->writeBool, capturedHdrLayers);
SAFE_PARCEL(parcel->writeUint32, static_cast<uint32_t>(capturedDataspace));
SAFE_PARCEL(parcel->writeInt32, result);
return NO_ERROR;
@@ -57,6 +58,7 @@ status_t ScreenCaptureResults::readFromParcel(const android::Parcel* parcel) {
}
SAFE_PARCEL(parcel->readBool, &capturedSecureLayers);
+ SAFE_PARCEL(parcel->readBool, &capturedHdrLayers);
uint32_t dataspace = 0;
SAFE_PARCEL(parcel->readUint32, &dataspace);
capturedDataspace = static_cast<ui::Dataspace>(dataspace);
diff --git a/libs/gui/include/gui/ScreenCaptureResults.h b/libs/gui/include/gui/ScreenCaptureResults.h
index 99c35c1a3d..724c11c881 100644
--- a/libs/gui/include/gui/ScreenCaptureResults.h
+++ b/libs/gui/include/gui/ScreenCaptureResults.h
@@ -33,6 +33,7 @@ public:
sp<GraphicBuffer> buffer;
sp<Fence> fence = Fence::NO_FENCE;
bool capturedSecureLayers{false};
+ bool capturedHdrLayers{false};
ui::Dataspace capturedDataspace{ui::Dataspace::V0_SRGB};
status_t result = OK;
};
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index d39176be14..fb15eacd2c 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -6795,6 +6795,7 @@ std::shared_future<renderengine::RenderEngineResult> SurfaceFlinger::renderScree
if (regionSampling) {
settings.backgroundBlurRadius = 0;
}
+ captureResults.capturedHdrLayers |= isHdrDataspace(settings.sourceDataspace);
}
clientCompositionLayers.insert(clientCompositionLayers.end(),
diff --git a/services/surfaceflinger/tests/ScreenCapture_test.cpp b/services/surfaceflinger/tests/ScreenCapture_test.cpp
index f9b31853fc..6a7d8b8ca5 100644
--- a/services/surfaceflinger/tests/ScreenCapture_test.cpp
+++ b/services/surfaceflinger/tests/ScreenCapture_test.cpp
@@ -112,7 +112,7 @@ TEST_F(ScreenCaptureTest, SetFlagsSecureEUidSystem) {
args.captureSecureLayers = true;
ASSERT_EQ(NO_ERROR, ScreenCapture::captureDisplay(args, mCaptureResults));
ASSERT_TRUE(mCaptureResults.capturedSecureLayers);
- ScreenCapture sc(mCaptureResults.buffer);
+ ScreenCapture sc(mCaptureResults.buffer, mCaptureResults.capturedHdrLayers);
sc.expectColor(Rect(0, 0, 32, 32), Color::RED);
}
@@ -147,7 +147,7 @@ TEST_F(ScreenCaptureTest, CaptureChildSetParentFlagsSecureEUidSystem) {
args.captureSecureLayers = true;
ASSERT_EQ(NO_ERROR, ScreenCapture::captureDisplay(args, mCaptureResults));
ASSERT_TRUE(mCaptureResults.capturedSecureLayers);
- ScreenCapture sc(mCaptureResults.buffer);
+ ScreenCapture sc(mCaptureResults.buffer, mCaptureResults.capturedHdrLayers);
sc.expectColor(Rect(0, 0, 10, 10), Color::BLUE);
}
@@ -374,7 +374,7 @@ TEST_F(ScreenCaptureTest, CaptureBufferLayerWithoutBufferFails) {
ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(child, Color::RED, 32, 32));
SurfaceComposerClient::Transaction().apply(true);
ASSERT_EQ(NO_ERROR, ScreenCapture::captureLayers(args, captureResults));
- ScreenCapture sc(captureResults.buffer);
+ ScreenCapture sc(captureResults.buffer, captureResults.capturedHdrLayers);
sc.expectColor(Rect(0, 0, 9, 9), Color::RED);
}
@@ -860,6 +860,46 @@ TEST_F(ScreenCaptureTest, CaptureOffscreen) {
mCapture->expectColor(Rect(0, 0, 32, 32), Color::RED);
}
+TEST_F(ScreenCaptureTest, CaptureNonHdrLayer) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test layer", 32, 32,
+ ISurfaceComposerClient::eFXSurfaceBufferState,
+ mBGSurfaceControl.get()));
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::BLACK, 32, 32));
+ Transaction()
+ .show(layer)
+ .setLayer(layer, INT32_MAX)
+ .setDataspace(layer, ui::Dataspace::V0_SRGB)
+ .apply();
+
+ LayerCaptureArgs captureArgs;
+ captureArgs.layerHandle = layer->getHandle();
+
+ ScreenCapture::captureLayers(&mCapture, captureArgs);
+ mCapture->expectColor(Rect(0, 0, 32, 32), Color::BLACK);
+ ASSERT_FALSE(mCapture->capturedHdrLayers());
+}
+
+TEST_F(ScreenCaptureTest, CaptureHdrLayer) {
+ sp<SurfaceControl> layer;
+ ASSERT_NO_FATAL_FAILURE(layer = createLayer("test layer", 32, 32,
+ ISurfaceComposerClient::eFXSurfaceBufferState,
+ mBGSurfaceControl.get()));
+ ASSERT_NO_FATAL_FAILURE(fillBufferStateLayerColor(layer, Color::BLACK, 32, 32));
+ Transaction()
+ .show(layer)
+ .setLayer(layer, INT32_MAX)
+ .setDataspace(layer, ui::Dataspace::BT2020_ITU_PQ)
+ .apply();
+
+ LayerCaptureArgs captureArgs;
+ captureArgs.layerHandle = layer->getHandle();
+
+ ScreenCapture::captureLayers(&mCapture, captureArgs);
+ mCapture->expectColor(Rect(0, 0, 32, 32), Color::BLACK);
+ ASSERT_TRUE(mCapture->capturedHdrLayers());
+}
+
// In the following tests we verify successful skipping of a parent layer,
// so we use the same verification logic and only change how we mutate
// the parent layer to verify that various properties are ignored.
diff --git a/services/surfaceflinger/tests/TransactionTestHarnesses.h b/services/surfaceflinger/tests/TransactionTestHarnesses.h
index 60cffb19df..8ce63bc64c 100644
--- a/services/surfaceflinger/tests/TransactionTestHarnesses.h
+++ b/services/surfaceflinger/tests/TransactionTestHarnesses.h
@@ -79,7 +79,8 @@ public:
BufferItem item;
itemConsumer->acquireBuffer(&item, 0, true);
- auto sc = std::make_unique<ScreenCapture>(item.mGraphicBuffer);
+ constexpr bool kContainsHdr = false;
+ auto sc = std::make_unique<ScreenCapture>(item.mGraphicBuffer, kContainsHdr);
itemConsumer->releaseBuffer(item);
SurfaceComposerClient::destroyDisplay(vDisplay);
return sc;
diff --git a/services/surfaceflinger/tests/utils/ScreenshotUtils.h b/services/surfaceflinger/tests/utils/ScreenshotUtils.h
index ee7e92cbf6..f879430db0 100644
--- a/services/surfaceflinger/tests/utils/ScreenshotUtils.h
+++ b/services/surfaceflinger/tests/utils/ScreenshotUtils.h
@@ -60,7 +60,8 @@ public:
DisplayCaptureArgs& captureArgs) {
ScreenCaptureResults captureResults;
ASSERT_EQ(NO_ERROR, captureDisplay(captureArgs, captureResults));
- *sc = std::make_unique<ScreenCapture>(captureResults.buffer);
+ *sc = std::make_unique<ScreenCapture>(captureResults.buffer,
+ captureResults.capturedHdrLayers);
}
static status_t captureLayers(LayerCaptureArgs& captureArgs,
@@ -81,9 +82,12 @@ public:
static void captureLayers(std::unique_ptr<ScreenCapture>* sc, LayerCaptureArgs& captureArgs) {
ScreenCaptureResults captureResults;
ASSERT_EQ(NO_ERROR, captureLayers(captureArgs, captureResults));
- *sc = std::make_unique<ScreenCapture>(captureResults.buffer);
+ *sc = std::make_unique<ScreenCapture>(captureResults.buffer,
+ captureResults.capturedHdrLayers);
}
+ bool capturedHdrLayers() const { return mContainsHdr; }
+
void expectColor(const Rect& rect, const Color& color, uint8_t tolerance = 0) {
ASSERT_NE(nullptr, mOutBuffer);
ASSERT_NE(nullptr, mPixels);
@@ -181,7 +185,8 @@ public:
EXPECT_EQ(height, mOutBuffer->getHeight());
}
- explicit ScreenCapture(const sp<GraphicBuffer>& outBuffer) : mOutBuffer(outBuffer) {
+ explicit ScreenCapture(const sp<GraphicBuffer>& outBuffer, bool containsHdr)
+ : mOutBuffer(outBuffer), mContainsHdr(containsHdr) {
if (mOutBuffer) {
mOutBuffer->lock(GRALLOC_USAGE_SW_READ_OFTEN, reinterpret_cast<void**>(&mPixels));
}
@@ -193,6 +198,7 @@ public:
private:
sp<GraphicBuffer> mOutBuffer;
+ bool mContainsHdr = mContainsHdr;
uint8_t* mPixels = nullptr;
};
} // namespace