@shopify/react-native-skia 2.4.17 → 2.4.19

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (87) hide show
  1. package/android/cpp/rnskia-android/RNSkAndroidVideo.cpp +34 -0
  2. package/android/cpp/rnskia-android/RNSkAndroidVideo.h +3 -0
  3. package/android/src/main/java/com/shopify/reactnative/skia/RNSkVideo.java +72 -18
  4. package/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java +7 -7
  5. package/apple/RNSkAppleVideo.h +30 -3
  6. package/apple/RNSkAppleVideo.mm +172 -17
  7. package/cpp/api/JsiSkApi.h +15 -13
  8. package/cpp/api/JsiSkHostObjects.h +57 -3
  9. package/cpp/api/JsiSkImage.h +19 -5
  10. package/cpp/api/JsiSkPicture.h +19 -5
  11. package/cpp/api/JsiSkSurface.h +19 -5
  12. package/cpp/api/JsiVideo.h +15 -2
  13. package/cpp/api/recorder/Convertor.h +4 -2
  14. package/cpp/jsi2/EnumMapper.h +49 -34
  15. package/cpp/jsi2/JSIConverter.h +149 -99
  16. package/cpp/jsi2/NativeObject.h +23 -25
  17. package/cpp/jsi2/Promise.cpp +10 -6
  18. package/cpp/jsi2/Promise.h +9 -7
  19. package/cpp/rnskia/RNDawnContext.h +3 -8
  20. package/cpp/rnskia/RNSkManager.cpp +13 -7
  21. package/cpp/rnskia/RNSkVideo.h +3 -0
  22. package/cpp/rnwgpu/api/GPUAdapter.cpp +31 -32
  23. package/cpp/rnwgpu/api/GPUAdapter.h +1 -1
  24. package/cpp/rnwgpu/api/GPUBuffer.cpp +8 -8
  25. package/cpp/rnwgpu/api/GPUCommandEncoder.h +4 -4
  26. package/cpp/rnwgpu/api/GPUDevice.h +12 -12
  27. package/cpp/rnwgpu/api/GPUQueue.cpp +45 -44
  28. package/cpp/rnwgpu/api/GPUQueue.h +1 -1
  29. package/cpp/rnwgpu/api/GPURenderBundleEncoder.h +1 -1
  30. package/cpp/rnwgpu/api/GPURenderPassEncoder.h +1 -1
  31. package/cpp/rnwgpu/api/descriptors/GPUBindGroupEntry.h +1 -1
  32. package/cpp/rnwgpu/api/descriptors/GPUComputePipelineDescriptor.h +1 -1
  33. package/cpp/rnwgpu/api/descriptors/GPUImageCopyExternalImage.h +7 -6
  34. package/cpp/rnwgpu/api/descriptors/GPURenderPassDescriptor.h +1 -1
  35. package/cpp/rnwgpu/api/descriptors/GPURenderPipelineDescriptor.h +1 -1
  36. package/cpp/rnwgpu/api/descriptors/GPUVertexState.h +1 -1
  37. package/cpp/rnwgpu/async/AsyncRunner.cpp +2 -1
  38. package/cpp/rnwgpu/async/AsyncRunner.h +2 -1
  39. package/lib/commonjs/external/reanimated/useVideo.js +30 -31
  40. package/lib/commonjs/external/reanimated/useVideo.js.map +1 -1
  41. package/lib/commonjs/renderer/Offscreen.js +1 -0
  42. package/lib/commonjs/renderer/Offscreen.js.map +1 -1
  43. package/lib/commonjs/skia/types/Video/Video.d.ts +3 -0
  44. package/lib/commonjs/skia/types/Video/Video.js.map +1 -1
  45. package/lib/commonjs/skia/web/JsiVideo.d.ts +3 -0
  46. package/lib/commonjs/skia/web/JsiVideo.js +9 -0
  47. package/lib/commonjs/skia/web/JsiVideo.js.map +1 -1
  48. package/lib/commonjs/sksg/Container.web.js +1 -0
  49. package/lib/commonjs/sksg/Container.web.js.map +1 -1
  50. package/lib/commonjs/sksg/HostConfig.js +4 -1
  51. package/lib/commonjs/sksg/HostConfig.js.map +1 -1
  52. package/lib/commonjs/sksg/Reconciler.js +6 -6
  53. package/lib/commonjs/sksg/Reconciler.js.map +1 -1
  54. package/lib/commonjs/sksg/StaticContainer.js +1 -0
  55. package/lib/commonjs/sksg/StaticContainer.js.map +1 -1
  56. package/lib/module/external/reanimated/useVideo.js +30 -31
  57. package/lib/module/external/reanimated/useVideo.js.map +1 -1
  58. package/lib/module/renderer/Offscreen.js +1 -0
  59. package/lib/module/renderer/Offscreen.js.map +1 -1
  60. package/lib/module/skia/types/Video/Video.d.ts +3 -0
  61. package/lib/module/skia/types/Video/Video.js.map +1 -1
  62. package/lib/module/skia/web/JsiVideo.d.ts +3 -0
  63. package/lib/module/skia/web/JsiVideo.js +9 -0
  64. package/lib/module/skia/web/JsiVideo.js.map +1 -1
  65. package/lib/module/sksg/Container.web.js +1 -0
  66. package/lib/module/sksg/Container.web.js.map +1 -1
  67. package/lib/module/sksg/HostConfig.js +4 -1
  68. package/lib/module/sksg/HostConfig.js.map +1 -1
  69. package/lib/module/sksg/Reconciler.js +6 -6
  70. package/lib/module/sksg/Reconciler.js.map +1 -1
  71. package/lib/module/sksg/StaticContainer.js +1 -0
  72. package/lib/module/sksg/StaticContainer.js.map +1 -1
  73. package/lib/typescript/lib/commonjs/skia/web/JsiVideo.d.ts +3 -0
  74. package/lib/typescript/lib/commonjs/sksg/HostConfig.d.ts +2 -0
  75. package/lib/typescript/lib/module/skia/web/JsiVideo.d.ts +3 -0
  76. package/lib/typescript/lib/module/sksg/HostConfig.d.ts +2 -0
  77. package/lib/typescript/src/skia/types/Video/Video.d.ts +3 -0
  78. package/lib/typescript/src/skia/web/JsiVideo.d.ts +3 -0
  79. package/package.json +1 -1
  80. package/src/external/reanimated/useVideo.ts +32 -32
  81. package/src/renderer/Offscreen.tsx +1 -0
  82. package/src/skia/types/Video/Video.ts +3 -0
  83. package/src/skia/web/JsiVideo.ts +12 -0
  84. package/src/sksg/Container.web.ts +1 -0
  85. package/src/sksg/HostConfig.ts +4 -0
  86. package/src/sksg/Reconciler.ts +5 -6
  87. package/src/sksg/StaticContainer.ts +1 -0
