@shopify/react-native-skia 0.1.199 → 0.1.201

Sign up to get free protection for your applications and to get access to all the features.
Files changed (24) hide show
  1. package/android/CMakeLists.txt +1 -1
  2. package/android/cpp/jni/include/JniSkiaBaseView.h +74 -13
  3. package/android/cpp/jni/include/JniSkiaDomView.h +20 -12
  4. package/android/cpp/jni/include/JniSkiaDrawView.h +20 -14
  5. package/android/cpp/jni/include/JniSkiaPictureView.h +24 -15
  6. package/android/cpp/rnskia-android/RNSkAndroidPlatformContext.h +2 -2
  7. package/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp +41 -44
  8. package/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.h +4 -6
  9. package/android/cpp/rnskia-android/SkiaOpenGLHelper.h +310 -0
  10. package/android/cpp/rnskia-android/SkiaOpenGLSurfaceFactory.cpp +132 -0
  11. package/android/cpp/rnskia-android/SkiaOpenGLSurfaceFactory.h +125 -0
  12. package/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java +80 -11
  13. package/android/src/main/java/com/shopify/reactnative/skia/SkiaDomView.java +2 -0
  14. package/android/src/main/java/com/shopify/reactnative/skia/SkiaDrawView.java +2 -0
  15. package/android/src/main/java/com/shopify/reactnative/skia/SkiaPictureView.java +3 -0
  16. package/android/src/main/java/com/shopify/reactnative/skia/ViewScreenshotService.java +7 -5
  17. package/cpp/api/JsiSkHostObjects.h +0 -10
  18. package/cpp/rnskia/RNSkJsView.cpp +35 -10
  19. package/cpp/rnskia/RNSkJsiViewApi.h +1 -1
  20. package/cpp/rnskia/RNSkView.h +9 -9
  21. package/ios/RNSkia-iOS/ViewScreenshotService.mm +1 -0
  22. package/package.json +2 -3
  23. package/android/cpp/rnskia-android/SkiaOpenGLRenderer.cpp +0 -347
  24. package/android/cpp/rnskia-android/SkiaOpenGLRenderer.h +0 -124
