diff --git a/node_modules/@shopify/react-native-skia/android/cpp/rnskia-android/OpenGLContext.h b/node_modules/@shopify/react-native-skia/android/cpp/rnskia-android/OpenGLContext.h index a3b0e0e..3826fea 100644 --- a/node_modules/@shopify/react-native-skia/android/cpp/rnskia-android/OpenGLContext.h +++ b/node_modules/@shopify/react-native-skia/android/cpp/rnskia-android/OpenGLContext.h @@ -201,6 +201,13 @@ private: if (_directContext == nullptr) { throw std::runtime_error("GrDirectContexts::MakeGL failed"); } + + // This singleton is thread-local: every simultaneous TextureView can own a + // separate Ganesh context. Budget one eighth of Astra's 64 MiB aggregate + // cache ceiling per context (wash + waveform + rack + EQ transitions can + // briefly reach eight) instead of accidentally granting each one 64 MiB. + constexpr size_t kAstraGaneshCachePerContext = 8ULL * 1024ULL * 1024ULL; + _directContext->setResourceCacheLimit(kAstraGaneshCachePerContext); } }; diff --git a/node_modules/@shopify/react-native-skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp b/node_modules/@shopify/react-native-skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp index e8e4c03..0ce542c 100644 --- a/node_modules/@shopify/react-native-skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp +++ b/node_modules/@shopify/react-native-skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp @@ -5,8 +5,6 @@ #include #include -#include "RNSkLog.h" - #if defined(SK_GRAPHITE) #include "RNDawnContext.h" #else @@ -50,18 +48,6 @@ bool RNSkOpenGLCanvasProvider::renderToCanvas( if (_surfaceHolder != nullptr && cb != nullptr) { // Get the surface auto surface = _surfaceHolder->getSurface(); - if (_jSurfaceTexture) { - JNIEnv *env = facebook::jni::Environment::current(); - 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()); @@ -86,7 +72,10 @@ void RNSkOpenGLCanvasProvider::surfaceAvailable(jobject jSurfaceTexture, ANativeWindow *window = nullptr; JNIEnv *env = facebook::jni::Environment::current(); if (!opaque) { - _jSurfaceTexture = env->NewGlobalRef(jSurfaceTexture); + // The framework-owned TextureView is the SurfaceTexture consumer. Calling + // updateTexImage() here from RNSkia's producer context fails every frame + // with "EGLConsumer is not attached" and retains the failed JNI work. + // Presenting the ANativeWindow already queues buffers for TextureView. jclass surfaceClass = env->FindClass("android/view/Surface"); jmethodID surfaceConstructor = env->GetMethodID( surfaceClass, "", "(Landroid/graphics/SurfaceTexture;)V"); @@ -95,15 +84,10 @@ void RNSkOpenGLCanvasProvider::surfaceAvailable(jobject jSurfaceTexture, env->NewObject(surfaceClass, surfaceConstructor, jSurfaceTexture); window = ANativeWindow_fromSurface(env, jSurface); - jclass surfaceTextureClass = env->GetObjectClass(_jSurfaceTexture); - _updateTexImageMethod = - env->GetMethodID(surfaceTextureClass, "updateTexImage", "()V"); - // Acquire the native window from the Surface // Clean up local references env->DeleteLocalRef(jSurface); env->DeleteLocalRef(surfaceClass); - env->DeleteLocalRef(surfaceTextureClass); } else { window = ANativeWindow_fromSurface(env, jSurfaceTexture); } @@ -112,6 +96,12 @@ void RNSkOpenGLCanvasProvider::surfaceAvailable(jobject jSurfaceTexture, #else _surfaceHolder = OpenGLContext::getInstance().MakeWindow(window); #endif + // ANativeWindow_fromSurface() returns an acquired reference and the window + // context acquires its own. Drop the caller's reference now so TextureView + // destruction can release the final native window/buffer queue. + if (window != nullptr) { + ANativeWindow_release(window); + } // Post redraw request to ensure we paint in the next draw cycle. _requestRedraw(); @@ -120,11 +110,15 @@ 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; - } +#if !defined(SK_GRAPHITE) + // The window surface is gone, so switch back to the shared pbuffer before + // evicting resources that were unlocked by its destruction. This prevents + // dead TextureViews from lingering in Ganesh's cache until process death. + auto &context = OpenGLContext::getInstance(); + context.makeCurrent(); + context.getDirectContext()->purgeUnlockedResources( + GrPurgeResourceOptions::kAllResources); +#endif } void RNSkOpenGLCanvasProvider::surfaceSizeChanged(jobject jSurface, int width, diff --git a/node_modules/@shopify/react-native-skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.h b/node_modules/@shopify/react-native-skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.h index ca5768d..0b3c5fa 100644 --- a/node_modules/@shopify/react-native-skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.h +++ b/node_modules/@shopify/react-native-skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.h @@ -36,7 +36,5 @@ public: private: std::unique_ptr _surfaceHolder = nullptr; std::shared_ptr _platformContext; - jobject _jSurfaceTexture = nullptr; - jmethodID _updateTexImageMethod = nullptr; }; } // namespace RNSkia