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

Commit bb2d0cc7 authored by John Reck's avatar John Reck
Browse files

Surface:lockHardwareCanvas

Bug: 17440886

Change-Id: I1f2d98c63ec1a2814c2258cf7e0096139263770a
parent ea6f0ae8
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -33369,6 +33369,7 @@ package android.view {
    method public int describeContents();
    method public boolean isValid();
    method public android.graphics.Canvas lockCanvas(android.graphics.Rect) throws java.lang.IllegalArgumentException, android.view.Surface.OutOfResourcesException;
    method public android.graphics.Canvas lockHardwareCanvas();
    method public void readFromParcel(android.os.Parcel);
    method public void release();
    method public deprecated void unlockCanvas(android.graphics.Canvas);
+110 −13
Original line number Diff line number Diff line
@@ -87,6 +87,8 @@ public class Surface implements Parcelable {
    // non compatibility mode.
    private Matrix mCompatibleMatrix;

    private HwuiContext mHwuiContext;

    /** @hide */
    @IntDef({ROTATION_0, ROTATION_90, ROTATION_180, ROTATION_270})
    @Retention(RetentionPolicy.SOURCE)
@@ -171,6 +173,10 @@ public class Surface implements Parcelable {
                nativeRelease(mNativeObject);
                setNativeObjectLocked(0);
            }
            if (mHwuiContext != null) {
                mHwuiContext.destroy();
                mHwuiContext = null;
            }
        }
    }

