From d8b68717400487a3dd20d1cc7c11f6e1ee6d3fd9 Mon Sep 17 00:00:00 2001 From: Peiyong Lin Date: Tue, 6 Mar 2018 18:34:21 -0800 Subject: [PATCH] Add lockHardwareWideColorGamutCanvas. This patch adds a hidden API to return a hardware canvas with wide color gamut support. The hardware canvas returned from BaseSurfaceHolder.lockHardwareCanvas doesn't support wide color gamut, this patch makes sure that a wide color gamut canvas context is created when calling lockHardwareCanvas. Verified this approach works by building ImageWallpaper to use this API. Without this API an 8 bit logo P3 doesn't show the logo, with this API the logo is shown correctly. See b/74116826 for more info. BUG: 74116826 Test: Build ImageWallpaper using this API with an 8 bit P3 image Change-Id: Id20343fabcd7f0873d79ce72a235ea9b7c1f3e77 --- core/java/android/view/Surface.java | 52 ++++++++++++++++++++++++++--- core/jni/android_view_Surface.cpp | 8 +++-- 2 files changed, 54 insertions(+), 6 deletions(-) diff --git a/core/java/android/view/Surface.java b/core/java/android/view/Surface.java index 8830c90addacd..d3b1e5c52596a 100644 --- a/core/java/android/view/Surface.java +++ b/core/java/android/view/Surface.java @@ -396,7 +396,44 @@ public class Surface implements Parcelable { synchronized (mLock) { checkNotReleasedLocked(); if (mHwuiContext == null) { - mHwuiContext = new HwuiContext(); + mHwuiContext = new HwuiContext(false); + } + return mHwuiContext.lockCanvas( + nativeGetWidth(mNativeObject), + nativeGetHeight(mNativeObject)); + } + } + + /** + * Gets a {@link Canvas} for drawing into this surface that supports wide color gamut. + * + * After drawing into the provided {@link Canvas}, the caller must + * invoke {@link #unlockCanvasAndPost} to post the new contents to the surface. + * + * Unlike {@link #lockCanvas(Rect)} and {@link #lockHardwareCanvas()}, + * this will return a hardware-accelerated canvas that supports wide color gamut. + * See the + * unsupported drawing operations for a list of what is and isn't + * supported in a hardware-accelerated canvas. It is also required to + * fully cover the surface every time {@link #lockHardwareCanvas()} is + * called as the buffer is not preserved between frames. Partial updates + * are not supported. + * + * @return A canvas for drawing into the surface. + * + * @throws IllegalStateException If the canvas cannot be locked. + * + * @hide + */ + public Canvas lockHardwareWideColorGamutCanvas() { + synchronized (mLock) { + checkNotReleasedLocked(); + if (mHwuiContext != null && !mHwuiContext.isWideColorGamut()) { + mHwuiContext.destroy(); + mHwuiContext = null; + } + if (mHwuiContext == null) { + mHwuiContext = new HwuiContext(true); } return mHwuiContext.lockCanvas( nativeGetWidth(mNativeObject), @@ -829,11 +866,14 @@ public class Surface implements Parcelable { private final RenderNode mRenderNode; private long mHwuiRenderer; private DisplayListCanvas mCanvas; + private final boolean mIsWideColorGamut; - HwuiContext() { + HwuiContext(boolean isWideColorGamut) { mRenderNode = RenderNode.create("HwuiCanvas", null); mRenderNode.setClipToBounds(false); - mHwuiRenderer = nHwuiCreate(mRenderNode.mNativeRenderNode, mNativeObject); + mIsWideColorGamut = isWideColorGamut; + mHwuiRenderer = nHwuiCreate(mRenderNode.mNativeRenderNode, mNativeObject, + isWideColorGamut); } Canvas lockCanvas(int width, int height) { @@ -864,9 +904,13 @@ public class Surface implements Parcelable { mHwuiRenderer = 0; } } + + boolean isWideColorGamut() { + return mIsWideColorGamut; + } } - private static native long nHwuiCreate(long rootNode, long surface); + private static native long nHwuiCreate(long rootNode, long surface, boolean isWideColorGamut); private static native void nHwuiSetSurface(long renderer, long surface); private static native void nHwuiDraw(long renderer); private static native void nHwuiDestroy(long renderer); diff --git a/core/jni/android_view_Surface.cpp b/core/jni/android_view_Surface.cpp index f5c09fd316de9..f70cf07b9535f 100644 --- a/core/jni/android_view_Surface.cpp +++ b/core/jni/android_view_Surface.cpp @@ -546,12 +546,16 @@ public: } }; -static jlong create(JNIEnv* env, jclass clazz, jlong rootNodePtr, jlong surfacePtr) { +static jlong create(JNIEnv* env, jclass clazz, jlong rootNodePtr, jlong surfacePtr, + jboolean isWideColorGamut) { RenderNode* rootNode = reinterpret_cast(rootNodePtr); sp surface(reinterpret_cast(surfacePtr)); ContextFactory factory; RenderProxy* proxy = new RenderProxy(false, rootNode, &factory); proxy->loadSystemProperties(); + if (isWideColorGamut) { + proxy->setWideGamut(true); + } proxy->setSwapBehavior(SwapBehavior::kSwap_discardBuffer); proxy->initialize(surface); // Shadows can't be used via this interface, so just set the light source @@ -620,7 +624,7 @@ static const JNINativeMethod gSurfaceMethods[] = { {"nativeSetAutoRefreshEnabled", "(JZ)I", (void*)nativeSetAutoRefreshEnabled}, // HWUI context - {"nHwuiCreate", "(JJ)J", (void*) hwui::create }, + {"nHwuiCreate", "(JJZ)J", (void*) hwui::create }, {"nHwuiSetSurface", "(JJ)V", (void*) hwui::setSurface }, {"nHwuiDraw", "(J)V", (void*) hwui::draw }, {"nHwuiDestroy", "(J)V", (void*) hwui::destroy },