@@ -126,8 +126,8 @@ public:
126
126
  * Throws if the object has been disposed.
127
127
  * @return Underlying object
128
128
  */
129
- T getObject() { return _object; }
130
- const T getObject() const { return _object; }
129
+ T getObject() { return validateObject(); }
130
+ const T getObject() const { return validateObject(); }
131
131
 
132
132
  /**
133
133
  * Updates the inner object with a new version of the object.
@@ -139,15 +139,57 @@ public:
139
139
  * macro.
140
140
  */
141
141
  JSI_HOST_FUNCTION(dispose) {
142
- // This is a no-op on native
142
+ safeDispose();
143
143
  return jsi::Value::undefined();
144
144
  }
145
145
 
146
+ protected:
147
+ /**
148
+ * Override to implement disposal of allocated resources like smart pointers.
149
+ * This method will only be called once for each instance of this class.
150
+ */
151
+ virtual void releaseResources() = 0;
152
+
153
+ /**
154
+ * Returns true if the object has been disposed.
155
+ */
156
+ bool isDisposed() const { return _isDisposed.load(std::memory_order_acquire); }
157
+
158
+ /**
159
+ * Returns the underlying object without checking if disposed.
160
+ * Use this in destructors and releaseResources() where we need to access
161
+ * the object even after dispose() was called.
162
+ */
163
+ T getObjectUnchecked() const { return _object; }
164
+
146
165
  private:
166
+ /**
167
+ * Validates that _object was not disposed and returns it.
168
+ */
169
+ T validateObject() const {
170
+ if (_isDisposed.load(std::memory_order_acquire)) {
171
+ throw std::runtime_error("Attempted to access a disposed object.");
172
+ }
173
+ return _object;
174
+ }
175
+
176
+ void safeDispose() {
177
+ bool expected = false;
178
+ if (_isDisposed.compare_exchange_strong(expected, true,
179
+ std::memory_order_acq_rel)) {
180
+ releaseResources();
181
+ }
182
+ }
183
+
147
184
  /**
148
185
  * Wrapped object.
149
186
  */
150
187
  T _object;
188
+
189
+ /**
190
+ * Resource disposed flag.
191
+ */
192
+ std::atomic<bool> _isDisposed = {false};
151
193
  };
152
194
 
153
195
  template <typename T>
