From b0444c85fe399682f99a77d2693ae0b7181e4bd8 Mon Sep 17 00:00:00 2001 From: William Candillon Date: Wed, 20 Nov 2024 14:10:14 +0100 Subject: [PATCH 1/7] remove textureView hack --- .../RNSkOpenGLCanvasProvider.cpp | 35 +--------------- .../rnskia-android/RNSkOpenGLCanvasProvider.h | 2 - .../reactnative/skia/SkiaBaseView.java | 40 +++---------------- 3 files changed, 8 insertions(+), 69 deletions(-) diff --git a/packages/skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp b/packages/skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp index e932e35fcf..f1ecadb7b1 100644 --- a/packages/skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp +++ b/packages/skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp @@ -46,18 +46,9 @@ float RNSkOpenGLCanvasProvider::getScaledHeight() { bool RNSkOpenGLCanvasProvider::renderToCanvas( const std::function &cb) { - JNIEnv *env = facebook::jni::Environment::current(); if (_surfaceHolder != nullptr && cb != nullptr) { // Get the surface auto surface = _surfaceHolder->getSurface(); - env->CallVoidMethod(_jSurfaceTexture, _updateTexImageMethod); - - // Check for exceptions - if (env->ExceptionCheck()) { - RNSkLogger::logToConsole("updateAndRelease() failed. The exception above " - "can safely be ignored"); - env->ExceptionClear(); - } if (surface) { // Draw into canvas using callback cb(surface->getCanvas()); @@ -74,29 +65,12 @@ bool RNSkOpenGLCanvasProvider::renderToCanvas( return false; } -void RNSkOpenGLCanvasProvider::surfaceAvailable(jobject jSurfaceTexture, - int width, int height) { +void RNSkOpenGLCanvasProvider::surfaceAvailable(jobject jSurface, int width, + int height) { // Create renderer! 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 auto window = ANativeWindow_fromSurface(env, jSurface); - // Clean up local references - env->DeleteLocalRef(jSurface); - env->DeleteLocalRef(surfaceClass); - env->DeleteLocalRef(surfaceTextureClass); #if defined(SK_GRAPHITE) _surfaceHolder = DawnContext::getInstance().MakeWindow(window, width, height); #else @@ -111,11 +85,6 @@ void RNSkOpenGLCanvasProvider::surfaceDestroyed() { // destroy the renderer (a unique pointer so the dtor will be called // immediately.) _surfaceHolder = nullptr; - if (_jSurfaceTexture) { - JNIEnv *env = facebook::jni::Environment::current(); - env->DeleteGlobalRef(_jSurfaceTexture); - _jSurfaceTexture = nullptr; - } } void RNSkOpenGLCanvasProvider::surfaceSizeChanged(int width, int height) { diff --git a/packages/skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.h b/packages/skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.h index 1504bf938c..2dc58108a0 100644 --- a/packages/skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.h +++ b/packages/skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.h @@ -36,7 +36,5 @@ class RNSkOpenGLCanvasProvider private: std::unique_ptr _surfaceHolder = nullptr; std::shared_ptr _platformContext; - jobject _jSurfaceTexture = nullptr; - jmethodID _updateTexImageMethod = nullptr; }; } // namespace RNSkia diff --git a/packages/skia/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java b/packages/skia/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java index af546b130b..8bbe020646 100644 --- a/packages/skia/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java +++ b/packages/skia/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java @@ -3,8 +3,11 @@ import android.content.Context; import android.graphics.SurfaceTexture; import android.util.Log; +import android.view.Surface; import android.view.TextureView; +import androidx.annotation.NonNull; + import com.facebook.react.views.view.ReactViewGroup; public abstract class SkiaBaseView extends ReactViewGroup implements TextureView.SurfaceTextureListener { @@ -12,8 +15,6 @@ public abstract class SkiaBaseView extends ReactViewGroup implements TextureView private String tag = "SkiaView"; - private boolean isDropped = false; - public SkiaBaseView(Context context) { super(context); mTexture = new TextureView(context); @@ -22,29 +23,10 @@ public SkiaBaseView(Context context) { addView(mTexture); } - 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()); - } - } - void dropInstance() { - isDropped = true; unregisterView(); } - @Override - protected void onAttachedToWindow() { - super.onAttachedToWindow(); - if (this.getMeasuredWidth() == 0) { - createSurfaceTexture(); - } - } - @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { Log.i(tag, "onLayout " + this.getMeasuredWidth() + "/" + this.getMeasuredHeight()); @@ -53,16 +35,13 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto } @Override - public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { + public void onSurfaceTextureAvailable(@NonNull SurfaceTexture surface, int width, int height) { Log.i(tag, "onSurfaceTextureAvailable " + width + "/" + height); - surfaceAvailable(surface, width, height); + surfaceAvailable(new Surface(surface), width, height); } @Override - public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { - if (isDropped) { - return; - } + public void onSurfaceTextureSizeChanged(@NonNull SurfaceTexture surface, int width, int height) { Log.i(tag, "onSurfaceTextureSizeChanged " + width + "/" + height); surfaceSizeChanged(width, height); } @@ -72,13 +51,6 @@ public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { Log.i(tag, "onSurfaceTextureDestroyed"); // https://developer.android.com/reference/android/view/TextureView.SurfaceTextureListener#onSurfaceTextureDestroyed(android.graphics.SurfaceTexture) surfaceDestroyed(); - // 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); - if (!isDropped) { - createSurfaceTexture(); - } return false; } From a8a271a5ba39ec31c2b6711f0580bcad2d2799d7 Mon Sep 17 00:00:00 2001 From: William Candillon Date: Thu, 21 Nov 2024 11:08:58 +0100 Subject: [PATCH 2/7] :wrench: --- .../android/cpp/jni/include/JniSkiaBaseView.h | 4 +- .../android/cpp/jni/include/JniSkiaDomView.h | 4 +- .../cpp/jni/include/JniSkiaPictureView.h | 4 +- .../cpp/rnskia-android/OpenGLContext.h | 4 +- .../rnskia-android/OpenGLWindowContext.cpp | 63 +++++-------------- .../cpp/rnskia-android/OpenGLWindowContext.h | 27 ++++---- .../cpp/rnskia-android/RNSkAndroidView.h | 6 +- .../RNSkOpenGLCanvasProvider.cpp | 12 +++- .../rnskia-android/RNSkOpenGLCanvasProvider.h | 2 +- .../android/cpp/rnskia-android/gl/Display.h | 4 ++ .../reactnative/skia/SkiaBaseView.java | 4 +- .../shopify/reactnative/skia/SkiaDomView.java | 2 +- .../reactnative/skia/SkiaPictureView.java | 2 +- packages/skia/cpp/rnskia/WindowContext.h | 1 - .../ios/RNSkia-iOS/SkiaMetalSurfaceFactory.h | 2 - 15 files changed, 60 insertions(+), 81 deletions(-) diff --git a/packages/skia/android/cpp/jni/include/JniSkiaBaseView.h b/packages/skia/android/cpp/jni/include/JniSkiaBaseView.h index fad912d7b9..7985d62be7 100644 --- a/packages/skia/android/cpp/jni/include/JniSkiaBaseView.h +++ b/packages/skia/android/cpp/jni/include/JniSkiaBaseView.h @@ -33,8 +33,8 @@ class JniSkiaBaseView { _skiaAndroidView->surfaceAvailable(surface, width, height); } - virtual void surfaceSizeChanged(int width, int height) { - _skiaAndroidView->surfaceSizeChanged(width, height); + virtual void surfaceSizeChanged(jobject surface, int width, int height) { + _skiaAndroidView->surfaceSizeChanged(surface, width, height); } virtual void surfaceDestroyed() { _skiaAndroidView->surfaceDestroyed(); } diff --git a/packages/skia/android/cpp/jni/include/JniSkiaDomView.h b/packages/skia/android/cpp/jni/include/JniSkiaDomView.h index 0c1ac6e791..3820dd4c3b 100644 --- a/packages/skia/android/cpp/jni/include/JniSkiaDomView.h +++ b/packages/skia/android/cpp/jni/include/JniSkiaDomView.h @@ -51,8 +51,8 @@ class JniSkiaDomView : public jni::HybridClass, JniSkiaBaseView::surfaceAvailable(surface, width, height); } - void surfaceSizeChanged(int width, int height) override { - JniSkiaBaseView::surfaceSizeChanged(width, height); + void surfaceSizeChanged(jobject surface, int width, int height) override { + JniSkiaBaseView::surfaceSizeChanged(surface, width, height); } void surfaceDestroyed() override { JniSkiaBaseView::surfaceDestroyed(); } diff --git a/packages/skia/android/cpp/jni/include/JniSkiaPictureView.h b/packages/skia/android/cpp/jni/include/JniSkiaPictureView.h index a3aaef90a3..f756d32ca2 100644 --- a/packages/skia/android/cpp/jni/include/JniSkiaPictureView.h +++ b/packages/skia/android/cpp/jni/include/JniSkiaPictureView.h @@ -53,8 +53,8 @@ class JniSkiaPictureView : public jni::HybridClass, JniSkiaBaseView::surfaceAvailable(surface, width, height); } - void surfaceSizeChanged(int width, int height) override { - JniSkiaBaseView::surfaceSizeChanged(width, height); + void surfaceSizeChanged(jobject surface, int width, int height) override { + JniSkiaBaseView::surfaceSizeChanged(surface, width, height); } void surfaceDestroyed() override { JniSkiaBaseView::surfaceDestroyed(); } diff --git a/packages/skia/android/cpp/rnskia-android/OpenGLContext.h b/packages/skia/android/cpp/rnskia-android/OpenGLContext.h index ce118e5f8d..a8c088df0c 100644 --- a/packages/skia/android/cpp/rnskia-android/OpenGLContext.h +++ b/packages/skia/android/cpp/rnskia-android/OpenGLContext.h @@ -125,9 +125,11 @@ class OpenGLContext { #endif } + // TODO: remove width, height std::unique_ptr MakeWindow(ANativeWindow *window, int width, int height) { - return std::make_unique(this, window, width, height); + return std::make_unique(_directContext, + _glDisplay.get(), window); } private: diff --git a/packages/skia/android/cpp/rnskia-android/OpenGLWindowContext.cpp b/packages/skia/android/cpp/rnskia-android/OpenGLWindowContext.cpp index a1860c678a..8d110dc9ed 100644 --- a/packages/skia/android/cpp/rnskia-android/OpenGLWindowContext.cpp +++ b/packages/skia/android/cpp/rnskia-android/OpenGLWindowContext.cpp @@ -17,73 +17,42 @@ namespace RNSkia { sk_sp OpenGLWindowContext::getSurface() { if (_skSurface == nullptr) { - struct ReleaseContext { - std::unique_ptr surface = nullptr; - }; - - if (!_window) { - throw std::runtime_error("No native window provided"); - } - auto releaseCtx = new ReleaseContext(); - releaseCtx->surface = - _context->_glDisplay->makeWindowSurface(_context->_glConfig, _window); - if (!releaseCtx->surface) { - throw std::runtime_error("Failed to create window surface"); - } - _glSurface = releaseCtx->surface.get(); - - // Now make this one current - auto success = _context->_glContext->makeCurrent(releaseCtx->surface.get()); - if (!success) { - throw std::runtime_error("Failed to make window surface current"); - } - - // Set up parameters for the render target so that it - // matches the underlying OpenGL context. - GrGLFramebufferInfo fboInfo; - - // We pass 0 as the framebuffer id, since the - // underlying Skia GrGlGpu will read this when wrapping the context in the - // render target and the GrGlGpu object. - fboInfo.fFBOID = 0; - fboInfo.fFormat = 0x8058; // GL_RGBA8 - GLint stencil; glGetIntegerv(GL_STENCIL_BITS, &stencil); GLint samples; glGetIntegerv(GL_SAMPLES, &samples); - auto colorType = kN32_SkColorType; + auto colorType = kRGBA_8888_SkColorType; auto maxSamples = - _context->_directContext->maxSurfaceSampleCountForColorType(colorType); + _directContext->maxSurfaceSampleCountForColorType(colorType); if (samples > maxSamples) { samples = maxSamples; } - auto renderTarget = GrBackendRenderTargets::MakeGL(_width, _height, samples, - stencil, fboInfo); - - SkSurfaceProps props(0, kUnknown_SkPixelGeometry); + GrGLFramebufferInfo fbInfo; + fbInfo.fFBOID = 0; + fbInfo.fFormat = GR_GL_RGBA8; + // fbInfo.fProtected = + // skgpu::Protected(fDisplayParams.fCreateProtectedNativeBackend); - // Create surface object + auto backendRT = GrBackendRenderTargets::MakeGL(_width, _height, samples, + stencil, fbInfo); + sk_sp colorSpace(nullptr); + SkSurfaceProps surfaceProps(0, kRGB_H_SkPixelGeometry); _skSurface = SkSurfaces::WrapBackendRenderTarget( - _context->_directContext.get(), renderTarget, - kBottomLeft_GrSurfaceOrigin, colorType, nullptr, &props, - [](void *addr) { - auto releaseCtx = reinterpret_cast(addr); - delete releaseCtx; - }, - reinterpret_cast(releaseCtx)); + _directContext.get(), backendRT, kBottomLeft_GrSurfaceOrigin, + kRGBA_8888_SkColorType, colorSpace, &surfaceProps); } return _skSurface; } void OpenGLWindowContext::present() { - _context->_glContext->makeCurrent(_glSurface); - _context->_directContext->flushAndSubmit(); + _glContext->makeCurrent(_glSurface.get()); + // TODO: is flushAndSubmit needed here? + _directContext->flushAndSubmit(); _glSurface->present(); } diff --git a/packages/skia/android/cpp/rnskia-android/OpenGLWindowContext.h b/packages/skia/android/cpp/rnskia-android/OpenGLWindowContext.h index f4ee4a077b..f0015f01e4 100644 --- a/packages/skia/android/cpp/rnskia-android/OpenGLWindowContext.h +++ b/packages/skia/android/cpp/rnskia-android/OpenGLWindowContext.h @@ -31,18 +31,23 @@ namespace RNSkia { -class OpenGLContext; - class OpenGLWindowContext : public WindowContext { public: - OpenGLWindowContext(OpenGLContext *context, ANativeWindow *window, int width, - int height) - : _context(context), _window(window), _width(width), _height(height) { + OpenGLWindowContext(sk_sp directContext, + gl::Display *display, ANativeWindow *window) + : _directContext(directContext), _display(display), _window(window) { ANativeWindow_acquire(_window); + _width = ANativeWindow_getWidth(_window); + _height = ANativeWindow_getHeight(_window); + auto config = display->chooseConfig(); + _glSurface = display->makeWindowSurface(config, _window); + _glContext = display->makeContext(config, nullptr); } ~OpenGLWindowContext() { _skSurface = nullptr; + _display->clearContext(); + _glContext = nullptr; _glSurface = nullptr; ANativeWindow_release(_window); } @@ -51,21 +56,17 @@ class OpenGLWindowContext : public WindowContext { void present() override; - void resize(int width, int height) override { - _skSurface = nullptr; - _width = width; - _height = height; - } - int getWidth() override { return _width; }; int getHeight() override { return _height; }; private: - OpenGLContext *_context; + sk_sp _directContext; + gl::Display *_display; ANativeWindow *_window; sk_sp _skSurface = nullptr; - gl::Surface *_glSurface = nullptr; + std::unique_ptr _glContext = nullptr; + std::unique_ptr _glSurface = nullptr; int _width = 0; int _height = 0; }; diff --git a/packages/skia/android/cpp/rnskia-android/RNSkAndroidView.h b/packages/skia/android/cpp/rnskia-android/RNSkAndroidView.h index 8bdc60df63..f1e40c1f59 100644 --- a/packages/skia/android/cpp/rnskia-android/RNSkAndroidView.h +++ b/packages/skia/android/cpp/rnskia-android/RNSkAndroidView.h @@ -15,7 +15,7 @@ class RNSkBaseAndroidView { virtual void surfaceDestroyed() = 0; - virtual void surfaceSizeChanged(int width, int height) = 0; + virtual void surfaceSizeChanged(jobject surface, int width, int height) = 0; virtual float getPixelDensity() = 0; @@ -50,9 +50,9 @@ class RNSkAndroidView : public T, public RNSkBaseAndroidView { ->surfaceDestroyed(); } - void surfaceSizeChanged(int width, int height) override { + void surfaceSizeChanged(jobject surface, int width, int height) override { std::static_pointer_cast(T::getCanvasProvider()) - ->surfaceSizeChanged(width, height); + ->surfaceSizeChanged(surface, 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/packages/skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp b/packages/skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp index f1ecadb7b1..a144f93b88 100644 --- a/packages/skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp +++ b/packages/skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp @@ -65,6 +65,7 @@ bool RNSkOpenGLCanvasProvider::renderToCanvas( return false; } +// TODO: remove width/height here void RNSkOpenGLCanvasProvider::surfaceAvailable(jobject jSurface, int width, int height) { // Create renderer! @@ -87,15 +88,20 @@ void RNSkOpenGLCanvasProvider::surfaceDestroyed() { _surfaceHolder = nullptr; } -void RNSkOpenGLCanvasProvider::surfaceSizeChanged(int width, int height) { +// TODO: remove width/height here +void RNSkOpenGLCanvasProvider::surfaceSizeChanged(jobject jSurface, int width, + int height) { if (width == 0 && height == 0) { // Setting width/height to zero is nothing we need to care about when // it comes to invalidating the surface. return; } - // Recreate RenderContext surface based on size change??? - _surfaceHolder->resize(width, height); + JNIEnv *env = facebook::jni::Environment::current(); + // Acquire the native window from the Surface + auto window = ANativeWindow_fromSurface(env, jSurface); + _surfaceHolder = + OpenGLContext::getInstance().MakeWindow(window, width, height); // Redraw after size change _requestRedraw(); diff --git a/packages/skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.h b/packages/skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.h index 2dc58108a0..ff52498aec 100644 --- a/packages/skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.h +++ b/packages/skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.h @@ -31,7 +31,7 @@ class RNSkOpenGLCanvasProvider void surfaceDestroyed(); - void surfaceSizeChanged(int width, int height); + void surfaceSizeChanged(jobject jSurface, int width, int height); private: std::unique_ptr _surfaceHolder = nullptr; diff --git a/packages/skia/android/cpp/rnskia-android/gl/Display.h b/packages/skia/android/cpp/rnskia-android/gl/Display.h index c48ca74951..cce0b65f62 100644 --- a/packages/skia/android/cpp/rnskia-android/gl/Display.h +++ b/packages/skia/android/cpp/rnskia-android/gl/Display.h @@ -35,6 +35,10 @@ class Display { bool isValid() const { return _display != EGL_NO_DISPLAY; } + void clearContext() { + eglMakeCurrent(_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + } + EGLConfig chooseConfig() { EGLint att[] = {EGL_RENDERABLE_TYPE, diff --git a/packages/skia/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java b/packages/skia/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java index 8bbe020646..a123870780 100644 --- a/packages/skia/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java +++ b/packages/skia/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java @@ -43,7 +43,7 @@ public void onSurfaceTextureAvailable(@NonNull SurfaceTexture surface, int width @Override public void onSurfaceTextureSizeChanged(@NonNull SurfaceTexture surface, int width, int height) { Log.i(tag, "onSurfaceTextureSizeChanged " + width + "/" + height); - surfaceSizeChanged(width, height); + surfaceSizeChanged(new Surface(surface), width, height); } @Override @@ -65,7 +65,7 @@ public void onSurfaceTextureUpdated(SurfaceTexture surface) { protected abstract void surfaceAvailable(Object surface, int width, int height); - protected abstract void surfaceSizeChanged(int width, int height); + protected abstract void surfaceSizeChanged(Object surface, int width, int height); protected abstract void surfaceDestroyed(); diff --git a/packages/skia/android/src/main/java/com/shopify/reactnative/skia/SkiaDomView.java b/packages/skia/android/src/main/java/com/shopify/reactnative/skia/SkiaDomView.java index 4da6f0474f..e40af4be2b 100644 --- a/packages/skia/android/src/main/java/com/shopify/reactnative/skia/SkiaDomView.java +++ b/packages/skia/android/src/main/java/com/shopify/reactnative/skia/SkiaDomView.java @@ -27,7 +27,7 @@ protected void finalize() throws Throwable { protected native void surfaceAvailable(Object surface, int width, int height); - protected native void surfaceSizeChanged(int width, int height); + protected native void surfaceSizeChanged(Object surface, int width, int height); protected native void surfaceDestroyed(); diff --git a/packages/skia/android/src/main/java/com/shopify/reactnative/skia/SkiaPictureView.java b/packages/skia/android/src/main/java/com/shopify/reactnative/skia/SkiaPictureView.java index 56e5bb3e23..74627a19f2 100644 --- a/packages/skia/android/src/main/java/com/shopify/reactnative/skia/SkiaPictureView.java +++ b/packages/skia/android/src/main/java/com/shopify/reactnative/skia/SkiaPictureView.java @@ -26,7 +26,7 @@ protected void finalize() throws Throwable { protected native void surfaceAvailable(Object surface, int width, int height); - protected native void surfaceSizeChanged(int width, int height); + protected native void surfaceSizeChanged(Object surface, int width, int height); protected native void surfaceDestroyed(); diff --git a/packages/skia/cpp/rnskia/WindowContext.h b/packages/skia/cpp/rnskia/WindowContext.h index 6fe778fccf..6f6f110cb9 100644 --- a/packages/skia/cpp/rnskia/WindowContext.h +++ b/packages/skia/cpp/rnskia/WindowContext.h @@ -17,7 +17,6 @@ class WindowContext { virtual ~WindowContext() = default; virtual sk_sp getSurface() = 0; virtual void present() = 0; - virtual void resize(int width, int height) = 0; virtual int getWidth() = 0; virtual int getHeight() = 0; }; diff --git a/packages/skia/ios/RNSkia-iOS/SkiaMetalSurfaceFactory.h b/packages/skia/ios/RNSkia-iOS/SkiaMetalSurfaceFactory.h index 53d7010fb3..e541532369 100644 --- a/packages/skia/ios/RNSkia-iOS/SkiaMetalSurfaceFactory.h +++ b/packages/skia/ios/RNSkia-iOS/SkiaMetalSurfaceFactory.h @@ -107,8 +107,6 @@ class IOSSkiaContext : public RNSkia::WindowContext { _skSurface = nullptr; } - void resize(int width, int height) override { _skSurface = nullptr; } - int getWidth() override { return _layer.frame.size.width * _layer.contentsScale; }; From 5f7368e69c0eff5787241fa3161ef51e85e01048 Mon Sep 17 00:00:00 2001 From: William Candillon Date: Thu, 21 Nov 2024 11:22:00 +0100 Subject: [PATCH 3/7] :wrenchj: --- .../android/cpp/rnskia-android/OpenGLContext.h | 3 +-- .../cpp/rnskia-android/OpenGLWindowContext.cpp | 6 ++++-- .../cpp/rnskia-android/OpenGLWindowContext.h | 17 +++++------------ .../rnskia-android/RNSkOpenGLCanvasProvider.cpp | 6 +++--- .../shopify/reactnative/skia/SkiaBaseView.java | 12 ++++++------ 5 files changed, 19 insertions(+), 25 deletions(-) diff --git a/packages/skia/android/cpp/rnskia-android/OpenGLContext.h b/packages/skia/android/cpp/rnskia-android/OpenGLContext.h index a8c088df0c..f9974fb829 100644 --- a/packages/skia/android/cpp/rnskia-android/OpenGLContext.h +++ b/packages/skia/android/cpp/rnskia-android/OpenGLContext.h @@ -128,8 +128,7 @@ class OpenGLContext { // TODO: remove width, height std::unique_ptr MakeWindow(ANativeWindow *window, int width, int height) { - return std::make_unique(_directContext, - _glDisplay.get(), window); + return std::make_unique(_directContext, _glDisplay.get(), _glContext.get(), window); } private: diff --git a/packages/skia/android/cpp/rnskia-android/OpenGLWindowContext.cpp b/packages/skia/android/cpp/rnskia-android/OpenGLWindowContext.cpp index 8d110dc9ed..297306a8c8 100644 --- a/packages/skia/android/cpp/rnskia-android/OpenGLWindowContext.cpp +++ b/packages/skia/android/cpp/rnskia-android/OpenGLWindowContext.cpp @@ -16,7 +16,7 @@ namespace RNSkia { sk_sp OpenGLWindowContext::getSurface() { if (_skSurface == nullptr) { - + _glContext->makeCurrent(_glSurface.get()); GLint stencil; glGetIntegerv(GL_STENCIL_BITS, &stencil); @@ -38,7 +38,9 @@ sk_sp OpenGLWindowContext::getSurface() { // fbInfo.fProtected = // skgpu::Protected(fDisplayParams.fCreateProtectedNativeBackend); - auto backendRT = GrBackendRenderTargets::MakeGL(_width, _height, samples, + auto width = ANativeWindow_getWidth(_window); + auto height = ANativeWindow_getHeight(_window); + auto backendRT = GrBackendRenderTargets::MakeGL(width, height, samples, stencil, fbInfo); sk_sp colorSpace(nullptr); SkSurfaceProps surfaceProps(0, kRGB_H_SkPixelGeometry); diff --git a/packages/skia/android/cpp/rnskia-android/OpenGLWindowContext.h b/packages/skia/android/cpp/rnskia-android/OpenGLWindowContext.h index f0015f01e4..7bcfa0cb14 100644 --- a/packages/skia/android/cpp/rnskia-android/OpenGLWindowContext.h +++ b/packages/skia/android/cpp/rnskia-android/OpenGLWindowContext.h @@ -34,20 +34,15 @@ namespace RNSkia { class OpenGLWindowContext : public WindowContext { public: OpenGLWindowContext(sk_sp directContext, - gl::Display *display, ANativeWindow *window) - : _directContext(directContext), _display(display), _window(window) { + gl::Display *display, gl::Context* glContext, ANativeWindow *window) + : _directContext(directContext), _display(display), _glContext(glContext), _window(window) { ANativeWindow_acquire(_window); - _width = ANativeWindow_getWidth(_window); - _height = ANativeWindow_getHeight(_window); auto config = display->chooseConfig(); _glSurface = display->makeWindowSurface(config, _window); - _glContext = display->makeContext(config, nullptr); } ~OpenGLWindowContext() { _skSurface = nullptr; - _display->clearContext(); - _glContext = nullptr; _glSurface = nullptr; ANativeWindow_release(_window); } @@ -56,19 +51,17 @@ class OpenGLWindowContext : public WindowContext { void present() override; - int getWidth() override { return _width; }; + int getWidth() override { return ANativeWindow_getWidth(_window); }; - int getHeight() override { return _height; }; + int getHeight() override { return ANativeWindow_getHeight(_window); }; private: sk_sp _directContext; gl::Display *_display; ANativeWindow *_window; sk_sp _skSurface = nullptr; - std::unique_ptr _glContext = nullptr; + gl::Context* _glContext = nullptr; std::unique_ptr _glSurface = nullptr; - int _width = 0; - int _height = 0; }; } // namespace RNSkia diff --git a/packages/skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp b/packages/skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp index a144f93b88..0d3d61484e 100644 --- a/packages/skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp +++ b/packages/skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp @@ -99,9 +99,9 @@ void RNSkOpenGLCanvasProvider::surfaceSizeChanged(jobject jSurface, int width, JNIEnv *env = facebook::jni::Environment::current(); // Acquire the native window from the Surface - auto window = ANativeWindow_fromSurface(env, jSurface); - _surfaceHolder = - OpenGLContext::getInstance().MakeWindow(window, width, height); + // auto window = ANativeWindow_fromSurface(env, jSurface); + // _surfaceHolder = + // OpenGLContext::getInstance().MakeWindow(window, width, height); // Redraw after size change _requestRedraw(); diff --git a/packages/skia/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java b/packages/skia/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java index a123870780..1618038ccc 100644 --- a/packages/skia/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java +++ b/packages/skia/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java @@ -51,16 +51,16 @@ public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { Log.i(tag, "onSurfaceTextureDestroyed"); // https://developer.android.com/reference/android/view/TextureView.SurfaceTextureListener#onSurfaceTextureDestroyed(android.graphics.SurfaceTexture) surfaceDestroyed(); - return false; + return true; } - //private long _prevTimestamp = 0; + 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; + 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); From b351790abb755a79b8130257dde7455a47d41f79 Mon Sep 17 00:00:00 2001 From: William Candillon Date: Thu, 21 Nov 2024 11:40:47 +0100 Subject: [PATCH 4/7] :wrench: --- apps/paper/ios/Podfile.lock | 4 +- .../cpp/rnskia-android/OpenGLContext.h | 3 +- .../rnskia-android/OpenGLWindowContext.cpp | 4 +- .../cpp/rnskia-android/OpenGLWindowContext.h | 10 ++-- .../RNSkOpenGLCanvasProvider.cpp | 50 ++++++++++++++----- .../rnskia-android/RNSkOpenGLCanvasProvider.h | 2 + .../reactnative/skia/SkiaBaseView.java | 4 +- packages/skia/cpp/rnskia/WindowContext.h | 1 + .../ios/RNSkia-iOS/SkiaMetalSurfaceFactory.h | 2 + 9 files changed, 58 insertions(+), 22 deletions(-) diff --git a/apps/paper/ios/Podfile.lock b/apps/paper/ios/Podfile.lock index 70fbb6cc2b..f235036e83 100644 --- a/apps/paper/ios/Podfile.lock +++ b/apps/paper/ios/Podfile.lock @@ -1283,7 +1283,7 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - react-native-wgpu (0.1.19): + - react-native-wgpu (0.1.7): - DoubleConversion - glog - hermes-engine @@ -1937,7 +1937,7 @@ SPEC CHECKSUMS: react-native-safe-area-context: ab8f4a3d8180913bd78ae75dd599c94cce3d5e9a react-native-skia: 1f36fe252564881d77ad424f84a8986098cc73b7 react-native-slider: 97ce0bd921f40de79cead9754546d5e4e7ba44f8 - react-native-wgpu: 8d0437a304318e0e3d6ccbfed2a39880f8eae4dd + react-native-wgpu: fb9d60b0f4c63a03fb60bd986d758aeffca6ee13 React-nativeconfig: 57781b79e11d5af7573e6f77cbf1143b71802a6d React-NativeModulesApple: 7ff2e2cfb2e5fa5bdedcecf28ce37e696c6ef1e1 React-perflogger: 8a360ccf603de6ddbe9ff8f54383146d26e6c936 diff --git a/packages/skia/android/cpp/rnskia-android/OpenGLContext.h b/packages/skia/android/cpp/rnskia-android/OpenGLContext.h index f9974fb829..5608c141e7 100644 --- a/packages/skia/android/cpp/rnskia-android/OpenGLContext.h +++ b/packages/skia/android/cpp/rnskia-android/OpenGLContext.h @@ -128,7 +128,8 @@ class OpenGLContext { // TODO: remove width, height std::unique_ptr MakeWindow(ANativeWindow *window, int width, int height) { - return std::make_unique(_directContext, _glDisplay.get(), _glContext.get(), window); + return std::make_unique( + _directContext, _glDisplay.get(), _glContext.get(), window); } private: diff --git a/packages/skia/android/cpp/rnskia-android/OpenGLWindowContext.cpp b/packages/skia/android/cpp/rnskia-android/OpenGLWindowContext.cpp index 297306a8c8..3e525504ca 100644 --- a/packages/skia/android/cpp/rnskia-android/OpenGLWindowContext.cpp +++ b/packages/skia/android/cpp/rnskia-android/OpenGLWindowContext.cpp @@ -40,8 +40,8 @@ sk_sp OpenGLWindowContext::getSurface() { auto width = ANativeWindow_getWidth(_window); auto height = ANativeWindow_getHeight(_window); - auto backendRT = GrBackendRenderTargets::MakeGL(width, height, samples, - stencil, fbInfo); + auto backendRT = + GrBackendRenderTargets::MakeGL(width, height, samples, stencil, fbInfo); sk_sp colorSpace(nullptr); SkSurfaceProps surfaceProps(0, kRGB_H_SkPixelGeometry); _skSurface = SkSurfaces::WrapBackendRenderTarget( diff --git a/packages/skia/android/cpp/rnskia-android/OpenGLWindowContext.h b/packages/skia/android/cpp/rnskia-android/OpenGLWindowContext.h index 7bcfa0cb14..63294eb88f 100644 --- a/packages/skia/android/cpp/rnskia-android/OpenGLWindowContext.h +++ b/packages/skia/android/cpp/rnskia-android/OpenGLWindowContext.h @@ -34,8 +34,10 @@ namespace RNSkia { class OpenGLWindowContext : public WindowContext { public: OpenGLWindowContext(sk_sp directContext, - gl::Display *display, gl::Context* glContext, ANativeWindow *window) - : _directContext(directContext), _display(display), _glContext(glContext), _window(window) { + gl::Display *display, gl::Context *glContext, + ANativeWindow *window) + : _directContext(directContext), _display(display), _glContext(glContext), + _window(window) { ANativeWindow_acquire(_window); auto config = display->chooseConfig(); _glSurface = display->makeWindowSurface(config, _window); @@ -55,12 +57,14 @@ class OpenGLWindowContext : public WindowContext { int getHeight() override { return ANativeWindow_getHeight(_window); }; + void resize(int width, int height) override { _skSurface = nullptr; } + private: sk_sp _directContext; gl::Display *_display; ANativeWindow *_window; sk_sp _skSurface = nullptr; - gl::Context* _glContext = nullptr; + gl::Context *_glContext = nullptr; std::unique_ptr _glSurface = nullptr; }; diff --git a/packages/skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp b/packages/skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp index 0d3d61484e..a893ba6bda 100644 --- a/packages/skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp +++ b/packages/skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp @@ -46,9 +46,18 @@ float RNSkOpenGLCanvasProvider::getScaledHeight() { bool RNSkOpenGLCanvasProvider::renderToCanvas( const std::function &cb) { + JNIEnv *env = facebook::jni::Environment::current(); if (_surfaceHolder != nullptr && cb != nullptr) { // Get the surface auto surface = _surfaceHolder->getSurface(); + env->CallVoidMethod(_jSurfaceTexture, _updateTexImageMethod); + + // Check for exceptions + if (env->ExceptionCheck()) { + RNSkLogger::logToConsole("updateAndRelease() failed. The exception above " + "can safely be ignored"); + env->ExceptionClear(); + } if (surface) { // Draw into canvas using callback cb(surface->getCanvas()); @@ -65,13 +74,29 @@ bool RNSkOpenGLCanvasProvider::renderToCanvas( return false; } -// TODO: remove width/height here -void RNSkOpenGLCanvasProvider::surfaceAvailable(jobject jSurface, int width, - int height) { +void RNSkOpenGLCanvasProvider::surfaceAvailable(jobject jSurfaceTexture, + int width, int height) { // Create renderer! 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 auto window = ANativeWindow_fromSurface(env, jSurface); + // Clean up local references + env->DeleteLocalRef(jSurface); + env->DeleteLocalRef(surfaceClass); + env->DeleteLocalRef(surfaceTextureClass); #if defined(SK_GRAPHITE) _surfaceHolder = DawnContext::getInstance().MakeWindow(window, width, height); #else @@ -86,24 +111,25 @@ void RNSkOpenGLCanvasProvider::surfaceDestroyed() { // destroy the renderer (a unique pointer so the dtor will be called // immediately.) _surfaceHolder = nullptr; + if (_jSurfaceTexture) { + JNIEnv *env = facebook::jni::Environment::current(); + env->DeleteGlobalRef(_jSurfaceTexture); + _jSurfaceTexture = nullptr; + } } -// TODO: remove width/height here -void RNSkOpenGLCanvasProvider::surfaceSizeChanged(jobject jSurface, int width, - int height) { +void RNSkOpenGLCanvasProvider::surfaceSizeChanged(jobject jSurfaceTexture, + int width, int height) { if (width == 0 && height == 0) { // Setting width/height to zero is nothing we need to care about when // it comes to invalidating the surface. return; } - JNIEnv *env = facebook::jni::Environment::current(); - // Acquire the native window from the Surface - // auto window = ANativeWindow_fromSurface(env, jSurface); - // _surfaceHolder = - // OpenGLContext::getInstance().MakeWindow(window, width, height); + // Recreate RenderContext surface based on size change??? + _surfaceHolder->resize(width, height); // Redraw after size change _requestRedraw(); } -} // namespace RNSkia +} // namespace RNSkia \ No newline at end of file diff --git a/packages/skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.h b/packages/skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.h index ff52498aec..fb73bcaa74 100644 --- a/packages/skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.h +++ b/packages/skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.h @@ -36,5 +36,7 @@ class RNSkOpenGLCanvasProvider private: std::unique_ptr _surfaceHolder = nullptr; std::shared_ptr _platformContext; + jobject _jSurfaceTexture = nullptr; + jmethodID _updateTexImageMethod = nullptr; }; } // namespace RNSkia diff --git a/packages/skia/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java b/packages/skia/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java index 1618038ccc..06a8a6e8f6 100644 --- a/packages/skia/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java +++ b/packages/skia/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java @@ -37,13 +37,13 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto @Override public void onSurfaceTextureAvailable(@NonNull SurfaceTexture surface, int width, int height) { Log.i(tag, "onSurfaceTextureAvailable " + width + "/" + height); - surfaceAvailable(new Surface(surface), width, height); + surfaceAvailable(surface, width, height); } @Override public void onSurfaceTextureSizeChanged(@NonNull SurfaceTexture surface, int width, int height) { Log.i(tag, "onSurfaceTextureSizeChanged " + width + "/" + height); - surfaceSizeChanged(new Surface(surface), width, height); + surfaceSizeChanged(surface, width, height); } @Override diff --git a/packages/skia/cpp/rnskia/WindowContext.h b/packages/skia/cpp/rnskia/WindowContext.h index 6f6f110cb9..6fe778fccf 100644 --- a/packages/skia/cpp/rnskia/WindowContext.h +++ b/packages/skia/cpp/rnskia/WindowContext.h @@ -17,6 +17,7 @@ class WindowContext { virtual ~WindowContext() = default; virtual sk_sp getSurface() = 0; virtual void present() = 0; + virtual void resize(int width, int height) = 0; virtual int getWidth() = 0; virtual int getHeight() = 0; }; diff --git a/packages/skia/ios/RNSkia-iOS/SkiaMetalSurfaceFactory.h b/packages/skia/ios/RNSkia-iOS/SkiaMetalSurfaceFactory.h index e541532369..3461ba1ac1 100644 --- a/packages/skia/ios/RNSkia-iOS/SkiaMetalSurfaceFactory.h +++ b/packages/skia/ios/RNSkia-iOS/SkiaMetalSurfaceFactory.h @@ -115,6 +115,8 @@ class IOSSkiaContext : public RNSkia::WindowContext { return _layer.frame.size.height * _layer.contentsScale; }; + void resize(int width, int height) override { _skSurface = nullptr; } + private: SkiaMetalContext *_context; sk_sp _skSurface = nullptr; From c0c032b4f0e69f16a3e38fef68edeebeb2254464 Mon Sep 17 00:00:00 2001 From: William Candillon Date: Thu, 21 Nov 2024 12:15:56 +0100 Subject: [PATCH 5/7] update examples --- apps/paper/ios/Podfile.lock | 4 ++-- apps/paper/src/Examples/API/Data.tsx | 14 ++++++++++---- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/apps/paper/ios/Podfile.lock b/apps/paper/ios/Podfile.lock index f235036e83..70fbb6cc2b 100644 --- a/apps/paper/ios/Podfile.lock +++ b/apps/paper/ios/Podfile.lock @@ -1283,7 +1283,7 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - react-native-wgpu (0.1.7): + - react-native-wgpu (0.1.19): - DoubleConversion - glog - hermes-engine @@ -1937,7 +1937,7 @@ SPEC CHECKSUMS: react-native-safe-area-context: ab8f4a3d8180913bd78ae75dd599c94cce3d5e9a react-native-skia: 1f36fe252564881d77ad424f84a8986098cc73b7 react-native-slider: 97ce0bd921f40de79cead9754546d5e4e7ba44f8 - react-native-wgpu: fb9d60b0f4c63a03fb60bd986d758aeffca6ee13 + react-native-wgpu: 8d0437a304318e0e3d6ccbfed2a39880f8eae4dd React-nativeconfig: 57781b79e11d5af7573e6f77cbf1143b71802a6d React-NativeModulesApple: 7ff2e2cfb2e5fa5bdedcecf28ce37e696c6ef1e1 React-perflogger: 8a360ccf603de6ddbe9ff8f54383146d26e6c936 diff --git a/apps/paper/src/Examples/API/Data.tsx b/apps/paper/src/Examples/API/Data.tsx index a19eaba18a..f753532850 100644 --- a/apps/paper/src/Examples/API/Data.tsx +++ b/apps/paper/src/Examples/API/Data.tsx @@ -1,5 +1,4 @@ import React from "react"; -import { useWindowDimensions } from "react-native"; import { AlphaType, Canvas, @@ -28,12 +27,19 @@ const img = Skia.Image.MakeImage( 256 * 4 )!; +const surface = Skia.Surface.MakeOffscreen(256, 256)!; +const canvas = surface.getCanvas(); +canvas.drawColor(Skia.Color("cyan")); +const paint = Skia.Paint(); +paint.setColor(Skia.Color("magenta")); +canvas.drawCircle(128, 128, 128, paint); +const img1 = surface.makeImageSnapshot().makeNonTextureImage(); + export const Data = () => { - const { width } = useWindowDimensions(); - const SIZE = width; return ( - + + ); }; From 8f7c42adad34c41b8a334de85de172eb17f7a816 Mon Sep 17 00:00:00 2001 From: William Candillon Date: Thu, 21 Nov 2024 14:06:31 +0100 Subject: [PATCH 6/7] :wrench: --- .../RNSkOpenGLCanvasProvider.cpp | 4 +- .../reactnative/skia/SkiaBaseView.java | 50 +++++++++++++++---- .../shopify/reactnative/skia/SkiaDomView.java | 2 - .../reactnative/skia/SkiaPictureView.java | 2 - .../SkiaDrawViewManagerInterface.java | 18 ------- 5 files changed, 41 insertions(+), 35 deletions(-) delete mode 100644 packages/skia/android/src/paper/java/com/facebook/react/viewmanagers/SkiaDrawViewManagerInterface.java diff --git a/packages/skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp b/packages/skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp index a893ba6bda..4650283fb3 100644 --- a/packages/skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp +++ b/packages/skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp @@ -126,8 +126,8 @@ void RNSkOpenGLCanvasProvider::surfaceSizeChanged(jobject jSurfaceTexture, return; } - // Recreate RenderContext surface based on size change??? - _surfaceHolder->resize(width, height); + _surfaceHolder = nullptr; + surfaceAvailable(jSurfaceTexture, width, height); // Redraw after size change _requestRedraw(); diff --git a/packages/skia/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java b/packages/skia/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java index 06a8a6e8f6..f942da8893 100644 --- a/packages/skia/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java +++ b/packages/skia/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java @@ -3,11 +3,8 @@ import android.content.Context; import android.graphics.SurfaceTexture; import android.util.Log; -import android.view.Surface; import android.view.TextureView; -import androidx.annotation.NonNull; - import com.facebook.react.views.view.ReactViewGroup; public abstract class SkiaBaseView extends ReactViewGroup implements TextureView.SurfaceTextureListener { @@ -15,6 +12,8 @@ public abstract class SkiaBaseView extends ReactViewGroup implements TextureView private String tag = "SkiaView"; + private boolean isDropped = false; + public SkiaBaseView(Context context) { super(context); mTexture = new TextureView(context); @@ -23,10 +22,29 @@ public SkiaBaseView(Context context) { addView(mTexture); } + 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()); + } + } + void dropInstance() { + isDropped = true; unregisterView(); } + @Override + protected void onAttachedToWindow() { + super.onAttachedToWindow(); + if (this.getMeasuredWidth() == 0) { + createSurfaceTexture(); + } + } + @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { Log.i(tag, "onLayout " + this.getMeasuredWidth() + "/" + this.getMeasuredHeight()); @@ -35,13 +53,16 @@ protected void onLayout(boolean changed, int left, int top, int right, int botto } @Override - public void onSurfaceTextureAvailable(@NonNull SurfaceTexture surface, int width, int height) { + public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) { Log.i(tag, "onSurfaceTextureAvailable " + width + "/" + height); surfaceAvailable(surface, width, height); } @Override - public void onSurfaceTextureSizeChanged(@NonNull SurfaceTexture surface, int width, int height) { + public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) { + if (isDropped) { + return; + } Log.i(tag, "onSurfaceTextureSizeChanged " + width + "/" + height); surfaceSizeChanged(surface, width, height); } @@ -51,16 +72,23 @@ public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { Log.i(tag, "onSurfaceTextureDestroyed"); // https://developer.android.com/reference/android/view/TextureView.SurfaceTextureListener#onSurfaceTextureDestroyed(android.graphics.SurfaceTexture) surfaceDestroyed(); - return true; + // 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); + if (!isDropped) { + createSurfaceTexture(); + } + return false; } - private long _prevTimestamp = 0; + //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; +// 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); diff --git a/packages/skia/android/src/main/java/com/shopify/reactnative/skia/SkiaDomView.java b/packages/skia/android/src/main/java/com/shopify/reactnative/skia/SkiaDomView.java index e40af4be2b..eafe21a8f0 100644 --- a/packages/skia/android/src/main/java/com/shopify/reactnative/skia/SkiaDomView.java +++ b/packages/skia/android/src/main/java/com/shopify/reactnative/skia/SkiaDomView.java @@ -37,8 +37,6 @@ protected void finalize() throws Throwable { protected native void setDebugMode(boolean show); - protected native void updateTouchPoints(double[] points); - protected native void registerView(int nativeId); protected native void unregisterView(); diff --git a/packages/skia/android/src/main/java/com/shopify/reactnative/skia/SkiaPictureView.java b/packages/skia/android/src/main/java/com/shopify/reactnative/skia/SkiaPictureView.java index 74627a19f2..f4dc2a4695 100644 --- a/packages/skia/android/src/main/java/com/shopify/reactnative/skia/SkiaPictureView.java +++ b/packages/skia/android/src/main/java/com/shopify/reactnative/skia/SkiaPictureView.java @@ -36,8 +36,6 @@ protected void finalize() throws Throwable { protected native void setDebugMode(boolean show); - protected native void updateTouchPoints(double[] points); - protected native void registerView(int nativeId); protected native void unregisterView(); diff --git a/packages/skia/android/src/paper/java/com/facebook/react/viewmanagers/SkiaDrawViewManagerInterface.java b/packages/skia/android/src/paper/java/com/facebook/react/viewmanagers/SkiaDrawViewManagerInterface.java deleted file mode 100644 index a73c85e29c..0000000000 --- a/packages/skia/android/src/paper/java/com/facebook/react/viewmanagers/SkiaDrawViewManagerInterface.java +++ /dev/null @@ -1,18 +0,0 @@ -/** -* This code was generated by [react-native-codegen](https://www.npmjs.com/package/react-native-codegen). -* -* Do not edit this file as changes may cause incorrect behavior and will be lost -* once the code is regenerated. -* -* @generated by codegen project: GeneratePropsJavaInterface.js -*/ - -package com.facebook.react.viewmanagers; - -import android.view.View; -import androidx.annotation.Nullable; - -public interface SkiaDrawViewManagerInterface { - void setMode(T view, @Nullable String value); - void setDebug(T view, boolean value); -} From aa6f5611e2cedcd68024da5d459f7a77f80fa518 Mon Sep 17 00:00:00 2001 From: William Candillon Date: Thu, 21 Nov 2024 14:25:46 +0100 Subject: [PATCH 7/7] :green_heart: --- .../cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp | 12 ++++++++++-- .../com/shopify/reactnative/skia/SkiaBaseView.java | 10 +++++----- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/packages/skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp b/packages/skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp index 4650283fb3..48d1e497bb 100644 --- a/packages/skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp +++ b/packages/skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp @@ -76,6 +76,10 @@ bool RNSkOpenGLCanvasProvider::renderToCanvas( void RNSkOpenGLCanvasProvider::surfaceAvailable(jobject jSurfaceTexture, int width, int height) { + // If the surface is 0, we can skip it + if (width == 0 && height == 0) { + return; + } // Create renderer! JNIEnv *env = facebook::jni::Environment::current(); @@ -126,8 +130,12 @@ void RNSkOpenGLCanvasProvider::surfaceSizeChanged(jobject jSurfaceTexture, return; } - _surfaceHolder = nullptr; - surfaceAvailable(jSurfaceTexture, width, height); + if (_surfaceHolder == nullptr) { + _surfaceHolder = nullptr; + surfaceAvailable(jSurfaceTexture, width, height); + } else { + _surfaceHolder->resize(width, height); + } // Redraw after size change _requestRedraw(); diff --git a/packages/skia/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java b/packages/skia/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java index f942da8893..8f88d6b23b 100644 --- a/packages/skia/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java +++ b/packages/skia/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java @@ -82,13 +82,13 @@ public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) { return false; } - //private long _prevTimestamp = 0; + 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; + 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);