From d70dbc7482eb78fb8ea9af1d49c4970c495f422c Mon Sep 17 00:00:00 2001 From: William Candillon Date: Sun, 7 Jan 2024 20:31:38 +0100 Subject: [PATCH 1/6] :wrench: --- .../RNSkOpenGLCanvasProvider.cpp | 1 - .../rnskia-android/SkiaOpenGLSurfaceFactory.h | 37 +------- .../reactnative/skia/SkiaBaseView.java | 86 ++++++------------- 3 files changed, 29 insertions(+), 95 deletions(-) diff --git a/package/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp b/package/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp index e3d92aa3ea..c5e7ae9cd0 100644 --- a/package/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp +++ b/package/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp @@ -39,7 +39,6 @@ bool RNSkOpenGLCanvasProvider::renderToCanvas( if (!_surfaceHolder->makeCurrent()) { return false; } - _surfaceHolder->updateTexImage(); // Draw into canvas using callback cb(surface->getCanvas()); diff --git a/package/android/cpp/rnskia-android/SkiaOpenGLSurfaceFactory.h b/package/android/cpp/rnskia-android/SkiaOpenGLSurfaceFactory.h index b9c12fc893..4c48f4a01a 100644 --- a/package/android/cpp/rnskia-android/SkiaOpenGLSurfaceFactory.h +++ b/package/android/cpp/rnskia-android/SkiaOpenGLSurfaceFactory.h @@ -44,32 +44,13 @@ class ThreadContextHolder { */ class WindowSurfaceHolder { public: - WindowSurfaceHolder(jobject jSurfaceTexture, int width, int height) + WindowSurfaceHolder(jobject jSurface, int width, int height) : _width(width), _height(height) { JNIEnv *env = facebook::jni::Environment::current(); - _jSurfaceTexture = env->NewGlobalRef(jSurfaceTexture); - jclass surfaceClass = env->FindClass("android/view/Surface"); - jmethodID surfaceConstructor = env->GetMethodID( - surfaceClass, "", "(Landroid/graphics/SurfaceTexture;)V"); - // Create a new Surface instance - jobject jSurface = - env->NewObject(surfaceClass, surfaceConstructor, jSurfaceTexture); - - jclass surfaceTextureClass = env->GetObjectClass(_jSurfaceTexture); - _updateTexImageMethod = - env->GetMethodID(surfaceTextureClass, "updateTexImage", "()V"); - - // Acquire the native window from the Surface _window = ANativeWindow_fromSurface(env, jSurface); - // Clean up local references - env->DeleteLocalRef(jSurface); - env->DeleteLocalRef(surfaceClass); - env->DeleteLocalRef(surfaceTextureClass); } ~WindowSurfaceHolder() { - JNIEnv *env = facebook::jni::Environment::current(); - env->DeleteGlobalRef(_jSurfaceTexture); ANativeWindow_release(_window); } @@ -81,20 +62,6 @@ class WindowSurfaceHolder { */ sk_sp getSurface(); - void updateTexImage() { - JNIEnv *env = facebook::jni::Environment::current(); - - // Call updateTexImage on the SurfaceTexture object - env->CallVoidMethod(_jSurfaceTexture, _updateTexImageMethod); - - // Check for exceptions - if (env->ExceptionCheck()) { - RNSkLogger::logToConsole("updateAndRelease() failed. The exception above " - "can safely be ignored"); - env->ExceptionClear(); - } - } - /** * Resizes the surface * @param width @@ -132,9 +99,7 @@ class WindowSurfaceHolder { private: ANativeWindow *_window; sk_sp _skSurface = nullptr; - jobject _jSurfaceTexture = nullptr; EGLSurface _glSurface = EGL_NO_SURFACE; - jmethodID _updateTexImageMethod = nullptr; int _width = 0; int _height = 0; }; diff --git a/package/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java b/package/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java index 0aeedd4442..c10c124c61 100644 --- a/package/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java +++ b/package/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java @@ -1,24 +1,24 @@ package com.shopify.reactnative.skia; import android.content.Context; -import android.graphics.SurfaceTexture; +import android.view.SurfaceHolder; +import android.view.SurfaceView; import android.util.Log; import android.view.MotionEvent; -import android.view.TextureView; import com.facebook.react.views.view.ReactViewGroup; -public abstract class SkiaBaseView extends ReactViewGroup implements TextureView.SurfaceTextureListener { - private TextureView mTexture; +public abstract class SkiaBaseView extends ReactViewGroup implements SurfaceHolder.Callback { + private SurfaceView mSurfaceView; private String tag = "SkiaView"; public SkiaBaseView(Context context) { super(context); - mTexture = new TextureView(context); - mTexture.setSurfaceTextureListener(this); - mTexture.setOpaque(false); - addView(mTexture); + mSurfaceView = new SurfaceView(context); + mSurfaceView.getHolder().addCallback(this); + mSurfaceView.setZOrderOnTop(true); // Necessary to make the surface view transparent + addView(mSurfaceView); } public void destroySurface() { @@ -26,29 +26,33 @@ public void destroySurface() { surfaceDestroyed(); } - private void createSurfaceTexture() { - // This API Level is >= 26, we created our own SurfaceTexture to have a faster time to first frame - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) { - Log.i(tag, "Create SurfaceTexture"); - SurfaceTexture surface = new SurfaceTexture(false); - mTexture.setSurfaceTexture(surface); - this.onSurfaceTextureAvailable(surface, this.getMeasuredWidth(), this.getMeasuredHeight()); - } + @Override + protected void onLayout(boolean changed, int left, int top, int right, int bottom) { + Log.i(tag, "onLayout " + this.getMeasuredWidth() + "/" + this.getMeasuredHeight()); + super.onLayout(changed, left, top, right, bottom); + mSurfaceView.layout(0, 0, this.getMeasuredWidth(), this.getMeasuredHeight()); } @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); - if (this.getMeasuredWidth() == 0) { - createSurfaceTexture(); + public void surfaceCreated(SurfaceHolder holder) { + Log.i(tag, "surfaceCreated"); + if (holder.getSurface() == null) { + Log.i(tag, "getSurface()"); } + surfaceAvailable(holder.getSurface(), this.getMeasuredWidth(), this.getMeasuredHeight()); } @Override - protected void onLayout(boolean changed, int left, int top, int right, int bottom) { - Log.i(tag, "onLayout " + this.getMeasuredWidth() + "/" + this.getMeasuredHeight()); - super.onLayout(changed, left, top, right, bottom); - mTexture.layout(0, 0, this.getMeasuredWidth(), this.getMeasuredHeight()); + public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { + Log.i(tag, "surfaceChanged " + width + "/" + height); + surfaceSizeChanged(width, height); + } + + @Override + public void surfaceDestroyed(SurfaceHolder holder) { + Log.i(tag, "surfaceDestroyed"); + destroySurface(); + // Additional clean-up as necessary } @Override @@ -121,40 +125,6 @@ private static int motionActionToType(int action) { return actionType; } - @Override - public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { - Log.i(tag, "onSurfaceTextureAvailable " + width + "/" + height); - surfaceAvailable(surface, width, height); - } - - @Override - public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { - Log.i(tag, "onSurfaceTextureSizeChanged " + width + "/" + height); - surfaceSizeChanged(width, height); - } - - @Override - public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { - Log.i(tag, "onSurfaceTextureDestroyed"); - // https://developer.android.com/reference/android/view/TextureView.SurfaceTextureListener#onSurfaceTextureDestroyed(android.graphics.SurfaceTexture) - destroySurface(); - // Because of React Native Screens (which dettach the view), we always keep the surface alive. - // If not, Texture view will recreate the texture surface by itself and - // we will lose the fast first time to frame. - // We only delete the surface when the view is dropped (destroySurface invoked by SkiaBaseViewManager); - createSurfaceTexture(); - return false; - } - - //private long _prevTimestamp = 0; - @Override - public void onSurfaceTextureUpdated(SurfaceTexture surface) { -// long timestamp = surface.getTimestamp(); -// long frameDuration = (timestamp - _prevTimestamp)/1000000; -// Log.i(tag, "onSurfaceTextureUpdated "+frameDuration+"ms"); -// _prevTimestamp = timestamp; - } - protected abstract void surfaceAvailable(Object surface, int width, int height); protected abstract void surfaceSizeChanged(int width, int height); From 4e48868bf0bc85278af6f11032dd25bde498d0d0 Mon Sep 17 00:00:00 2001 From: William Candillon Date: Sun, 7 Jan 2024 20:40:39 +0100 Subject: [PATCH 2/6] :wrench: --- example/src/Examples/Stickers/Stickers.tsx | 2 ++ .../com/shopify/reactnative/skia/SkiaBaseView.java | 14 +++++++++++++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/example/src/Examples/Stickers/Stickers.tsx b/example/src/Examples/Stickers/Stickers.tsx index 6c590c0a54..dc1c2bc18a 100644 --- a/example/src/Examples/Stickers/Stickers.tsx +++ b/example/src/Examples/Stickers/Stickers.tsx @@ -33,10 +33,12 @@ export const Stickers = () => { ); diff --git a/package/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java b/package/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java index c10c124c61..b0d511308c 100644 --- a/package/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java +++ b/package/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java @@ -1,10 +1,12 @@ package com.shopify.reactnative.skia; import android.content.Context; +import android.graphics.PixelFormat; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.util.Log; import android.view.MotionEvent; +import android.view.ViewGroup; import com.facebook.react.views.view.ReactViewGroup; @@ -17,7 +19,16 @@ public SkiaBaseView(Context context) { super(context); mSurfaceView = new SurfaceView(context); mSurfaceView.getHolder().addCallback(this); - mSurfaceView.setZOrderOnTop(true); // Necessary to make the surface view transparent + + // Set the surface view to be transparent + mSurfaceView.setZOrderOnTop(true); + mSurfaceView.getHolder().setFormat(PixelFormat.TRANSPARENT); + + // Adjust the layout parameters to ensure proper layering + LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); + mSurfaceView.setLayoutParams(params); + + // Add the surface view to the ReactViewGroup addView(mSurfaceView); } @@ -30,6 +41,7 @@ public void destroySurface() { protected void onLayout(boolean changed, int left, int top, int right, int bottom) { Log.i(tag, "onLayout " + this.getMeasuredWidth() + "/" + this.getMeasuredHeight()); super.onLayout(changed, left, top, right, bottom); + // Ensure that the surface view fills the entire ReactViewGroup mSurfaceView.layout(0, 0, this.getMeasuredWidth(), this.getMeasuredHeight()); } From 112a49d55c348ed0854337a95cd1a0b307246c81 Mon Sep 17 00:00:00 2001 From: William Candillon Date: Mon, 8 Jan 2024 12:17:13 +0100 Subject: [PATCH 3/6] :wrench: --- .../reactnative/skia/SkiaBaseView.java | 84 +++++++++++-------- 1 file changed, 47 insertions(+), 37 deletions(-) diff --git a/package/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java b/package/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java index b0d511308c..b89a2904e9 100644 --- a/package/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java +++ b/package/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java @@ -1,35 +1,47 @@ package com.shopify.reactnative.skia; +import android.annotation.SuppressLint; import android.content.Context; +import android.graphics.Bitmap; +import android.graphics.Canvas; +import android.graphics.Matrix; +import android.graphics.Paint; import android.graphics.PixelFormat; -import android.view.SurfaceHolder; -import android.view.SurfaceView; +import android.media.Image; +import android.media.ImageReader; +import android.os.Build; import android.util.Log; import android.view.MotionEvent; import android.view.ViewGroup; +import android.hardware.HardwareBuffer; -import com.facebook.react.views.view.ReactViewGroup; +import androidx.annotation.RequiresApi; -public abstract class SkiaBaseView extends ReactViewGroup implements SurfaceHolder.Callback { - private SurfaceView mSurfaceView; +import com.facebook.react.views.view.ReactViewGroup; +@RequiresApi(api = Build.VERSION_CODES.Q) +public abstract class SkiaBaseView extends ReactViewGroup { + private ImageReader mImageReader = null; + private Bitmap mBitmap = null; private String tag = "SkiaView"; + @SuppressLint("WrongConstant") public SkiaBaseView(Context context) { super(context); - mSurfaceView = new SurfaceView(context); - mSurfaceView.getHolder().addCallback(this); - // Set the surface view to be transparent - mSurfaceView.setZOrderOnTop(true); - mSurfaceView.getHolder().setFormat(PixelFormat.TRANSPARENT); - - // Adjust the layout parameters to ensure proper layering + // Adjust layout parameters LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); - mSurfaceView.setLayoutParams(params); + setLayoutParams(params); + setWillNotDraw(false); + } - // Add the surface view to the ReactViewGroup - addView(mSurfaceView); + @Override + protected void onDraw(Canvas canvas) { + super.onDraw(canvas); + if (mBitmap != null) { + Log.i(tag, "drawBitmap"); + canvas.drawBitmap(mBitmap, new Matrix(), new Paint()); + } } public void destroySurface() { @@ -37,35 +49,33 @@ public void destroySurface() { surfaceDestroyed(); } + @SuppressLint("WrongConstant") @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { Log.i(tag, "onLayout " + this.getMeasuredWidth() + "/" + this.getMeasuredHeight()); super.onLayout(changed, left, top, right, bottom); - // Ensure that the surface view fills the entire ReactViewGroup - mSurfaceView.layout(0, 0, this.getMeasuredWidth(), this.getMeasuredHeight()); - } - - @Override - public void surfaceCreated(SurfaceHolder holder) { - Log.i(tag, "surfaceCreated"); - if (holder.getSurface() == null) { - Log.i(tag, "getSurface()"); + if (mImageReader != null) { + mImageReader.close(); } - surfaceAvailable(holder.getSurface(), this.getMeasuredWidth(), this.getMeasuredHeight()); - } - - @Override - public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { - Log.i(tag, "surfaceChanged " + width + "/" + height); - surfaceSizeChanged(width, height); + long usage = HardwareBuffer.USAGE_CPU_READ_RARELY | + HardwareBuffer.USAGE_CPU_WRITE_RARELY | + HardwareBuffer.USAGE_GPU_COLOR_OUTPUT | + HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE; + mImageReader = ImageReader.newInstance(getMeasuredWidth(), getMeasuredHeight(), PixelFormat.RGBA_8888, 2, usage); + mImageReader.setOnImageAvailableListener(reader -> { + try (Image image = reader.acquireLatestImage()) { + if (image != null) { + HardwareBuffer hb = image.getHardwareBuffer(); + mBitmap = Bitmap.wrapHardwareBuffer(hb, null); + hb.close(); + invalidate(); + } + } + }, null); + surfaceAvailable(mImageReader.getSurface(), getMeasuredWidth(), getMeasuredHeight()); + // } } - @Override - public void surfaceDestroyed(SurfaceHolder holder) { - Log.i(tag, "surfaceDestroyed"); - destroySurface(); - // Additional clean-up as necessary - } @Override public boolean onTouchEvent(MotionEvent ev) { From c32e56ce90db01a39879713aa9382858a29e63cc Mon Sep 17 00:00:00 2001 From: William Candillon Date: Mon, 8 Jan 2024 22:48:47 +0100 Subject: [PATCH 4/6] :wrench: --- .../reactnative/skia/PlatformContext.java | 26 ++++----- .../reactnative/skia/SkiaBaseView.java | 56 ++++++++++++------- 2 files changed, 48 insertions(+), 34 deletions(-) diff --git a/package/android/src/main/java/com/shopify/reactnative/skia/PlatformContext.java b/package/android/src/main/java/com/shopify/reactnative/skia/PlatformContext.java index 6d62047a21..9e6d5d2432 100644 --- a/package/android/src/main/java/com/shopify/reactnative/skia/PlatformContext.java +++ b/package/android/src/main/java/com/shopify/reactnative/skia/PlatformContext.java @@ -49,19 +49,19 @@ private byte[] getStreamAsBytes(InputStream is) throws IOException { } private void postFrameLoop() { - Choreographer.FrameCallback frameCallback = new Choreographer.FrameCallback() { - @Override - public void doFrame(long frameTimeNanos) { - if (_drawLoopActive) { - Choreographer.getInstance().postFrameCallback(this); - } - if (_isPaused) { - return; - } - notifyDrawLoop(); - } - }; - Choreographer.getInstance().postFrameCallback(frameCallback); +// Choreographer.FrameCallback frameCallback = new Choreographer.FrameCallback() { +// @Override +// public void doFrame(long frameTimeNanos) { +// if (_drawLoopActive) { +// Choreographer.getInstance().postFrameCallback(this); +// } +// if (_isPaused) { +// return; +// } +// notifyDrawLoop(); +// } +// }; +// Choreographer.getInstance().postFrameCallback(frameCallback); } diff --git a/package/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java b/package/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java index b89a2904e9..d281011316 100644 --- a/package/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java +++ b/package/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java @@ -11,6 +11,7 @@ import android.media.ImageReader; import android.os.Build; import android.util.Log; +import android.view.Choreographer; import android.view.MotionEvent; import android.view.ViewGroup; import android.hardware.HardwareBuffer; @@ -20,15 +21,15 @@ import com.facebook.react.views.view.ReactViewGroup; @RequiresApi(api = Build.VERSION_CODES.Q) -public abstract class SkiaBaseView extends ReactViewGroup { +public abstract class SkiaBaseView extends ReactViewGroup implements Choreographer.FrameCallback { private ImageReader mImageReader = null; private Bitmap mBitmap = null; private String tag = "SkiaView"; + private Choreographer choreographer; @SuppressLint("WrongConstant") public SkiaBaseView(Context context) { super(context); - // Adjust layout parameters LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); setLayoutParams(params); @@ -39,7 +40,6 @@ public SkiaBaseView(Context context) { protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (mBitmap != null) { - Log.i(tag, "drawBitmap"); canvas.drawBitmap(mBitmap, new Matrix(), new Paint()); } } @@ -55,27 +55,41 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto Log.i(tag, "onLayout " + this.getMeasuredWidth() + "/" + this.getMeasuredHeight()); super.onLayout(changed, left, top, right, bottom); if (mImageReader != null) { - mImageReader.close(); - } - long usage = HardwareBuffer.USAGE_CPU_READ_RARELY | - HardwareBuffer.USAGE_CPU_WRITE_RARELY | - HardwareBuffer.USAGE_GPU_COLOR_OUTPUT | - HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE; - mImageReader = ImageReader.newInstance(getMeasuredWidth(), getMeasuredHeight(), PixelFormat.RGBA_8888, 2, usage); - mImageReader.setOnImageAvailableListener(reader -> { - try (Image image = reader.acquireLatestImage()) { - if (image != null) { - HardwareBuffer hb = image.getHardwareBuffer(); - mBitmap = Bitmap.wrapHardwareBuffer(hb, null); - hb.close(); - invalidate(); + // mImageReader.close(); + // surfaceSizeChanged(getMeasuredWidth(), getMeasuredHeight()); + } else { + long usage = HardwareBuffer.USAGE_CPU_READ_RARELY | + HardwareBuffer.USAGE_CPU_WRITE_RARELY | + HardwareBuffer.USAGE_GPU_COLOR_OUTPUT | + HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE; + mImageReader = ImageReader.newInstance(getMeasuredWidth(), getMeasuredHeight(), PixelFormat.RGBA_8888, 2, usage); + mImageReader.setOnImageAvailableListener(reader -> { + try (Image image = reader.acquireLatestImage()) { + if (image != null) { + HardwareBuffer hb = image.getHardwareBuffer(); + mBitmap = Bitmap.wrapHardwareBuffer(hb, null); + hb.close(); + invalidate(); + } } - } - }, null); - surfaceAvailable(mImageReader.getSurface(), getMeasuredWidth(), getMeasuredHeight()); - // } + }, null); + surfaceAvailable(mImageReader.getSurface(), getMeasuredWidth(), getMeasuredHeight()); + choreographer = Choreographer.getInstance(); + choreographer.postFrameCallback(this); + } } + @Override + public void doFrame(long frameTimeNanos) { + Log.i(tag, "doFrame: " + frameTimeNanos); + choreographer.postFrameCallback(this); + if (mImageReader.getSurface() != null) { + long start = System.nanoTime(); + surfaceSizeChanged(getMeasuredWidth(), getMeasuredHeight()); + long end = System.nanoTime(); + Log.i(tag, "render time: " + (end - start) / 1000000 + "ms"); + } + } @Override public boolean onTouchEvent(MotionEvent ev) { From 3d74bb82529f0250067f51d558fa05c917ec78a7 Mon Sep 17 00:00:00 2001 From: William Candillon Date: Mon, 8 Jan 2024 23:04:27 +0100 Subject: [PATCH 5/6] :wrench: --- package/android/cpp/rnskia-android/RNSkAndroidView.h | 2 -- .../com/shopify/reactnative/skia/SkiaBaseView.java | 12 +++++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/package/android/cpp/rnskia-android/RNSkAndroidView.h b/package/android/cpp/rnskia-android/RNSkAndroidView.h index bfb41ccbc5..b9e7dbf67d 100644 --- a/package/android/cpp/rnskia-android/RNSkAndroidView.h +++ b/package/android/cpp/rnskia-android/RNSkAndroidView.h @@ -56,8 +56,6 @@ class RNSkAndroidView : public T, public RNSkBaseAndroidView { void surfaceSizeChanged(int width, int height) override { std::static_pointer_cast(T::getCanvasProvider()) ->surfaceSizeChanged(width, height); - // This is only need for the first time to frame, this renderImmediate call - // will invoke updateTexImage for the previous frame RNSkView::renderImmediate(); } diff --git a/package/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java b/package/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java index d281011316..f034204655 100644 --- a/package/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java +++ b/package/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java @@ -40,6 +40,8 @@ public SkiaBaseView(Context context) { protected void onDraw(Canvas canvas) { super.onDraw(canvas); if (mBitmap != null) { + end = System.nanoTime(); + Log.i(tag, "render time: " + (end - start) / 1000000 + "ms"); canvas.drawBitmap(mBitmap, new Matrix(), new Paint()); } } @@ -66,10 +68,10 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto mImageReader.setOnImageAvailableListener(reader -> { try (Image image = reader.acquireLatestImage()) { if (image != null) { + start = System.nanoTime(); HardwareBuffer hb = image.getHardwareBuffer(); mBitmap = Bitmap.wrapHardwareBuffer(hb, null); hb.close(); - invalidate(); } } }, null); @@ -79,15 +81,15 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto } } + long start; + long end; + @Override public void doFrame(long frameTimeNanos) { - Log.i(tag, "doFrame: " + frameTimeNanos); choreographer.postFrameCallback(this); if (mImageReader.getSurface() != null) { - long start = System.nanoTime(); surfaceSizeChanged(getMeasuredWidth(), getMeasuredHeight()); - long end = System.nanoTime(); - Log.i(tag, "render time: " + (end - start) / 1000000 + "ms"); + invalidate(); } } From 017ecae5bfe451935c32f504c24d424093898510 Mon Sep 17 00:00:00 2001 From: William Candillon Date: Tue, 9 Jan 2024 08:40:34 +0100 Subject: [PATCH 6/6] Fix rendering --- externals/depot_tools | 2 +- externals/skia | 2 +- .../reactnative/skia/SkiaBaseView.java | 28 ++++++++++--------- 3 files changed, 17 insertions(+), 15 deletions(-) diff --git a/externals/depot_tools b/externals/depot_tools index 911ccd864c..fd6e527668 160000 --- a/externals/depot_tools +++ b/externals/depot_tools @@ -1 +1 @@ -Subproject commit 911ccd864c77a8d9c91066858dfbd4517f9e83e2 +Subproject commit fd6e527668c2010f96a0a95e7e057994827def92 diff --git a/externals/skia b/externals/skia index 89907a0ce7..ab212df482 160000 --- a/externals/skia +++ b/externals/skia @@ -1 +1 @@ -Subproject commit 89907a0ce7c0c883898b8c88b55b7b7f733f7058 +Subproject commit ab212df482c8fd5b1c1fb302717876d542549624 diff --git a/package/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java b/package/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java index f034204655..4e4900c1ba 100644 --- a/package/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java +++ b/package/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java @@ -27,10 +27,12 @@ public abstract class SkiaBaseView extends ReactViewGroup implements Choreograph private String tag = "SkiaView"; private Choreographer choreographer; + private Paint paint = new Paint(); + private Matrix matrix = new Matrix(); + @SuppressLint("WrongConstant") public SkiaBaseView(Context context) { super(context); - // Adjust layout parameters LayoutParams params = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT); setLayoutParams(params); setWillNotDraw(false); @@ -42,7 +44,7 @@ protected void onDraw(Canvas canvas) { if (mBitmap != null) { end = System.nanoTime(); Log.i(tag, "render time: " + (end - start) / 1000000 + "ms"); - canvas.drawBitmap(mBitmap, new Matrix(), new Paint()); + canvas.drawBitmap(mBitmap, matrix, paint); } } @@ -56,6 +58,7 @@ public void destroySurface() { protected void onLayout(boolean changed, int left, int top, int right, int bottom) { Log.i(tag, "onLayout " + this.getMeasuredWidth() + "/" + this.getMeasuredHeight()); super.onLayout(changed, left, top, right, bottom); + // TODO: fix lifecycle there if (mImageReader != null) { // mImageReader.close(); // surfaceSizeChanged(getMeasuredWidth(), getMeasuredHeight()); @@ -65,16 +68,6 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto HardwareBuffer.USAGE_GPU_COLOR_OUTPUT | HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE; mImageReader = ImageReader.newInstance(getMeasuredWidth(), getMeasuredHeight(), PixelFormat.RGBA_8888, 2, usage); - mImageReader.setOnImageAvailableListener(reader -> { - try (Image image = reader.acquireLatestImage()) { - if (image != null) { - start = System.nanoTime(); - HardwareBuffer hb = image.getHardwareBuffer(); - mBitmap = Bitmap.wrapHardwareBuffer(hb, null); - hb.close(); - } - } - }, null); surfaceAvailable(mImageReader.getSurface(), getMeasuredWidth(), getMeasuredHeight()); choreographer = Choreographer.getInstance(); choreographer.postFrameCallback(this); @@ -88,8 +81,17 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto public void doFrame(long frameTimeNanos) { choreographer.postFrameCallback(this); if (mImageReader.getSurface() != null) { + // TODO: use drawFrame() instead surfaceSizeChanged(getMeasuredWidth(), getMeasuredHeight()); - invalidate(); + try (Image image = mImageReader.acquireLatestImage()) { + if (image != null) { + start = System.nanoTime(); + HardwareBuffer hb = image.getHardwareBuffer(); + mBitmap = Bitmap.wrapHardwareBuffer(hb, null); + hb.close(); + invalidate(); + } + } } }