@shopify/react-native-skia 0.1.121 → 0.1.124

Sign up to get free protection for your applications and to get access to all the features.
Files changed (144) 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/api/JsiSkApi.h +2 -0
  14. package/cpp/api/JsiSkColor.h +49 -0
  15. package/cpp/api/JsiSkPath.h +31 -2
  16. package/cpp/api/JsiSkPathFactory.h +96 -1
  17. package/cpp/api/third_party/CSSColorParser.h +324 -0
  18. package/cpp/rnskia/RNSkAnimation.h +3 -8
  19. package/cpp/rnskia/RNSkDrawView.cpp +84 -126
  20. package/cpp/rnskia/RNSkDrawView.h +7 -37
  21. package/cpp/rnskia/RNSkJsiViewApi.h +8 -5
  22. package/cpp/rnskia/RNSkManager.cpp +2 -2
  23. package/cpp/rnskia/RNSkManager.h +2 -2
  24. package/cpp/rnskia/RNSkPlatformContext.h +1 -1
  25. package/cpp/rnskia/RNSkValueApi.h +6 -2
  26. package/cpp/rnskia/values/RNSkClockValue.h +21 -13
  27. package/cpp/rnskia/values/RNSkDerivedValue.h +13 -6
  28. package/cpp/rnskia/values/RNSkReadonlyValue.h +17 -16
  29. package/cpp/rnskia/values/RNSkValue.h +8 -3
  30. package/cpp/utils/RNSkTimingInfo.h +13 -1
  31. package/ios/RNSkia-iOS/RNSkDrawViewImpl.h +8 -10
  32. package/ios/RNSkia-iOS/RNSkDrawViewImpl.mm +25 -10
  33. package/ios/RNSkia-iOS/SkiaDrawView.mm +21 -16
  34. package/lib/commonjs/renderer/Canvas.js +17 -8
  35. package/lib/commonjs/renderer/Canvas.js.map +1 -1
  36. package/lib/commonjs/renderer/components/Paint.js +1 -1
  37. package/lib/commonjs/renderer/components/Paint.js.map +1 -1
  38. package/lib/commonjs/renderer/components/colorFilters/Lerp.js +1 -1
  39. package/lib/commonjs/renderer/components/colorFilters/Lerp.js.map +1 -1
  40. package/lib/commonjs/renderer/components/shaders/Shader.js +2 -2
  41. package/lib/commonjs/renderer/components/shaders/Shader.js.map +1 -1
  42. package/lib/commonjs/renderer/components/shapes/Path.js +10 -2
  43. package/lib/commonjs/renderer/components/shapes/Path.js.map +1 -1
  44. package/lib/commonjs/renderer/nodes/Node.js +3 -3
  45. package/lib/commonjs/renderer/nodes/Node.js.map +1 -1
  46. package/lib/commonjs/renderer/processors/Circles.js +3 -2
  47. package/lib/commonjs/renderer/processors/Circles.js.map +1 -1
  48. package/lib/commonjs/renderer/processors/Font.js +1 -1
  49. package/lib/commonjs/renderer/processors/Font.js.map +1 -1
  50. package/lib/commonjs/renderer/processors/Paint.js +6 -1
  51. package/lib/commonjs/renderer/processors/Paint.js.map +1 -1
  52. package/lib/commonjs/renderer/processors/Rects.js +6 -6
  53. package/lib/commonjs/renderer/processors/Rects.js.map +1 -1
  54. package/lib/commonjs/skia/Color.js +3 -25
  55. package/lib/commonjs/skia/Color.js.map +1 -1
  56. package/lib/commonjs/skia/Image/Image.js.map +1 -1
  57. package/lib/commonjs/skia/ImageFilter/ImageFilterFactory.js.map +1 -1
  58. package/lib/commonjs/skia/Paint/Paint.js +13 -1
  59. package/lib/commonjs/skia/Paint/Paint.js.map +1 -1
  60. package/lib/commonjs/skia/Paint/usePaint.js +2 -4
  61. package/lib/commonjs/skia/Paint/usePaint.js.map +1 -1
  62. package/lib/commonjs/skia/Path/Path.js +13 -1
  63. package/lib/commonjs/skia/Path/Path.js.map +1 -1
  64. package/lib/commonjs/skia/Shader/Shader.js.map +1 -1
  65. package/lib/commonjs/skia/Skia.js +43 -3
  66. package/lib/commonjs/skia/Skia.js.map +1 -1
  67. package/lib/commonjs/values/animation/timing/functions/getResolvedParams.js +3 -3
  68. package/lib/commonjs/values/animation/timing/functions/getResolvedParams.js.map +1 -1
  69. package/lib/module/renderer/Canvas.js +12 -6
  70. package/lib/module/renderer/Canvas.js.map +1 -1
  71. package/lib/module/renderer/components/Paint.js +2 -2
  72. package/lib/module/renderer/components/Paint.js.map +1 -1
  73. package/lib/module/renderer/components/colorFilters/Lerp.js +1 -1
  74. package/lib/module/renderer/components/colorFilters/Lerp.js.map +1 -1
  75. package/lib/module/renderer/components/shaders/Shader.js +3 -2
  76. package/lib/module/renderer/components/shaders/Shader.js.map +1 -1
  77. package/lib/module/renderer/components/shapes/Path.js +10 -3
  78. package/lib/module/renderer/components/shapes/Path.js.map +1 -1
  79. package/lib/module/renderer/nodes/Node.js +3 -3
  80. package/lib/module/renderer/nodes/Node.js.map +1 -1
  81. package/lib/module/renderer/processors/Circles.js +3 -2
  82. package/lib/module/renderer/processors/Circles.js.map +1 -1
  83. package/lib/module/renderer/processors/Font.js +1 -1
  84. package/lib/module/renderer/processors/Font.js.map +1 -1
  85. package/lib/module/renderer/processors/Paint.js +6 -1
  86. package/lib/module/renderer/processors/Paint.js.map +1 -1
  87. package/lib/module/renderer/processors/Rects.js +5 -6
  88. package/lib/module/renderer/processors/Rects.js.map +1 -1
  89. package/lib/module/skia/Color.js +2 -21
  90. package/lib/module/skia/Color.js.map +1 -1
  91. package/lib/module/skia/Image/Image.js.map +1 -1
  92. package/lib/module/skia/ImageFilter/ImageFilterFactory.js.map +1 -1
  93. package/lib/module/skia/Paint/Paint.js +6 -0
  94. package/lib/module/skia/Paint/Paint.js.map +1 -1
  95. package/lib/module/skia/Paint/usePaint.js +2 -3
  96. package/lib/module/skia/Paint/usePaint.js.map +1 -1
  97. package/lib/module/skia/Path/Path.js +11 -0
  98. package/lib/module/skia/Path/Path.js.map +1 -1
  99. package/lib/module/skia/Shader/Shader.js.map +1 -1
  100. package/lib/module/skia/Skia.js +45 -2
  101. package/lib/module/skia/Skia.js.map +1 -1
  102. package/lib/module/values/animation/timing/functions/getResolvedParams.js +3 -3
  103. package/lib/module/values/animation/timing/functions/getResolvedParams.js.map +1 -1
  104. package/lib/typescript/src/renderer/Canvas.d.ts +6 -0
  105. package/lib/typescript/src/renderer/components/shapes/Path.d.ts +3 -1
  106. package/lib/typescript/src/renderer/processors/Paint.d.ts +2 -1
  107. package/lib/typescript/src/skia/Color.d.ts +0 -1
  108. package/lib/typescript/src/skia/Image/Image.d.ts +3 -3
  109. package/lib/typescript/src/skia/ImageFilter/ImageFilterFactory.d.ts +2 -2
  110. package/lib/typescript/src/skia/Paint/Paint.d.ts +3 -2
  111. package/lib/typescript/src/skia/Path/Path.d.ts +13 -0
  112. package/lib/typescript/src/skia/Path/PathFactory.d.ts +7 -1
  113. package/lib/typescript/src/skia/Picture/Picture.d.ts +2 -2
  114. package/lib/typescript/src/skia/RuntimeEffect/RuntimeEffect.d.ts +3 -3
  115. package/lib/typescript/src/skia/Shader/Shader.d.ts +2 -2
  116. package/lib/typescript/src/skia/Shader/ShaderFactory.d.ts +9 -9
  117. package/lib/typescript/src/skia/Skia.d.ts +5 -3
  118. package/lib/typescript/src/values/animation/types.d.ts +5 -5
  119. package/package.json +1 -1
  120. package/scripts/install-npm.js +1 -1
  121. package/src/renderer/Canvas.tsx +13 -6
  122. package/src/renderer/components/Paint.tsx +2 -2
  123. package/src/renderer/components/colorFilters/Lerp.tsx +1 -1
  124. package/src/renderer/components/shaders/Shader.tsx +1 -1
  125. package/src/renderer/components/shapes/Path.tsx +12 -4
  126. package/src/renderer/nodes/Node.ts +3 -3
  127. package/src/renderer/processors/Circles.ts +2 -1
  128. package/src/renderer/processors/Font.ts +1 -1
  129. package/src/renderer/processors/Paint.ts +5 -0
  130. package/src/renderer/processors/Rects.ts +3 -2
  131. package/src/skia/Color.ts +3 -20
  132. package/src/skia/Image/Image.ts +3 -3
  133. package/src/skia/ImageFilter/ImageFilterFactory.ts +2 -2
  134. package/src/skia/Paint/Paint.ts +9 -2
  135. package/src/skia/Paint/usePaint.ts +2 -4
  136. package/src/skia/Path/Path.ts +16 -0
  137. package/src/skia/Path/PathFactory.ts +8 -1
  138. package/src/skia/Picture/Picture.ts +2 -2
  139. package/src/skia/RuntimeEffect/RuntimeEffect.ts +4 -4
  140. package/src/skia/Shader/Shader.ts +2 -2
  141. package/src/skia/Shader/ShaderFactory.ts +9 -9
  142. package/src/skia/Skia.ts +47 -3
  143. package/src/values/animation/timing/functions/getResolvedParams.ts +2 -2
  144. package/src/values/animation/types.ts +5 -5
