@shopify/react-native-skia 0.1.122 → 0.1.123

Sign up to get free protection for your applications and to get access to all the features.
Files changed (63) hide show
  1. package/android/CMakeLists.txt +3 -1
  2. package/android/cpp/jni/JniSkiaDrawView.cpp +14 -71
  3. package/android/cpp/jni/JniSkiaManager.cpp +1 -1
  4. package/android/cpp/jni/include/JniSkiaDrawView.h +18 -22
  5. package/android/cpp/jni/include/JniSkiaManager.h +4 -4
  6. package/android/cpp/rnskia-android/RNSkDrawViewImpl.cpp +68 -0
  7. package/android/cpp/rnskia-android/RNSkDrawViewImpl.h +48 -0
  8. package/android/cpp/{jni/include/JniPlatformContextWrapper.h → rnskia-android/RNSkPlatformContextImpl.h} +4 -4
  9. package/android/cpp/{jni → rnskia-android}/SkiaOpenGLRenderer.cpp +39 -54
  10. package/android/cpp/{jni/include → rnskia-android}/SkiaOpenGLRenderer.h +2 -31
  11. package/android/src/main/java/com/shopify/reactnative/skia/RNSkiaViewManager.java +1 -1
  12. package/android/src/main/java/com/shopify/reactnative/skia/SkiaDrawView.java +21 -28
  13. package/cpp/rnskia/RNSkDrawView.cpp +77 -116
  14. package/cpp/rnskia/RNSkDrawView.h +5 -35
  15. package/cpp/rnskia/RNSkJsiViewApi.h +8 -5
  16. package/cpp/rnskia/RNSkManager.cpp +2 -2
  17. package/cpp/rnskia/RNSkManager.h +2 -2
  18. package/cpp/rnskia/RNSkPlatformContext.h +1 -1
  19. package/cpp/rnskia/values/RNSkClockValue.h +16 -8
  20. package/cpp/rnskia/values/RNSkReadonlyValue.h +11 -5
  21. package/cpp/utils/RNSkTimingInfo.h +13 -1
  22. package/ios/RNSkia-iOS/RNSkDrawViewImpl.h +5 -7
  23. package/ios/RNSkia-iOS/RNSkDrawViewImpl.mm +25 -10
  24. package/ios/RNSkia-iOS/SkiaDrawView.mm +21 -15
  25. package/lib/commonjs/renderer/Canvas.js +3 -3
  26. package/lib/commonjs/renderer/Canvas.js.map +1 -1
  27. package/lib/commonjs/renderer/components/Paint.js +1 -1
  28. package/lib/commonjs/renderer/components/Paint.js.map +1 -1
  29. package/lib/commonjs/renderer/components/shapes/Path.js +9 -1
  30. package/lib/commonjs/renderer/components/shapes/Path.js.map +1 -1
  31. package/lib/commonjs/renderer/processors/Paint.js +6 -1
  32. package/lib/commonjs/renderer/processors/Paint.js.map +1 -1
  33. package/lib/commonjs/skia/Paint/Paint.js +13 -1
  34. package/lib/commonjs/skia/Paint/Paint.js.map +1 -1
  35. package/lib/commonjs/skia/Paint/usePaint.js +2 -4
  36. package/lib/commonjs/skia/Paint/usePaint.js.map +1 -1
  37. package/lib/commonjs/skia/Skia.js +3 -1
  38. package/lib/commonjs/skia/Skia.js.map +1 -1
  39. package/lib/module/renderer/Canvas.js +2 -2
  40. package/lib/module/renderer/Canvas.js.map +1 -1
  41. package/lib/module/renderer/components/Paint.js +2 -2
  42. package/lib/module/renderer/components/Paint.js.map +1 -1
  43. package/lib/module/renderer/components/shapes/Path.js +9 -2
  44. package/lib/module/renderer/components/shapes/Path.js.map +1 -1
  45. package/lib/module/renderer/processors/Paint.js +6 -1
  46. package/lib/module/renderer/processors/Paint.js.map +1 -1
  47. package/lib/module/skia/Paint/Paint.js +6 -0
  48. package/lib/module/skia/Paint/Paint.js.map +1 -1
  49. package/lib/module/skia/Paint/usePaint.js +2 -3
  50. package/lib/module/skia/Paint/usePaint.js.map +1 -1
  51. package/lib/module/skia/Skia.js +3 -1
  52. package/lib/module/skia/Skia.js.map +1 -1
  53. package/lib/typescript/src/renderer/components/shapes/Path.d.ts +3 -1
  54. package/lib/typescript/src/renderer/processors/Paint.d.ts +2 -1
  55. package/lib/typescript/src/skia/Paint/Paint.d.ts +1 -0
  56. package/package.json +1 -1
  57. package/src/renderer/Canvas.tsx +2 -2
  58. package/src/renderer/components/Paint.tsx +2 -2
  59. package/src/renderer/components/shapes/Path.tsx +11 -3
  60. package/src/renderer/processors/Paint.ts +5 -0
  61. package/src/skia/Paint/Paint.ts +7 -0
  62. package/src/skia/Paint/usePaint.ts +2 -4
  63. package/src/skia/Skia.ts +4 -1
