diff options
author | 2023-01-25 16:51:18 -0500 | |
---|---|---|
committer | 2023-01-26 10:43:33 -0500 | |
commit | 55887762f3ecf61771cb57c6a3395a473158f42f (patch) | |
tree | 2b8cc06d830d3f2eea881db033d184a4b065da14 | |
parent | b9c3176c090e292080fa77529e780b02208e9323 (diff) |
Add extended brightness plumbing to VRI
Test: manual, builds & boots
Bug: 266628247
Change-Id: I6310883f3d10bb3eefa3cc189938b6c2c1a14544
21 files changed, 239 insertions, 57 deletions
diff --git a/core/java/android/view/ThreadedRenderer.java b/core/java/android/view/ThreadedRenderer.java index 9c6e823b549e..2db2132ed354 100644 --- a/core/java/android/view/ThreadedRenderer.java +++ b/core/java/android/view/ThreadedRenderer.java @@ -572,17 +572,10 @@ public final class ThreadedRenderer extends HardwareRenderer { } @Override - public void setSurfaceControl(@Nullable SurfaceControl surfaceControl) { - super.setSurfaceControl(surfaceControl); + public void setSurfaceControl(@Nullable SurfaceControl surfaceControl, + @Nullable BLASTBufferQueue blastBufferQueue) { + super.setSurfaceControl(surfaceControl, blastBufferQueue); mWebViewOverlayProvider.setSurfaceControl(surfaceControl); - updateWebViewOverlayCallbacks(); - } - - /** - * Sets the BLASTBufferQueue being used for rendering. This is required to be specified - * for WebView overlay support - */ - public void setBlastBufferQueue(@Nullable BLASTBufferQueue blastBufferQueue) { mWebViewOverlayProvider.setBLASTBufferQueue(blastBufferQueue); updateWebViewOverlayCallbacks(); } diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java index 84ed845d62f8..81b20a49dd1e 100644 --- a/core/java/android/view/ViewRootImpl.java +++ b/core/java/android/view/ViewRootImpl.java @@ -683,6 +683,10 @@ public final class ViewRootImpl implements ViewParent, private BLASTBufferQueue mBlastBufferQueue; + private boolean mUpdateSdrHdrRatioInfo = false; + private float mDesiredSdrHdrRatio = 1f; + private float mRenderSdrHdrRatio = 1f; + /** * Child container layer of {@code mSurface} with the same bounds as its parent, and cropped to * the surface insets. This surface is created only if a client requests it via {@link @@ -1627,18 +1631,16 @@ public final class ViewRootImpl implements ViewParent, final boolean hasSurfaceInsets = insets.left != 0 || insets.right != 0 || insets.top != 0 || insets.bottom != 0; final boolean translucent = attrs.format != PixelFormat.OPAQUE || hasSurfaceInsets; - mAttachInfo.mThreadedRenderer = ThreadedRenderer.create(mContext, translucent, + final ThreadedRenderer renderer = ThreadedRenderer.create(mContext, translucent, attrs.getTitle().toString()); + mAttachInfo.mThreadedRenderer = renderer; + renderer.setSurfaceControl(mSurfaceControl, mBlastBufferQueue); updateColorModeIfNeeded(attrs.getColorMode()); updateForceDarkMode(); - if (mAttachInfo.mThreadedRenderer != null) { - mAttachInfo.mHardwareAccelerated = - mAttachInfo.mHardwareAccelerationRequested = true; - if (mHardwareRendererObserver != null) { - mAttachInfo.mThreadedRenderer.addObserver(mHardwareRendererObserver); - } - mAttachInfo.mThreadedRenderer.setSurfaceControl(mSurfaceControl); - mAttachInfo.mThreadedRenderer.setBlastBufferQueue(mBlastBufferQueue); + mAttachInfo.mHardwareAccelerated = true; + mAttachInfo.mHardwareAccelerationRequested = true; + if (mHardwareRendererObserver != null) { + renderer.addObserver(mHardwareRendererObserver); } } } @@ -2264,8 +2266,7 @@ public final class ViewRootImpl implements ViewParent, } if (mAttachInfo.mThreadedRenderer != null) { - mAttachInfo.mThreadedRenderer.setSurfaceControl(null); - mAttachInfo.mThreadedRenderer.setBlastBufferQueue(null); + mAttachInfo.mThreadedRenderer.setSurfaceControl(null, null); } } @@ -4828,6 +4829,13 @@ public final class ViewRootImpl implements ViewParent, useAsyncReport = true; + if (mUpdateSdrHdrRatioInfo) { + mUpdateSdrHdrRatioInfo = false; + applyTransactionOnDraw(mTransaction.setExtendedRangeBrightness( + getSurfaceControl(), mRenderSdrHdrRatio, mDesiredSdrHdrRatio)); + mAttachInfo.mThreadedRenderer.setTargetSdrHdrRatio(mRenderSdrHdrRatio); + } + if (forceDraw) { mAttachInfo.mThreadedRenderer.forceDrawNextFrame(); } @@ -5361,7 +5369,20 @@ public final class ViewRootImpl implements ViewParent, && !getConfiguration().isScreenWideColorGamut()) { colorMode = ActivityInfo.COLOR_MODE_DEFAULT; } - mAttachInfo.mThreadedRenderer.setColorMode(colorMode); + float desiredRatio = mAttachInfo.mThreadedRenderer.setColorMode(colorMode); + if (desiredRatio != mDesiredSdrHdrRatio) { + mDesiredSdrHdrRatio = desiredRatio; + mUpdateSdrHdrRatioInfo = true; + } + } + + /** happylint */ + public void setTargetSdrHdrRatio(float ratio) { + if (mRenderSdrHdrRatio != ratio) { + mRenderSdrHdrRatio = ratio; + mUpdateSdrHdrRatioInfo = true; + invalidate(); + } } @Override @@ -8435,8 +8456,7 @@ public final class ViewRootImpl implements ViewParent, updateBlastSurfaceIfNeeded(); } if (mAttachInfo.mThreadedRenderer != null) { - mAttachInfo.mThreadedRenderer.setSurfaceControl(mSurfaceControl); - mAttachInfo.mThreadedRenderer.setBlastBufferQueue(mBlastBufferQueue); + mAttachInfo.mThreadedRenderer.setSurfaceControl(mSurfaceControl, mBlastBufferQueue); } if (mPreviousTransformHint != transformHint) { mPreviousTransformHint = transformHint; diff --git a/graphics/java/android/graphics/HardwareRenderer.java b/graphics/java/android/graphics/HardwareRenderer.java index f815a5e91e76..c3eb7aa454ae 100644 --- a/graphics/java/android/graphics/HardwareRenderer.java +++ b/graphics/java/android/graphics/HardwareRenderer.java @@ -158,6 +158,7 @@ public class HardwareRenderer { private boolean mOpaque = true; private boolean mForceDark = false; private @ActivityInfo.ColorMode int mColorMode = ActivityInfo.COLOR_MODE_DEFAULT; + private float mDesiredSdrHdrRatio = 1f; /** * Creates a new instance of a HardwareRenderer. The HardwareRenderer will default @@ -319,7 +320,8 @@ public class HardwareRenderer { * @param surfaceControl The surface control to pass to render thread in hwui. * If null, any previous references held in render thread will be discarded. */ - public void setSurfaceControl(@Nullable SurfaceControl surfaceControl) { + public void setSurfaceControl(@Nullable SurfaceControl surfaceControl, + @Nullable BLASTBufferQueue blastBufferQueue) { nSetSurfaceControl(mNativeProxy, surfaceControl != null ? surfaceControl.mNativeObject : 0); } @@ -643,11 +645,12 @@ public class HardwareRenderer { * @param colorMode The @{@link ActivityInfo.ColorMode} to request * @hide */ - public void setColorMode(@ActivityInfo.ColorMode int colorMode) { + public float setColorMode(@ActivityInfo.ColorMode int colorMode) { if (mColorMode != colorMode) { mColorMode = colorMode; - nSetColorMode(mNativeProxy, colorMode); + mDesiredSdrHdrRatio = nSetColorMode(mNativeProxy, colorMode); } + return mDesiredSdrHdrRatio; } /** @@ -663,6 +666,12 @@ public class HardwareRenderer { nSetColorMode(mNativeProxy, colorMode); } + /** @hide */ + public void setTargetSdrHdrRatio(float ratio) { + if (ratio < 1.f || Float.isNaN(ratio) || Float.isInfinite(ratio)) ratio = 1.f; + nSetTargetSdrHdrRatio(mNativeProxy, ratio); + } + /** * Blocks until all previously queued work has completed. * @@ -1451,7 +1460,9 @@ public class HardwareRenderer { private static native void nSetOpaque(long nativeProxy, boolean opaque); - private static native void nSetColorMode(long nativeProxy, int colorMode); + private static native float nSetColorMode(long nativeProxy, int colorMode); + + private static native void nSetTargetSdrHdrRatio(long nativeProxy, float ratio); private static native void nSetSdrWhitePoint(long nativeProxy, float whitePoint); diff --git a/libs/hwui/ColorMode.h b/libs/hwui/ColorMode.h index 3df5c3c9caed..e45db01c0e34 100644 --- a/libs/hwui/ColorMode.h +++ b/libs/hwui/ColorMode.h @@ -25,10 +25,8 @@ enum class ColorMode { // WideColorGamut selects the most optimal colorspace & format for the device's display // Most commonly DisplayP3 + RGBA_8888 currently. WideColorGamut = 1, - // HDR Rec2020 + F16 + // Extended range Display P3 Hdr = 2, - // HDR Rec2020 + 1010102 - Hdr10 = 3, // Alpha 8 A8 = 4, }; diff --git a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp index 58923089deb0..d6aad7d3eede 100644 --- a/libs/hwui/jni/android_graphics_HardwareRenderer.cpp +++ b/libs/hwui/jni/android_graphics_HardwareRenderer.cpp @@ -232,10 +232,16 @@ static void android_view_ThreadedRenderer_setOpaque(JNIEnv* env, jobject clazz, proxy->setOpaque(opaque); } -static void android_view_ThreadedRenderer_setColorMode(JNIEnv* env, jobject clazz, - jlong proxyPtr, jint colorMode) { +static jfloat android_view_ThreadedRenderer_setColorMode(JNIEnv* env, jobject clazz, jlong proxyPtr, + jint colorMode) { RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); - proxy->setColorMode(static_cast<ColorMode>(colorMode)); + return proxy->setColorMode(static_cast<ColorMode>(colorMode)); +} + +static void android_view_ThreadedRenderer_setTargetSdrHdrRatio(JNIEnv* env, jobject clazz, + jlong proxyPtr, jfloat ratio) { + RenderProxy* proxy = reinterpret_cast<RenderProxy*>(proxyPtr); + return proxy->setRenderSdrHdrRatio(ratio); } static void android_view_ThreadedRenderer_setSdrWhitePoint(JNIEnv* env, jobject clazz, @@ -924,7 +930,9 @@ static const JNINativeMethod gMethods[] = { {"nSetLightAlpha", "(JFF)V", (void*)android_view_ThreadedRenderer_setLightAlpha}, {"nSetLightGeometry", "(JFFFF)V", (void*)android_view_ThreadedRenderer_setLightGeometry}, {"nSetOpaque", "(JZ)V", (void*)android_view_ThreadedRenderer_setOpaque}, - {"nSetColorMode", "(JI)V", (void*)android_view_ThreadedRenderer_setColorMode}, + {"nSetColorMode", "(JI)F", (void*)android_view_ThreadedRenderer_setColorMode}, + {"nSetTargetSdrHdrRatio", "(JF)V", + (void*)android_view_ThreadedRenderer_setTargetSdrHdrRatio}, {"nSetSdrWhitePoint", "(JF)V", (void*)android_view_ThreadedRenderer_setSdrWhitePoint}, {"nSetIsHighEndGfx", "(Z)V", (void*)android_view_ThreadedRenderer_setIsHighEndGfx}, {"nSetIsLowRam", "(Z)V", (void*)android_view_ThreadedRenderer_setIsLowRam}, diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.cpp b/libs/hwui/pipeline/skia/SkiaPipeline.cpp index 3692f0940b28..2017eb6eb7da 100644 --- a/libs/hwui/pipeline/skia/SkiaPipeline.cpp +++ b/libs/hwui/pipeline/skia/SkiaPipeline.cpp @@ -642,12 +642,9 @@ void SkiaPipeline::setSurfaceColorProperties(ColorMode colorMode) { mSurfaceColorSpace = DeviceInfo::get()->getWideColorSpace(); break; case ColorMode::Hdr: - mSurfaceColorType = SkColorType::kRGBA_F16_SkColorType; - mSurfaceColorSpace = SkColorSpace::MakeRGB(GetPQSkTransferFunction(), SkNamedGamut::kRec2020); - break; - case ColorMode::Hdr10: - mSurfaceColorType = SkColorType::kRGBA_1010102_SkColorType; - mSurfaceColorSpace = SkColorSpace::MakeRGB(GetPQSkTransferFunction(), SkNamedGamut::kRec2020); + mSurfaceColorType = SkColorType::kN32_SkColorType; + mSurfaceColorSpace = SkColorSpace::MakeRGB( + GetExtendedTransferFunction(mTargetSdrHdrRatio), SkNamedGamut::kDisplayP3); break; case ColorMode::A8: mSurfaceColorType = SkColorType::kAlpha_8_SkColorType; @@ -656,6 +653,16 @@ void SkiaPipeline::setSurfaceColorProperties(ColorMode colorMode) { } } +void SkiaPipeline::setTargetSdrHdrRatio(float ratio) { + if (mColorMode == ColorMode::Hdr) { + mTargetSdrHdrRatio = ratio; + mSurfaceColorSpace = SkColorSpace::MakeRGB(GetExtendedTransferFunction(mTargetSdrHdrRatio), + SkNamedGamut::kDisplayP3); + } else { + mTargetSdrHdrRatio = 1.f; + } +} + // Overdraw debugging // These colors should be kept in sync with Caches::getOverdrawColor() with a few differences. diff --git a/libs/hwui/pipeline/skia/SkiaPipeline.h b/libs/hwui/pipeline/skia/SkiaPipeline.h index 4f9334654c9b..befee8989383 100644 --- a/libs/hwui/pipeline/skia/SkiaPipeline.h +++ b/libs/hwui/pipeline/skia/SkiaPipeline.h @@ -78,6 +78,8 @@ public: virtual void setHardwareBuffer(AHardwareBuffer* buffer) override; bool hasHardwareBuffer() override { return mHardwareBuffer != nullptr; } + void setTargetSdrHdrRatio(float ratio) override; + protected: sk_sp<SkSurface> getBufferSkSurface( const renderthread::HardwareBufferRenderParams& bufferParams); @@ -92,6 +94,7 @@ protected: ColorMode mColorMode = ColorMode::Default; SkColorType mSurfaceColorType; sk_sp<SkColorSpace> mSurfaceColorSpace; + float mTargetSdrHdrRatio = 1.f; bool isCapturingSkp() const { return mCaptureMode != CaptureMode::None; } diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp index b94b6cf0546a..99298bc0fe9b 100644 --- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp +++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.cpp @@ -185,6 +185,13 @@ bool SkiaVulkanPipeline::setSurface(ANativeWindow* surface, SwapBehavior /*swapB return mVkSurface != nullptr; } +void SkiaVulkanPipeline::setTargetSdrHdrRatio(float ratio) { + SkiaPipeline::setTargetSdrHdrRatio(ratio); + if (mVkSurface) { + mVkSurface->setColorSpace(mSurfaceColorSpace); + } +} + bool SkiaVulkanPipeline::isSurfaceReady() { return CC_UNLIKELY(mVkSurface != nullptr); } diff --git a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h index 2c7b268e8174..d921ddb0d0fb 100644 --- a/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h +++ b/libs/hwui/pipeline/skia/SkiaVulkanPipeline.h @@ -53,6 +53,8 @@ public: void onStop() override; bool isSurfaceReady() override; bool isContextReady() override; + bool supportsExtendedRangeHdr() const override { return true; } + void setTargetSdrHdrRatio(float ratio) override; static void invokeFunctor(const renderthread::RenderThread& thread, Functor* functor); static sk_sp<Bitmap> allocateHardwareBitmap(renderthread::RenderThread& thread, diff --git a/libs/hwui/renderthread/CanvasContext.cpp b/libs/hwui/renderthread/CanvasContext.cpp index 8dea6845c9f8..0cc68cc00710 100644 --- a/libs/hwui/renderthread/CanvasContext.cpp +++ b/libs/hwui/renderthread/CanvasContext.cpp @@ -299,9 +299,40 @@ void CanvasContext::setOpaque(bool opaque) { 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 a274d2f2377f..a811670e8176 100644 --- a/libs/hwui/renderthread/CanvasContext.h +++ b/libs/hwui/renderthread/CanvasContext.h @@ -137,7 +137,9 @@ public: 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 @@ private: 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 b06c5dd9ad36..fab2f46e91c3 100644 --- a/libs/hwui/renderthread/DrawFrameTask.cpp +++ b/libs/hwui/renderthread/DrawFrameTask.cpp @@ -91,6 +91,7 @@ void DrawFrameTask::run() { 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 c5c5fe280743..4130d4abe09e 100644 --- a/libs/hwui/renderthread/DrawFrameTask.h +++ b/libs/hwui/renderthread/DrawFrameTask.h @@ -100,6 +100,8 @@ public: mHardwareBufferParams = params; } + void setRenderSdrHdrRatio(float ratio) { mRenderSdrHdrRatio = ratio; } + private: void postAndWait(); bool syncFrameState(TreeInfo& info); @@ -112,6 +114,7 @@ private: 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 02257db9df6a..5b7cf7538bd7 100644 --- a/libs/hwui/renderthread/EglManager.cpp +++ b/libs/hwui/renderthread/EglManager.cpp @@ -450,6 +450,11 @@ Result<EGLSurface, EGLint> EglManager::createSurface(EGLNativeWindowType window, 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 @@ Result<EGLSurface, EGLint> EglManager::createSurface(EGLNativeWindowType window, } 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 715c17dfc895..c68fcdfc76f2 100644 --- a/libs/hwui/renderthread/IRenderPipeline.h +++ b/libs/hwui/renderthread/IRenderPipeline.h @@ -95,6 +95,9 @@ public: 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 5edb0b1dd818..1e011c231343 100644 --- a/libs/hwui/renderthread/RenderProxy.cpp +++ b/libs/hwui/renderthread/RenderProxy.cpp @@ -143,8 +143,20 @@ void RenderProxy::setOpaque(bool opaque) { 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 2aafe76f94f9..82072a6e2499 100644 --- a/libs/hwui/renderthread/RenderProxy.h +++ b/libs/hwui/renderthread/RenderProxy.h @@ -87,7 +87,8 @@ public: 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 7dd3561cb220..2efa5d691ca5 100644 --- a/libs/hwui/renderthread/VulkanSurface.cpp +++ b/libs/hwui/renderthread/VulkanSurface.cpp @@ -199,7 +199,14 @@ bool VulkanSurface::InitializeWindowInfoStruct(ANativeWindow* window, ColorMode 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 @@ int VulkanSurface::getCurrentBuffersAge() { 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 26486669e712..e2ddc6b07768 100644 --- a/libs/hwui/renderthread/VulkanSurface.h +++ b/libs/hwui/renderthread/VulkanSurface.h @@ -46,6 +46,8 @@ public: } 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 @@ private: uint32_t bufferFormat; android_dataspace dataspace; sk_sp<SkColorSpace> colorspace; + ColorMode colorMode; int transform; size_t bufferCount; uint64_t windowUsageFlags; diff --git a/libs/hwui/utils/Color.cpp b/libs/hwui/utils/Color.cpp index 3afb419f9b8b..230c7f92fbf7 100644 --- a/libs/hwui/utils/Color.cpp +++ b/libs/hwui/utils/Color.cpp @@ -101,6 +101,26 @@ uint32_t ColorTypeToBufferFormat(SkColorType colorType) { return AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM; } } + +SkColorType BufferFormatToColorType(uint32_t format) { + switch (format) { + case AHARDWAREBUFFER_FORMAT_R8G8B8A8_UNORM: + return kN32_SkColorType; + case AHARDWAREBUFFER_FORMAT_R8G8B8X8_UNORM: + return kN32_SkColorType; + case AHARDWAREBUFFER_FORMAT_R5G6B5_UNORM: + return kRGB_565_SkColorType; + case AHARDWAREBUFFER_FORMAT_R10G10B10A2_UNORM: + return kRGBA_1010102_SkColorType; + case AHARDWAREBUFFER_FORMAT_R16G16B16A16_FLOAT: + return kRGBA_F16_SkColorType; + case AHARDWAREBUFFER_FORMAT_R8_UNORM: + return kAlpha_8_SkColorType; + default: + ALOGV("Unsupported format: %d, return unknown by default", format); + return kUnknown_SkColorType; + } +} #endif namespace { @@ -396,6 +416,27 @@ skcms_TransferFunction GetPQSkTransferFunction(float sdr_white_level) { return fn; } +static skcms_TransferFunction trfn_apply_gain(const skcms_TransferFunction trfn, float gain) { + float pow_gain_ginv = sk_float_pow(gain, 1 / trfn.g); + skcms_TransferFunction result; + result.g = trfn.g; + result.a = trfn.a * pow_gain_ginv; + result.b = trfn.b * pow_gain_ginv; + result.c = trfn.c * gain; + result.d = trfn.d; + result.e = trfn.e * gain; + result.f = trfn.f * gain; + return result; +} + +skcms_TransferFunction GetExtendedTransferFunction(float sdrHdrRatio) { + if (sdrHdrRatio <= 1.f) { + return SkNamedTransferFn::kSRGB; + } + // Scale the transfer by the sdrHdrRatio + return trfn_apply_gain(SkNamedTransferFn::kSRGB, sdrHdrRatio); +} + // Skia skcms' default HLG maps encoded [0, 1] to linear [1, 12] in order to follow ARIB // but LinearEffect expects a decoded [0, 1] range instead to follow Rec 2100. std::optional<skcms_TransferFunction> GetHLGScaleTransferFunction() { diff --git a/libs/hwui/utils/Color.h b/libs/hwui/utils/Color.h index 00f910f45c38..0fd61c7b990b 100644 --- a/libs/hwui/utils/Color.h +++ b/libs/hwui/utils/Color.h @@ -100,6 +100,7 @@ SkImageInfo BufferDescriptionToImageInfo(const AHardwareBuffer_Desc& bufferDesc, sk_sp<SkColorSpace> colorSpace); uint32_t ColorTypeToBufferFormat(SkColorType colorType); +SkColorType BufferFormatToColorType(uint32_t bufferFormat); #endif ANDROID_API sk_sp<SkColorSpace> DataSpaceToColorSpace(android_dataspace dataspace); @@ -129,6 +130,7 @@ struct Lab { Lab sRGBToLab(SkColor color); SkColor LabToSRGB(const Lab& lab, SkAlpha alpha); skcms_TransferFunction GetPQSkTransferFunction(float sdr_white_level = 0.f); +skcms_TransferFunction GetExtendedTransferFunction(float sdrHdrRatio); std::optional<skcms_TransferFunction> GetHLGScaleTransferFunction(); } /* namespace uirenderer */ |