Merge "Fix vr_hwc crash when re-entering vr" into pi-dev
diff --git a/cmds/lshal/ListCommand.cpp b/cmds/lshal/ListCommand.cpp
index 8e393c0..ff22048 100644
--- a/cmds/lshal/ListCommand.cpp
+++ b/cmds/lshal/ListCommand.cpp
@@ -503,7 +503,7 @@
using namespace ::android::hidl::manager::V1_0;
using namespace ::android::hidl::base::V1_0;
using std::literals::chrono_literals::operator""s;
- auto ret = timeoutIPC(2s, manager, &IServiceManager::debugDump, [&] (const auto &infos) {
+ auto ret = timeoutIPC(10s, manager, &IServiceManager::debugDump, [&] (const auto &infos) {
std::map<std::string, TableEntry> entries;
for (const auto &info : infos) {
std::string interfaceName = std::string{info.interfaceName.c_str()} + "/" +
diff --git a/opengl/include/GLES2/gl2ext.h b/opengl/include/GLES2/gl2ext.h
index 3ad39d9..e8d7515 100644
--- a/opengl/include/GLES2/gl2ext.h
+++ b/opengl/include/GLES2/gl2ext.h
@@ -3612,17 +3612,6 @@
#define GL_SHADER_BINARY_VIV 0x8FC4
#endif /* GL_VIV_shader_binary */
-/* Temporary hack to allow frameworks/base/libs/hwui/debug to build.
- * This function was removed from the Khronos version of the headers
- * (it is specified with the EXT prefix, not OES). */
-#ifndef GL_ANDROID_draw_elements_base_vertex_backwards_compatibility
-#define GL_ANDROID_draw_elements_base_vertex_backwards_compatibility 1
-typedef void (GL_APIENTRYP PFNGLMULTIDRAWELEMENTSBASEVERTEXOESPROC) (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, const GLint *basevertex);
-#ifdef GL_GLEXT_PROTOTYPES
-GL_APICALL void GL_APIENTRY glMultiDrawElementsBaseVertexOES (GLenum mode, const GLsizei *count, GLenum type, const void *const*indices, GLsizei primcount, const GLint *basevertex);
-#endif
-#endif /* GL_ANDROID_draw_elements_base_vertex_backwards_compatibility */
-
#ifdef __cplusplus
}
#endif
diff --git a/services/surfaceflinger/DisplayDevice.cpp b/services/surfaceflinger/DisplayDevice.cpp
index 58a774b..d90ab1d 100644
--- a/services/surfaceflinger/DisplayDevice.cpp
+++ b/services/surfaceflinger/DisplayDevice.cpp
@@ -55,6 +55,7 @@
using namespace android::hardware::configstore;
using namespace android::hardware::configstore::V1_0;
using android::ui::ColorMode;
+using android::ui::RenderIntent;
/*
* Initialize the display to the specified values.
@@ -75,8 +76,8 @@
std::unique_ptr<RE::Surface> renderSurface,
int displayWidth,
int displayHeight,
- bool supportWideColor,
- bool supportHdr,
+ bool hasWideColorGamut,
+ bool hasHdr10,
int initialPowerMode)
: lastCompositionHadVisibleLayers(false),
mFlinger(flinger),
@@ -98,8 +99,8 @@
mActiveConfig(0),
mActiveColorMode(ColorMode::NATIVE),
mColorTransform(HAL_COLOR_TRANSFORM_IDENTITY),
- mDisplayHasWideColor(supportWideColor),
- mDisplayHasHdr(supportHdr)
+ mHasWideColorGamut(hasWideColorGamut),
+ mHasHdr10(hasHdr10)
{
// clang-format on
@@ -268,6 +269,14 @@
return mActiveColorMode;
}
+RenderIntent DisplayDevice::getActiveRenderIntent() const {
+ return mActiveRenderIntent;
+}
+
+void DisplayDevice::setActiveRenderIntent(RenderIntent renderIntent) {
+ mActiveRenderIntent = renderIntent;
+}
+
void DisplayDevice::setColorTransform(const mat4& transform) {
const bool isIdentity = (transform == mat4());
mColorTransform =
@@ -279,10 +288,15 @@
}
void DisplayDevice::setCompositionDataSpace(ui::Dataspace dataspace) {
+ mCompositionDataSpace = dataspace;
ANativeWindow* const window = mNativeWindow.get();
native_window_set_buffers_data_space(window, static_cast<android_dataspace>(dataspace));
}
+ui::Dataspace DisplayDevice::getCompositionDataSpace() const {
+ return mCompositionDataSpace;
+}
+
// ----------------------------------------------------------------------------
void DisplayDevice::setLayerStack(uint32_t stack) {
@@ -464,8 +478,8 @@
tr[0][1], tr[1][1], tr[2][1], tr[0][2], tr[1][2], tr[2][2]);
auto const surface = static_cast<Surface*>(window);
ui::Dataspace dataspace = surface->getBuffersDataSpace();
- result.appendFormat(" wideColor=%d, hdr=%d, colorMode=%s, dataspace: %s (%d)\n",
- mDisplayHasWideColor, mDisplayHasHdr,
+ result.appendFormat(" wideColorGamut=%d, hdr10=%d, colorMode=%s, dataspace: %s (%d)\n",
+ mHasWideColorGamut, mHasHdr10,
decodeColorMode(mActiveColorMode).c_str(),
dataspaceDetails(static_cast<android_dataspace>(dataspace)).c_str(), dataspace);
diff --git a/services/surfaceflinger/DisplayDevice.h b/services/surfaceflinger/DisplayDevice.h
index e844d11..bedf765 100644
--- a/services/surfaceflinger/DisplayDevice.h
+++ b/services/surfaceflinger/DisplayDevice.h
@@ -84,8 +84,8 @@
std::unique_ptr<RE::Surface> renderSurface,
int displayWidth,
int displayHeight,
- bool supportWideColor,
- bool supportHdr,
+ bool hasWideColorGamut,
+ bool hasHdr10,
int initialPowerMode);
// clang-format on
@@ -135,8 +135,8 @@
// machine happy without actually queueing a buffer if nothing has changed
status_t beginFrame(bool mustRecompose) const;
status_t prepareFrame(HWComposer& hwc);
- bool getWideColorSupport() const { return mDisplayHasWideColor; }
- bool getHdrSupport() const { return mDisplayHasHdr; }
+ bool hasWideColorGamut() const { return mHasWideColorGamut; }
+ bool hasHdr10() const { return mHasHdr10; }
void swapBuffers(HWComposer& hwc) const;
@@ -165,9 +165,12 @@
ui::ColorMode getActiveColorMode() const;
void setActiveColorMode(ui::ColorMode mode);
+ ui::RenderIntent getActiveRenderIntent() const;
+ void setActiveRenderIntent(ui::RenderIntent renderIntent);
android_color_transform_t getColorTransform() const;
void setColorTransform(const mat4& transform);
void setCompositionDataSpace(ui::Dataspace dataspace);
+ ui::Dataspace getCompositionDataSpace() const;
/* ------------------------------------------------------------------------
* Display active config management.
@@ -241,14 +244,17 @@
int mActiveConfig;
// current active color mode
ui::ColorMode mActiveColorMode;
+ // Current active render intent.
+ ui::RenderIntent mActiveRenderIntent;
+ ui::Dataspace mCompositionDataSpace;
// Current color transform
android_color_transform_t mColorTransform;
// Need to know if display is wide-color capable or not.
// Initialized by SurfaceFlinger when the DisplayDevice is created.
// Fed to RenderEngine during composition.
- bool mDisplayHasWideColor;
- bool mDisplayHasHdr;
+ bool mHasWideColorGamut;
+ bool mHasHdr10;
};
struct DisplayDeviceState {
@@ -290,9 +296,9 @@
bool isSecure() const override { return mDevice->isSecure(); }
bool needsFiltering() const override { return mDevice->needsFiltering(); }
Rect getSourceCrop() const override { return mSourceCrop; }
- bool getWideColorSupport() const override { return mDevice->getWideColorSupport(); }
- ui::ColorMode getActiveColorMode() const override {
- return mDevice->getActiveColorMode();
+ bool getWideColorSupport() const override { return mDevice->hasWideColorGamut(); }
+ ui::Dataspace getDataSpace() const override {
+ return mDevice->getCompositionDataSpace();
}
private:
diff --git a/services/surfaceflinger/Layer.cpp b/services/surfaceflinger/Layer.cpp
index 9d356d8..8c0050e 100644
--- a/services/surfaceflinger/Layer.cpp
+++ b/services/surfaceflinger/Layer.cpp
@@ -1643,6 +1643,21 @@
return true;
}
+// Dataspace::UNKNOWN, Dataspace::SRGB, Dataspace::SRGB_LINEAR,
+// Dataspace::V0_SRGB and Dataspace::V0_SRGB_LINEAR are considered legacy
+// SRGB data space for now.
+// Note that Dataspace::V0_SRGB and Dataspace::V0_SRGB_LINEAR are not legacy
+// data space, however since framework doesn't distinguish them out of legacy
+// SRGB, we have to treat them as the same for now.
+bool Layer::isLegacySrgbDataSpace() const {
+ // TODO(lpy) b/77652630, need to figure out when UNKNOWN can be treated as SRGB.
+ return mDrawingState.dataSpace == ui::Dataspace::UNKNOWN ||
+ mDrawingState.dataSpace == ui::Dataspace::SRGB ||
+ mDrawingState.dataSpace == ui::Dataspace::SRGB_LINEAR ||
+ mDrawingState.dataSpace == ui::Dataspace::V0_SRGB ||
+ mDrawingState.dataSpace == ui::Dataspace::V0_SRGB_LINEAR;
+}
+
void Layer::setParent(const sp<Layer>& layer) {
mCurrentParent = layer;
}
diff --git a/services/surfaceflinger/Layer.h b/services/surfaceflinger/Layer.h
index 8d2a048..d382a1a 100644
--- a/services/surfaceflinger/Layer.h
+++ b/services/surfaceflinger/Layer.h
@@ -297,6 +297,13 @@
bool reparent(const sp<IBinder>& newParentHandle);
bool detachChildren();
+ // Before color management is introduced, contents on Android have to be
+ // desaturated in order to match what they appears like visually.
+ // With color management, these contents will appear desaturated, thus
+ // needed to be saturated so that they match what they are designed for
+ // visually. When returns true, legacy SRGB data space is passed to HWC.
+ bool isLegacySrgbDataSpace() const;
+
// If we have received a new buffer this frame, we will pass its surface
// damage down to hardware composer. Otherwise, we must send a region with
// one empty rect.
diff --git a/services/surfaceflinger/RenderArea.h b/services/surfaceflinger/RenderArea.h
index bf0707f..4f812fc 100644
--- a/services/surfaceflinger/RenderArea.h
+++ b/services/surfaceflinger/RenderArea.h
@@ -25,15 +25,14 @@
virtual bool isSecure() const = 0;
virtual bool needsFiltering() const = 0;
virtual Rect getSourceCrop() const = 0;
+ virtual bool getWideColorSupport() const = 0;
+ virtual ui::Dataspace getDataSpace() const = 0;
virtual void render(std::function<void()> drawLayers) { drawLayers(); }
int getReqHeight() const { return mReqHeight; };
int getReqWidth() const { return mReqWidth; };
Transform::orientation_flags getRotationFlags() const { return mRotationFlags; };
- virtual bool getWideColorSupport() const = 0;
- virtual ui::ColorMode getActiveColorMode() const = 0;
-
status_t updateDimensions();
private:
diff --git a/services/surfaceflinger/SurfaceFlinger.cpp b/services/surfaceflinger/SurfaceFlinger.cpp
index 183c1eb..a8680e2 100644
--- a/services/surfaceflinger/SurfaceFlinger.cpp
+++ b/services/surfaceflinger/SurfaceFlinger.cpp
@@ -157,6 +157,31 @@
return std::string(value) == "true";
}
+DisplayColorSetting toDisplayColorSetting(int value) {
+ switch(value) {
+ case 0:
+ return DisplayColorSetting::MANAGED;
+ case 1:
+ return DisplayColorSetting::UNMANAGED;
+ case 2:
+ return DisplayColorSetting::ENHANCED;
+ default:
+ return DisplayColorSetting::MANAGED;
+ }
+}
+
+std::string decodeDisplayColorSetting(DisplayColorSetting displayColorSetting) {
+ switch(displayColorSetting) {
+ case DisplayColorSetting::MANAGED:
+ return std::string("Natural Mode");
+ case DisplayColorSetting::UNMANAGED:
+ return std::string("Saturated Mode");
+ case DisplayColorSetting::ENHANCED:
+ return std::string("Auto Color Mode");
+ }
+ return std::string("Unknown Display Color Setting");
+}
+
NativeWindowSurface::~NativeWindowSurface() = default;
namespace impl {
@@ -690,6 +715,9 @@
ALOGE("Run StartPropertySetThread failed!");
}
+ mLegacySrgbSaturationMatrix = getBE().mHwc->getDataspaceSaturationMatrix(HWC_DISPLAY_PRIMARY,
+ Dataspace::SRGB_LINEAR);
+
ALOGV("Done initializing");
}
@@ -697,14 +725,13 @@
char value[PROPERTY_VALUE_MAX];
property_get("persist.sys.sf.color_saturation", value, "1.0");
- mSaturation = atof(value);
- ALOGV("Saturation is set to %.2f", mSaturation);
+ mGlobalSaturationFactor = atof(value);
+ ALOGV("Saturation is set to %.2f", mGlobalSaturationFactor);
property_get("persist.sys.sf.native_mode", value, "0");
- mForceNativeColorMode = atoi(value) == 1;
- if (mForceNativeColorMode) {
- ALOGV("Forcing native color mode");
- }
+ mDisplayColorSetting = toDisplayColorSetting(atoi(value));
+ ALOGV("Display Color Setting is set to %s.",
+ decodeDisplayColorSetting(mDisplayColorSetting).c_str());
}
void SurfaceFlinger::startBootAnim() {
@@ -989,11 +1016,29 @@
}
void SurfaceFlinger::setActiveColorModeInternal(const sp<DisplayDevice>& hw,
- ColorMode mode) {
+ ColorMode mode, Dataspace dataSpace) {
int32_t type = hw->getDisplayType();
ColorMode currentMode = hw->getActiveColorMode();
+ Dataspace currentDataSpace = hw->getCompositionDataSpace();
+ RenderIntent currentRenderIntent = hw->getActiveRenderIntent();
- if (mode == currentMode) {
+ // Natural Mode means it's color managed and the color must be right,
+ // thus we pick RenderIntent::COLORIMETRIC as render intent.
+ // Native Mode means the display is not color managed, and whichever
+ // render intent is picked doesn't matter, thus return
+ // RenderIntent::COLORIMETRIC as default here.
+ RenderIntent renderIntent = RenderIntent::COLORIMETRIC;
+
+ // In Auto Color Mode, we want to strech to panel color space, right now
+ // only the built-in display supports it.
+ if (mDisplayColorSetting == DisplayColorSetting::ENHANCED &&
+ mBuiltinDisplaySupportsEnhance &&
+ hw->getDisplayType() == DisplayDevice::DISPLAY_PRIMARY) {
+ renderIntent = RenderIntent::ENHANCE;
+ }
+
+ if (mode == currentMode && dataSpace == currentDataSpace &&
+ renderIntent == currentRenderIntent) {
return;
}
@@ -1002,11 +1047,15 @@
return;
}
- ALOGD("Set active color mode: %s (%d), type=%d", decodeColorMode(mode).c_str(), mode,
- hw->getDisplayType());
-
hw->setActiveColorMode(mode);
- getHwComposer().setActiveColorMode(type, mode, RenderIntent::COLORIMETRIC);
+ hw->setCompositionDataSpace(dataSpace);
+ hw->setActiveRenderIntent(renderIntent);
+ getHwComposer().setActiveColorMode(type, mode, renderIntent);
+
+ ALOGV("Set active color mode: %s (%d), active render intent: %s (%d), type=%d",
+ decodeColorMode(mode).c_str(), mode,
+ decodeRenderIntent(renderIntent).c_str(), renderIntent,
+ hw->getDisplayType());
}
@@ -1037,7 +1086,7 @@
ALOGW("Attempt to set active color mode %s %d for virtual display",
decodeColorMode(mMode).c_str(), mMode);
} else {
- mFlinger.setActiveColorModeInternal(hw, mMode);
+ mFlinger.setActiveColorModeInternal(hw, mMode, Dataspace::UNKNOWN);
}
return true;
}
@@ -1072,7 +1121,7 @@
std::unique_ptr<HdrCapabilities> capabilities =
getBE().mHwc->getHdrCapabilities(displayDevice->getHwcDisplayId());
if (capabilities) {
- if (displayDevice->getWideColorSupport() && !displayDevice->getHdrSupport()) {
+ if (displayDevice->hasWideColorGamut() && !displayDevice->hasHdr10()) {
// insert HDR10 as we will force client composition for HDR10
// layers
std::vector<int32_t> types = capabilities->getSupportedHdrTypes();
@@ -1821,73 +1870,78 @@
}
mat4 SurfaceFlinger::computeSaturationMatrix() const {
- if (mSaturation == 1.0f) {
+ if (mGlobalSaturationFactor == 1.0f) {
return mat4();
}
// Rec.709 luma coefficients
float3 luminance{0.213f, 0.715f, 0.072f};
- luminance *= 1.0f - mSaturation;
+ luminance *= 1.0f - mGlobalSaturationFactor;
return mat4(
- vec4{luminance.r + mSaturation, luminance.r, luminance.r, 0.0f},
- vec4{luminance.g, luminance.g + mSaturation, luminance.g, 0.0f},
- vec4{luminance.b, luminance.b, luminance.b + mSaturation, 0.0f},
+ vec4{luminance.r + mGlobalSaturationFactor, luminance.r, luminance.r, 0.0f},
+ vec4{luminance.g, luminance.g + mGlobalSaturationFactor, luminance.g, 0.0f},
+ vec4{luminance.b, luminance.b, luminance.b + mGlobalSaturationFactor, 0.0f},
vec4{0.0f, 0.0f, 0.0f, 1.0f}
);
}
-// pickColorMode translates a given dataspace into the best available color mode.
-// Currently only support sRGB and Display-P3.
-ColorMode SurfaceFlinger::pickColorMode(Dataspace dataSpace) const {
- if (mForceNativeColorMode) {
- return ColorMode::NATIVE;
+// Returns a dataspace that fits all visible layers. The returned dataspace
+// can only be one of
+//
+// - Dataspace::V0_SRGB
+// - Dataspace::DISPLAY_P3
+// - Dataspace::V0_SCRGB_LINEAR
+// TODO(b/73825729) Add BT2020 data space.
+ui::Dataspace SurfaceFlinger::getBestDataspace(
+ const sp<const DisplayDevice>& displayDevice) const {
+ Dataspace bestDataspace = Dataspace::V0_SRGB;
+ for (const auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
+ switch (layer->getDataSpace()) {
+ case Dataspace::V0_SCRGB:
+ case Dataspace::V0_SCRGB_LINEAR:
+ // return immediately
+ return Dataspace::V0_SCRGB_LINEAR;
+ case Dataspace::BT2020_PQ:
+ case Dataspace::BT2020_ITU_PQ:
+ // Historically, HDR dataspaces are ignored by SurfaceFlinger. But
+ // since SurfaceFlinger simulates HDR support now, it should honor
+ // them unless there is also native support.
+ if (!displayDevice->hasHdr10()) {
+ return Dataspace::V0_SCRGB_LINEAR;
+ }
+ break;
+ case Dataspace::DISPLAY_P3:
+ bestDataspace = Dataspace::DISPLAY_P3;
+ break;
+ default:
+ break;
+ }
}
- switch (dataSpace) {
- // treat Unknown as regular SRGB buffer, since that's what the rest of the
- // system expects.
- case Dataspace::UNKNOWN:
- case Dataspace::SRGB:
- case Dataspace::V0_SRGB:
- return ColorMode::SRGB;
- break;
-
- case Dataspace::DISPLAY_P3:
- return ColorMode::DISPLAY_P3;
- break;
-
- default:
- // TODO (courtneygo): Do we want to assert an error here?
- ALOGE("No color mode mapping for %s (%#x)",
- dataspaceDetails(static_cast<android_dataspace>(dataSpace)).c_str(),
- dataSpace);
- return ColorMode::SRGB;
- break;
- }
+ return bestDataspace;
}
-Dataspace SurfaceFlinger::bestTargetDataSpace(
- Dataspace a, Dataspace b, bool hasHdr) const {
- // Only support sRGB and Display-P3 right now.
- if (a == Dataspace::DISPLAY_P3 || b == Dataspace::DISPLAY_P3) {
- return Dataspace::DISPLAY_P3;
- }
- if (a == Dataspace::V0_SCRGB_LINEAR || b == Dataspace::V0_SCRGB_LINEAR) {
- return Dataspace::DISPLAY_P3;
- }
- if (a == Dataspace::V0_SCRGB || b == Dataspace::V0_SCRGB) {
- return Dataspace::DISPLAY_P3;
- }
- if (!hasHdr) {
- if (a == Dataspace::BT2020_PQ || b == Dataspace::BT2020_PQ) {
- return Dataspace::DISPLAY_P3;
- }
- if (a == Dataspace::BT2020_ITU_PQ || b == Dataspace::BT2020_ITU_PQ) {
- return Dataspace::DISPLAY_P3;
- }
+// Pick the ColorMode / Dataspace for the display device.
+// TODO(b/73825729) Add BT2020 color mode.
+void SurfaceFlinger::pickColorMode(const sp<DisplayDevice>& displayDevice,
+ ColorMode* outMode, Dataspace* outDataSpace) const {
+ if (mDisplayColorSetting == DisplayColorSetting::UNMANAGED) {
+ *outMode = ColorMode::NATIVE;
+ *outDataSpace = Dataspace::UNKNOWN;
+ return;
}
- return Dataspace::V0_SRGB;
+ switch (getBestDataspace(displayDevice)) {
+ case Dataspace::DISPLAY_P3:
+ case Dataspace::V0_SCRGB_LINEAR:
+ *outMode = ColorMode::DISPLAY_P3;
+ *outDataSpace = Dataspace::DISPLAY_P3;
+ break;
+ default:
+ *outMode = ColorMode::SRGB;
+ *outDataSpace = Dataspace::V0_SRGB;
+ break;
+ }
}
void SurfaceFlinger::setUpHWComposer() {
@@ -1970,7 +2024,7 @@
for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
if ((layer->getDataSpace() == Dataspace::BT2020_PQ ||
layer->getDataSpace() == Dataspace::BT2020_ITU_PQ) &&
- !displayDevice->getHdrSupport()) {
+ !displayDevice->hasHdr10()) {
layer->forceClientComposition(hwcId);
}
@@ -1984,19 +2038,10 @@
}
if (hasWideColorDisplay) {
- ColorMode newColorMode;
- Dataspace newDataSpace = Dataspace::V0_SRGB;
-
- for (auto& layer : displayDevice->getVisibleLayersSortedByZ()) {
- newDataSpace = bestTargetDataSpace(layer->getDataSpace(), newDataSpace,
- displayDevice->getHdrSupport());
- ALOGV("layer: %s, dataspace: %s (%#x), newDataSpace: %s (%#x)",
- layer->getName().string(), dataspaceDetails(static_cast<android_dataspace>(layer->getDataSpace())).c_str(),
- layer->getDataSpace(), dataspaceDetails(static_cast<android_dataspace>(newDataSpace)).c_str(), newDataSpace);
- }
- newColorMode = pickColorMode(newDataSpace);
-
- setActiveColorModeInternal(displayDevice, newColorMode);
+ ColorMode colorMode;
+ Dataspace dataSpace;
+ pickColorMode(displayDevice, &colorMode, &dataSpace);
+ setActiveColorModeInternal(displayDevice, colorMode, dataSpace);
}
}
@@ -2204,29 +2249,40 @@
sp<DisplayDevice> SurfaceFlinger::setupNewDisplayDeviceInternal(
const wp<IBinder>& display, int hwcId, const DisplayDeviceState& state,
const sp<DisplaySurface>& dispSurface, const sp<IGraphicBufferProducer>& producer) {
- bool hasWideColorSupport = false;
+ bool hasWideColorGamut = false;
if (hasWideColorDisplay) {
- std::vector<ColorMode> modes = getHwComposer().getColorModes(state.type);
+ std::vector<ColorMode> modes = getHwComposer().getColorModes(hwcId);
for (ColorMode colorMode : modes) {
switch (colorMode) {
case ColorMode::DISPLAY_P3:
case ColorMode::ADOBE_RGB:
case ColorMode::DCI_P3:
- hasWideColorSupport = true;
+ hasWideColorGamut = true;
break;
+ // TODO(lpy) Handle BT2020, BT2100_PQ and BT2100_HLG properly.
default:
break;
}
+
+ std::vector<RenderIntent> renderIntents = getHwComposer().getRenderIntents(hwcId,
+ colorMode);
+ if (state.type == DisplayDevice::DISPLAY_PRIMARY) {
+ for (auto intent : renderIntents) {
+ if (intent == RenderIntent::ENHANCE) {
+ mBuiltinDisplaySupportsEnhance = true;
+ break;
+ }
+ }
+ }
}
}
- bool hasHdrSupport = false;
- std::unique_ptr<HdrCapabilities> hdrCapabilities =
- getHwComposer().getHdrCapabilities(state.type);
+ bool hasHdr10 = false;
+ std::unique_ptr<HdrCapabilities> hdrCapabilities = getHwComposer().getHdrCapabilities(hwcId);
if (hdrCapabilities) {
const std::vector<int32_t> types = hdrCapabilities->getSupportedHdrTypes();
auto iter = std::find(types.cbegin(), types.cend(), HAL_HDR_HDR10);
- hasHdrSupport = iter != types.cend();
+ hasHdr10 = iter != types.cend();
}
auto nativeWindowSurface = mCreateNativeWindowSurface(producer);
@@ -2260,18 +2316,19 @@
sp<DisplayDevice> hw =
new DisplayDevice(this, state.type, hwcId, state.isSecure, display, nativeWindow,
dispSurface, std::move(renderSurface), displayWidth, displayHeight,
- hasWideColorSupport, hasHdrSupport, initialPowerMode);
+ hasWideColorGamut, hasHdr10, initialPowerMode);
if (maxFrameBufferAcquiredBuffers >= 3) {
nativeWindowSurface->preallocateBuffers();
}
ColorMode defaultColorMode = ColorMode::NATIVE;
- if (hasWideColorSupport) {
+ Dataspace defaultDataSpace = Dataspace::UNKNOWN;
+ if (hasWideColorGamut) {
defaultColorMode = ColorMode::SRGB;
+ defaultDataSpace = Dataspace::V0_SRGB;
}
- setActiveColorModeInternal(hw, defaultColorMode);
- hw->setCompositionDataSpace(Dataspace::UNKNOWN);
+ setActiveColorModeInternal(hw, defaultColorMode, defaultDataSpace);
hw->setLayerStack(state.layerStack);
hw->setProjection(state.orientation, state.viewport, state.frame);
hw->setDisplayName(state.displayName);
@@ -2822,23 +2879,27 @@
const Region bounds(displayDevice->bounds());
const DisplayRenderArea renderArea(displayDevice);
const auto hwcId = displayDevice->getHwcDisplayId();
+ const bool hasClientComposition = getBE().mHwc->hasClientComposition(hwcId);
+ const bool hasDeviceComposition = getBE().mHwc->hasDeviceComposition(hwcId);
+ const bool skipClientColorTransform = getBE().mHwc->hasCapability(
+ HWC2::Capability::SkipClientColorTransform);
+ ATRACE_INT("hasClientComposition", hasClientComposition);
mat4 oldColorMatrix;
- const bool applyColorMatrix = !getBE().mHwc->hasDeviceComposition(hwcId) &&
- !getBE().mHwc->hasCapability(HWC2::Capability::SkipClientColorTransform);
+ mat4 legacySrgbSaturationMatrix = mLegacySrgbSaturationMatrix;
+ const bool applyColorMatrix = !hasDeviceComposition && !skipClientColorTransform;
if (applyColorMatrix) {
- mat4 colorMatrix = mColorMatrix * mDaltonizer();
+ mat4 colorMatrix = mColorMatrix * computeSaturationMatrix() * mDaltonizer();
oldColorMatrix = getRenderEngine().setupColorTransform(colorMatrix);
+ legacySrgbSaturationMatrix = colorMatrix * legacySrgbSaturationMatrix;
}
- bool hasClientComposition = getBE().mHwc->hasClientComposition(hwcId);
if (hasClientComposition) {
ALOGV("hasClientComposition");
Dataspace outputDataspace = Dataspace::UNKNOWN;
- if (displayDevice->getWideColorSupport() &&
- displayDevice->getActiveColorMode() == ColorMode::DISPLAY_P3) {
- outputDataspace = Dataspace::DISPLAY_P3;
+ if (displayDevice->hasWideColorGamut()) {
+ outputDataspace = displayDevice->getCompositionDataSpace();
}
getBE().mRenderEngine->setOutputDataSpace(outputDataspace);
@@ -2855,7 +2916,6 @@
}
// Never touch the framebuffer if we don't have any framebuffer layers
- const bool hasDeviceComposition = getBE().mHwc->hasDeviceComposition(hwcId);
if (hasDeviceComposition) {
// when using overlays, we assume a fully transparent framebuffer
// NOTE: we could reduce how much we need to clear, for instance
@@ -2930,7 +2990,20 @@
break;
}
case HWC2::Composition::Client: {
+ // Only apply saturation matrix layer that is legacy SRGB dataspace
+ // when auto color mode is on.
+ bool restore = false;
+ mat4 savedMatrix;
+ if (mDisplayColorSetting == DisplayColorSetting::ENHANCED &&
+ layer->isLegacySrgbDataSpace()) {
+ savedMatrix =
+ getRenderEngine().setupColorTransform(legacySrgbSaturationMatrix);
+ restore = true;
+ }
layer->draw(renderArea, clip);
+ if (restore) {
+ getRenderEngine().setupColorTransform(savedMatrix);
+ }
break;
}
default:
@@ -4004,7 +4077,7 @@
void SurfaceFlinger::dumpWideColorInfo(String8& result) const {
result.appendFormat("hasWideColorDisplay: %d\n", hasWideColorDisplay);
- result.appendFormat("forceNativeColorMode: %d\n", mForceNativeColorMode);
+ result.appendFormat("DisplayColorSetting: %d\n", mDisplayColorSetting);
// TODO: print out if wide-color mode is active or not
@@ -4500,15 +4573,22 @@
return NO_ERROR;
}
case 1022: { // Set saturation boost
- mSaturation = std::max(0.0f, std::min(data.readFloat(), 2.0f));
+ mGlobalSaturationFactor = std::max(0.0f, std::min(data.readFloat(), 2.0f));
invalidateHwcGeometry();
repaintEverything();
return NO_ERROR;
}
case 1023: { // Set native mode
- mForceNativeColorMode = data.readInt32() == 1;
+ int32_t value = data.readInt32();
+ if (value > 2) {
+ return BAD_VALUE;
+ }
+ if (value == 2 && !mBuiltinDisplaySupportsEnhance) {
+ return BAD_VALUE;
+ }
+ mDisplayColorSetting = toDisplayColorSetting(value);
invalidateHwcGeometry();
repaintEverything();
return NO_ERROR;
@@ -4535,6 +4615,23 @@
reply->writeBool(mTracing.isEnabled());
return NO_ERROR;
}
+ // Is a DisplayColorSetting supported?
+ case 1027: {
+ int32_t value = data.readInt32();
+ switch (value) {
+ case 0:
+ reply->writeBool(hasWideColorDisplay);
+ return NO_ERROR;
+ case 1:
+ reply->writeBool(true);
+ return NO_ERROR;
+ case 2:
+ reply->writeBool(mBuiltinDisplaySupportsEnhance);
+ return NO_ERROR;
+ default:
+ return BAD_VALUE;
+ }
+ }
}
}
return err;
@@ -4602,6 +4699,7 @@
mCrop(crop),
mFlinger(flinger),
mChildrenOnly(childrenOnly) {}
+ const Transform& getTransform() const override { return mTransform; }
Rect getBounds() const override {
const Layer::State& layerState(mLayer->getDrawingState());
return Rect(layerState.active.w, layerState.active.h);
@@ -4610,7 +4708,15 @@
int getWidth() const override { return mLayer->getDrawingState().active.w; }
bool isSecure() const override { return false; }
bool needsFiltering() const override { return false; }
- const Transform& getTransform() const { return mTransform; }
+ Rect getSourceCrop() const override {
+ if (mCrop.isEmpty()) {
+ return getBounds();
+ } else {
+ return mCrop;
+ }
+ }
+ bool getWideColorSupport() const override { return false; }
+ Dataspace getDataSpace() const override { return Dataspace::UNKNOWN; }
class ReparentForDrawing {
public:
@@ -4639,16 +4745,6 @@
}
}
- Rect getSourceCrop() const override {
- if (mCrop.isEmpty()) {
- return getBounds();
- } else {
- return mCrop;
- }
- }
- bool getWideColorSupport() const override { return false; }
- ColorMode getActiveColorMode() const override { return ColorMode::NATIVE; }
-
private:
const sp<Layer> mLayer;
const Rect mCrop;
@@ -4820,9 +4916,8 @@
}
Dataspace outputDataspace = Dataspace::UNKNOWN;
- if (renderArea.getWideColorSupport() &&
- renderArea.getActiveColorMode() == ColorMode::DISPLAY_P3) {
- outputDataspace = Dataspace::DISPLAY_P3;
+ if (renderArea.getWideColorSupport()) {
+ outputDataspace = renderArea.getDataSpace();
}
getBE().mRenderEngine->setOutputDataSpace(outputDataspace);
diff --git a/services/surfaceflinger/SurfaceFlinger.h b/services/surfaceflinger/SurfaceFlinger.h
index a29d1d7..14028ff 100644
--- a/services/surfaceflinger/SurfaceFlinger.h
+++ b/services/surfaceflinger/SurfaceFlinger.h
@@ -123,6 +123,12 @@
eTransactionMask = 0x0f,
};
+enum class DisplayColorSetting : int32_t {
+ MANAGED = 0,
+ UNMANAGED = 1,
+ ENHANCED = 2,
+};
+
// A thin interface to abstract creating instances of Surface (gui/Surface.h) to
// use as a NativeWindow.
class NativeWindowSurface {
@@ -467,7 +473,9 @@
bool stateLockHeld);
// Called on the main thread in response to setActiveColorMode()
- void setActiveColorModeInternal(const sp<DisplayDevice>& hw, ui::ColorMode colorMode);
+ void setActiveColorModeInternal(const sp<DisplayDevice>& hw,
+ ui::ColorMode colorMode,
+ ui::Dataspace dataSpace);
// Returns whether the transaction actually modified any state
bool handleMessageTransaction();
@@ -641,9 +649,10 @@
// Given a dataSpace, returns the appropriate color_mode to use
// to display that dataSpace.
- ui::ColorMode pickColorMode(ui::Dataspace dataSpace) const;
- ui::Dataspace bestTargetDataSpace(ui::Dataspace a, ui::Dataspace b,
- bool hasHdr) const;
+ ui::Dataspace getBestDataspace(const sp<const DisplayDevice>& displayDevice) const;
+ void pickColorMode(const sp<DisplayDevice>& displayDevice,
+ ui::ColorMode* outMode,
+ ui::Dataspace* outDataSpace) const;
mat4 computeSaturationMatrix() const;
@@ -846,7 +855,6 @@
size_t mNumLayers;
-
// Verify that transaction is being called by an approved process:
// either AID_GRAPHICS or AID_SYSTEM.
status_t CheckTransactCodeCredentials(uint32_t code);
@@ -856,8 +864,12 @@
static bool useVrFlinger;
std::thread::id mMainThreadId;
- float mSaturation = 1.0f;
- bool mForceNativeColorMode = false;
+ DisplayColorSetting mDisplayColorSetting = DisplayColorSetting::MANAGED;
+ // Applied on sRGB layers when the render intent is non-colorimetric.
+ mat4 mLegacySrgbSaturationMatrix;
+ // Applied globally.
+ float mGlobalSaturationFactor = 1.0f;
+ bool mBuiltinDisplaySupportsEnhance = false;
using CreateBufferQueueFunction =
std::function<void(sp<IGraphicBufferProducer>* /* outProducer */,