@@ -264,13 +270,22 @@ public class Surface implements Parcelable {
     * @param canvas The canvas previously obtained from {@link #lockCanvas}.
     */
    public void unlockCanvasAndPost(Canvas canvas) {
        synchronized (mLock) {
            checkNotReleasedLocked();

            if (mHwuiContext != null) {
                mHwuiContext.unlockAndPost(canvas);
            } else {
                unlockSwCanvasAndPost(canvas);
            }
        }
    }

    private void unlockSwCanvasAndPost(Canvas canvas) {
        if (canvas != mCanvas) {
            throw new IllegalArgumentException("canvas object must be the same instance that "
                    + "was previously returned by lockCanvas");
        }

        synchronized (mLock) {
            checkNotReleasedLocked();
        if (mNativeObject != mLockedObject) {
            Log.w(TAG, "WARNING: Surface's mNativeObject (0x" +
                    Long.toHexString(mNativeObject) + ") != mLockedObject (0x" +
@@ -286,6 +301,30 @@ public class Surface implements Parcelable {
            mLockedObject = 0;
        }
    }

    /**
     * Gets a {@link Canvas} for drawing into this surface.
     *
     * 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)} this will return a hardware-accelerated
     * canvas. 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.
     *
     * @return A canvas for drawing into the surface.
     *
     * @throws IllegalStateException If the canvas cannot be locked.
     */
    public Canvas lockHardwareCanvas() {
        synchronized (mLock) {
            checkNotReleasedLocked();
            if (mHwuiContext == null) {
                mHwuiContext = new HwuiContext();
            }
            return mHwuiContext.lockCanvas();
        }
    }

    /**
@@ -415,6 +454,9 @@ public class Surface implements Parcelable {
            }
            mNativeObject = ptr;
            mGenerationId += 1;
            if (mHwuiContext != null) {
                mHwuiContext.updateSurface();
            }
        }
    }

@@ -518,4 +560,59 @@ public class Surface implements Parcelable {
            mOrigMatrix.set(m);
        }
    }

    private final class HwuiContext {
        private final RenderNode mRenderNode;
        private long mHwuiRenderer;
        private HardwareCanvas mCanvas;

        HwuiContext() {
            mRenderNode = RenderNode.create("HwuiCanvas", null);
            mRenderNode.setClipToBounds(false);
            mHwuiRenderer = nHwuiCreate(mRenderNode.mNativeRenderNode, mNativeObject);
        }

        Canvas lockCanvas() {
            if (mCanvas != null) {
                throw new IllegalStateException("Surface was already locked!");
            }
            mCanvas = mRenderNode.start(0, 0);
            return mCanvas;
        }

        void unlockAndPost(Canvas canvas) {
            if (canvas != mCanvas) {
                throw new IllegalArgumentException("canvas object must be the same instance that "
                        + "was previously returned by lockCanvas");
            }
            mRenderNode.end(mCanvas);
            mCanvas = null;
            nHwuiDraw(mHwuiRenderer);
        }

        void updateSurface() {
            nHwuiSetSurface(mHwuiRenderer, mNativeObject);
        }

        void destroy() {
            if (mHwuiRenderer != 0) {
                nHwuiDestroy(mHwuiRenderer);
                mHwuiRenderer = 0;
            }
        }

        @Override
        protected void finalize() throws Throwable {
            try {
                destroy();
            } finally {
                super.finalize();
            }
        }
    }

    private static native long nHwuiCreate(long rootNode, long surface);
    private static native void nHwuiSetSurface(long renderer, long surface);
    private static native void nHwuiDraw(long renderer);
    private static native void nHwuiDestroy(long renderer);
}
+56 −0
Original line number Diff line number Diff line
@@ -47,6 +47,11 @@

#include <ScopedUtfChars.h>

#include <AnimationContext.h>
#include <DisplayListRenderer.h>
#include <RenderNode.h>
#include <renderthread/RenderProxy.h>

// ----------------------------------------------------------------------------

namespace android {
@@ -352,8 +357,53 @@ static void nativeWriteToParcel(JNIEnv* env, jclass clazz,
    parcel->writeStrongBinder( self != 0 ? self->getIGraphicBufferProducer()->asBinder() : NULL);
}

namespace uirenderer {

using namespace android::uirenderer::renderthread;

class ContextFactory : public IContextFactory {
public:
    virtual AnimationContext* createAnimationContext(renderthread::TimeLord& clock) {
        return new AnimationContext(clock);
    }
};

static jlong create(JNIEnv* env, jclass clazz, jlong rootNodePtr, jlong surfacePtr) {
    RenderNode* rootNode = reinterpret_cast<RenderNode*>(rootNodePtr);
    sp<Surface> surface(reinterpret_cast<Surface*>(surfacePtr));
    ContextFactory factory;
    RenderProxy* proxy = new RenderProxy(false, rootNode, &factory);
    proxy->loadSystemProperties();
    proxy->initialize(surface);
    // Shadows can't be used via this interface, so just set the light source
    // to all 0s. (and width & height are unused, TODO remove them)
    proxy->setup(0, 0, (Vector3){0, 0, 0}, 0, 0, 0);
    return (jlong) proxy;
}

static void setSurface(JNIEnv* env, jclass clazz, jlong rendererPtr, jlong surfacePtr) {
    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(rendererPtr);
    sp<Surface> surface(reinterpret_cast<Surface*>(surfacePtr));
    proxy->updateSurface(surface);
}

static void draw(JNIEnv* env, jclass clazz, jlong rendererPtr) {
    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(rendererPtr);
    nsecs_t frameTimeNs = systemTime(CLOCK_MONOTONIC);
    proxy->syncAndDrawFrame(frameTimeNs, 0, 1.0f);
}

static void destroy(JNIEnv* env, jclass clazz, jlong rendererPtr) {
    RenderProxy* proxy = reinterpret_cast<RenderProxy*>(rendererPtr);
    delete proxy;
}

} // uirenderer

// ----------------------------------------------------------------------------

namespace hwui = android::uirenderer;

static JNINativeMethod gSurfaceMethods[] = {
    {"nativeCreateFromSurfaceTexture", "(Landroid/graphics/SurfaceTexture;)J",
            (void*)nativeCreateFromSurfaceTexture },
@@ -375,6 +425,12 @@ static JNINativeMethod gSurfaceMethods[] = {
            (void*)nativeReadFromParcel },
    {"nativeWriteToParcel", "(JLandroid/os/Parcel;)V",
            (void*)nativeWriteToParcel },

    // HWUI context
    {"nHwuiCreate", "(JJ)J", (void*) hwui::create },
    {"nHwuiSetSurface", "(JJ)V", (void*) hwui::setSurface },
    {"nHwuiDraw", "(J)V", (void*) hwui::draw },
    {"nHwuiDestroy", "(J)V", (void*) hwui::destroy },
};

int register_android_view_Surface(JNIEnv* env)
+1 −1
Original line number Diff line number Diff line
@@ -20,7 +20,7 @@ namespace uirenderer {
namespace renderthread {

TimeLord::TimeLord()
        : mFrameIntervalNanos(0)
        : mFrameIntervalNanos(milliseconds_to_nanoseconds(16))
        , mFrameTimeNanos(0) {
}

+2 −2
Original line number Diff line number Diff line
@@ -81,8 +81,8 @@ int main(int argc, char* argv[]) {
    rootNode->mutateStagingProperties().setClipToBounds(false);
    rootNode->setPropertyFieldsDirty(RenderNode::GENERIC);

    RenderProxy* proxy = new RenderProxy(false, rootNode, new ContextFactory());
    proxy->setFrameInterval(milliseconds_to_nanoseconds(16));
    ContextFactory factory;
    RenderProxy* proxy = new RenderProxy(false, rootNode, &factory);
    proxy->loadSystemProperties();
    proxy->initialize(surface);
    float lightX = width / 2.0;
Loading