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
This commit is contained in:
Peiyong Lin
2018-03-06 18:34:21 -08:00
parent 0aa191ccbf
commit d8b6871740
2 changed files with 54 additions and 6 deletions

View File

@@ -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 <a href="{@docRoot}guide/topics/graphics/hardware-accel.html#unsupported">
* unsupported drawing operations</a> 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);

View File

@@ -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<RenderNode*>(rootNodePtr);
sp<Surface> surface(reinterpret_cast<Surface*>(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 },