Support DISPLAY_P3 dataspace to BT2020 in SF
Adding support to fallback to ColorMode BT2020 with
SRGB when P3 layers are present when external display supports BT2020 with SRGB
transfer function. (Before fallback was to BT709_sRGB)
Bug: 115335239
Test: ./libsurfaceflinger_unittest --gtest_filter=GetBestColorModeTest.*
Change-Id: Iec7154d411cb3dcc4fd1158199bc45207799bb27
diff --git a/libs/ui/Android.bp b/libs/ui/Android.bp
index 7b35409..0a0c8ca 100644
--- a/libs/ui/Android.bp
+++ b/libs/ui/Android.bp
@@ -78,7 +78,7 @@
shared_libs: [
"android.hardware.graphics.allocator@2.0",
- "android.hardware.graphics.common@1.1",
+ "android.hardware.graphics.common@1.2",
"android.hardware.graphics.mapper@2.0",
"android.hardware.graphics.mapper@2.1",
"android.hardware.configstore@1.0",
@@ -97,7 +97,7 @@
],
export_shared_lib_headers: [
- "android.hardware.graphics.common@1.1",
+ "android.hardware.graphics.common@1.2",
],
static_libs: [
diff --git a/libs/ui/DebugUtils.cpp b/libs/ui/DebugUtils.cpp
index 61df02d..ee06d93 100644
--- a/libs/ui/DebugUtils.cpp
+++ b/libs/ui/DebugUtils.cpp
@@ -234,6 +234,9 @@
case ColorMode::BT2020:
return std::string("ColorMode::BT2020");
+ case ColorMode::DISPLAY_BT2020:
+ return std::string("ColorMode::DISPLAY_BT2020");
+
case ColorMode::BT2100_PQ:
return std::string("ColorMode::BT2100_PQ");
diff --git a/libs/ui/include/ui/GraphicTypes.h b/libs/ui/include/ui/GraphicTypes.h
index 0fa819d..1d53ac8 100644
--- a/libs/ui/include/ui/GraphicTypes.h
+++ b/libs/ui/include/ui/GraphicTypes.h
@@ -17,6 +17,7 @@
#pragma once
#include <android/hardware/graphics/common/1.1/types.h>
+#include <android/hardware/graphics/common/1.2/types.h>
#include <system/graphics.h>
// android::ui::* in this header file will alias different types as
@@ -25,10 +26,10 @@
namespace ui {
using android::hardware::graphics::common::V1_0::Hdr;
-using android::hardware::graphics::common::V1_1::ColorMode;
-using android::hardware::graphics::common::V1_1::Dataspace;
using android::hardware::graphics::common::V1_1::PixelFormat;
using android::hardware::graphics::common::V1_1::RenderIntent;
+using android::hardware::graphics::common::V1_2::ColorMode;
+using android::hardware::graphics::common::V1_2::Dataspace;
} // namespace ui
} // namespace android
diff --git a/services/surfaceflinger/Android.bp b/services/surfaceflinger/Android.bp
index 339f83b..16003a2 100644
--- a/services/surfaceflinger/Android.bp
+++ b/services/surfaceflinger/Android.bp
@@ -30,6 +30,7 @@
"android.hardware.configstore@1.1",
"android.hardware.configstore@1.2",
"android.hardware.graphics.allocator@2.0",
+ "android.hardware.graphics.common@1.2",
"android.hardware.graphics.composer@2.1",
"android.hardware.graphics.composer@2.2",
"android.hardware.graphics.composer@2.3",
@@ -79,6 +80,7 @@
],
export_shared_lib_headers: [
"android.hardware.graphics.allocator@2.0",
+ "android.hardware.graphics.common@1.2",
"android.hardware.graphics.composer@2.1",
"android.hardware.graphics.composer@2.2",
"android.hardware.graphics.composer@2.3",
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 60cad02..6f645df 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -37,8 +37,8 @@
#include <ui/DebugUtils.h>
#include <ui/DisplayInfo.h>
#include <ui/PixelFormat.h>
-#include <utils/RefBase.h>
#include <utils/Log.h>
+#include <utils/RefBase.h>
#include "DisplayHardware/DisplaySurface.h"
#include "DisplayHardware/HWComposer.h"
@@ -66,7 +66,8 @@
namespace {
// ordered list of known SDR color modes
-const std::array<ColorMode, 2> sSdrColorModes = {
+const std::array<ColorMode, 3> sSdrColorModes = {
+ ColorMode::DISPLAY_BT2020,
ColorMode::DISPLAY_P3,
ColorMode::SRGB,
};
@@ -96,6 +97,8 @@
return Dataspace::SRGB;
case ColorMode::DISPLAY_P3:
return Dataspace::DISPLAY_P3;
+ case ColorMode::DISPLAY_BT2020:
+ return Dataspace::DISPLAY_BT2020;
case ColorMode::BT2100_HLG:
return Dataspace::BT2020_HLG;
case ColorMode::BT2100_PQ:
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
index 163b26c..f0bccaa 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.cpp
@@ -354,16 +354,26 @@
{
Error error = kDefaultError;
- if (mClient_2_2) {
- mClient_2_2->getColorModes_2_2(display,
- [&](const auto& tmpError, const auto& tmpModes) {
- error = tmpError;
- if (error != Error::NONE) {
- return;
- }
+ if (mClient_2_3) {
+ mClient_2_3->getColorModes_2_3(display, [&](const auto& tmpError, const auto& tmpModes) {
+ error = tmpError;
+ if (error != Error::NONE) {
+ return;
+ }
- *outModes = tmpModes;
- });
+ *outModes = tmpModes;
+ });
+ } else if (mClient_2_2) {
+ mClient_2_2->getColorModes_2_2(display, [&](const auto& tmpError, const auto& tmpModes) {
+ error = tmpError;
+ if (error != Error::NONE) {
+ return;
+ }
+
+ for (types::V1_1::ColorMode colorMode : tmpModes) {
+ outModes->push_back(static_cast<ColorMode>(colorMode));
+ }
+ });
} else {
mClient->getColorModes(display,
[&](const auto& tmpError, const auto& tmpModes) {
@@ -555,8 +565,11 @@
RenderIntent renderIntent)
{
hardware::Return<Error> ret(kDefaultError);
- if (mClient_2_2) {
- ret = mClient_2_2->setColorMode_2_2(display, mode, renderIntent);
+ if (mClient_2_3) {
+ ret = mClient_2_3->setColorMode_2_3(display, mode, renderIntent);
+ } else if (mClient_2_2) {
+ ret = mClient_2_2->setColorMode_2_2(display, static_cast<types::V1_1::ColorMode>(mode),
+ renderIntent);
} else {
ret = mClient->setColorMode(display,
static_cast<types::V1_0::ColorMode>(mode));
@@ -934,15 +947,22 @@
}
Error error = kDefaultError;
- mClient_2_2->getRenderIntents(display, colorMode,
- [&](const auto& tmpError, const auto& tmpKeys) {
+
+ auto getRenderIntentsLambda = [&](const auto& tmpError, const auto& tmpKeys) {
error = tmpError;
if (error != Error::NONE) {
return;
}
*outRenderIntents = tmpKeys;
- });
+ };
+
+ if (mClient_2_3) {
+ mClient_2_3->getRenderIntents_2_3(display, colorMode, getRenderIntentsLambda);
+ } else {
+ mClient_2_2->getRenderIntents(display, static_cast<types::V1_1::ColorMode>(colorMode),
+ getRenderIntentsLambda);
+ }
return error;
}
@@ -955,14 +975,14 @@
}
Error error = kDefaultError;
- mClient_2_2->getDataspaceSaturationMatrix(dataspace, [&](const auto& tmpError, const auto& tmpMatrix) {
- error = tmpError;
- if (error != Error::NONE) {
- return;
- }
-
- *outMatrix = mat4(tmpMatrix.data());
- });
+ mClient_2_2->getDataspaceSaturationMatrix(static_cast<types::V1_1::Dataspace>(dataspace),
+ [&](const auto& tmpError, const auto& tmpMatrix) {
+ error = tmpError;
+ if (error != Error::NONE) {
+ return;
+ }
+ *outMatrix = mat4(tmpMatrix.data());
+ });
return error;
}
diff --git a/services/surfaceflinger/DisplayHardware/ComposerHal.h b/services/surfaceflinger/DisplayHardware/ComposerHal.h
index 94be6e9..4188352 100644
--- a/services/surfaceflinger/DisplayHardware/ComposerHal.h
+++ b/services/surfaceflinger/DisplayHardware/ComposerHal.h
@@ -49,10 +49,10 @@
using types::V1_0::Hdr;
using types::V1_0::Transform;
-using types::V1_1::ColorMode;
-using types::V1_1::Dataspace;
using types::V1_1::PixelFormat;
using types::V1_1::RenderIntent;
+using types::V1_2::ColorMode;
+using types::V1_2::Dataspace;
using V2_1::Config;
using V2_1::Display;
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index f0723e8..bd28978 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -124,6 +124,7 @@
case ColorMode::ADOBE_RGB:
case ColorMode::DCI_P3:
case ColorMode::BT2020:
+ case ColorMode::DISPLAY_BT2020:
case ColorMode::BT2100_PQ:
case ColorMode::BT2100_HLG:
return true;
@@ -2008,6 +2009,7 @@
// can only be one of
// - Dataspace::SRGB (use legacy dataspace and let HWC saturate when colors are enhanced)
// - Dataspace::DISPLAY_P3
+// - Dataspace::DISPLAY_BT2020
// The returned HDR data space is one of
// - Dataspace::UNKNOWN
// - Dataspace::BT2020_HLG
@@ -2021,6 +2023,12 @@
switch (layer->getDataSpace()) {
case Dataspace::V0_SCRGB:
case Dataspace::V0_SCRGB_LINEAR:
+ case Dataspace::BT2020:
+ case Dataspace::BT2020_ITU:
+ case Dataspace::BT2020_LINEAR:
+ case Dataspace::DISPLAY_BT2020:
+ bestDataSpace = Dataspace::DISPLAY_BT2020;
+ break;
case Dataspace::DISPLAY_P3:
bestDataSpace = Dataspace::DISPLAY_P3;
break;
diff --git a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
index b474e42..d32627a 100644
--- a/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
+++ b/services/surfaceflinger/tests/unittests/DisplayTransactionTest.cpp
@@ -22,6 +22,7 @@
#include <log/log.h>
+#include <ui/DebugUtils.h>
#include "TestableSurfaceFlinger.h"
#include "mock/DisplayHardware/MockComposer.h"
#include "mock/DisplayHardware/MockDisplaySurface.h"
@@ -997,6 +998,93 @@
}
/* ------------------------------------------------------------------------
+ * DisplayDevice::GetBestColorMode
+ */
+class GetBestColorModeTest : public DisplayTransactionTest {
+public:
+ GetBestColorModeTest()
+ : DisplayTransactionTest(),
+ mInjector(FakeDisplayDeviceInjector(mFlinger, DisplayDevice::DISPLAY_PRIMARY, 0)) {}
+
+ void setHasWideColorGamut(bool hasWideColorGamut) { mHasWideColorGamut = hasWideColorGamut; }
+
+ void addHwcColorModesMapping(ui::ColorMode colorMode,
+ std::vector<ui::RenderIntent> renderIntents) {
+ mHwcColorModes[colorMode] = renderIntents;
+ }
+
+ void setInputDataspace(ui::Dataspace dataspace) { mInputDataspace = dataspace; }
+
+ void setInputRenderIntent(ui::RenderIntent renderIntent) { mInputRenderIntent = renderIntent; }
+
+ void getBestColorMode() {
+ mInjector.setHwcColorModes(mHwcColorModes);
+ mInjector.setHasWideColorGamut(mHasWideColorGamut);
+ auto displayDevice = mInjector.inject();
+
+ displayDevice->getBestColorMode(mInputDataspace, mInputRenderIntent, &mOutDataspace,
+ &mOutColorMode, &mOutRenderIntent);
+ }
+
+ ui::Dataspace mOutDataspace;
+ ui::ColorMode mOutColorMode;
+ ui::RenderIntent mOutRenderIntent;
+
+private:
+ ui::Dataspace mInputDataspace;
+ ui::RenderIntent mInputRenderIntent;
+ bool mHasWideColorGamut = false;
+ std::unordered_map<ui::ColorMode, std::vector<ui::RenderIntent>> mHwcColorModes;
+ FakeDisplayDeviceInjector mInjector;
+};
+
+TEST_F(GetBestColorModeTest, DataspaceDisplayP3_ColorModeSRGB) {
+ addHwcColorModesMapping(ui::ColorMode::SRGB,
+ std::vector<ui::RenderIntent>(1, RenderIntent::COLORIMETRIC));
+ setInputDataspace(ui::Dataspace::DISPLAY_P3);
+ setInputRenderIntent(ui::RenderIntent::COLORIMETRIC);
+ setHasWideColorGamut(true);
+
+ getBestColorMode();
+
+ ASSERT_EQ(ui::Dataspace::SRGB, mOutDataspace);
+ ASSERT_EQ(ui::ColorMode::SRGB, mOutColorMode);
+ ASSERT_EQ(ui::RenderIntent::COLORIMETRIC, mOutRenderIntent);
+}
+
+TEST_F(GetBestColorModeTest, DataspaceDisplayP3_ColorModeDisplayP3) {
+ addHwcColorModesMapping(ui::ColorMode::DISPLAY_P3,
+ std::vector<ui::RenderIntent>(1, RenderIntent::COLORIMETRIC));
+ addHwcColorModesMapping(ui::ColorMode::SRGB,
+ std::vector<ui::RenderIntent>(1, RenderIntent::COLORIMETRIC));
+ addHwcColorModesMapping(ui::ColorMode::DISPLAY_BT2020,
+ std::vector<ui::RenderIntent>(1, RenderIntent::COLORIMETRIC));
+ setInputDataspace(ui::Dataspace::DISPLAY_P3);
+ setInputRenderIntent(ui::RenderIntent::COLORIMETRIC);
+ setHasWideColorGamut(true);
+
+ getBestColorMode();
+
+ ASSERT_EQ(ui::Dataspace::DISPLAY_P3, mOutDataspace);
+ ASSERT_EQ(ui::ColorMode::DISPLAY_P3, mOutColorMode);
+ ASSERT_EQ(ui::RenderIntent::COLORIMETRIC, mOutRenderIntent);
+}
+
+TEST_F(GetBestColorModeTest, DataspaceDisplayP3_ColorModeDISPLAY_BT2020) {
+ addHwcColorModesMapping(ui::ColorMode::DISPLAY_BT2020,
+ std::vector<ui::RenderIntent>(1, RenderIntent::COLORIMETRIC));
+ setInputDataspace(ui::Dataspace::DISPLAY_P3);
+ setInputRenderIntent(ui::RenderIntent::COLORIMETRIC);
+ setHasWideColorGamut(true);
+
+ getBestColorMode();
+
+ ASSERT_EQ(ui::Dataspace::DISPLAY_BT2020, mOutDataspace);
+ ASSERT_EQ(ui::ColorMode::DISPLAY_BT2020, mOutColorMode);
+ ASSERT_EQ(ui::RenderIntent::COLORIMETRIC, mOutRenderIntent);
+}
+
+/* ------------------------------------------------------------------------
* SurfaceFlinger::setupNewDisplayDeviceInternal
*/
diff --git a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
index 2046439..62afde9 100644
--- a/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
+++ b/services/surfaceflinger/tests/unittests/TestableSurfaceFlinger.h
@@ -369,6 +369,18 @@
return *this;
}
+ auto& setHwcColorModes(
+ const std::unordered_map<ui::ColorMode, std::vector<ui::RenderIntent>>
+ hwcColorModes) {
+ mCreationArgs.hwcColorModes = hwcColorModes;
+ return *this;
+ }
+
+ auto& setHasWideColorGamut(bool hasWideColorGamut) {
+ mCreationArgs.hasWideColorGamut = hasWideColorGamut;
+ return *this;
+ }
+
sp<DisplayDevice> inject() {
DisplayDeviceState state;
state.type = mCreationArgs.type;
diff --git a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
index ecf3181..c0395c0 100644
--- a/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
+++ b/services/surfaceflinger/tests/unittests/mock/DisplayHardware/MockComposer.h
@@ -30,10 +30,10 @@
using android::hardware::graphics::common::V1_0::ColorTransform;
using android::hardware::graphics::common::V1_0::Hdr;
using android::hardware::graphics::common::V1_0::Transform;
-using android::hardware::graphics::common::V1_1::ColorMode;
-using android::hardware::graphics::common::V1_1::Dataspace;
using android::hardware::graphics::common::V1_1::PixelFormat;
using android::hardware::graphics::common::V1_1::RenderIntent;
+using android::hardware::graphics::common::V1_2::ColorMode;
+using android::hardware::graphics::common::V1_2::Dataspace;
using android::hardware::graphics::composer::V2_1::Config;
using android::hardware::graphics::composer::V2_1::Display;