@@ -45,7 +45,7 @@ add_library(
45
45
 
46
46
  "${PROJECT_SOURCE_DIR}/cpp/jni/JniPlatformContext.cpp"
47
47
  "${PROJECT_SOURCE_DIR}/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp"
48
- "${PROJECT_SOURCE_DIR}/cpp/rnskia-android/SkiaOpenGLRenderer.cpp"
48
+ "${PROJECT_SOURCE_DIR}/cpp/rnskia-android/SkiaOpenGLSurfaceFactory.cpp"
49
49
 
50
50
  "${PROJECT_SOURCE_DIR}/../cpp/jsi/JsiHostObject.cpp"
51
51
  "${PROJECT_SOURCE_DIR}/../cpp/jsi/JsiValue.cpp"
@@ -10,6 +10,8 @@
10
10
  #include <JniSkiaManager.h>
11
11
  #include <RNSkAndroidView.h>
12
12
 
13
+ #include <android/bitmap.h>
14
+
13
15
  namespace RNSkia {
14
16
 
15
17
  namespace jsi = facebook::jsi;
@@ -18,7 +20,7 @@ class JniSkiaBaseView {
18
20
  public:
19
21
  JniSkiaBaseView(jni::alias_ref<JniSkiaManager::javaobject> skiaManager,
20
22
  std::shared_ptr<RNSkBaseAndroidView> skiaView)
21
- : _manager(skiaManager->cthis()), _skiaView(skiaView) {}
23
+ : _manager(skiaManager->cthis()), _skiaAndroidView(skiaView) {}
22
24
 
23
25
  ~JniSkiaBaseView() {}
24
26
 
@@ -28,38 +30,97 @@ public:
28
30
 
29
31
  protected:
30
32
  virtual void updateTouchPoints(jni::JArrayDouble touches) {
31
- _skiaView->updateTouchPoints(touches);
33
+ _skiaAndroidView->updateTouchPoints(touches);
32
34
  }
33
35
 
34
36
  virtual void surfaceAvailable(jobject surface, int width, int height) {
35
- _skiaView->surfaceAvailable(surface, width, height);
37
+ _skiaAndroidView->surfaceAvailable(surface, width, height);
36
38
  }
37
39
 
38
40
  virtual void surfaceSizeChanged(int width, int height) {
39
- _skiaView->surfaceSizeChanged(width, height);
41
+ _skiaAndroidView->surfaceSizeChanged(width, height);
40
42
  }
41
43
 
42
- virtual void surfaceDestroyed() { _skiaView->surfaceDestroyed(); }
44
+ virtual void surfaceDestroyed() { _skiaAndroidView->surfaceDestroyed(); }
43
45
 
44
- virtual void setMode(std::string mode) { _skiaView->setMode(mode); }
46
+ virtual void setMode(std::string mode) { _skiaAndroidView->setMode(mode); }
45
47
 
46
- virtual void setDebugMode(bool show) { _skiaView->setShowDebugInfo(show); }
48
+ virtual void setDebugMode(bool show) {
49
+ _skiaAndroidView->setShowDebugInfo(show);
50
+ }
47
51
 
48
52
  virtual void registerView(int nativeId) {
49
- getSkiaManager()->registerSkiaView(nativeId, _skiaView->getSkiaView());
53
+ getSkiaManager()->registerSkiaView(nativeId,
54
+ _skiaAndroidView->getSkiaView());
50
55
  }
51
56
 
52
57
  virtual void unregisterView() {
53
- getSkiaManager()->setSkiaView(_skiaView->getSkiaView()->getNativeId(),
54
- nullptr);
58
+ getSkiaManager()->setSkiaView(
59
+ _skiaAndroidView->getSkiaView()->getNativeId(), nullptr);
55
60
  getSkiaManager()->unregisterSkiaView(
56
- _skiaView->getSkiaView()->getNativeId());
57
- _skiaView->viewDidUnmount();
61
+ _skiaAndroidView->getSkiaView()->getNativeId());
62
+ _skiaAndroidView->viewDidUnmount();
58
63
  }
59
64
 
65
+ /**
66
+ * Android specific method for rendering an offscreen GPU buffer to an Android
67
+ * bitmap. The result can be used to render the first frame of the Skia render
68
+ * to avoid flickering on android.
69
+ */
70
+ /*
71
+ // TODO: Remove if we find another solution for first frame rendering
72
+ // protected native Object renderToBitmap(Object bitmap, int width, int
73
+ height); virtual jobject renderToBitmap(jobject bitmapIn, int width, int
74
+ height) { auto platformContext = getSkiaManager()->getPlatformContext(); auto
75
+ provider = std::make_shared<RNSkOffscreenCanvasProvider>( platformContext,
76
+ []() {}, width, height);
77
+
78
+ // Render into a gpu backed buffer
79
+ _skiaAndroidView->getSkiaView()->getRenderer()->renderImmediate(provider);
80
+ auto rect = SkRect::MakeXYWH(0, 0, width, height);
81
+ auto image = provider->makeSnapshot(&rect);
82
+
83
+ AndroidBitmapInfo infoIn;
84
+ auto env = facebook::jni::Environment::current();
85
+ void *pixels;
86
+
87
+ // Get image info
88
+ if (AndroidBitmap_getInfo(env, bitmapIn, &infoIn) !=
89
+ ANDROID_BITMAP_RESULT_SUCCESS) {
90
+ return env->NewStringUTF("failed");
91
+ }
92
+
93
+ // Check image
94
+ if (infoIn.format != ANDROID_BITMAP_FORMAT_RGBA_8888 &&
95
+ infoIn.format != ANDROID_BITMAP_FORMAT_RGB_565) {
96
+ return env->NewStringUTF("Only support ANDROID_BITMAP_FORMAT_RGBA_8888 "
97
+ "and ANDROID_BITMAP_FORMAT_RGB_565");
98
+ }
99
+
100
+ auto imageInfo = SkImageInfo::Make(image->width(), image->height(),
101
+ image->colorType(), image->alphaType());
102
+
103
+ // Lock all images
104
+ if (AndroidBitmap_lockPixels(env, bitmapIn, &pixels) !=
105
+ ANDROID_BITMAP_RESULT_SUCCESS) {
106
+ return env->NewStringUTF("AndroidBitmap_lockPixels failed!");
107
+ }
108
+
109
+ // Set pixels from SkImage
110
+ image->readPixels(imageInfo, pixels, imageInfo.minRowBytes(), 0, 0);
111
+
112
+ // Unlocks everything
113
+ AndroidBitmap_unlockPixels(env, bitmapIn);
114
+
115
+ image = nullptr;
116
+ provider = nullptr;
117
+
118
+ return bitmapIn;
119
+ }*/
120
+
60
121
  private:
61
122
  JniSkiaManager *_manager;
62
- std::shared_ptr<RNSkBaseAndroidView> _skiaView;
123
+ std::shared_ptr<RNSkBaseAndroidView> _skiaAndroidView;
63
124
  };
64
125
 
65
126
  } // namespace RNSkia