@@ -15,7 +15,7 @@ using namespace facebook;
15
15
  /**
16
16
  Implements an animation that can be used to drive other values
17
17
  */
18
- class RNSkAnimation : public RNSkClockValue, public std::enable_shared_from_this<RNSkAnimation>
18
+ class RNSkAnimation : public RNSkClockValue
19
19
  {
20
20
 
21
21
  public:
@@ -23,8 +23,8 @@ public:
23
23
  size_t identifier,
24
24
  jsi::Runtime& runtime,
25
25
  const jsi::Value *arguments,
26
- size_t count)
27
- : RNSkClockValue(platformContext, identifier, runtime, arguments, count) {
26
+ size_t count) :
27
+ RNSkClockValue(platformContext, identifier, runtime, arguments, count) {
28
28
  // Save the update function
29
29
  _updateFunction = std::make_shared<jsi::Function>(arguments[0].asObject(runtime).asFunction(runtime));
30
30
 
@@ -32,11 +32,6 @@ public:
32
32
  _args[1] = jsi::Value::undefined();
33
33
  }
34
34
 
35
- ~RNSkAnimation() {
36
- // We need to stop/unsubscribe
37
- stopClock();
38
- }
39
-
40
35
  JSI_HOST_FUNCTION(cancel) {
41
36
  stopClock();
42
37
  return jsi::Value::undefined();
@@ -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,63 +66,63 @@ 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
-
89
- // Set up debug font/paints
90
- auto font = SkFont();
91
- font.setSize(14);
92
- auto paint = SkPaint();
93
- paint.setColor(SkColors::kRed);
94
69
 
95
70
  // Create draw drawCallback wrapper
96
71
  _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);
