Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d8b68717 authored by Peiyong Lin's avatar Peiyong Lin
Browse files

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
parent 0aa191cc
Loading
Loading
Loading
Loading
+48 −4
Original line number Diff line number Diff line
@@ -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);
+6 −2
Original line number Diff line number Diff line
@@ -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 },