@@ -34,18 +34,21 @@ public:
34
34
  }
35
35
 
36
36
  static void registerNatives() {
37
- registerHybrid(
38
- {makeNativeMethod("initHybrid", JniSkiaDomView::initHybrid),
39
- makeNativeMethod("surfaceAvailable", JniSkiaDomView::surfaceAvailable),
40
- makeNativeMethod("surfaceDestroyed", JniSkiaDomView::surfaceDestroyed),
41
- makeNativeMethod("surfaceSizeChanged",
42
- JniSkiaDomView::surfaceSizeChanged),
43
- makeNativeMethod("setMode", JniSkiaDomView::setMode),
44
- makeNativeMethod("setDebugMode", JniSkiaDomView::setDebugMode),
45
- makeNativeMethod("updateTouchPoints",
46
- JniSkiaDomView::updateTouchPoints),
47
- makeNativeMethod("registerView", JniSkiaDomView::registerView),
48
- makeNativeMethod("unregisterView", JniSkiaDomView::unregisterView)});
37
+ registerHybrid({
38
+ makeNativeMethod("initHybrid", JniSkiaDomView::initHybrid),
39
+ makeNativeMethod("surfaceAvailable", JniSkiaDomView::surfaceAvailable),
40
+ makeNativeMethod("surfaceDestroyed", JniSkiaDomView::surfaceDestroyed),
41
+ makeNativeMethod("surfaceSizeChanged",
42
+ JniSkiaDomView::surfaceSizeChanged),
43
+ makeNativeMethod("setMode", JniSkiaDomView::setMode),
44
+ makeNativeMethod("setDebugMode", JniSkiaDomView::setDebugMode),
45
+ makeNativeMethod("updateTouchPoints",
46
+ JniSkiaDomView::updateTouchPoints),
47
+ makeNativeMethod("registerView", JniSkiaDomView::registerView),
48
+ makeNativeMethod("unregisterView", JniSkiaDomView::unregisterView)
49
+ // TODO: Remove if we find another solution for first frame rendering
50
+ // makeNativeMethod("renderToBitmap", JniSkiaDomView::renderToBitmap)
51
+ });
49
52
  }
50
53
 
51
54
  protected:
@@ -73,6 +76,11 @@ protected:
73
76
 
74
77
  void unregisterView() override { JniSkiaBaseView::unregisterView(); }
75
78
 
79
+ // TODO: Remove if we find another solution for first frame rendering
80
+ /*jobject renderToBitmap(jobject bitmap, int width, int height) override {
81
+ return JniSkiaBaseView::renderToBitmap(bitmap, width, height);
82
+ }*/
83
+
76
84
  private:
77
85
  friend HybridBase;
78
86
 
@@ -33,20 +33,21 @@ public:
33
33
  }
34
34
 