72
+ [weakSelf = weak_from_this(),
73
+ callback = std::move(callback)](std::shared_ptr<JsiSkCanvas> canvas,
74
+ int width,
75
+ int height,
76
+ double timestamp,
77
+ std::shared_ptr<RNSkPlatformContext> context) {
78
+
79
+ auto self = weakSelf.lock();
80
+ if(self) {
81
+ auto runtime = context->getJsRuntime();
82
+
83
+ // Update info parameter
84
+ self->_infoObject->beginDrawOperation(width, height, timestamp);
85
+
86
+ // Set up arguments array
87
+ std::vector<jsi::Value> args(2);
88
+ args[0] = jsi::Object::createFromHostObject(*runtime, canvas);
89
+ args[1] = jsi::Object::createFromHostObject(*runtime, self->_infoObject);
90
+
91
+ // To be able to call the drawing function we'll wrap it once again
92
+ callback->call(*runtime,
93
+ static_cast<const jsi::Value *>(args.data()),
94
+ (size_t)2);
95
+
96
+ // Reset touches
97
+ self->_infoObject->endDrawOperation();
98
+
99
+ // Draw debug overlays
100
+ if (self->_showDebugOverlay) {
101
+
102
+ // Display average rendering timer
103
+ auto jsAvg = self->_jsTimingInfo.getAverage();
104
+ //auto jsFps = _jsTimingInfo.getFps();
105
+
106
+ auto gpuAvg = self->_gpuTimingInfo.getAverage();
107
+ //auto gpuFps = _gpuTimingInfo.getFps();
108
+
109
+ auto total = jsAvg + gpuAvg;
110
+
111
+ // Build string
112
+ std::ostringstream stream;
113
+ stream << "js: " << jsAvg << "ms gpu: " << gpuAvg << "ms " << " total: " << total << "ms";
114
+
115
+ std::string debugString = stream.str();
116
+
117
+ // Set up debug font/paints
118
+ auto font = SkFont();
119
+ font.setSize(14);
120
+ auto paint = SkPaint();
121
+ paint.setColor(SkColors::kRed);
122
+ canvas->getCanvas()->drawSimpleText(
123
+ debugString.c_str(), debugString.size(), SkTextEncoding::kUTF8, 8,
124
+ 18, font, paint);
125
+ }
144
126
  }
145
127
  });
