From d2d1c436a8ab24fce9ae620516cd12cd6d51679f Mon Sep 17 00:00:00 2001 From: Kudo Chien Date: Thu, 22 Jun 2023 22:54:59 +0800 Subject: [PATCH] [go] update @shopify/react-native-skia to 0.1.195 (#23036) # Why update @shopify/react-native-skia vendoring module for sdk 49 # How - `et uvm -m @shopify/react-native-skia -c 0.1.195` # Test Plan - unversioned expo go + unversioned ncl skia --- .../cpp/rnskia-android/RNSkAndroidView.h | 4 + .../RNSkOpenGLCanvasProvider.cpp | 5 +- .../rnskia-android/RNSkOpenGLCanvasProvider.h | 2 +- .../cpp/rnskia-android/SkiaOpenGLRenderer.cpp | 104 +++------ .../cpp/rnskia-android/SkiaOpenGLRenderer.h | 13 +- .../skia/ViewScreenshotService.java | 207 +++++++++--------- .../cpp/rnskia/RNSkDomView.cpp | 5 +- .../cpp/rnskia/RNSkPictureView.h | 14 +- .../react-native-skia/cpp/rnskia/RNSkView.h | 15 +- .../cpp/rnskia/dom/base/JsiDomDrawingNode.h | 4 +- apps/native-component-list/package.json | 2 +- ios/Podfile.lock | 4 +- .../cpp/rnskia/RNSkDomView.cpp | 5 +- .../cpp/rnskia/RNSkPictureView.h | 14 +- .../react-native-skia/cpp/rnskia/RNSkView.h | 15 +- .../cpp/rnskia/dom/base/JsiDomDrawingNode.h | 4 +- .../ios/RNSkia-iOS/RNSkMetalCanvasProvider.h | 2 +- .../ios/RNSkia-iOS/RNSkMetalCanvasProvider.mm | 15 +- .../ios/RNSkia-iOS/SkiaUIView.mm | 10 + .../react-native-skia.podspec.json | 4 +- packages/expo/bundledNativeModules.json | 2 +- yarn.lock | 8 +- 22 files changed, 227 insertions(+), 231 deletions(-) diff --git a/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/RNSkAndroidView.h b/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/RNSkAndroidView.h index 020ff54240add..3ee87baecad6e 100644 --- a/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/RNSkAndroidView.h +++ b/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/RNSkAndroidView.h @@ -42,6 +42,10 @@ class RNSkAndroidView : public T, public RNSkBaseAndroidView { void surfaceAvailable(jobject surface, int width, int height) override { std::static_pointer_cast(T::getCanvasProvider()) ->surfaceAvailable(surface, width, height); + + // Try to render directly when the surface has been set so that + // we don't have to wait until the draw loop returns. + RNSkView::renderImmediate(); } void surfaceDestroyed() override { diff --git a/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp b/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp index 00a8a60eefc46..5764b75b8c97c 100644 --- a/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp +++ b/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp @@ -23,11 +23,12 @@ float RNSkOpenGLCanvasProvider::getScaledWidth() { return _width; } float RNSkOpenGLCanvasProvider::getScaledHeight() { return _height; } -void RNSkOpenGLCanvasProvider::renderToCanvas( +bool RNSkOpenGLCanvasProvider::renderToCanvas( const std::function &cb) { if (_renderer != nullptr) { - _renderer->run(cb, _width, _height); + return _renderer->run(cb, _width, _height); } + return false; } void RNSkOpenGLCanvasProvider::surfaceAvailable(jobject surface, int width, diff --git a/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.h b/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.h index c7e8a40985b23..f340b4e18ea01 100644 --- a/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.h +++ b/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.h @@ -25,7 +25,7 @@ class RNSkOpenGLCanvasProvider float getScaledHeight() override; - void renderToCanvas(const std::function &cb) override; + bool renderToCanvas(const std::function &cb) override; void surfaceAvailable(jobject surface, int width, int height); diff --git a/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/SkiaOpenGLRenderer.cpp b/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/SkiaOpenGLRenderer.cpp index 1de8d28b81ea2..353d4a4fedcca 100644 --- a/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/SkiaOpenGLRenderer.cpp +++ b/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/SkiaOpenGLRenderer.cpp @@ -4,6 +4,8 @@ #include #include +#define STENCIL_BUFFER_SIZE 8 + namespace RNSkia { /** Static members */ sk_sp MakeOffscreenGLSurface(int width, int height) { @@ -137,7 +139,7 @@ SkiaOpenGLRenderer::~SkiaOpenGLRenderer() { _nativeWindow = nullptr; } -void SkiaOpenGLRenderer::run(const std::function &cb, +bool SkiaOpenGLRenderer::run(const std::function &cb, int width, int height) { switch (_renderState) { case RenderState::Initializing: { @@ -148,31 +150,48 @@ void SkiaOpenGLRenderer::run(const std::function &cb, case RenderState::Rendering: { // Make sure to initialize the rendering pipeline if (!ensureInitialised()) { - break; - } - - // Ensure we have the Skia surface to draw on. We need to - // pass width and height since the surface will be recreated - // when the view is resized. - if (!ensureSkiaSurface(width, height)) { - return; + return false; } if (cb != nullptr) { - // Reset Skia Context since it might be modified by another Skia View - // during rendering. + // RNSkLogger::logToConsole("SKIARENDER - Render begin"); + getThreadDrawingContext()->skContext->resetContext(); + SkColorType colorType; + // setup surface for fbo0 + GrGLFramebufferInfo fboInfo; + fboInfo.fFBOID = 0; + fboInfo.fFormat = 0x8058; + colorType = kN32_SkColorType; + + GrBackendRenderTarget backendRT(width, height, 0, STENCIL_BUFFER_SIZE, + fboInfo); + + SkSurfaceProps props(0, kUnknown_SkPixelGeometry); + + sk_sp renderTarget(SkSurface::MakeFromBackendRenderTarget( + getThreadDrawingContext()->skContext.get(), backendRT, + kBottomLeft_GrSurfaceOrigin, colorType, nullptr, &props)); + + auto canvas = renderTarget->getCanvas(); + // Draw picture into surface - cb(_skSurface->getCanvas()); + cb(canvas); + // Flush - _skSurface->flushAndSubmit(); + canvas->flush(); if (!eglSwapBuffers(getThreadDrawingContext()->glDisplay, _glSurface)) { RNSkLogger::logToConsole("eglSwapBuffers failed: %d\n", eglGetError()); + return false; } + + // RNSkLogger::logToConsole("SKIARENDER - render done"); + return true; } - break; + + return false; } case RenderState::Finishing: { _renderState = RenderState::Done; @@ -184,14 +203,11 @@ void SkiaOpenGLRenderer::run(const std::function &cb, _glSurface = EGL_NO_SURFACE; } - // Release Skia Surface - _skSurface = nullptr; - - break; + return true; } case RenderState::Done: { // Do nothing. We're done. - break; + return true; } } } @@ -326,54 +342,4 @@ bool SkiaOpenGLRenderer::initGLSurface() { return true; } - -bool SkiaOpenGLRenderer::ensureSkiaSurface(int width, int height) { - if (getThreadDrawingContext()->skContext == nullptr) { - return false; - } - - if (_skSurface == nullptr || !_skRenderTarget.isValid() || - _prevWidth != width || _prevHeight != height) { - glViewport(0, 0, width, height); - - _prevWidth = width; - _prevHeight = height; - - GLint buffer; - glGetIntegerv(GL_FRAMEBUFFER_BINDING, &buffer); - - GLint stencil; - glGetIntegerv(GL_STENCIL_BITS, &stencil); - - GLint samples; - glGetIntegerv(GL_SAMPLES, &samples); - - auto maxSamples = - getThreadDrawingContext()->skContext->maxSurfaceSampleCountForColorType( - kRGBA_8888_SkColorType); - - if (samples > maxSamples) - samples = maxSamples; - - GrGLFramebufferInfo fbInfo; - fbInfo.fFBOID = buffer; - fbInfo.fFormat = 0x8058; - - _skRenderTarget = - GrBackendRenderTarget(width, height, samples, stencil, fbInfo); - - _skSurface = SkSurface::MakeFromBackendRenderTarget( - getThreadDrawingContext()->skContext.get(), _skRenderTarget, - kBottomLeft_GrSurfaceOrigin, kRGBA_8888_SkColorType, nullptr, nullptr); - - if (!_skSurface) { - RNSkLogger::logToConsole( - "JniSkiaDrawView::setupSurface - skSurface could not be created!"); - return false; - } - - return true; - } - return true; -} } // namespace RNSkia \ No newline at end of file diff --git a/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/SkiaOpenGLRenderer.h b/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/SkiaOpenGLRenderer.h index e7d89133b7c0a..9b6330cfcdeb6 100644 --- a/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/SkiaOpenGLRenderer.h +++ b/android/vendored/unversioned/@shopify/react-native-skia/android/cpp/rnskia-android/SkiaOpenGLRenderer.h @@ -60,7 +60,7 @@ class SkiaOpenGLRenderer { * @param width Width of surface to render if there is a picture * @param height Height of surface to render if there is a picture */ - void run(const std::function &cb, int width, int height); + bool run(const std::function &cb, int width, int height); /** * Sets the state to finishing. Next time the renderer will be called it @@ -102,15 +102,6 @@ class SkiaOpenGLRenderer { */ bool initGLSurface(); - /** - * Ensures that we have a valid Skia surface to draw to. The surface will - * be recreated if the width/height change. - * @param width Width of the underlying view - * @param height Height of the underlying view - * @return True if initialization went well - */ - bool ensureSkiaSurface(int width, int height); - /** * To be able to use static contexts (and avoid reloading the skia context for * each new view, we track the OpenGL and Skia drawing context per thread. @@ -121,8 +112,6 @@ class SkiaOpenGLRenderer { EGLSurface _glSurface = EGL_NO_SURFACE; ANativeWindow *_nativeWindow = nullptr; - GrBackendRenderTarget _skRenderTarget; - sk_sp _skSurface; int _prevWidth = 0; int _prevHeight = 0; diff --git a/android/vendored/unversioned/@shopify/react-native-skia/android/src/main/java/com/shopify/reactnative/skia/ViewScreenshotService.java b/android/vendored/unversioned/@shopify/react-native-skia/android/src/main/java/com/shopify/reactnative/skia/ViewScreenshotService.java index b0c4431ce4838..adb8104567b51 100644 --- a/android/vendored/unversioned/@shopify/react-native-skia/android/src/main/java/com/shopify/reactnative/skia/ViewScreenshotService.java +++ b/android/vendored/unversioned/@shopify/react-native-skia/android/src/main/java/com/shopify/reactnative/skia/ViewScreenshotService.java @@ -58,123 +58,124 @@ public static Bitmap makeViewScreenshotFromTag(ReactContext context, int tag) { paint.setDither(true); // Render the main view and its children - final Canvas c = new Canvas(bitmap); - view.draw(c); + final Canvas canvas = new Canvas(bitmap); - // Enumerate children - final List childrenList = getAllChildren(view); + // Renders view with child views to canvas + renderViewToCanvas(canvas, view, paint); - for (final View child : childrenList) { - // skip any child that we don't know how to process - if (child instanceof TextureView) { - // skip all invisible to user child views - if (child.getVisibility() != VISIBLE) continue; + return bitmap; + } - final TextureView tvChild = (TextureView) child; - tvChild.setOpaque(false); // <-- switch off background fill - - // TextureView should use bitmaps with matching size, - // otherwise content of the TextureView will be scaled to provided bitmap dimensions - final Bitmap childBitmapBuffer = tvChild.getBitmap(Bitmap.createBitmap(child.getWidth(), child.getHeight(), Bitmap.Config.ARGB_8888)); - - final int countCanvasSave = c.save(); - applyTransformations(c, view, child); - - // due to re-use of bitmaps for screenshot, we can get bitmap that is bigger in size than requested - c.drawBitmap(childBitmapBuffer, 0, 0, paint); - - c.restoreToCount(countCanvasSave); - } else if (child instanceof SurfaceView) { - final SurfaceView svChild = (SurfaceView)child; - final CountDownLatch latch = new CountDownLatch(1); - - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - final Bitmap childBitmapBuffer = Bitmap.createBitmap(child.getWidth(), child.getHeight(), Bitmap.Config.ARGB_8888); - try { - PixelCopy.request(svChild, childBitmapBuffer, new PixelCopy.OnPixelCopyFinishedListener() { - @Override - public void onPixelCopyFinished(int copyResult) { - final int countCanvasSave = c.save(); - applyTransformations(c, view, child); - c.drawBitmap(childBitmapBuffer, 0, 0, paint); - c.restoreToCount(countCanvasSave); - latch.countDown(); - } - }, new Handler(Looper.getMainLooper())); - latch.await(SURFACE_VIEW_READ_PIXELS_TIMEOUT, TimeUnit.SECONDS); - } catch (Exception e) { - Log.e(TAG, "Cannot PixelCopy for " + svChild, e); - } - } else { - Bitmap cache = svChild.getDrawingCache(); - if (cache != null) { - c.drawBitmap(svChild.getDrawingCache(), 0, 0, paint); - } + private static void renderViewToCanvas(Canvas canvas, View view, Paint paint) { + // Apply transformations for the current view + canvas.save(); + applyTransformations(canvas, view); + + // Draw children if the view has children + if ((view instanceof ViewGroup)) { + // Draw children + ViewGroup group = (ViewGroup) view; + + // Hide visible children - this needs to be done because view.draw(canvas) + // will render all visible non-texture/surface views directly - causing + // views to be rendered twice - once by view.draw() and once when we + // enumerate children. We therefore need to turn off rendering of visible + // children before we call view.draw: + List visibleChildren = new ArrayList<>(); + for (int i = 0; i < group.getChildCount(); i++) { + View child = group.getChildAt(i); + if (child.getVisibility() == VISIBLE) { + visibleChildren.add(child); + child.setVisibility(View.INVISIBLE); } } - } - - return bitmap; - } - private static List getAllChildren(@NonNull final View v) { - if (!(v instanceof ViewGroup)) { - final ArrayList viewArrayList = new ArrayList<>(); - viewArrayList.add(v); + // Draw ourselves + view.draw(canvas); - return viewArrayList; - } + // Enable children again + for (int i = 0; i < visibleChildren.size(); i++) { + View child = visibleChildren.get(i); + child.setVisibility(VISIBLE); + } - final ArrayList result = new ArrayList<>(); + // Draw children + for (int i = 0; i < group.getChildCount(); i++) { + View child = group.getChildAt(i); - ViewGroup viewGroup = (ViewGroup) v; - for (int i = 0; i < viewGroup.getChildCount(); i++) { - View child = viewGroup.getChildAt(i); + // skip all invisible to user child views + if (child.getVisibility() != VISIBLE) continue; - //Do not add any parents, just add child elements - result.addAll(getAllChildren(child)); + // skip any child that we don't know how to process + if (child instanceof TextureView) { + final TextureView tvChild = (TextureView) child; + tvChild.setOpaque(false); // <-- switch off background fill + + canvas.save(); + applyTransformations(canvas, child); + + // TextureView should use bitmaps with matching size, + // otherwise content of the TextureView will be scaled to provided bitmap dimensions + final Bitmap childBitmapBuffer = tvChild.getBitmap(Bitmap.createBitmap(child.getWidth(), child.getHeight(), Bitmap.Config.ARGB_8888)); + canvas.drawBitmap(childBitmapBuffer, 0, 0, paint); + + canvas.restore(); + + } else if (child instanceof SurfaceView) { + final SurfaceView svChild = (SurfaceView) child; + final CountDownLatch latch = new CountDownLatch(1); + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + final Bitmap childBitmapBuffer = Bitmap.createBitmap(child.getWidth(), child.getHeight(), Bitmap.Config.ARGB_8888); + try { + PixelCopy.request(svChild, childBitmapBuffer, copyResult -> { + canvas.save(); + applyTransformations(canvas, child); + canvas.drawBitmap(childBitmapBuffer, 0, 0, paint); + canvas.restore(); + latch.countDown(); + }, new Handler(Looper.getMainLooper())); + latch.await(SURFACE_VIEW_READ_PIXELS_TIMEOUT, TimeUnit.SECONDS); + } catch (Exception e) { + Log.e(TAG, "Cannot PixelCopy for " + svChild, e); + } + } else { + Bitmap cache = svChild.getDrawingCache(); + if (cache != null) { + canvas.save(); + applyTransformations(canvas, child); + canvas.drawBitmap(svChild.getDrawingCache(), 0, 0, paint); + canvas.restore(); + } + } + } else { + // Regular views needs to be rendered again to ensure correct z-index + // order with texture views and surface views. + renderViewToCanvas(canvas, child, paint); + } + } + } else { + // Draw ourselves + view.draw(canvas); } - return result; + // Restore canvas + canvas.restore(); } - /** - * Concat all the transformation matrix's from parent to child. - */ @NonNull - @SuppressWarnings("UnusedReturnValue") - private static Matrix applyTransformations(final Canvas c, @NonNull final View root, @NonNull final View child) { - final Matrix transform = new Matrix(); - final LinkedList ms = new LinkedList<>(); - - // find all parents of the child view - View iterator = child; - do { - ms.add(iterator); - - iterator = (View) iterator.getParent(); - } while (iterator != root); - - // apply transformations from parent --> child order - Collections.reverse(ms); - - for (final View v : ms) { - c.save(); - - // apply each view transformations, so each child will be affected by them - final float dx = v.getLeft() + ((v != child) ? v.getPaddingLeft() : 0) + v.getTranslationX(); - final float dy = v.getTop() + ((v != child) ? v.getPaddingTop() : 0) + v.getTranslationY(); - c.translate(dx, dy); - c.rotate(v.getRotation(), v.getPivotX(), v.getPivotY()); - c.scale(v.getScaleX(), v.getScaleY()); - - // compute the matrix just for any future use - transform.postTranslate(dx, dy); - transform.postRotate(v.getRotation(), v.getPivotX(), v.getPivotY()); - transform.postScale(v.getScaleX(), v.getScaleY()); - } - - return transform; + private static void applyTransformations(final Canvas c, @NonNull final View view) { + // Get the transformation matrix of the view + final Matrix matrix = view.getMatrix(); + + // Create a new matrix for translation + final Matrix translateMatrix = new Matrix(); + final float dx = view.getLeft() + view.getPaddingLeft() + view.getTranslationX(); + final float dy = view.getTop() + view.getPaddingTop() + view.getTranslationY(); + translateMatrix.setTranslate(dx, dy); + + // Pre-concatenate the current matrix of the canvas with the translation and transformation matrices of the view + c.concat(translateMatrix); + c.concat(matrix); } - } diff --git a/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkDomView.cpp b/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkDomView.cpp index 9226a5649bb80..6ff1df7f6fdf4 100644 --- a/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkDomView.cpp +++ b/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkDomView.cpp @@ -36,15 +36,16 @@ bool RNSkDomRenderer::tryRender( // We render on the main thread if (_renderLock->try_lock()) { + bool result = false; // If we have a Dom Node we can render directly on the main thread if (_root != nullptr) { - canvasProvider->renderToCanvas(std::bind( + result = canvasProvider->renderToCanvas(std::bind( &RNSkDomRenderer::renderCanvas, this, std::placeholders::_1, canvasProvider->getScaledWidth(), canvasProvider->getScaledHeight())); } _renderLock->unlock(); - return true; + return result; } else { return false; } diff --git a/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkPictureView.h b/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkPictureView.h index 71cd91e023274..715c304b6a480 100644 --- a/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkPictureView.h +++ b/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkPictureView.h @@ -44,8 +44,7 @@ class RNSkPictureRenderer : RNSkRenderer(requestRedraw), _platformContext(context) {} bool tryRender(std::shared_ptr canvasProvider) override { - performDraw(canvasProvider); - return true; + return performDraw(canvasProvider); } void @@ -64,11 +63,7 @@ class RNSkPictureRenderer } private: - void performDraw(std::shared_ptr canvasProvider) { - if (_picture == nullptr) { - return; - } - + bool performDraw(std::shared_ptr canvasProvider) { canvasProvider->renderToCanvas([=](SkCanvas *canvas) { // Make sure to scale correctly auto pd = _platformContext->getPixelDensity(); @@ -76,10 +71,13 @@ class RNSkPictureRenderer canvas->save(); canvas->scale(pd, pd); - canvas->drawPicture(_picture->getObject()); + if (_picture != nullptr) { + canvas->drawPicture(_picture->getObject()); + } canvas->restore(); }); + return true; } std::shared_ptr _platformContext; diff --git a/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkView.h b/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkView.h index ba52e1fec8924..2cfda8aad8f15 100644 --- a/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkView.h +++ b/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkView.h @@ -44,7 +44,7 @@ class RNSkCanvasProvider { /** Render to a canvas */ - virtual void renderToCanvas(const std::function &) = 0; + virtual bool renderToCanvas(const std::function &) = 0; protected: std::function _requestRedraw; @@ -123,8 +123,9 @@ class RNSkImageCanvasProvider : public RNSkCanvasProvider { /** Render to a canvas */ - void renderToCanvas(const std::function &cb) override { + bool renderToCanvas(const std::function &cb) override { cb(_surface->getCanvas()); + return true; }; private: @@ -224,6 +225,15 @@ class RNSkView : public std::enable_shared_from_this { */ void requestRedraw() { _redrawRequestCounter++; } + /** + Renders immediate. Be carefull to not call this method from another thread + than the UI thread + */ + void renderImmediate() { + _renderer->renderImmediate(_canvasProvider); + _redrawRequestCounter = 0; + } + /** Sets the native id of the view */ @@ -409,6 +419,7 @@ class RNSkView : public std::enable_shared_from_this { size_t _drawingLoopId = 0; std::atomic _redrawRequestCounter = {1}; + bool _initialDrawingDone = false; }; } // namespace RNSkia diff --git a/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/dom/base/JsiDomDrawingNode.h b/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/dom/base/JsiDomDrawingNode.h index 302c49bfd3cf4..d0514e62b863b 100644 --- a/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/dom/base/JsiDomDrawingNode.h +++ b/android/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/dom/base/JsiDomDrawingNode.h @@ -30,7 +30,9 @@ class JsiDomDrawingNode : public JsiDomRenderNode { #endif // Save paint if the paint property is set if (_paintProp->isSet()) { - draw(_paintProp->getUnsafeDerivedValue().get()); + auto localCtx = _paintProp->getUnsafeDerivedValue().get(); + localCtx->setCanvas(context->getCanvas()); + draw(localCtx); } else { // Call abstract draw method draw(context); diff --git a/apps/native-component-list/package.json b/apps/native-component-list/package.json index f78354e61ff30..9d4782e841f76 100644 --- a/apps/native-component-list/package.json +++ b/apps/native-component-list/package.json @@ -56,7 +56,7 @@ "@react-navigation/native": "~6.0.13", "@react-navigation/stack": "~6.3.2", "@shopify/flash-list": "1.4.3", - "@shopify/react-native-skia": "0.1.193", + "@shopify/react-native-skia": "0.1.195", "date-format": "^2.0.0", "deep-object-diff": "^1.1.9", "expo": "~49.0.0-alpha.1", diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 995ef03019f9e..11d326d942007 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -2089,7 +2089,7 @@ PODS: - ReactCommon/turbomodule/core - react-native-segmented-control (2.4.1): - React-Core - - react-native-skia (0.1.193): + - react-native-skia (0.1.195): - React - React-callinvoker - React-Core @@ -3763,7 +3763,7 @@ SPEC CHECKSUMS: react-native-pager-view: 0ccb8bf60e2ebd38b1f3669fa3650ecce81db2df react-native-safe-area-context: 36cc67648134e89465663b8172336a19eeda493d react-native-segmented-control: 0e4b5d93911e2234f110057df2b41738b326ab3e - react-native-skia: d770660c767ab137636bd30bf18a1b70a18055c8 + react-native-skia: a1bb816972960f3506c1339738eac794814fbac0 react-native-slider: 33b8d190b59d4f67a541061bb91775d53d617d9d react-native-webview: b8ec89966713985111a14d6e4bf98d8b54bced0d React-NativeModulesApple: 038cd625999ff352fc13d11fd335ea7509794599 diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkDomView.cpp b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkDomView.cpp index 9226a5649bb80..6ff1df7f6fdf4 100644 --- a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkDomView.cpp +++ b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkDomView.cpp @@ -36,15 +36,16 @@ bool RNSkDomRenderer::tryRender( // We render on the main thread if (_renderLock->try_lock()) { + bool result = false; // If we have a Dom Node we can render directly on the main thread if (_root != nullptr) { - canvasProvider->renderToCanvas(std::bind( + result = canvasProvider->renderToCanvas(std::bind( &RNSkDomRenderer::renderCanvas, this, std::placeholders::_1, canvasProvider->getScaledWidth(), canvasProvider->getScaledHeight())); } _renderLock->unlock(); - return true; + return result; } else { return false; } diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkPictureView.h b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkPictureView.h index 71cd91e023274..715c304b6a480 100644 --- a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkPictureView.h +++ b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkPictureView.h @@ -44,8 +44,7 @@ class RNSkPictureRenderer : RNSkRenderer(requestRedraw), _platformContext(context) {} bool tryRender(std::shared_ptr canvasProvider) override { - performDraw(canvasProvider); - return true; + return performDraw(canvasProvider); } void @@ -64,11 +63,7 @@ class RNSkPictureRenderer } private: - void performDraw(std::shared_ptr canvasProvider) { - if (_picture == nullptr) { - return; - } - + bool performDraw(std::shared_ptr canvasProvider) { canvasProvider->renderToCanvas([=](SkCanvas *canvas) { // Make sure to scale correctly auto pd = _platformContext->getPixelDensity(); @@ -76,10 +71,13 @@ class RNSkPictureRenderer canvas->save(); canvas->scale(pd, pd); - canvas->drawPicture(_picture->getObject()); + if (_picture != nullptr) { + canvas->drawPicture(_picture->getObject()); + } canvas->restore(); }); + return true; } std::shared_ptr _platformContext; diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkView.h b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkView.h index ba52e1fec8924..2cfda8aad8f15 100644 --- a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkView.h +++ b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/RNSkView.h @@ -44,7 +44,7 @@ class RNSkCanvasProvider { /** Render to a canvas */ - virtual void renderToCanvas(const std::function &) = 0; + virtual bool renderToCanvas(const std::function &) = 0; protected: std::function _requestRedraw; @@ -123,8 +123,9 @@ class RNSkImageCanvasProvider : public RNSkCanvasProvider { /** Render to a canvas */ - void renderToCanvas(const std::function &cb) override { + bool renderToCanvas(const std::function &cb) override { cb(_surface->getCanvas()); + return true; }; private: @@ -224,6 +225,15 @@ class RNSkView : public std::enable_shared_from_this { */ void requestRedraw() { _redrawRequestCounter++; } + /** + Renders immediate. Be carefull to not call this method from another thread + than the UI thread + */ + void renderImmediate() { + _renderer->renderImmediate(_canvasProvider); + _redrawRequestCounter = 0; + } + /** Sets the native id of the view */ @@ -409,6 +419,7 @@ class RNSkView : public std::enable_shared_from_this { size_t _drawingLoopId = 0; std::atomic _redrawRequestCounter = {1}; + bool _initialDrawingDone = false; }; } // namespace RNSkia diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/dom/base/JsiDomDrawingNode.h b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/dom/base/JsiDomDrawingNode.h index 302c49bfd3cf4..d0514e62b863b 100644 --- a/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/dom/base/JsiDomDrawingNode.h +++ b/ios/vendored/unversioned/@shopify/react-native-skia/cpp/rnskia/dom/base/JsiDomDrawingNode.h @@ -30,7 +30,9 @@ class JsiDomDrawingNode : public JsiDomRenderNode { #endif // Save paint if the paint property is set if (_paintProp->isSet()) { - draw(_paintProp->getUnsafeDerivedValue().get()); + auto localCtx = _paintProp->getUnsafeDerivedValue().get(); + localCtx->setCanvas(context->getCanvas()); + draw(localCtx); } else { // Call abstract draw method draw(context); diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/RNSkMetalCanvasProvider.h b/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/RNSkMetalCanvasProvider.h index 1f6df376d6a02..df6ac457d3cf8 100644 --- a/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/RNSkMetalCanvasProvider.h +++ b/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/RNSkMetalCanvasProvider.h @@ -24,7 +24,7 @@ class RNSkMetalCanvasProvider : public RNSkia::RNSkCanvasProvider { float getScaledWidth() override; float getScaledHeight() override; - void renderToCanvas(const std::function &cb) override; + bool renderToCanvas(const std::function &cb) override; void setSize(int width, int height); diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/RNSkMetalCanvasProvider.mm b/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/RNSkMetalCanvasProvider.mm index 15a444530bd21..395e5cb2329ce 100644 --- a/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/RNSkMetalCanvasProvider.mm +++ b/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/RNSkMetalCanvasProvider.mm @@ -63,10 +63,10 @@ /** Render to a canvas */ -void RNSkMetalCanvasProvider::renderToCanvas( +bool RNSkMetalCanvasProvider::renderToCanvas( const std::function &cb) { if (_width <= 0 || _height <= 0) { - return; + return false; } // Make sure to NOT render or try any render operations while we're in the @@ -77,13 +77,12 @@ // accessed from the main thread so we need to check here. if ([[NSThread currentThread] isMainThread]) { auto state = UIApplication.sharedApplication.applicationState; - if (state == UIApplicationStateBackground || - state == UIApplicationStateInactive) { + if (state == UIApplicationStateBackground) { // Request a redraw in the next run loop callback _requestRedraw(); // and don't draw now since it might cause errors in the metal renderer if // we try to render while in the background. (see above issue) - return; + return false; } } @@ -114,7 +113,7 @@ */ id currentDrawable = [_layer nextDrawable]; if (currentDrawable == nullptr) { - return; + return false; } GrMtlTextureInfo fbInfo; @@ -130,7 +129,7 @@ GrBackendRenderTarget backendRT(_layer.drawableSize.width, if (skSurface == nullptr || skSurface->getCanvas() == nullptr) { RNSkia::RNSkLogger::logToConsole( "Skia surface could not be created from parameters."); - return; + return false; } SkCanvas *canvas = skSurface->getCanvas(); @@ -143,6 +142,8 @@ GrBackendRenderTarget backendRT(_layer.drawableSize.width, [commandBuffer presentDrawable:currentDrawable]; [commandBuffer commit]; } + + return true; }; void RNSkMetalCanvasProvider::setSize(int width, int height) { diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/SkiaUIView.mm b/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/SkiaUIView.mm index 4a7a4745c8dfc..8dbbead98a8c4 100644 --- a/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/SkiaUIView.mm +++ b/ios/vendored/unversioned/@shopify/react-native-skia/ios/RNSkia-iOS/SkiaUIView.mm @@ -93,6 +93,16 @@ - (void)dealloc { assert(_impl == nullptr); } +#pragma Render + +- (void)drawRect:(CGRect)rect { + // We override drawRect to ensure we to direct rendering when the + // underlying OS view needs to render: + if (_impl != nullptr) { + _impl->getDrawView()->renderImmediate(); + } +} + #pragma mark Layout - (void)layoutSubviews { diff --git a/ios/vendored/unversioned/@shopify/react-native-skia/react-native-skia.podspec.json b/ios/vendored/unversioned/@shopify/react-native-skia/react-native-skia.podspec.json index aa72f68f927a8..d6dbca80a9067 100644 --- a/ios/vendored/unversioned/@shopify/react-native-skia/react-native-skia.podspec.json +++ b/ios/vendored/unversioned/@shopify/react-native-skia/react-native-skia.podspec.json @@ -1,6 +1,6 @@ { "name": "react-native-skia", - "version": "0.1.193", + "version": "0.1.195", "summary": "High-performance React Native Graphics using Skia", "description": "@shopify/react-native-skia", "homepage": "https://github.com/shopify/react-native-skia", @@ -13,7 +13,7 @@ }, "source": { "git": "https://github.com/shopify/react-native-skia/react-native-skia.git", - "tag": "0.1.193" + "tag": "0.1.195" }, "requires_arc": true, "pod_target_xcconfig": { diff --git a/packages/expo/bundledNativeModules.json b/packages/expo/bundledNativeModules.json index 44ae47739124d..4f6338bd1500c 100644 --- a/packages/expo/bundledNativeModules.json +++ b/packages/expo/bundledNativeModules.json @@ -99,7 +99,7 @@ "sentry-expo": "~7.0.0", "unimodules-app-loader": "~4.2.0", "unimodules-image-loader-interface": "~6.1.0", - "@shopify/react-native-skia": "0.1.193", + "@shopify/react-native-skia": "0.1.195", "@shopify/flash-list": "1.4.3", "@sentry/react-native": "5.5.0" } diff --git a/yarn.lock b/yarn.lock index 870338da2f8f9..184c0737f7273 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3539,10 +3539,10 @@ recyclerlistview "4.2.0" tslib "2.4.0" -"@shopify/react-native-skia@0.1.193": - version "0.1.193" - resolved "https://registry.yarnpkg.com/@shopify/react-native-skia/-/react-native-skia-0.1.193.tgz#f03e5ec1afb7a97fb31c391369abeccadb2ada76" - integrity sha512-Y8aM8jFbV4F7HB8prnizA1fS7ILCqsgH/EcxtIlz3JTFMHeUHQb7MuCZL8PaqWPcUCFXwPM3EHWob4ynckpzCQ== +"@shopify/react-native-skia@0.1.195": + version "0.1.195" + resolved "https://registry.yarnpkg.com/@shopify/react-native-skia/-/react-native-skia-0.1.195.tgz#b911bccf651967356a9ac2203318be4b3b2fb709" + integrity sha512-uVehYdr2jInBnpZ70f28MzlAIPcjnrv9nK7pLitbLkQUkq4RGfO/SkUvpK52uQGIf1wK3fgJYhDfaJK4fOBE/g== dependencies: canvaskit-wasm "0.38.0" react-reconciler "^0.27.0"