@@ -168,6 +210,12 @@ public:
168
210
  obj.asObject(runtime).asHostObject(runtime))
169
211
  ->getObject();
170
212
  }
213
+
214
+ protected:
215
+ void releaseResources() override {
216
+ // Clear internally allocated objects
217
+ this->setObject(nullptr);
218
+ }
171
219
  };
172
220
 
173
221
  template <typename T>
@@ -186,6 +234,12 @@ public:
186
234
  obj.asObject(runtime).asHostObject(runtime))
187
235
  ->getObject();
188
236
  }
237
+
238
+ protected:
239
+ void releaseResources() override {
240
+ // Clear internally allocated objects
241
+ this->setObject(nullptr);
242
+ }
189
243
  };
190
244
 
191
245
  } // namespace RNSkia
@@ -293,20 +293,34 @@ public:
293
293
  _dispatcher->processQueue();
294
294
  }
295
295
 
296
- ~JsiSkImage() override {
296
+ protected:
297
+ void releaseResources() override {
297
298
  // Queue deletion on the creation thread if needed
298
- auto image = getObject();
299
+ auto image = getObjectUnchecked();
299
300
  if (image && _dispatcher) {
300
301
  _dispatcher->run([image]() {
301
302
  // Image will be deleted when this lambda is destroyed
302
303
  });
303
304
  }
304
- // Clear the object to prevent base class destructor from deleting it
305
- setObject(nullptr);
305
+ // Clear the object
306
+ JsiSkWrappingSkPtrHostObject<SkImage>::releaseResources();
307
+ }
308
+
309
+ public:
310
+ ~JsiSkImage() override {
311
+ // If already disposed, resources were already cleaned up
312
+ if (isDisposed()) {
313
+ return;
314
+ }
315
+ // Use the same cleanup path as dispose()
316
+ releaseResources();
306
317
  }
307
318
 
308
319
  size_t getMemoryPressure() const override {
309
- auto image = getObject();
320
+ if (isDisposed()) {
321
+ return 0;
322
+ }
323
+ auto image = getObjectUnchecked();
310
324
  if (image) {
311
325
  if (image->isTextureBacked()) {
312
326
  return image->textureSize();
@@ -34,16 +34,27 @@ public:
34
34
  _dispatcher->processQueue();
35
35
  }
36
36
 
37
- ~JsiSkPicture() override {
37
+ protected:
38
+ void releaseResources() override {
38
39
  // Queue deletion on the creation thread if needed
39
- auto picture = getObject();
40
+ auto picture = getObjectUnchecked();
40
41
  if (picture && _dispatcher) {
41
42
  _dispatcher->run([picture]() {
42
43
  // Picture will be deleted when this lambda is destroyed
43
44
  });
44
45
  }
45
- // Clear the object to prevent base class destructor from deleting it
46
- setObject(nullptr);
46
+ // Clear the object
47
+ JsiSkWrappingSkPtrHostObject<SkPicture>::releaseResources();
48
+ }
49
+
50
+ public:
51
+ ~JsiSkPicture() override {
52
+ // If already disposed, resources were already cleaned up
53
+ if (isDisposed()) {
54
+ return;
55
+ }
56
+ // Use the same cleanup path as dispose()
57
+ releaseResources();
47
58
  }
48
59
 
49
60
  JSI_HOST_FUNCTION(makeShader) {
@@ -91,7 +102,10 @@ public:
91
102
  JSI_EXPORT_FUNC(JsiSkPicture, dispose))
92
103
 
93
104
  size_t getMemoryPressure() const override {
94
- auto picture = getObject();
105
+ if (isDisposed()) {
106
+ return 0;
107
+ }
108
+ auto picture = getObjectUnchecked();
95
109
  if (!picture) {
96
110
  return 0;
97
111
  }
@@ -45,16 +45,27 @@ public:
45
45
  _dispatcher->processQueue();
46
46
  }
47
47
 
48
- ~JsiSkSurface() override {
48
+ protected:
49
+ void releaseResources() override {
49
50
  // Queue deletion on the creation thread if needed
50
- auto surface = getObject();
51
+ auto surface = getObjectUnchecked();
51
52
  if (surface && _dispatcher) {
52
53
  _dispatcher->run([surface]() {
53
54
  // Surface will be deleted when this lambda is destroyed
54
55
  });
55
56
  }
56
- // Clear the object to prevent base class destructor from deleting it
57
- setObject(nullptr);
57
+ // Clear the object
58
+ JsiSkWrappingSkPtrHostObject<SkSurface>::releaseResources();
59
+ }
60
+
61
+ public:
62
+ ~JsiSkSurface() override {
63
+ // If already disposed, resources were already cleaned up
64
+ if (isDisposed()) {
65
+ return;
66
+ }
67
+ // Use the same cleanup path as dispose()
68
+ releaseResources();
58
69
  }
59
70
 
60
71
  EXPORT_JSI_API_TYPENAME(JsiSkSurface, Surface)
@@ -117,7 +128,10 @@ public:
117
128
  }
118
129
 
119
130
  size_t getMemoryPressure() const override {
120
- auto surface = getObject();
131
+ if (isDisposed()) {
132
+ return 0;
133
+ }
134
+ auto surface = getObjectUnchecked();
121
135
  if (!surface) {
122
136
  return 0;
123
137
  }
@@ -49,6 +49,10 @@ public:
49
49
 
50
50
  JSI_HOST_FUNCTION(framerate) { return getObject()->framerate(); }
51
51
 
52
+ JSI_HOST_FUNCTION(currentTime) { return getObject()->currentTime(); }
53
+
54
+ JSI_HOST_FUNCTION(isPlaying) { return getObject()->isPlaying(); }
55
+
52
56
  JSI_HOST_FUNCTION(seek) {
53
57
  double timestamp = arguments[0].asNumber();
54
58
  getObject()->seek(timestamp);
@@ -86,12 +90,21 @@ public:
86
90
  return jsi::Value::undefined();
87
91
  }
88
92
 
93
+ JSI_HOST_FUNCTION(setLooping) {
94
+ auto looping = arguments[0].asBool();
95
+ getObject()->setLooping(looping);
96
+ return jsi::Value::undefined();
97
+ }
98
+
89
99
  JSI_EXPORT_FUNCTIONS(
90
100
  JSI_EXPORT_FUNC(JsiVideo, nextImage), JSI_EXPORT_FUNC(JsiVideo, duration),
91
- JSI_EXPORT_FUNC(JsiVideo, framerate), JSI_EXPORT_FUNC(JsiVideo, seek),
101
+ JSI_EXPORT_FUNC(JsiVideo, framerate),
102
+ JSI_EXPORT_FUNC(JsiVideo, currentTime),
103
+ JSI_EXPORT_FUNC(JsiVideo, isPlaying), JSI_EXPORT_FUNC(JsiVideo, seek),
92
104
  JSI_EXPORT_FUNC(JsiVideo, rotation), JSI_EXPORT_FUNC(JsiVideo, size),
93
105
  JSI_EXPORT_FUNC(JsiVideo, play), JSI_EXPORT_FUNC(JsiVideo, pause),
94
- JSI_EXPORT_FUNC(JsiVideo, setVolume), JSI_EXPORT_FUNC(JsiVideo, dispose))
106
+ JSI_EXPORT_FUNC(JsiVideo, setVolume),
107
+ JSI_EXPORT_FUNC(JsiVideo, setLooping), JSI_EXPORT_FUNC(JsiVideo, dispose))
95
108
 
96
109
  JsiVideo(std::shared_ptr<RNSkPlatformContext> context,
97
110
  std::shared_ptr<RNSkVideo> video)
@@ -667,7 +667,8 @@ SkPath1DPathEffect::Style getPropertyValue(jsi::Runtime &runtime,
667
667
  throw std::runtime_error("Invalid prop value for Path1DEffectStyle received");
668
668
  }
669
669
 
670
- // Wrapper type for blend mode to avoid conflict with int template specialization
670
+ // Wrapper type for blend mode to avoid conflict with int template
671
+ // specialization
671
672
  struct BlendModeValue {
672
673
  int value;
673
674
  BlendModeValue(int v = 0) : value(v) {}
@@ -745,7 +746,8 @@ BlendModeValue getPropertyValue(jsi::Runtime &runtime, const jsi::Value &val) {
745
746
  throw std::runtime_error("Invalid prop value for BlendMode received");
746
747
  }
747
748
 
748
- // Keep SkBlendMode specialization for other usages (Shaders, ImageFilters, ColorFilters, Drawings)
749
+ // Keep SkBlendMode specialization for other usages (Shaders, ImageFilters,
750
+ // ColorFilters, Drawings)
749
751
  template <>
750
752
  SkBlendMode getPropertyValue(jsi::Runtime &runtime, const jsi::Value &val) {
751
753
  if (val.isString()) {
@@ -6,40 +6,55 @@
6
6
  namespace rnwgpu {
7
7
 
8
8
  namespace EnumMapper {
9
- // Add these two methods in namespace "EnumMapper" to allow parsing a custom enum:
10
- // 1. `static void convertJSUnionToEnum(const std::string& inUnion, Enum* outEnum)`
11
- // 2. `static void convertEnumToJSUnion(Enum inEnum, std::string* outUnion)`
12
-
13
- static std::runtime_error invalidUnion(const std::string& passedUnion) {
14
- return std::runtime_error("Cannot convert JS Value to Enum: Invalid Union value passed! (\"" + std::string(passedUnion) + "\")");
15
- }
16
-
17
- template <typename T> static std::runtime_error invalidEnum(T passedEnum) {
18
- return std::runtime_error("Cannot convert Enum to JS Value: Invalid Enum passed! (Value #" +
19
- std::to_string(static_cast<int>(passedEnum)) + ")");
20
- }
21
-
22
- // Trait to check if a convertJSUnionToEnum function for enum type T exists
23
- template <typename T, typename = void> struct has_js_union_to_enum : std::false_type {};
24
- template <typename T>
25
- struct has_js_union_to_enum<T, std::void_t<decltype(convertJSUnionToEnum(std::declval<std::string>(), std::declval<T*>()))>>
26
- : std::true_type {};
27
-
28
- // Trait to check if a convertEnumToJSUnion function for enum type T exists
29
- template <typename T, typename = void> struct has_enum_to_js_union : std::false_type {};
30
- template <typename T>
31
- struct has_enum_to_js_union<T, std::void_t<decltype(convertEnumToJSUnion(std::declval<T>(), std::declval<std::string*>()))>>
32
- : std::true_type {};
33
-
34
- template <typename TEnum> static void convertJSUnionToEnum(const std::string&, TEnum*) {
35
- static_assert(has_js_union_to_enum<TEnum>::value,
36
- "Cannot convert a JS union to this enum type. Did you implement EnumMapper::convertJSUnionToEnum(...)?");
37
- }
38
-
39
- template <typename TEnum> static void convertEnumToJSUnion(TEnum, std::string*) {
40
- static_assert(has_enum_to_js_union<TEnum>::value,
41
- "Cannot convert this enum type to a JS union. Did you implement EnumMapper::convertEnumToJSUnion(...)?");
42
- }
9
+ // Add these two methods in namespace "EnumMapper" to allow parsing a custom
10
+ // enum:
11
+ // 1. `static void convertJSUnionToEnum(const std::string& inUnion, Enum*
12
+ // outEnum)`
13
+ // 2. `static void convertEnumToJSUnion(Enum inEnum, std::string* outUnion)`
14
+
15
+ static std::runtime_error invalidUnion(const std::string &passedUnion) {
16
+ return std::runtime_error(
17
+ "Cannot convert JS Value to Enum: Invalid Union value passed! (\"" +
18
+ std::string(passedUnion) + "\")");
19
+ }
20
+
21
+ template <typename T> static std::runtime_error invalidEnum(T passedEnum) {
22
+ return std::runtime_error(
23
+ "Cannot convert Enum to JS Value: Invalid Enum passed! (Value #" +
24
+ std::to_string(static_cast<int>(passedEnum)) + ")");
25
+ }
26
+
27
+ // Trait to check if a convertJSUnionToEnum function for enum type T exists
28
+ template <typename T, typename = void>
29
+ struct has_js_union_to_enum : std::false_type {};
30
+ template <typename T>
31
+ struct has_js_union_to_enum<
32
+ T, std::void_t<decltype(convertJSUnionToEnum(std::declval<std::string>(),
33
+ std::declval<T *>()))>>
34
+ : std::true_type {};
35
+
36
+ // Trait to check if a convertEnumToJSUnion function for enum type T exists
37
+ template <typename T, typename = void>
38
+ struct has_enum_to_js_union : std::false_type {};
39
+ template <typename T>
40
+ struct has_enum_to_js_union<
41
+ T, std::void_t<decltype(convertEnumToJSUnion(
42
+ std::declval<T>(), std::declval<std::string *>()))>>
43
+ : std::true_type {};
44
+
45
+ template <typename TEnum>
46
+ static void convertJSUnionToEnum(const std::string &, TEnum *) {
47
+ static_assert(has_js_union_to_enum<TEnum>::value,
48
+ "Cannot convert a JS union to this enum type. Did you "
49
+ "implement EnumMapper::convertJSUnionToEnum(...)?");
50
+ }
51
+
52
+ template <typename TEnum>
53
+ static void convertEnumToJSUnion(TEnum, std::string *) {
54
+ static_assert(has_enum_to_js_union<TEnum>::value,
55
+ "Cannot convert this enum type to a JS union. Did you "
56
+ "implement EnumMapper::convertEnumToJSUnion(...)?");
57
+ }
43
58
  } // namespace EnumMapper
44
59
 
45
60
  } // namespace rnwgpu