35
35
  static void registerNatives() {
36
- registerHybrid(
37
- {makeNativeMethod("initHybrid", JniSkiaDrawView::initHybrid),
38
- makeNativeMethod("surfaceAvailable",
39
- JniSkiaDrawView::surfaceAvailable),
40
- makeNativeMethod("surfaceDestroyed",
41
- JniSkiaDrawView::surfaceDestroyed),
42
- makeNativeMethod("surfaceSizeChanged",
43
- JniSkiaDrawView::surfaceSizeChanged),
44
- makeNativeMethod("setMode", JniSkiaDrawView::setMode),
45
- makeNativeMethod("setDebugMode", JniSkiaDrawView::setDebugMode),
46
- makeNativeMethod("updateTouchPoints",
47
- JniSkiaDrawView::updateTouchPoints),
48
- makeNativeMethod("registerView", JniSkiaDrawView::registerView),
49
- makeNativeMethod("unregisterView", JniSkiaDrawView::unregisterView)});
36
+ registerHybrid({
37
+ makeNativeMethod("initHybrid", JniSkiaDrawView::initHybrid),
38
+ makeNativeMethod("surfaceAvailable", JniSkiaDrawView::surfaceAvailable),
39
+ makeNativeMethod("surfaceDestroyed", JniSkiaDrawView::surfaceDestroyed),
40
+ makeNativeMethod("surfaceSizeChanged",
41
+ JniSkiaDrawView::surfaceSizeChanged),
42
+ makeNativeMethod("setMode", JniSkiaDrawView::setMode),
43
+ makeNativeMethod("setDebugMode", JniSkiaDrawView::setDebugMode),
44
+ makeNativeMethod("updateTouchPoints",
45
+ JniSkiaDrawView::updateTouchPoints),
46
+ makeNativeMethod("registerView", JniSkiaDrawView::registerView),
47
+ makeNativeMethod("unregisterView", JniSkiaDrawView::unregisterView),
48
+ // TODO: Remove if we find another solution for first frame rendering
49
+ // makeNativeMethod("renderToBitmap", JniSkiaDrawView::renderToBitmap)
50
+ });
50
51
  }
51
52
 
52
53
  protected:
@@ -74,6 +75,11 @@ protected:
74
75
 
75
76
  void unregisterView() override { JniSkiaBaseView::unregisterView(); }
76
77
 
78
+ // TODO: Remove if we find another solution for first frame rendering
79
+ /*jobject renderToBitmap(jobject bitmap, int width, int height) override {
80
+ return JniSkiaBaseView::renderToBitmap(bitmap, width, height);
81
+ }*/
82
+
77
83
  private:
78
84
  friend HybridBase;
79
85
 
@@ -33,21 +33,24 @@ public:
33
33
  }
34
34
 
35
35
  static void registerNatives() {
36
- registerHybrid(
37
- {makeNativeMethod("initHybrid", JniSkiaPictureView::initHybrid),
38
- makeNativeMethod("surfaceAvailable",
39
- JniSkiaPictureView::surfaceAvailable),
40
- makeNativeMethod("surfaceDestroyed",
41
- JniSkiaPictureView::surfaceDestroyed),
42
- makeNativeMethod("surfaceSizeChanged",
43
- JniSkiaPictureView::surfaceSizeChanged),
44
- makeNativeMethod("setMode", JniSkiaPictureView::setMode),
45
- makeNativeMethod("setDebugMode", JniSkiaPictureView::setDebugMode),
46
- makeNativeMethod("updateTouchPoints",
47
- JniSkiaPictureView::updateTouchPoints),
48
- makeNativeMethod("registerView", JniSkiaPictureView::registerView),
49
- makeNativeMethod("unregisterView",
50
- JniSkiaPictureView::unregisterView)});
36
+ registerHybrid({
37
+ makeNativeMethod("initHybrid", JniSkiaPictureView::initHybrid),
38
+ makeNativeMethod("surfaceAvailable",
39
+ JniSkiaPictureView::surfaceAvailable),
40
+ makeNativeMethod("surfaceDestroyed",
41
+ JniSkiaPictureView::surfaceDestroyed),
42
+ makeNativeMethod("surfaceSizeChanged",
43
+ JniSkiaPictureView::surfaceSizeChanged),
44
+ makeNativeMethod("setMode", JniSkiaPictureView::setMode),
45
+ makeNativeMethod("setDebugMode", JniSkiaPictureView::setDebugMode),
46
+ makeNativeMethod("updateTouchPoints",
47
+ JniSkiaPictureView::updateTouchPoints),
48
+ makeNativeMethod("registerView", JniSkiaPictureView::registerView),
49
+ makeNativeMethod("unregisterView", JniSkiaPictureView::unregisterView),
50
+ // TODO: Remove if we find another solution for first frame rendering
51
+ // makeNativeMethod("renderToBitmap",
52
+ // JniSkiaPictureView::renderToBitmap)
53
+ });
51
54
  }
