Add extended brightness plumbing to VRI
Test: manual, builds & boots
Bug: 266628247
Change-Id: I6310883f3d10bb3eefa3cc189938b6c2c1a14544
diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp
index 8dea684..0cc68cc 100644
--- a/libs/hwui/renderthread/CanvasContext.cpp
+++ b/libs/hwui/renderthread/CanvasContext.cpp
@@ -299,9 +299,40 @@
mOpaque = opaque;
}
-void CanvasContext::setColorMode(ColorMode mode) {
- mRenderPipeline->setSurfaceColorProperties(mode);
- setupPipelineSurface();
+float CanvasContext::setColorMode(ColorMode mode) {
+ if (mode != mColorMode) {
+ if (mode == ColorMode::Hdr && !mRenderPipeline->supportsExtendedRangeHdr()) {
+ mode = ColorMode::WideColorGamut;
+ }
+ mColorMode = mode;
+ mRenderPipeline->setSurfaceColorProperties(mode);
+ setupPipelineSurface();
+ }
+ switch (mColorMode) {
+ case ColorMode::Hdr:
+ return 3.f; // TODO: Refine this number
+ default:
+ return 1.f;
+ }
+}
+
+float CanvasContext::targetSdrHdrRatio() const {
+ if (mColorMode == ColorMode::Hdr) {
+ return mTargetSdrHdrRatio;
+ } else {
+ return 1.f;
+ }
+}
+
+void CanvasContext::setTargetSdrHdrRatio(float ratio) {
+ if (mTargetSdrHdrRatio == ratio) return;
+
+ mTargetSdrHdrRatio = ratio;
+ mRenderPipeline->setTargetSdrHdrRatio(ratio);
+ // We don't actually but we need to behave as if we do. Specifically we need to ensure
+ // all buffers in the swapchain are fully re-rendered as any partial updates to them will
+ // result in mixed target white points which looks really bad & flickery
+ mHaveNewSurface = true;
}
bool CanvasContext::makeCurrent() {
diff --git a/libs/hwui/renderthread/CanvasContext.h b/libs/hwui/renderthread/CanvasContext.h
index a274d2f..a811670 100644
--- a/libs/hwui/renderthread/CanvasContext.h
+++ b/libs/hwui/renderthread/CanvasContext.h
@@ -137,7 +137,9 @@
void setLightAlpha(uint8_t ambientShadowAlpha, uint8_t spotShadowAlpha);
void setLightGeometry(const Vector3& lightCenter, float lightRadius);
void setOpaque(bool opaque);
- void setColorMode(ColorMode mode);
+ float setColorMode(ColorMode mode);
+ float targetSdrHdrRatio() const;
+ void setTargetSdrHdrRatio(float ratio);
bool makeCurrent();
void prepareTree(TreeInfo& info, int64_t* uiFrameInfo, int64_t syncQueued, RenderNode* target);
// Returns the DequeueBufferDuration.
@@ -352,6 +354,9 @@
nsecs_t mLastDequeueBufferDuration = 0;
nsecs_t mSyncDelayDuration = 0;
nsecs_t mIdleDuration = 0;
+
+ ColorMode mColorMode = ColorMode::Default;
+ float mTargetSdrHdrRatio = 1.f;
};
} /* namespace renderthread */
diff --git a/libs/hwui/renderthread/DrawFrameTask.cpp b/libs/hwui/renderthread/DrawFrameTask.cpp
index b06c5dd..fab2f46 100644
--- a/libs/hwui/renderthread/DrawFrameTask.cpp
+++ b/libs/hwui/renderthread/DrawFrameTask.cpp
@@ -91,6 +91,7 @@
ATRACE_FORMAT("DrawFrames %" PRId64, vsyncId);
mContext->setSyncDelayDuration(systemTime(SYSTEM_TIME_MONOTONIC) - mSyncQueued);
+ mContext->setTargetSdrHdrRatio(mRenderSdrHdrRatio);
auto hardwareBufferParams = mHardwareBufferParams;
mContext->setHardwareBufferRenderParams(hardwareBufferParams);
diff --git a/libs/hwui/renderthread/DrawFrameTask.h b/libs/hwui/renderthread/DrawFrameTask.h
index c5c5fe2..4130d4a 100644
--- a/libs/hwui/renderthread/DrawFrameTask.h
+++ b/libs/hwui/renderthread/DrawFrameTask.h
@@ -100,6 +100,8 @@
mHardwareBufferParams = params;
}
+ void setRenderSdrHdrRatio(float ratio) { mRenderSdrHdrRatio = ratio; }
+
private:
void postAndWait();
bool syncFrameState(TreeInfo& info);
@@ -112,6 +114,7 @@
CanvasContext* mContext;
RenderNode* mTargetNode = nullptr;
Rect mContentDrawBounds;
+ float mRenderSdrHdrRatio = 1.f;
/*********************************************
* Single frame data
diff --git a/libs/hwui/renderthread/EglManager.cpp b/libs/hwui/renderthread/EglManager.cpp
index 02257db..5b7cf75 100644
--- a/libs/hwui/renderthread/EglManager.cpp
+++ b/libs/hwui/renderthread/EglManager.cpp
@@ -450,6 +450,11 @@
case ColorMode::Default:
attribs[1] = EGL_GL_COLORSPACE_LINEAR_KHR;
break;
+ // Extended Range HDR requires being able to manipulate the dataspace in ways
+ // we cannot easily do while going through EGLSurface. Given this requires
+ // composer3 support, just treat HDR as equivalent to wide color gamut if
+ // the GLES path is still being hit
+ case ColorMode::Hdr:
case ColorMode::WideColorGamut: {
skcms_Matrix3x3 colorGamut;
LOG_ALWAYS_FATAL_IF(!colorSpace->toXYZD50(&colorGamut),
@@ -466,14 +471,6 @@
}
break;
}
- case ColorMode::Hdr:
- config = mEglConfigF16;
- attribs[1] = EGL_GL_COLORSPACE_BT2020_PQ_EXT;
- break;
- case ColorMode::Hdr10:
- config = mEglConfig1010102;
- attribs[1] = EGL_GL_COLORSPACE_BT2020_PQ_EXT;
- break;
case ColorMode::A8:
LOG_ALWAYS_FATAL("Unreachable: A8 doesn't use a color space");
break;
diff --git a/libs/hwui/renderthread/IRenderPipeline.h b/libs/hwui/renderthread/IRenderPipeline.h
index 715c17d..c68fcdf 100644
--- a/libs/hwui/renderthread/IRenderPipeline.h
+++ b/libs/hwui/renderthread/IRenderPipeline.h
@@ -95,6 +95,9 @@
virtual void setPictureCapturedCallback(
const std::function<void(sk_sp<SkPicture>&&)>& callback) = 0;
+ virtual bool supportsExtendedRangeHdr() const { return false; }
+ virtual void setTargetSdrHdrRatio(float ratio) = 0;
+
virtual ~IRenderPipeline() {}
};
diff --git a/libs/hwui/renderthread/RenderProxy.cpp b/libs/hwui/renderthread/RenderProxy.cpp
index 5edb0b1..1e011c2 100644
--- a/libs/hwui/renderthread/RenderProxy.cpp
+++ b/libs/hwui/renderthread/RenderProxy.cpp
@@ -143,8 +143,20 @@
mRenderThread.queue().post([=]() { mContext->setOpaque(opaque); });
}
-void RenderProxy::setColorMode(ColorMode mode) {
- mRenderThread.queue().post([=]() { mContext->setColorMode(mode); });
+float RenderProxy::setColorMode(ColorMode mode) {
+ // We only need to figure out what the renderer supports for HDR, otherwise this can stay
+ // an async call since we already know the return value
+ if (mode == ColorMode::Hdr) {
+ return mRenderThread.queue().runSync(
+ [=]() -> float { return mContext->setColorMode(mode); });
+ } else {
+ mRenderThread.queue().post([=]() { mContext->setColorMode(mode); });
+ return 1.f;
+ }
+}
+
+void RenderProxy::setRenderSdrHdrRatio(float ratio) {
+ mDrawFrameTask.setRenderSdrHdrRatio(ratio);
}
int64_t* RenderProxy::frameInfo() {
diff --git a/libs/hwui/renderthread/RenderProxy.h b/libs/hwui/renderthread/RenderProxy.h
index 2aafe76..82072a6 100644
--- a/libs/hwui/renderthread/RenderProxy.h
+++ b/libs/hwui/renderthread/RenderProxy.h
@@ -87,7 +87,8 @@
void setLightGeometry(const Vector3& lightCenter, float lightRadius);
void setHardwareBufferRenderParams(const HardwareBufferRenderParams& params);
void setOpaque(bool opaque);
- void setColorMode(ColorMode mode);
+ float setColorMode(ColorMode mode);
+ void setRenderSdrHdrRatio(float ratio);
int64_t* frameInfo();
void forceDrawNextFrame();
int syncAndDrawFrame();
diff --git a/libs/hwui/renderthread/VulkanSurface.cpp b/libs/hwui/renderthread/VulkanSurface.cpp
index 7dd3561..2efa5d6 100644
--- a/libs/hwui/renderthread/VulkanSurface.cpp
+++ b/libs/hwui/renderthread/VulkanSurface.cpp
@@ -199,7 +199,14 @@
outWindowInfo->bufferFormat = ColorTypeToBufferFormat(colorType);
outWindowInfo->colorspace = colorSpace;
- outWindowInfo->dataspace = ColorSpaceToADataSpace(colorSpace.get(), colorType);
+ outWindowInfo->colorMode = colorMode;
+
+ if (colorMode == ColorMode::Hdr) {
+ outWindowInfo->dataspace =
+ static_cast<android_dataspace>(STANDARD_DCI_P3 | TRANSFER_SRGB | RANGE_EXTENDED);
+ } else {
+ outWindowInfo->dataspace = ColorSpaceToADataSpace(colorSpace.get(), colorType);
+ }
LOG_ALWAYS_FATAL_IF(
outWindowInfo->dataspace == HAL_DATASPACE_UNKNOWN && colorType != kAlpha_8_SkColorType,
"Unsupported colorspace");
@@ -496,6 +503,33 @@
return currentBuffer.hasValidContents ? (mPresentCount - currentBuffer.lastPresentedCount) : 0;
}
+void VulkanSurface::setColorSpace(sk_sp<SkColorSpace> colorSpace) {
+ mWindowInfo.colorspace = std::move(colorSpace);
+ for (int i = 0; i < kNumBufferSlots; i++) {
+ mNativeBuffers[i].skSurface.reset();
+ }
+
+ if (mWindowInfo.colorMode == ColorMode::Hdr) {
+ mWindowInfo.dataspace =
+ static_cast<android_dataspace>(STANDARD_DCI_P3 | TRANSFER_SRGB | RANGE_EXTENDED);
+ } else {
+ mWindowInfo.dataspace = ColorSpaceToADataSpace(
+ mWindowInfo.colorspace.get(), BufferFormatToColorType(mWindowInfo.bufferFormat));
+ }
+ LOG_ALWAYS_FATAL_IF(mWindowInfo.dataspace == HAL_DATASPACE_UNKNOWN &&
+ mWindowInfo.bufferFormat != AHARDWAREBUFFER_FORMAT_R8_UNORM,
+ "Unsupported colorspace");
+
+ if (mNativeWindow) {
+ int err = native_window_set_buffers_data_space(mNativeWindow.get(), mWindowInfo.dataspace);
+ if (err != 0) {
+ ALOGE("VulkanSurface::setColorSpace() native_window_set_buffers_data_space(%d) "
+ "failed: %s (%d)",
+ mWindowInfo.dataspace, strerror(-err), err);
+ }
+ }
+}
+
} /* namespace renderthread */
} /* namespace uirenderer */
} /* namespace android */
diff --git a/libs/hwui/renderthread/VulkanSurface.h b/libs/hwui/renderthread/VulkanSurface.h
index 2648666..e2ddc6b 100644
--- a/libs/hwui/renderthread/VulkanSurface.h
+++ b/libs/hwui/renderthread/VulkanSurface.h
@@ -46,6 +46,8 @@
}
const SkMatrix& getCurrentPreTransform() { return mWindowInfo.preTransform; }
+ void setColorSpace(sk_sp<SkColorSpace> colorSpace);
+
private:
/*
* All structs/methods in this private section are specifically for use by the VulkanManager
@@ -94,6 +96,7 @@
uint32_t bufferFormat;
android_dataspace dataspace;
sk_sp<SkColorSpace> colorspace;
+ ColorMode colorMode;
int transform;
size_t bufferCount;
uint64_t windowUsageFlags;