Loading api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -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); core/java/android/view/Surface.java +110 −13 Original line number Diff line number Diff line Loading @@ -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) Loading Loading @@ -171,6 +173,10 @@ public class Surface implements Parcelable { nativeRelease(mNativeObject); setNativeObjectLocked(0); } if (mHwuiContext != null) { mHwuiContext.destroy(); mHwuiContext = null; } } } Loading Loading @@ -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" + Loading @@ -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(); } } /** Loading Loading @@ -415,6 +454,9 @@ public class Surface implements Parcelable { } mNativeObject = ptr; mGenerationId += 1; if (mHwuiContext != null) { mHwuiContext.updateSurface(); } } } Loading Loading @@ -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); } core/jni/android_view_Surface.cpp +56 −0 Original line number Diff line number Diff line Loading @@ -47,6 +47,11 @@ #include <ScopedUtfChars.h> #include <AnimationContext.h> #include <DisplayListRenderer.h> #include <RenderNode.h> #include <renderthread/RenderProxy.h> // ---------------------------------------------------------------------------- namespace android { Loading Loading @@ -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 }, Loading @@ -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) Loading libs/hwui/renderthread/TimeLord.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -20,7 +20,7 @@ namespace uirenderer { namespace renderthread { TimeLord::TimeLord() : mFrameIntervalNanos(0) : mFrameIntervalNanos(milliseconds_to_nanoseconds(16)) , mFrameTimeNanos(0) { } Loading libs/hwui/tests/main.cpp +2 −2 Original line number Diff line number Diff line Loading @@ -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 Loading
api/current.txt +1 −0 Original line number Diff line number Diff line Loading @@ -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);
core/java/android/view/Surface.java +110 −13 Original line number Diff line number Diff line Loading @@ -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) Loading Loading @@ -171,6 +173,10 @@ public class Surface implements Parcelable { nativeRelease(mNativeObject); setNativeObjectLocked(0); } if (mHwuiContext != null) { mHwuiContext.destroy(); mHwuiContext = null; } } } Loading Loading @@ -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" + Loading @@ -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(); } } /** Loading Loading @@ -415,6 +454,9 @@ public class Surface implements Parcelable { } mNativeObject = ptr; mGenerationId += 1; if (mHwuiContext != null) { mHwuiContext.updateSurface(); } } } Loading Loading @@ -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); }
core/jni/android_view_Surface.cpp +56 −0 Original line number Diff line number Diff line Loading @@ -47,6 +47,11 @@ #include <ScopedUtfChars.h> #include <AnimationContext.h> #include <DisplayListRenderer.h> #include <RenderNode.h> #include <renderthread/RenderProxy.h> // ---------------------------------------------------------------------------- namespace android { Loading Loading @@ -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 }, Loading @@ -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) Loading
libs/hwui/renderthread/TimeLord.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -20,7 +20,7 @@ namespace uirenderer { namespace renderthread { TimeLord::TimeLord() : mFrameIntervalNanos(0) : mFrameIntervalNanos(milliseconds_to_nanoseconds(16)) , mFrameTimeNanos(0) { } Loading
libs/hwui/tests/main.cpp +2 −2 Original line number Diff line number Diff line Loading @@ -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