146
128
 
@@ -172,7 +154,7 @@ void RNSkDrawView::drawInCanvas(std::shared_ptr<JsiSkCanvas> canvas,
172
154
 
173
155
  sk_sp<SkImage> RNSkDrawView::makeImageSnapshot(std::shared_ptr<SkRect> bounds) {
174
156
  // Assert width/height
175
- auto surface = SkSurface::MakeRasterN32Premul(getWidth(), getHeight());
157
+ auto surface = SkSurface::MakeRasterN32Premul(getScaledWidth(), getScaledHeight());
176
158
  auto canvas = surface->getCanvas();
177
159
  auto jsiCanvas = std::make_shared<JsiSkCanvas>(_platformContext);
178
160
  jsiCanvas->setCanvas(canvas);
@@ -180,7 +162,7 @@ sk_sp<SkImage> RNSkDrawView::makeImageSnapshot(std::shared_ptr<SkRect> bounds) {
180
162
  milliseconds ms = duration_cast<milliseconds>(
181
163
  system_clock::now().time_since_epoch());
182
164
 
183
- drawInCanvas(jsiCanvas, getWidth(), getHeight(), ms.count() / 1000);
165
+ drawInCanvas(jsiCanvas, getScaledWidth(), getScaledHeight(), ms.count() / 1000);
184
166
 
185
167
  if(bounds != nullptr) {
186
168
  SkIRect b = SkIRect::MakeXYWH(bounds->x(), bounds->y(), bounds->width(), bounds->height());
@@ -196,10 +178,6 @@ void RNSkDrawView::updateTouchState(std::vector<RNSkTouchPoint>&& points) {
196
178
  }
197
179
 
198
180
  void RNSkDrawView::performDraw() {
199
- #if LOG_ALL_DRAWING
200
- RNSkLogger::logToConsole("RNSkDrawView::performDraw - %i", getNativeId());
201
- #endif
202
-
203
181
  // Start timing
204
182
  _jsTimingInfo.beginTiming();
205
183
 
@@ -207,7 +185,7 @@ void RNSkDrawView::performDraw() {
207
185
  // move the actual drawing onto the render thread later
208
186
  SkPictureRecorder recorder;
209
187
  SkRTreeFactory factory;
210
- SkCanvas* canvas = recorder.beginRecording(getWidth(), getHeight(), &factory);
188
+ SkCanvas* canvas = recorder.beginRecording(getScaledWidth(), getScaledHeight(), &factory);
211
189
  _jsiCanvas->setCanvas(canvas);
212
190
 
213
191
  // Get current milliseconds
@@ -216,7 +194,7 @@ void RNSkDrawView::performDraw() {
216
194
 
217
195
  try {
218
196
  // Perform the javascript drawing
219
- drawInCanvas(_jsiCanvas, getWidth(), getHeight(), ms.count() / 1000.0);
197
+ drawInCanvas(_jsiCanvas, getScaledWidth(), getScaledHeight(), ms.count() / 1000.0);
220
198
  } catch(...) {
221
199
  _jsTimingInfo.stopTiming();
222
200
  _jsDrawingLock->unlock();
@@ -234,37 +212,22 @@ void RNSkDrawView::performDraw() {
234
212
  // Post drawing message to the render thread where the picture recorded
235
213
  // will be sent to the GPU/backend for rendering to screen.
236
214
  auto gpuLock = _gpuDrawingLock;
237
- getPlatformContext()->runOnRenderThread([this, p = std::move(p), gpuLock]() {
238
-
239
- if(isInvalidated()) {
240
- gpuLock->unlock();
241
- return;
215
+ _platformContext->runOnRenderThread([weakSelf = weak_from_this(), p = std::move(p), gpuLock]() {
216
+ auto self = weakSelf.lock();
217
+ if (self) {
218
+ // Draw the picture recorded on the real GPU canvas
219
+ self->_gpuTimingInfo.beginTiming();
220
+ self->drawPicture(p);
221
+ self->_gpuTimingInfo.stopTiming();
242
222
  }
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
223
  // Unlock GPU drawing
261
224
  gpuLock->unlock();
262
225
  });
263
226
  } else {
264
227
  #ifdef DEBUG
265
- static size_t framesSkipped = 0;
266
- printf("SKIA/GPU: Skipped frames: %lu\n", ++framesSkipped);
228
+ _gpuTimingInfo.markSkipped();
267
229
  #endif
230
+ // Request a new redraw since the last frame was skipped.
268
231
  requestRedraw();
269
232
  }
270
233
 
@@ -280,39 +243,34 @@ void RNSkDrawView::beginDrawingLoop() {
280
243
  if (_drawingLoopId != 0 || _nativeId == 0) {
281
244
  return;
282
245
  }
283
-
284
246
  // Set to zero to avoid calling beginDrawLoop before we return
285
- _drawingLoopId = _platformContext->beginDrawLoop(
286
- _nativeId, std::bind(&RNSkDrawView::drawLoopCallback, this, std::placeholders::_1));
247
+ _drawingLoopId = _platformContext->beginDrawLoop(_nativeId,
248
+ [weakSelf = weak_from_this()](bool invalidated) {
249
+ auto self = weakSelf.lock();
250
+ if(self) {
251
+ self->drawLoopCallback(invalidated);
252
+ }
253
+ });
287
254
  }
288
255
 
289
256
  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
257
  if(_redrawRequestCounter > 0 || _drawingMode == RNSkDrawingMode::Continuous) {
300
258
  _redrawRequestCounter = 0;
301
259
 
302
- _vsyncTimingInfo.beginTiming();
303
-
304
260
  // We render on the javascript thread.
305
261
  if(_jsDrawingLock->try_lock()) {
306
- _platformContext->runOnJavascriptThread(std::bind(&RNSkDrawView::performDraw, this));
262
+ _platformContext->runOnJavascriptThread([weakSelf = weak_from_this()](){
263
+ auto self = weakSelf.lock();
264
+ if(self) {
265
+ self->performDraw();
266
+ }
267
+ });
307
268
  } else {
308
269
  #ifdef DEBUG
309
- static size_t framesSkipped = 0;
310
- printf("SKIA/JS: Skipped frames: %lu\n", ++framesSkipped);
270
+ _jsTimingInfo.markSkipped();
311
271
  #endif
312
272
  requestRedraw();
313
273
  }
314
-
315
- _vsyncTimingInfo.stopTiming();
316
274
  }
317
275
  }
318
276
 
@@ -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,33 +94,20 @@ 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
  */
110
- virtual int getWidth() { return -1; };
100
+ virtual float getScaledWidth() = 0;
111
101
 
112
102
  /**
113
103
  Returns the scaled height of the view
114
104
  */
115
- virtual int getHeight() { return -1; };
116
-
117
- /**
118
- Returns true if the view is invalidated
119
- */
120
- volatile bool isInvalidated() { return _isInvalidated; }
105
+ virtual float getScaledHeight() = 0;
121
106
 
122
107
  /**
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
 
@@ -34,8 +34,12 @@ public:
34
34
  }
35
35
 
36
36
  JSI_HOST_FUNCTION(createDerivedValue) {
37
- return jsi::Object::createFromHostObject(runtime,
38
- std::make_shared<RNSkDerivedValue>(_platformContext, runtime, arguments, count));
37
+ // Creation and initialization is done in two steps to be able to use weak references when setting
38
+ // up dependencies - since weak_from_this needs our instance to be a shared_ptr before calling
39
+ // weak_from_this().
40
+ auto derivedValue = std::make_shared<RNSkDerivedValue>(_platformContext, runtime, arguments, count);
41
+ derivedValue->initializeDependencies(runtime, arguments, count);
42
+ return jsi::Object::createFromHostObject(runtime, derivedValue);
39
43
  }
40
44
 
41
45
  JSI_HOST_FUNCTION(createAnimation) {
@@ -8,7 +8,6 @@
8
8
  #include <algorithm>
9
9
  #include <functional>
10
10
  #include <chrono>
11
- #include <mutex>
12
11
 
13
12
  namespace RNSkia
14
13
  {
@@ -33,12 +32,11 @@ public:
33
32
  size_t count) : RNSkReadonlyValue(platformContext),
34
33
  _runtime(runtime),
35
34
  _identifier(identifier) {
36
-
37
35
  // Start by updating to zero (start value)
38
36
  update(_runtime, static_cast<double>(0));
39
37
  }
40
38
 
41
- ~RNSkClockValue() {
39
+ virtual ~RNSkClockValue() {
42
40
  stopClock();
43
41
  }
44
42
 
@@ -73,8 +71,13 @@ public:
73
71
  _start += timeSinceStop;
74
72
 
75
73
  _state = RNSkClockState::Running;
76
- auto dispatch = std::bind(&RNSkClockValue::notifyUpdate, this, std::placeholders::_1);
77
- getContext()->beginDrawLoop(_identifier, dispatch);
74
+
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
+ });
78
81
  }
79
82
 
80
83
  virtual void stopClock() {
@@ -100,15 +103,20 @@ protected:
100
103
  return;
101
104
  }
102
105
 
103
- // Avoid moving on if we are being called after the dtor was started
104
106
  // Ensure we call any updates from the draw loop on the javascript thread
105
107
  getContext()->runOnJavascriptThread(
106
- [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
- }
108
+ // To ensure that this shared_ptr instance is not deallocated before we are done
109
+ // running the update lambda we pass a shared from this to the lambda scope.
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
 
@@ -127,7 +135,7 @@ protected:
127
135
  size_t _identifier;
128
136
  std::chrono::time_point<std::chrono::steady_clock> _start;
129
137
  std::chrono::time_point<std::chrono::steady_clock> _stop;
130
- std::atomic<RNSkClockState> _state;
138
+ std::atomic<RNSkClockState> _state = { RNSkClockState::NotStarted };
131
139
  };
132
140
 
133
141
  }
@@ -39,6 +39,11 @@ public:
39
39
  jsi::detail::throwJSError(runtime, "Expected array of dependencies as second parameter");
40
40
  }
41
41
 
42
+ // Get callback for calculating result
43
+ _callback = std::make_shared<jsi::Function>(arguments[0].asObject(runtime).asFunction(runtime));
44
+ }
45
+
46
+ void initializeDependencies(jsi::Runtime &runtime, const jsi::Value *arguments, size_t count) {
42
47
  // Save dependencies
43
48
  std::vector<std::shared_ptr<RNSkReadonlyValue>> dependencies;
44
49
 
@@ -59,21 +64,23 @@ public:
59
64
  dependencies.push_back(value);
60
65
  }
61
66
 
62
- // Get callback for calculating result
63
- _callback = std::make_shared<jsi::Function>(arguments[0].asObject(runtime).asFunction(runtime));
64
-
65
67
  // register change handler on dependencies
66
68
  _unsubscribers.reserve(_unsubscribers.size() + size);
67
69
  for(const auto &dep: dependencies) {
68
- auto dispatcher = std::bind(&RNSkDerivedValue::dependencyUpdated, this, std::placeholders::_1);
69
- _unsubscribers.push_back(dep->addListener(dispatcher));
70
+ _unsubscribers.push_back(dep->addListener([weakSelf = weak_from_this()](jsi::Runtime& runtime) {
71
+ auto self = weakSelf.lock();
72
+ if(self) {
73
+ auto selfAsThis = std::dynamic_pointer_cast<RNSkDerivedValue>(self);
74
+ selfAsThis->dependencyUpdated(runtime);
75
+ }
76
+ }));
70
77
  }
71
78
 
72
79
  // Set initial value
73
80
  dependencyUpdated(runtime);
74
81
  }
75
82
 
76
- ~RNSkDerivedValue() {
83
+ virtual ~RNSkDerivedValue() {
77
84
  // Unregister listeners
78
85
  for(const auto &unsubscribe: _unsubscribers) {
79
86
  unsubscribe();