52
55
 
53
56
  protected:
@@ -75,6 +78,12 @@ protected:
75
78
 
76
79
  void unregisterView() override { JniSkiaBaseView::unregisterView(); }
77
80
 
81
+ /*
82
+ TODO: Remove if we find another solution for first frame rendering
83
+ jobject renderToBitmap(jobject bitmap, int width, int height) override {
84
+ return JniSkiaBaseView::renderToBitmap(bitmap, width, height);
85
+ }*/
86
+
78
87
  private:
79
88
  friend HybridBase;
80
89
 
@@ -7,7 +7,7 @@
7
7
 
8
8
  #include <JniPlatformContext.h>
9
9
  #include <RNSkPlatformContext.h>
10
- #include <SkiaOpenGLRenderer.h>
10
+ #include <SkiaOpenGLSurfaceFactory.h>
11
11
 
12
12
  namespace RNSkia {
13
13
  namespace jsi = facebook::jsi;
@@ -38,7 +38,7 @@ public:
38
38
  }
39
39
 
40
40
  sk_sp<SkSurface> makeOffscreenSurface(int width, int height) override {
41
- return MakeOffscreenGLSurface(width, height);
41
+ return SkiaOpenGLSurfaceFactory::makeOffscreenSurface(width, height);
42
42
  }
43
43
 