@@ -18,10 +18,11 @@ public class SkiaDrawView extends TextureView implements TextureView.SurfaceText
18
18
  @DoNotStrip
19
19
  private HybridData mHybridData;
20
20
 
21
- private Surface mSurface;
21
+ @DoNotStrip
22
+ private boolean mViewRemoved;
22
23
 
23
24
  @DoNotStrip
24
- private boolean mIsRemoved = false;
25
+ private Surface mSurface;
25
26
 
26
27
  public SkiaDrawView(Context ctx) {
27
28
  super(ctx);
@@ -36,26 +37,25 @@ public class SkiaDrawView extends TextureView implements TextureView.SurfaceText
36
37
  // Texture view does not support setting the background color.
37
38
  }
38
39
 
39
- @Override
40
- protected void finalize() throws Throwable {
41
- mHybridData.resetNative();
42
- super.finalize();
40
+ public void releaseSurface() {
41
+ if(mSurface != null) {
42
+ mSurface.release();
43
+ mSurface = null;
44
+ }
45
+ // We can only reset the native side when the view was removed from screen.
46
+ // releasing the surface can also be done when the view is hidden and then
47
+ // we should only release the surface - and keep the native part around.
48
+ if(mViewRemoved) {
49
+ mHybridData.resetNative();
50
+ }
43
51
  }
44
52
 
45
-
46
- public void onRemoved() {
47
- // We'll mark the view removed since we reset the native part.
48
- // This means that none of the native methods should be called after
49
- // this point.
50
- mIsRemoved = true;
51
- mHybridData.resetNative();
53
+ void onViewRemoved() {
54
+ mViewRemoved = true;
52
55
  }
53
56
 
54
57
  @Override
55
58
  public boolean onTouchEvent(MotionEvent ev) {
56
- if(mIsRemoved) {
57
- return false;
58
- }
59
59
  int action = ev.getAction();
60
60
  int count = ev.getPointerCount();
61
61
  MotionEvent.PointerCoords r = new MotionEvent.PointerCoords();
@@ -88,30 +88,23 @@ public class SkiaDrawView extends TextureView implements TextureView.SurfaceText
88
88
 
89
89
  @Override
90
90
  public void onSurfaceTextureAvailable(SurfaceTexture surface, int width, int height) {
91
- if(mIsRemoved) {
92
- return;
93
- }
94
91
  mSurface = new Surface(surface);
95
92
  surfaceAvailable(mSurface, width, height);
96
93
  }
97
94
 
98
95
  @Override
99
96
  public void onSurfaceTextureSizeChanged(SurfaceTexture surface, int width, int height) {
100
- if(mIsRemoved) {
101
- return;
102
- }
103
97
  surfaceSizeChanged(width, height);
104
98
  }
105
99
 
106
100
  @Override
107
101
  public boolean onSurfaceTextureDestroyed(SurfaceTexture surface) {
108
- if(mIsRemoved) {
109
- return true;
110
- }
111
102
  surfaceDestroyed();
112
- mSurface.release();
113
- mSurface = null;
114
- return true;
103
+ // https://developer.android.com/reference/android/view/TextureView.SurfaceTextureListener#onSurfaceTextureDestroyed(android.graphics.SurfaceTexture)
104
+ // Invoked when the specified SurfaceTexture is about to be destroyed. If returns true,
105
+ // no rendering should happen inside the surface texture after this method is invoked.
106
+ // If returns false, the client needs to call SurfaceTexture#release().
107
+ return false;
115
108
  }
116
109
 
117
110
  @Override
@@ -40,31 +40,13 @@ RNSkDrawView::RNSkDrawView(std::shared_ptr<RNSkPlatformContext> context)
40
40
  _platformContext(std::move(context)),
41
41
  _infoObject(std::make_shared<RNSkInfoObject>()),
42
42
  _jsDrawingLock(std::make_shared<std::timed_mutex>()),
43
- _gpuDrawingLock(std::make_shared<std::timed_mutex>())
43
+ _gpuDrawingLock(std::make_shared<std::timed_mutex>()),
44
+ _jsTimingInfo("SKIA/JS"),
45
+ _gpuTimingInfo("SKIA/GPU")
44
46
  {}
45
47
 
46
48
  RNSkDrawView::~RNSkDrawView() {
47
- #if LOG_ALL_DRAWING
48
- RNSkLogger::logToConsole("RNSkDrawView::~RNSkDrawView - %i", getNativeId());
49
- #endif
50
-
51
- _isInvalidated = true;
52
-
53
49
  endDrawingLoop();
54
-
55
- // Wait for the drawing locks
56
- if(!_jsDrawingLock->try_lock_for(1250ms)) {
57
- RNSkLogger::logToConsole("Warning: JS drawing is still locked for native view with id %i", _nativeId);
58
- }
59
-
60
- if(!_gpuDrawingLock->try_lock_for(1250ms)) {
61
- RNSkLogger::logToConsole("Warning: SKIA drawing is still locked for native view with id %i", _nativeId);
62
- }
63
-
64
- onInvalidated();
65
-
66
- _jsDrawingLock = nullptr;
67
- _gpuDrawingLock = nullptr;
68
50
  }
69
51
 
70
52
  void RNSkDrawView::setNativeId(size_t nativeId) {
@@ -84,7 +66,6 @@ void RNSkDrawView::setDrawCallback(std::shared_ptr<jsi::Function> callback) {
84
66
  // Reset timing info
85
67
  _jsTimingInfo.reset();
86
68
  _gpuTimingInfo.reset();
87
- _vsyncTimingInfo.reset();
88
69
 
89
70
  // Set up debug font/paints
90
71
  auto font = SkFont();
@@ -94,53 +75,57 @@ void RNSkDrawView::setDrawCallback(std::shared_ptr<jsi::Function> callback) {
94
75
 
95
76
  // Create draw drawCallback wrapper
96
77
  _drawCallback = std::make_shared<RNSkDrawCallback>(
97
- [this, paint = std::move(paint), font = std::move(font), callback = std::move(callback)](std::shared_ptr<JsiSkCanvas> canvas, int width,
98
- int height, double timestamp,
99
- std::shared_ptr<RNSkPlatformContext> context) {
100
-
101
- auto runtime = context->getJsRuntime();
102
-
103
- // Update info parameter
104
- _infoObject->beginDrawOperation(width, height, timestamp);
105
-
106
- // Set up arguments array
107
- std::vector<jsi::Value> args(2);
108
- args[0] = jsi::Object::createFromHostObject(*runtime, canvas);
109
- args[1] = jsi::Object::createFromHostObject(*runtime, _infoObject);
110
-
111
- // To be able to call the drawing function we'll wrap it once again
112
- callback->call(*runtime,
113
- static_cast<const jsi::Value *>(args.data()),
114
- (size_t)2);
115
-
116
- // Reset touches
117
- _infoObject->endDrawOperation();
118
-
119
- // Draw debug overlays
120
- if (_showDebugOverlay) {
121
-
122
- // Display average rendering timer
123
- auto jsAvg = _jsTimingInfo.getAverage();
124
- //auto jsFps = _jsTimingInfo.getFps();
125
-
126
- auto gpuAvg = _gpuTimingInfo.getAverage();
127
- //auto gpuFps = _gpuTimingInfo.getFps();
128
-
129
- auto total = jsAvg + gpuAvg;
130
-
131
- //auto vsyncFps = _vsyncTimingInfo.getFps();
132
-
133
- // Build string
134
- std::ostringstream stream;
135
- stream << "js: " << jsAvg << "ms gpu: " << gpuAvg << "ms " << " total: " << total << "ms";
136
- // stream << "js:" << jsAvg << "ms/" << jsFps << "fps " << "gpu:" << gpuAvg << "ms/" <<
137
- // gpuFps << "fps" << " total:" << total << "ms/" << vsyncFps << "fps";
138
-
139
- std::string debugString = stream.str();
140
-
141
- canvas->getCanvas()->drawSimpleText(
142
- debugString.c_str(), debugString.size(), SkTextEncoding::kUTF8, 8,
143
- 18, font, paint);
78
+ [weakSelf = weak_from_this(),
79
+ paint = std::move(paint),
80
+ font = std::move(font),
81
+ callback = std::move(callback)](std::shared_ptr<JsiSkCanvas> canvas,
82
+ int width,
83
+ int height,
84
+ double timestamp,
85
+ std::shared_ptr<RNSkPlatformContext> context) {
86
+
87
+ auto self = weakSelf.lock();
88
+ if(self) {
89
+ auto runtime = context->getJsRuntime();
90
+
91
+ // Update info parameter
92
+ self->_infoObject->beginDrawOperation(width, height, timestamp);
93
+
94
+ // Set up arguments array
95
+ std::vector<jsi::Value> args(2);
96
+ args[0] = jsi::Object::createFromHostObject(*runtime, canvas);
97
+ args[1] = jsi::Object::createFromHostObject(*runtime, self->_infoObject);
98
+
99
+ // To be able to call the drawing function we'll wrap it once again
100
+ callback->call(*runtime,
101
+ static_cast<const jsi::Value *>(args.data()),
102
+ (size_t)2);
103
+
104
+ // Reset touches
105
+ self->_infoObject->endDrawOperation();
106
+
107
+ // Draw debug overlays
108
+ if (self->_showDebugOverlay) {
109
+
110
+ // Display average rendering timer
111
+ auto jsAvg = self->_jsTimingInfo.getAverage();
112
+ //auto jsFps = _jsTimingInfo.getFps();
113
+
114
+ auto gpuAvg = self->_gpuTimingInfo.getAverage();
115
+ //auto gpuFps = _gpuTimingInfo.getFps();
116
+
117
+ auto total = jsAvg + gpuAvg;
118
+
119
+ // Build string
120
+ std::ostringstream stream;
121
+ stream << "js: " << jsAvg << "ms gpu: " << gpuAvg << "ms " << " total: " << total << "ms";
122
+
123
+ std::string debugString = stream.str();
124
+
125
+ canvas->getCanvas()->drawSimpleText(
126
+ debugString.c_str(), debugString.size(), SkTextEncoding::kUTF8, 8,
127
+ 18, font, paint);
128
+ }
144
129
  }
145
130
  });
146
131
 
@@ -196,10 +181,6 @@ void RNSkDrawView::updateTouchState(std::vector<RNSkTouchPoint>&& points) {
196
181
  }
197
182
 
198
183
  void RNSkDrawView::performDraw() {
199
- #if LOG_ALL_DRAWING
200
- RNSkLogger::logToConsole("RNSkDrawView::performDraw - %i", getNativeId());
201
- #endif
202
-
203
184
  // Start timing
204
185
  _jsTimingInfo.beginTiming();
205
186
 
@@ -234,37 +215,22 @@ void RNSkDrawView::performDraw() {
234
215
  // Post drawing message to the render thread where the picture recorded
235
216
  // will be sent to the GPU/backend for rendering to screen.
236
217
  auto gpuLock = _gpuDrawingLock;
237
- getPlatformContext()->runOnRenderThread([this, p = std::move(p), gpuLock]() {
238
-
239
- if(isInvalidated()) {
240
- gpuLock->unlock();
241
- return;
218
+ _platformContext->runOnRenderThread([weakSelf = weak_from_this(), p = std::move(p), gpuLock]() {
219
+ auto self = weakSelf.lock();
220
+ if (self) {
221
+ // Draw the picture recorded on the real GPU canvas
222
+ self->_gpuTimingInfo.beginTiming();
223
+ self->drawPicture(p);
224
+ self->_gpuTimingInfo.stopTiming();
242
225
  }
243
-
244
- _gpuTimingInfo.beginTiming();
245
-
246
- // Draw the picture recorded on the real GPU canvas
247
- if(_nativeDrawFunc != nullptr) {
248
- #if LOG_ALL_DRAWING
249
- RNSkLogger::logToConsole("RNSkDrawView::drawFrame - %i", getNativeId());
250
- #endif
251
- _nativeDrawFunc(p);
252
- } else {
253
- #if LOG_ALL_DRAWING
254
- RNSkLogger::logToConsole("RNSkDrawView::drawFrame - %i SKIPPING, draw func is null", getNativeId());
255
- #endif
256
- }
257
-
258
- _gpuTimingInfo.stopTiming();
259
-
260
226
  // Unlock GPU drawing
261
227
  gpuLock->unlock();
262
228
  });
263
229
  } else {
264
230
  #ifdef DEBUG
265
- static size_t framesSkipped = 0;
266
- printf("SKIA/GPU: Skipped frames: %lu\n", ++framesSkipped);
231
+ _gpuTimingInfo.markSkipped();
267
232
  #endif
233
+ // Request a new redraw since the last frame was skipped.
268
234
  requestRedraw();
269
235
  }
270
236
 
@@ -280,39 +246,34 @@ void RNSkDrawView::beginDrawingLoop() {
280
246
  if (_drawingLoopId != 0 || _nativeId == 0) {
281
247
  return;
282
248
  }
283
-
284
249
  // Set to zero to avoid calling beginDrawLoop before we return
285
- _drawingLoopId = _platformContext->beginDrawLoop(
286
- _nativeId, std::bind(&RNSkDrawView::drawLoopCallback, this, std::placeholders::_1));
250
+ _drawingLoopId = _platformContext->beginDrawLoop(_nativeId,
251
+ [weakSelf = weak_from_this()](bool invalidated) {
252
+ auto self = weakSelf.lock();
253
+ if(self) {
254
+ self->drawLoopCallback(invalidated);
255
+ }
256
+ });
287
257
  }
288
258
 
289
259
  void RNSkDrawView::drawLoopCallback(bool invalidated) {
290
- if(invalidated) {
291
- _isInvalidated = true;
292
- onInvalidated();
293
- #if LOG_ALL_DRAWING
294
- RNSkLogger::logToConsole("RNSkDrawView::onInvalidated - %i", getNativeId());
295
- #endif
296
- return;
297
- }
298
-
299
260
  if(_redrawRequestCounter > 0 || _drawingMode == RNSkDrawingMode::Continuous) {
300
261
  _redrawRequestCounter = 0;
301
262
 
302
- _vsyncTimingInfo.beginTiming();
303
-
304
263
  // We render on the javascript thread.
305
264
  if(_jsDrawingLock->try_lock()) {
306
- _platformContext->runOnJavascriptThread(std::bind(&RNSkDrawView::performDraw, this));
265
+ _platformContext->runOnJavascriptThread([weakSelf = weak_from_this()](){
266
+ auto self = weakSelf.lock();
267
+ if(self) {
268
+ self->performDraw();
269
+ }
270
+ });
307
271
  } else {
308
272
  #ifdef DEBUG
309
- static size_t framesSkipped = 0;
310
- printf("SKIA/JS: Skipped frames: %lu\n", ++framesSkipped);
273
+ _jsTimingInfo.markSkipped();
311
274
  #endif
312
275
  requestRedraw();
313
276
  }
314
-
315
- _vsyncTimingInfo.stopTiming();
316
277
  }
317
278
  }
318
279
 
@@ -20,8 +20,6 @@
20
20
 
21
21
  #pragma clang diagnostic pop
22
22
 
23
- #define LOG_ALL_DRAWING 0
24
-
25
23
  class SkPicture;
26
24
  class SkRect;
27
25
  class SkImage;
@@ -35,7 +33,7 @@ using RNSkDrawCallback =
35
33
 
36
34
  enum RNSkDrawingMode { Default, Continuous };
37
35
 
38
- class RNSkDrawView {
36
+ class RNSkDrawView: public std::enable_shared_from_this<RNSkDrawView> {
39
37
  public:
40
38
  /**
41
39
  * Constructor
@@ -45,7 +43,7 @@ public:
45
43
  /**
46
44
  Destructor
47
45
  */
48
- ~RNSkDrawView();
46
+ virtual ~RNSkDrawView();
49
47
 
50
48
  /**
51
49
  * Repaints the Skia view using the underlying context and the drawcallback.
@@ -96,14 +94,6 @@ public:
96
94
  sk_sp<SkImage> makeImageSnapshot(std::shared_ptr<SkRect> bounds);
97
95
 
98
96
  protected:
99
- void setNativeDrawFunc(std::function<void(const sk_sp<SkPicture>)> drawFunc) {
100
- if(!_gpuDrawingLock->try_lock_for(250ms)) {
101
- RNSkLogger::logToConsole("Could not lock drawing when clearing drawing function - %i", _nativeId);
102
- }
103
- _nativeDrawFunc = drawFunc;
104
- _gpuDrawingLock->unlock();
105
- }
106
-
107
97
  /**
108
98
  Returns the scaled width of the view
109
99
  */
@@ -115,14 +105,9 @@ protected:
115
105
  virtual int getHeight() { return -1; };
116
106
 
117
107
  /**
118
- Returns true if the view is invalidated
119
- */
120
- volatile bool isInvalidated() { return _isInvalidated; }
121
-
122
- /**
123
- Override to be notified on invalidation
108
+ Override to render picture to GPU
124
109
  */
125
- virtual void onInvalidated() {}
110
+ virtual void drawPicture(const sk_sp<SkPicture> picture) = 0;
126
111
 
127
112
  /**
128
113
  * @return The platformcontext
@@ -210,12 +195,7 @@ private:
210
195
  /**
211
196
  Timing information for GPU rendering
212
197
  */
213
- RNSkTimingInfo _gpuTimingInfo;
214
-
215
- /**
216
- Measures vsync framerate
217
- */
218
- RNSkTimingInfo _vsyncTimingInfo;
198
+ RNSkTimingInfo _gpuTimingInfo;
219
199
 
220
200
  /**
221
201
  Redraw queue counter
@@ -227,16 +207,6 @@ private:
227
207
  */
228
208
  size_t _nativeId;
229
209
 
230
- /**
231
- Invalidation flag
232
- */
233
- std::atomic<bool> _isInvalidated = { false };
234
-
235
- /**
236
- Native draw handler
237
- */
238
- std::function<void(const sk_sp<SkPicture>)> _nativeDrawFunc;
239
-
240
210
  };
241
211
 
242
212
  } // namespace RNSkia
@@ -20,7 +20,7 @@ using CallbackInfo = struct CallbackInfo {
20
20
  view = nullptr;
21
21
  }
22
22
  std::shared_ptr<jsi::Function> drawCallback;
23
- RNSkDrawView *view;
23
+ std::shared_ptr<RNSkDrawView> view;
24
24
  };
25
25
 
26
26
  class RNSkJsiViewApi : public JsiHostObject {
@@ -105,7 +105,7 @@ public:
105
105
  sk_sp<SkImage> image;
106
106
  auto info = getEnsuredCallbackInfo(nativeId);
107
107
  if (info->view != nullptr) {
108
- if(count > 1 && !arguments[1].isUndefined() && arguments[1].isNull()) {
108
+ if(count > 1 && !arguments[1].isUndefined() && !arguments[1].isNull()) {
109
109
  auto rect = JsiSkRect::fromValue(runtime, arguments[1]);
110
110
  image = info->view->makeImageSnapshot(rect);
111
111
  } else {
@@ -226,7 +226,7 @@ public:
226
226
  * @param nativeId Id of view to register
227
227
  * @param view View to register
228
228
  */
229
- void registerSkiaDrawView(size_t nativeId, RNSkDrawView *view) {
229
+ void registerSkiaDrawView(size_t nativeId, std::shared_ptr<RNSkDrawView> view) {
230
230
  auto info = getEnsuredCallbackInfo(nativeId);
231
231
  info->view = view;
232
232
  if (info->drawCallback != nullptr) {
@@ -260,15 +260,18 @@ public:
260
260
  a valid view is set, the setDrawCallback method is called on the
261
261
  view (if a valid callback exists).
262
262
  */
263
- void setSkiaDrawView(size_t nativeId, RNSkDrawView *view) {
263
+ void setSkiaDrawView(size_t nativeId, std::shared_ptr<RNSkDrawView> view) {
264
264
  if (_callbackInfos.find(nativeId) == _callbackInfos.end()) {
265
265
  return;
266
266
  }
267
267
  auto info = getEnsuredCallbackInfo(nativeId);
268
- info->view = view;
269
268
  if (view != nullptr && info->drawCallback != nullptr) {
269
+ info->view = view;
270
270
  info->view->setNativeId(nativeId);
271
271
  info->view->setDrawCallback(info->drawCallback);
272
+ } else if(view == nullptr && info->drawCallback != nullptr) {
273
+ info->view->setDrawCallback(nullptr);
274
+ info->view = view;
272
275
  }
273
276
  }
274
277
 
@@ -45,7 +45,7 @@ void RNSkManager::invalidate() {
45
45
  _platformContext->invalidate();
46
46
  }
47
47
 
48
- void RNSkManager::registerSkiaDrawView(size_t nativeId, RNSkDrawView *view) {
48
+ void RNSkManager::registerSkiaDrawView(size_t nativeId, std::shared_ptr<RNSkDrawView> view) {
49
49
  if (!_isInvalidated && _viewApi != nullptr)
50
50
  _viewApi->registerSkiaDrawView(nativeId, view);
51
51
  }
@@ -55,7 +55,7 @@ void RNSkManager::unregisterSkiaDrawView(size_t nativeId) {
55
55
  _viewApi->unregisterSkiaDrawView(nativeId);
56
56
  }
57
57
 
58
- void RNSkManager::setSkiaDrawView(size_t nativeId, RNSkDrawView *view) {
58
+ void RNSkManager::setSkiaDrawView(size_t nativeId, std::shared_ptr<RNSkDrawView> view) {
59
59
  if (!_isInvalidated && _viewApi != nullptr)
60
60
  _viewApi->setSkiaDrawView(nativeId, view);
61
61
  }
@@ -41,7 +41,7 @@ public:
41
41
  * @param nativeId Native view id
42
42
  * @param view View to register
43
43
  */
44
- void registerSkiaDrawView(size_t nativeId, RNSkDrawView *view);
44
+ void registerSkiaDrawView(size_t nativeId, std::shared_ptr<RNSkDrawView> view);
45
45
 
46
46
  /**
47
47
  * Unregisters the RNSkDrawView from the list of registered views
@@ -54,7 +54,7 @@ public:
54
54
  Used when we want to remove a view without unregistering it
55
55
  - this happens typically on iOS.
56
56
  */
57
- void setSkiaDrawView(size_t nativeId, RNSkDrawView *view);
57
+ void setSkiaDrawView(size_t nativeId, std::shared_ptr<RNSkDrawView> view);
58
58
 
59
59
  /**
60
60
  * @return The platform context
@@ -43,7 +43,7 @@ public:
43
43
  /**
44
44
  * Destructor
45
45
  */
46
- ~RNSkPlatformContext() {
46
+ virtual ~RNSkPlatformContext() {
47
47
  invalidate();
48
48
  }
49
49
 
@@ -72,8 +72,12 @@ public:
72
72
  _start += timeSinceStop;
73
73
 
74
74
  _state = RNSkClockState::Running;
75
- auto dispatch = std::bind(&RNSkClockValue::notifyUpdate, this, std::placeholders::_1);
76
- getContext()->beginDrawLoop(_identifier, dispatch);
75
+ getContext()->beginDrawLoop(_identifier, [weakSelf = weak_from_this()](bool invalidated){
76
+ auto self = weakSelf.lock();
77
+ if(self) {
78
+ std::dynamic_pointer_cast<RNSkClockValue>(self)->notifyUpdate(invalidated);
79
+ }
80
+ });
77
81
  }
78
82
 
79
83
  virtual void stopClock() {
@@ -103,12 +107,16 @@ protected:
103
107
  getContext()->runOnJavascriptThread(
104
108
  // To ensure that this shared_ptr instance is not deallocated before we are done
105
109
  // running the update lambda we pass a shared from this to the lambda scope.
106
- [self = shared_from_this(), this]() {
107
- if(_state == RNSkClockState::Running) {
108
- auto now = std::chrono::high_resolution_clock::now();
109
- auto deltaFromStart = std::chrono::duration_cast<std::chrono::milliseconds>(now - _start).count();
110
- tick(_runtime, static_cast<double>(deltaFromStart));
111
- }
110
+ [weakSelf = weak_from_this()]() {
111
+ auto self = weakSelf.lock();
112
+ if(self) {
113
+ auto selfClockValue = std::dynamic_pointer_cast<RNSkClockValue>(self);
114
+ if(selfClockValue->getState() == RNSkClockState::Running) {
115
+ auto now = std::chrono::high_resolution_clock::now();
116
+ auto deltaFromStart = std::chrono::duration_cast<std::chrono::milliseconds>(now - selfClockValue->_start).count();
117
+ selfClockValue->tick(selfClockValue->_runtime, static_cast<double>(deltaFromStart));
118
+ }
119
+ }
112
120
  });
113
121
  }
114
122
 
@@ -48,10 +48,13 @@ public:
48
48
  }
49
49
  auto callback = std::make_shared<jsi::Function>(arguments[0].asObject(runtime).asFunction(runtime));
50
50
 
51
- auto unsubscribe = addListener([self = shared_from_this(),
52
- this,
51
+ auto unsubscribe = addListener([weakSelf = weak_from_this(),
53
52
  callback = std::move(callback)](jsi::Runtime& runtime){
54
- callback->call(runtime, get_current(runtime));
53
+ auto self = weakSelf.lock();
54
+ if(self) {
55
+ auto selfReadonlyValue = std::dynamic_pointer_cast<RNSkReadonlyValue>(self);
56
+ callback->call(runtime, selfReadonlyValue->get_current(runtime));
57
+ }
55
58
  });
56
59
 
57
60
  return jsi::Function::createFromHostFunction(runtime,
@@ -74,8 +77,11 @@ public:
74
77
  std::lock_guard<std::mutex> lock(_mutex);
75
78
  auto listenerId = _listenerId++;
76
79
  _listeners.emplace(listenerId, cb);
77
- return [self = shared_from_this(), this, listenerId]() {
78
- removeListener(listenerId);
80
+ return [weakSelf = weak_from_this(), listenerId]() {
81
+ auto self = weakSelf.lock();
82
+ if(self) {
83
+ self->removeListener(listenerId);
84
+ }
79
85
  };
80
86
  }
81
87
 
@@ -1,5 +1,6 @@
1
1
  #pragma once
2
2
 
3
+ #include <RNSkLog.h>
3
4
  #include <chrono>
4
5
 
5
6
  #define NUMBER_OF_DURATION_SAMPLES 10
@@ -12,7 +13,7 @@ using ms = duration<float, std::milli>;
12
13
 
13
14
  class RNSkTimingInfo {
14
15
  public:
15
- RNSkTimingInfo() {
16
+ RNSkTimingInfo(const std::string &name): _name(std::move(name)) {
16
17
  reset();
17
18
  }
18
19
 
@@ -25,6 +26,7 @@ public:
25
26
  _prevFpsTimer = -1;
26
27
  _frameCount = 0;
27
28
  _lastFrameCount = -1;
29
+ _didSkip = false;
28
30
  }
29
31
 
30
32
  void beginTiming() {
@@ -35,6 +37,14 @@ public:
35
37
  time_point<steady_clock> stop = high_resolution_clock::now();
36
38
  addLastDuration(duration_cast<milliseconds>(stop - _start).count());
37
39
  tick(stop);
40
+ if(_didSkip) {
41
+ _didSkip = false;
42
+ RNSkLogger::logToConsole("%s: Skipped frame. Previous frame time: %lldms", _name.c_str(), _lastDuration);
43
+ }
44
+ }
45
+
46
+ void markSkipped() {
47
+ _didSkip = true;
38
48
  }
39
49
 
40
50
  long getAverage() { return static_cast<long>(_average); }
@@ -86,6 +96,8 @@ private:
86
96
  long _prevFpsTimer;
87
97
  double _frameCount;
88
98
  double _lastFrameCount;
99
+ double _didSkip;
100
+ std::string _name;
89
101
  };
90
102
 
91
103
  } // namespace RNSkia
@@ -21,20 +21,18 @@
21
21
  class RNSkDrawViewImpl : public RNSkia::RNSkDrawView {
22
22
  public:
23
23
  RNSkDrawViewImpl(std::shared_ptr<RNSkia::RNSkPlatformContext> context);
24
+ ~RNSkDrawViewImpl();
24
25
 
25
- void setSize(int width, int height);
26
+ CALayer* getLayer() { return _layer; }
26
27
 
27
- CALayer* getLayer() { return _layer; };
28
+ void setSize(int width, int height);
28
29
 
29
30
  protected:
30
31
  int getWidth() override { return _width * _context->getPixelDensity(); };
31
- int getHeight() override { return _height * _context->getPixelDensity(); };
32
- void onInvalidated() override {
33
- setNativeDrawFunc(nullptr);
34
- };
32
+ int getHeight() override { return _height * _context->getPixelDensity(); };
35
33
 
36
34
  private:
37
- void drawFrame(const sk_sp<SkPicture> picture);
35
+ void drawPicture(const sk_sp<SkPicture> picture) override;
38
36
  bool createSkiaSurface();
39
37
 
40
38
  int _nativeId;