44
44
  void runOnMainThread(std::function<void()> task) override {
@@ -14,64 +14,60 @@ namespace RNSkia {
14
14
 
15
15
  RNSkOpenGLCanvasProvider::RNSkOpenGLCanvasProvider(
16
16
  std::function<void()> requestRedraw,
17
- std::shared_ptr<RNSkia::RNSkPlatformContext> context)
18
- : RNSkCanvasProvider(requestRedraw), _context(context) {}
17
+ std::shared_ptr<RNSkia::RNSkPlatformContext> platformContext)
18
+ : RNSkCanvasProvider(requestRedraw), _platformContext(platformContext) {}
19
19
 
20
20
  RNSkOpenGLCanvasProvider::~RNSkOpenGLCanvasProvider() {}
21
21
 
22
- float RNSkOpenGLCanvasProvider::getScaledWidth() { return _width; }
22
+ float RNSkOpenGLCanvasProvider::getScaledWidth() {
23
+ return _surfaceHolder ? _surfaceHolder->getWidth() : 0;
24
+ }
23
25
 
24
- float RNSkOpenGLCanvasProvider::getScaledHeight() { return _height; }
26
+ float RNSkOpenGLCanvasProvider::getScaledHeight() {
27
+ return _surfaceHolder ? _surfaceHolder->getHeight() : 0;
28
+ }
25
29
 
26
30
  bool RNSkOpenGLCanvasProvider::renderToCanvas(
27
31
  const std::function<void(SkCanvas *)> &cb) {
28
- if (_renderer != nullptr) {
29
- return _renderer->run(cb, _width, _height);
32
+
33
+ if (_surfaceHolder != nullptr && cb != nullptr) {
34
+ // Get the surface
35
+ auto surface = _surfaceHolder->getSurface();
36
+ if (surface) {
37
+
38
+ // Ensure we are ready to render
39
+ if (!_surfaceHolder->makeCurrent()) {
40
+ return false;
41
+ }
42
+
43
+ // Draw into canvas using callback
44
+ cb(surface->getCanvas());
45
+
46
+ // Swap buffers and show on screen
47
+ return _surfaceHolder->present();
48
+
49
+ } else {
50
+ // the render context did not provide a surface
51
+ return false;
52
+ }
30
53
  }
54
+
31
55
  return false;
32
56
  }
33
57
 
34
58
  void RNSkOpenGLCanvasProvider::surfaceAvailable(jobject surface, int width,
35
59
  int height) {
36
- _width = width;
37
- _height = height;
38
-
39
- if (_renderer == nullptr) {
40
- // Create renderer!
41
- _renderer = std::make_unique<SkiaOpenGLRenderer>(surface);
60
+ // Create renderer!
61
+ _surfaceHolder =
62
+ SkiaOpenGLSurfaceFactory::makeWindowedSurface(surface, width, height);
42
63
 
43
- // Redraw
44
- _requestRedraw();
45
- }
64
+ // Post redraw request to ensure we paint in the next draw cycle.
65
+ _requestRedraw();
46
66
  }
47
67
  void RNSkOpenGLCanvasProvider::surfaceDestroyed() {
48
- if (_renderer != nullptr) {
49
- // teardown
50
- _renderer->teardown();
51
-
52
- // Teardown renderer on the render thread since OpenGL demands
53
- // same thread access for OpenGL contexts.
54
- std::condition_variable cv;
55
- std::mutex m;
56
- std::unique_lock<std::mutex> lock(m);
57
-
58
- _context->runOnRenderThread([&cv, &m, weakSelf = weak_from_this()]() {
59
- // Lock
60
- std::unique_lock<std::mutex> lock(m);
61
-
62
- auto self = weakSelf.lock();
63
- if (self) {
64
- if (self->_renderer != nullptr) {
65
- self->_renderer->run(nullptr, 0, 0);
66
- }
67
- // Remove renderer
68
- self->_renderer = nullptr;
69
- }
70
- cv.notify_one();
71
- });
72
-
73
- cv.wait(lock);
74
- }
68
+ // destroy the renderer (a unique pointer so the dtor will be called
69
+ // immediately.)
70
+ _surfaceHolder = nullptr;
75
71
  }
76
72
 
77
73
  void RNSkOpenGLCanvasProvider::surfaceSizeChanged(int width, int height) {
@@ -80,8 +76,9 @@ void RNSkOpenGLCanvasProvider::surfaceSizeChanged(int width, int height) {
80
76
  // it comes to invalidating the surface.
81
77
  return;
82
78
  }
83
- _width = width;
84
- _height = height;
79
+
80
+ // Recreate RenderContext surface based on size change???
81
+ _surfaceHolder->resize(width, height);
85
82
 
86
83
  // Redraw after size change
87
84
  _requestRedraw();
@@ -6,7 +6,7 @@
6
6
 
7
7
  #include <RNSkJsView.h>
8
8
 
9
- #include "SkiaOpenGLRenderer.h"
9
+ #include "SkiaOpenGLSurfaceFactory.h"
10
10
  #include <android/native_window.h>
11
11
 
12
12
  namespace RNSkia {
@@ -17,7 +17,7 @@ class RNSkOpenGLCanvasProvider
17
17
  public:
18
18
  RNSkOpenGLCanvasProvider(
19
19
  std::function<void()> requestRedraw,
20
- std::shared_ptr<RNSkia::RNSkPlatformContext> context);
20
+ std::shared_ptr<RNSkia::RNSkPlatformContext> platformContext);
21
21
 
22
22
  ~RNSkOpenGLCanvasProvider();
23
23
 
@@ -34,9 +34,7 @@ public:
34
34
  void surfaceSizeChanged(int width, int height);
35
35
 
36
36
  private:
37
- std::unique_ptr<SkiaOpenGLRenderer> _renderer = nullptr;
38
- std::shared_ptr<RNSkPlatformContext> _context;
39
- float _width = -1;
40
- float _height = -1;
37
+ std::unique_ptr<WindowSurfaceHolder> _surfaceHolder = nullptr;
38
+ std::shared_ptr<RNSkPlatformContext> _platformContext;
41
39
  };
42
40
  } // namespace RNSkia