@shopify/react-native-skia 1.2.0 → 1.2.2

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 (182) hide show
  1. package/android/cpp/rnskia-android/RNSkAndroidPlatformContext.h +3 -3
  2. package/android/src/main/java/com/shopify/reactnative/skia/ViewScreenshotService.java +13 -8
  3. package/cpp/api/JsiNativeBuffer.h +43 -0
  4. package/cpp/api/JsiSkApi.h +3 -3
  5. package/cpp/api/JsiSkImageFactory.h +3 -3
  6. package/cpp/rnskia/RNSkPlatformContext.h +5 -5
  7. package/ios/RNSkia-iOS/RNSkiOSPlatformContext.h +3 -3
  8. package/ios/RNSkia-iOS/RNSkiOSPlatformContext.mm +70 -93
  9. package/ios/RNSkia-iOS/SkiaCVPixelBufferUtils.h +119 -0
  10. package/ios/RNSkia-iOS/SkiaCVPixelBufferUtils.mm +332 -0
  11. package/ios/RNSkia-iOS/SkiaMetalSurfaceFactory.h +2 -1
  12. package/ios/RNSkia-iOS/SkiaMetalSurfaceFactory.mm +27 -6
  13. package/lib/commonjs/external/ModuleProxy.d.ts +10 -0
  14. package/lib/commonjs/external/ModuleProxy.js +36 -0
  15. package/lib/commonjs/external/ModuleProxy.js.map +1 -0
  16. package/lib/commonjs/external/reanimated/ReanimatedProxy.d.ts +3 -0
  17. package/lib/commonjs/external/reanimated/ReanimatedProxy.js +18 -0
  18. package/lib/commonjs/external/reanimated/ReanimatedProxy.js.map +1 -0
  19. package/lib/commonjs/external/reanimated/buffers.js +9 -6
  20. package/lib/commonjs/external/reanimated/buffers.js.map +1 -1
  21. package/lib/commonjs/external/reanimated/interpolators.js +8 -7
  22. package/lib/commonjs/external/reanimated/interpolators.js.map +1 -1
  23. package/lib/commonjs/external/reanimated/renderHelpers.js +27 -11
  24. package/lib/commonjs/external/reanimated/renderHelpers.js.map +1 -1
  25. package/lib/commonjs/external/reanimated/textures.js +4 -3
  26. package/lib/commonjs/external/reanimated/textures.js.map +1 -1
  27. package/lib/commonjs/external/reanimated/useAnimatedImageValue.js +6 -6
  28. package/lib/commonjs/external/reanimated/useAnimatedImageValue.js.map +1 -1
  29. package/lib/commonjs/external/reanimated/useDerivedValueOnJS.js +6 -5
  30. package/lib/commonjs/external/reanimated/useDerivedValueOnJS.js.map +1 -1
  31. package/lib/commonjs/renderer/Offscreen.js +1 -5
  32. package/lib/commonjs/renderer/Offscreen.js.map +1 -1
  33. package/lib/commonjs/skia/types/Image/ImageFactory.d.ts +8 -15
  34. package/lib/commonjs/skia/types/Image/ImageFactory.js +1 -10
  35. package/lib/commonjs/skia/types/Image/ImageFactory.js.map +1 -1
  36. package/lib/commonjs/skia/types/NativeBuffer/NativeBufferFactory.d.ts +18 -0
  37. package/lib/commonjs/skia/types/NativeBuffer/NativeBufferFactory.js +13 -0
  38. package/lib/commonjs/skia/types/NativeBuffer/NativeBufferFactory.js.map +1 -0
  39. package/lib/commonjs/skia/types/NativeBuffer/index.d.ts +1 -0
  40. package/lib/commonjs/skia/types/NativeBuffer/index.js +17 -0
  41. package/lib/commonjs/skia/types/NativeBuffer/index.js.map +1 -0
  42. package/lib/commonjs/skia/types/Skia.d.ts +2 -2
  43. package/lib/commonjs/skia/types/Skia.js.map +1 -1
  44. package/lib/commonjs/skia/types/index.d.ts +1 -1
  45. package/lib/commonjs/skia/types/index.js +4 -4
  46. package/lib/commonjs/skia/types/index.js.map +1 -1
  47. package/lib/commonjs/skia/web/JsiSkImageFactory.d.ts +3 -2
  48. package/lib/commonjs/skia/web/JsiSkImageFactory.js +18 -2
  49. package/lib/commonjs/skia/web/JsiSkImageFactory.js.map +1 -1
  50. package/lib/commonjs/skia/web/JsiSkNativeBufferFactory.d.ts +8 -0
  51. package/lib/commonjs/skia/web/JsiSkNativeBufferFactory.js +29 -0
  52. package/lib/commonjs/skia/web/JsiSkNativeBufferFactory.js.map +1 -0
  53. package/lib/commonjs/skia/web/JsiSkia.js +2 -2
  54. package/lib/commonjs/skia/web/JsiSkia.js.map +1 -1
  55. package/lib/commonjs/specs/NativeSkiaModule.web.d.ts +0 -2
  56. package/lib/commonjs/specs/NativeSkiaModule.web.js +0 -8
  57. package/lib/commonjs/specs/NativeSkiaModule.web.js.map +1 -1
  58. package/lib/module/external/ModuleProxy.d.ts +10 -0
  59. package/lib/module/external/ModuleProxy.js +28 -0
  60. package/lib/module/external/ModuleProxy.js.map +1 -0
  61. package/lib/module/external/reanimated/ReanimatedProxy.d.ts +3 -0
  62. package/lib/module/external/reanimated/ReanimatedProxy.js +12 -0
  63. package/lib/module/external/reanimated/ReanimatedProxy.js.map +1 -0
  64. package/lib/module/external/reanimated/buffers.js +8 -6
  65. package/lib/module/external/reanimated/buffers.js.map +1 -1
  66. package/lib/module/external/reanimated/interpolators.js +7 -7
  67. package/lib/module/external/reanimated/interpolators.js.map +1 -1
  68. package/lib/module/external/reanimated/renderHelpers.js +26 -11
  69. package/lib/module/external/reanimated/renderHelpers.js.map +1 -1
  70. package/lib/module/external/reanimated/textures.js +3 -3
  71. package/lib/module/external/reanimated/textures.js.map +1 -1
  72. package/lib/module/external/reanimated/useAnimatedImageValue.js +5 -6
  73. package/lib/module/external/reanimated/useAnimatedImageValue.js.map +1 -1
  74. package/lib/module/external/reanimated/useDerivedValueOnJS.js +5 -5
  75. package/lib/module/external/reanimated/useDerivedValueOnJS.js.map +1 -1
  76. package/lib/module/renderer/Offscreen.js +1 -5
  77. package/lib/module/renderer/Offscreen.js.map +1 -1
  78. package/lib/module/skia/types/Image/ImageFactory.d.ts +8 -15
  79. package/lib/module/skia/types/Image/ImageFactory.js +1 -10
  80. package/lib/module/skia/types/Image/ImageFactory.js.map +1 -1
  81. package/lib/module/skia/types/NativeBuffer/NativeBufferFactory.d.ts +18 -0
  82. package/lib/module/skia/types/NativeBuffer/NativeBufferFactory.js +4 -0
  83. package/lib/module/skia/types/NativeBuffer/NativeBufferFactory.js.map +1 -0
  84. package/lib/module/skia/types/NativeBuffer/index.d.ts +1 -0
  85. package/lib/module/skia/types/NativeBuffer/index.js +2 -0
  86. package/lib/module/skia/types/NativeBuffer/index.js.map +1 -0
  87. package/lib/module/skia/types/Skia.d.ts +2 -2
  88. package/lib/module/skia/types/Skia.js.map +1 -1
  89. package/lib/module/skia/types/index.d.ts +1 -1
  90. package/lib/module/skia/types/index.js +1 -1
  91. package/lib/module/skia/types/index.js.map +1 -1
  92. package/lib/module/skia/web/JsiSkImageFactory.d.ts +3 -2
  93. package/lib/module/skia/web/JsiSkImageFactory.js +18 -2
  94. package/lib/module/skia/web/JsiSkImageFactory.js.map +1 -1
  95. package/lib/module/skia/web/JsiSkNativeBufferFactory.d.ts +8 -0
  96. package/lib/module/skia/web/JsiSkNativeBufferFactory.js +22 -0
  97. package/lib/module/skia/web/JsiSkNativeBufferFactory.js.map +1 -0
  98. package/lib/module/skia/web/JsiSkia.js +2 -2
  99. package/lib/module/skia/web/JsiSkia.js.map +1 -1
  100. package/lib/module/specs/NativeSkiaModule.web.d.ts +0 -2
  101. package/lib/module/specs/NativeSkiaModule.web.js +0 -3
  102. package/lib/module/specs/NativeSkiaModule.web.js.map +1 -1
  103. package/lib/typescript/src/external/ModuleProxy.d.ts +10 -0
  104. package/lib/typescript/src/external/reanimated/ReanimatedProxy.d.ts +3 -0
  105. package/lib/typescript/src/skia/types/Image/ImageFactory.d.ts +8 -15
  106. package/lib/typescript/src/skia/types/NativeBuffer/NativeBufferFactory.d.ts +18 -0
  107. package/lib/typescript/src/skia/types/NativeBuffer/index.d.ts +1 -0
  108. package/lib/typescript/src/skia/types/Skia.d.ts +2 -2
  109. package/lib/typescript/src/skia/types/index.d.ts +1 -1
  110. package/lib/typescript/src/skia/web/JsiSkImageFactory.d.ts +3 -2
  111. package/lib/typescript/src/skia/web/JsiSkNativeBufferFactory.d.ts +8 -0
  112. package/lib/typescript/src/specs/NativeSkiaModule.web.d.ts +0 -2
  113. package/libs/ios/libskia.xcframework/Info.plist +5 -5
  114. package/libs/ios/libskia.xcframework/ios-arm64_arm64e/libskia.a +0 -0
  115. package/libs/ios/libskia.xcframework/ios-arm64_arm64e_x86_64-simulator/libskia.a +0 -0
  116. package/libs/ios/libskottie.xcframework/Info.plist +5 -5
  117. package/libs/ios/libskottie.xcframework/ios-arm64_arm64e/libskottie.a +0 -0
  118. package/libs/ios/libskottie.xcframework/ios-arm64_arm64e_x86_64-simulator/libskottie.a +0 -0
  119. package/libs/ios/libskparagraph.xcframework/ios-arm64_arm64e/libskparagraph.a +0 -0
  120. package/libs/ios/libskparagraph.xcframework/ios-arm64_arm64e_x86_64-simulator/libskparagraph.a +0 -0
  121. package/libs/ios/libsksg.xcframework/ios-arm64_arm64e/libsksg.a +0 -0
  122. package/libs/ios/libsksg.xcframework/ios-arm64_arm64e_x86_64-simulator/libsksg.a +0 -0
  123. package/libs/ios/libskshaper.xcframework/ios-arm64_arm64e/libskshaper.a +0 -0
  124. package/libs/ios/libskshaper.xcframework/ios-arm64_arm64e_x86_64-simulator/libskshaper.a +0 -0
  125. package/libs/ios/libskunicode.xcframework/ios-arm64_arm64e/libskunicode.a +0 -0
  126. package/libs/ios/libskunicode.xcframework/ios-arm64_arm64e_x86_64-simulator/libskunicode.a +0 -0
  127. package/libs/ios/libsvg.xcframework/ios-arm64_arm64e/libsvg.a +0 -0
  128. package/libs/ios/libsvg.xcframework/ios-arm64_arm64e_x86_64-simulator/libsvg.a +0 -0
  129. package/package.json +1 -1
  130. package/src/external/ModuleProxy.ts +30 -0
  131. package/src/external/reanimated/ReanimatedProxy.ts +18 -0
  132. package/src/external/reanimated/buffers.ts +7 -6
  133. package/src/external/reanimated/interpolators.ts +7 -12
  134. package/src/external/reanimated/renderHelpers.ts +31 -18
  135. package/src/external/reanimated/textures.tsx +3 -3
  136. package/src/external/reanimated/useAnimatedImageValue.ts +5 -10
  137. package/src/external/reanimated/useDerivedValueOnJS.ts +5 -10
  138. package/src/renderer/Offscreen.tsx +1 -7
  139. package/src/skia/types/Image/ImageFactory.ts +7 -23
  140. package/src/skia/types/NativeBuffer/NativeBufferFactory.ts +38 -0
  141. package/src/skia/types/NativeBuffer/index.ts +1 -0
  142. package/src/skia/types/Skia.ts +2 -2
  143. package/src/skia/types/index.ts +1 -1
  144. package/src/skia/web/JsiSkImageFactory.ts +28 -6
  145. package/src/skia/web/JsiSkNativeBufferFactory.ts +35 -0
  146. package/src/skia/web/JsiSkia.ts +2 -2
  147. package/src/specs/NativeSkiaModule.web.ts +0 -4
  148. package/android/src/paper/java/com/facebook/react/viewmanagers/SkiaDrawViewManagerDelegate.java +0 -34
  149. package/cpp/api/JsiPlatformBuffer.h +0 -51
  150. package/cpp/skia/include/gpu/GrBackendDrawableInfo.h +0 -9
  151. package/lib/commonjs/external/reanimated/moduleWrapper.d.ts +0 -15
  152. package/lib/commonjs/external/reanimated/moduleWrapper.js +0 -46
  153. package/lib/commonjs/external/reanimated/moduleWrapper.js.map +0 -1
  154. package/lib/commonjs/skia/types/PlatformBuffer/PlatformBufferFactory.d.ts +0 -12
  155. package/lib/commonjs/skia/types/PlatformBuffer/PlatformBufferFactory.js +0 -6
  156. package/lib/commonjs/skia/types/PlatformBuffer/PlatformBufferFactory.js.map +0 -1
  157. package/lib/commonjs/skia/types/PlatformBuffer/index.d.ts +0 -1
  158. package/lib/commonjs/skia/types/PlatformBuffer/index.js +0 -17
  159. package/lib/commonjs/skia/types/PlatformBuffer/index.js.map +0 -1
  160. package/lib/commonjs/skia/web/JsiSkPlatformBufferFactory.d.ts +0 -8
  161. package/lib/commonjs/skia/web/JsiSkPlatformBufferFactory.js +0 -20
  162. package/lib/commonjs/skia/web/JsiSkPlatformBufferFactory.js.map +0 -1
  163. package/lib/module/external/reanimated/moduleWrapper.d.ts +0 -15
  164. package/lib/module/external/reanimated/moduleWrapper.js +0 -37
  165. package/lib/module/external/reanimated/moduleWrapper.js.map +0 -1
  166. package/lib/module/skia/types/PlatformBuffer/PlatformBufferFactory.d.ts +0 -12
  167. package/lib/module/skia/types/PlatformBuffer/PlatformBufferFactory.js +0 -2
  168. package/lib/module/skia/types/PlatformBuffer/PlatformBufferFactory.js.map +0 -1
  169. package/lib/module/skia/types/PlatformBuffer/index.d.ts +0 -1
  170. package/lib/module/skia/types/PlatformBuffer/index.js +0 -2
  171. package/lib/module/skia/types/PlatformBuffer/index.js.map +0 -1
  172. package/lib/module/skia/web/JsiSkPlatformBufferFactory.d.ts +0 -8
  173. package/lib/module/skia/web/JsiSkPlatformBufferFactory.js +0 -13
  174. package/lib/module/skia/web/JsiSkPlatformBufferFactory.js.map +0 -1
  175. package/lib/typescript/src/external/reanimated/moduleWrapper.d.ts +0 -15
  176. package/lib/typescript/src/skia/types/PlatformBuffer/PlatformBufferFactory.d.ts +0 -12
  177. package/lib/typescript/src/skia/types/PlatformBuffer/index.d.ts +0 -1
  178. package/lib/typescript/src/skia/web/JsiSkPlatformBufferFactory.d.ts +0 -8
  179. package/src/external/reanimated/moduleWrapper.ts +0 -83
  180. package/src/skia/types/PlatformBuffer/PlatformBufferFactory.ts +0 -14
  181. package/src/skia/types/PlatformBuffer/index.ts +0 -1
  182. package/src/skia/web/JsiSkPlatformBufferFactory.ts +0 -22
@@ -53,18 +53,18 @@ public:
53
53
  return SkiaOpenGLSurfaceFactory::makeOffscreenSurface(width, height);
54
54
  }
55
55
 
56
- sk_sp<SkImage> makeImageFromPlatformBuffer(void *buffer) override {
56
+ sk_sp<SkImage> makeImageFromNativeBuffer(void *buffer) override {
57
57
  return SkiaOpenGLSurfaceFactory::makeImageFromHardwareBuffer(buffer);
58
58
  }
59
59
 
60
- void releasePlatformBuffer(uint64_t pointer) override {
60
+ void releaseNativeBuffer(uint64_t pointer) override {
61
61
  #if __ANDROID_API__ >= 26
62
62
  AHardwareBuffer *buffer = reinterpret_cast<AHardwareBuffer *>(pointer);
63
63
  AHardwareBuffer_release(buffer);
64
64
  #endif
65
65
  }
66
66
 
67
- uint64_t makePlatformBuffer(sk_sp<SkImage> image) override {
67
+ uint64_t makeNativeBuffer(sk_sp<SkImage> image) override {
68
68
  #if __ANDROID_API__ >= 26
69
69
  auto bytesPerPixel = image->imageInfo().bytesPerPixel();
70
70
  int bytesPerRow = image->width() * bytesPerPixel;
@@ -162,16 +162,21 @@ public class ViewScreenshotService {
162
162
  latch.await(SURFACE_VIEW_READ_PIXELS_TIMEOUT, TimeUnit.SECONDS);
163
163
  } catch (Exception e) {
164
164
  Log.e(TAG, "Cannot PixelCopy for " + sv, e);
165
+ drawSurfaceViewFromCache(canvas, sv, paint, opacity);
165
166
  }
166
167
  } else {
167
- Bitmap cache = sv.getDrawingCache();
168
- if (cache != null) {
169
- canvas.save();
170
- applyTransformations(canvas, sv);
171
- paint.setAlpha(Math.round(opacity * 255)); // Set paint alpha based on opacity
172
- canvas.drawBitmap(cache, 0, 0, paint);
173
- canvas.restore();
174
- }
168
+ drawSurfaceViewFromCache(canvas, sv, paint, opacity);
169
+ }
170
+ }
171
+
172
+ private static void drawSurfaceViewFromCache(Canvas canvas, SurfaceView sv, Paint paint, float opacity) {
173
+ Bitmap cache = sv.getDrawingCache();
174
+ if (cache != null) {
175
+ canvas.save();
176
+ applyTransformations(canvas, sv);
177
+ paint.setAlpha(Math.round(opacity * 255)); // Set paint alpha based on opacity
178
+ canvas.drawBitmap(cache, 0, 0, paint);
179
+ canvas.restore();
175
180
  }
176
181
  }
177
182
 
@@ -0,0 +1,43 @@
1
+ #pragma once
2
+
3
+ #include <memory>
4
+ #include <utility>
5
+
6
+ #include <jsi/jsi.h>
7
+
8
+ #include "JsiSkImage.h"
9
+
10
+ namespace RNSkia {
11
+
12
+ namespace jsi = facebook::jsi;
13
+
14
+ /**
15
+ Implementation of the ParagraphBuilderFactory for making ParagraphBuilder JSI
16
+ object
17
+ */
18
+ class JsiNativeBufferFactory : public JsiSkHostObject {
19
+ public:
20
+ JSI_HOST_FUNCTION(MakeFromImage) {
21
+ auto image = JsiSkImage::fromValue(runtime, arguments[0]);
22
+ image->makeNonTextureImage();
23
+ uint64_t pointer = getContext()->makeNativeBuffer(image);
24
+ return jsi::BigInt::fromUint64(runtime, pointer);
25
+ }
26
+
27
+ JSI_HOST_FUNCTION(Release) {
28
+
29
+ jsi::BigInt pointer = arguments[0].asBigInt(runtime);
30
+ const uintptr_t nativeBufferPointer = pointer.asUint64(runtime);
31
+
32
+ getContext()->releaseNativeBuffer(nativeBufferPointer);
33
+ return jsi::Value::undefined();
34
+ }
35
+
36
+ JSI_EXPORT_FUNCTIONS(JSI_EXPORT_FUNC(JsiNativeBufferFactory, Release),
37
+ JSI_EXPORT_FUNC(JsiNativeBufferFactory, MakeFromImage))
38
+
39
+ explicit JsiNativeBufferFactory(std::shared_ptr<RNSkPlatformContext> context)
40
+ : JsiSkHostObject(std::move(context)) {}
41
+ };
42
+
43
+ } // namespace RNSkia
@@ -6,7 +6,7 @@
6
6
 
7
7
  #include "JsiSkHostObjects.h"
8
8
 
9
- #include "JsiPlatformBuffer.h"
9
+ #include "JsiNativeBuffer.h"
10
10
  #include "JsiSkAnimatedImage.h"
11
11
  #include "JsiSkAnimatedImageFactory.h"
12
12
  #include "JsiSkColor.h"
@@ -124,8 +124,8 @@ public:
124
124
  "ParagraphBuilder",
125
125
  std::make_shared<JsiSkParagraphBuilderFactory>(context));
126
126
 
127
- installReadonlyProperty(
128
- "PlatformBuffer", std::make_shared<JsiPlatformBufferFactory>(context));
127
+ installReadonlyProperty("NativeBuffer",
128
+ std::make_shared<JsiNativeBufferFactory>(context));
129
129
  }
130
130
  };
131
131
  } // namespace RNSkia
@@ -27,11 +27,11 @@ public:
27
27
  runtime, std::make_shared<JsiSkImage>(getContext(), std::move(image)));
28
28
  }
29
29
 
30
- JSI_HOST_FUNCTION(MakeImageFromPlatformBuffer) {
30
+ JSI_HOST_FUNCTION(MakeImageFromNativeBuffer) {
31
31
  jsi::BigInt pointer = arguments[0].asBigInt(runtime);
32
32
  const uintptr_t platformBufferPointer = pointer.asUint64(runtime);
33
33
  void *rawPointer = reinterpret_cast<void *>(platformBufferPointer);
34
- auto image = getContext()->makeImageFromPlatformBuffer(rawPointer);
34
+ auto image = getContext()->makeImageFromNativeBuffer(rawPointer);
35
35
  if (image == nullptr) {
36
36
  throw std::runtime_error("Failed to convert PlatformBuffer to SkImage!");
37
37
  }
@@ -81,7 +81,7 @@ public:
81
81
  JSI_EXPORT_FUNCTIONS(JSI_EXPORT_FUNC(JsiSkImageFactory, MakeImageFromEncoded),
82
82
  JSI_EXPORT_FUNC(JsiSkImageFactory, MakeImageFromViewTag),
83
83
  JSI_EXPORT_FUNC(JsiSkImageFactory,
84
- MakeImageFromPlatformBuffer),
84
+ MakeImageFromNativeBuffer),
85
85
  JSI_EXPORT_FUNC(JsiSkImageFactory, MakeImage))
86
86
 
87
87
  explicit JsiSkImageFactory(std::shared_ptr<RNSkPlatformContext> context)
@@ -134,17 +134,17 @@ public:
134
134
  virtual sk_sp<SkSurface> makeOffscreenSurface(int width, int height) = 0;
135
135
 
136
136
  /**
137
- * Creates an image from a native platform buffer.
138
- * - On iOS, this is a `CMSampleBuffer`
137
+ * Creates an image from a native buffer.
138
+ * - On iOS, this is a `CVPixelBufferRef`
139
139
  * - On Android, this is a `AHardwareBuffer*`
140
140
  * @param buffer The native platform buffer.
141
141
  * @return sk_sp<SkImage>
142
142
  */
143
- virtual sk_sp<SkImage> makeImageFromPlatformBuffer(void *buffer) = 0;
143
+ virtual sk_sp<SkImage> makeImageFromNativeBuffer(void *buffer) = 0;
144
144
 
145
- virtual void releasePlatformBuffer(uint64_t pointer) = 0;
145
+ virtual void releaseNativeBuffer(uint64_t pointer) = 0;
146
146
 
147
- virtual uint64_t makePlatformBuffer(sk_sp<SkImage> image) = 0;
147
+ virtual uint64_t makeNativeBuffer(sk_sp<SkImage> image) = 0;
148
148
 
149
149
  /**
150
150
  * Return the Platform specific font manager
@@ -59,11 +59,11 @@ public:
59
59
 
60
60
  sk_sp<SkImage> takeScreenshotFromViewTag(size_t tag) override;
61
61
 
62
- sk_sp<SkImage> makeImageFromPlatformBuffer(void *buffer) override;
62
+ sk_sp<SkImage> makeImageFromNativeBuffer(void *buffer) override;
63
63
 
64
- uint64_t makePlatformBuffer(sk_sp<SkImage> image) override;
64
+ uint64_t makeNativeBuffer(sk_sp<SkImage> image) override;
65
65
 
66
- void releasePlatformBuffer(uint64_t pointer) override;
66
+ void releaseNativeBuffer(uint64_t pointer) override;
67
67
 
68
68
  virtual void performStreamOperation(
69
69
  const std::string &sourceUri,
@@ -1,11 +1,12 @@
1
- #include "RNSkiOSPlatformContext.h"
1
+ #import "RNSkiOSPlatformContext.h"
2
2
 
3
3
  #import <CoreMedia/CMSampleBuffer.h>
4
4
  #import <React/RCTUtils.h>
5
5
  #include <thread>
6
6
  #include <utility>
7
7
 
8
- #include "SkiaMetalSurfaceFactory.h"
8
+ #import "SkiaCVPixelBufferUtils.h"
9
+ #import "SkiaMetalSurfaceFactory.h"
9
10
 
10
11
  #pragma clang diagnostic push
11
12
  #pragma clang diagnostic ignored "-Wdocumentation"
@@ -57,87 +58,89 @@ void RNSkiOSPlatformContext::performStreamOperation(
57
58
  std::thread(loader).detach();
58
59
  }
59
60
 
60
- void RNSkiOSPlatformContext::releasePlatformBuffer(uint64_t pointer) {
61
- CMSampleBufferRef sampleBuffer = reinterpret_cast<CMSampleBufferRef>(pointer);
62
- CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
63
- if (sampleBuffer) {
64
- CFRelease(sampleBuffer);
65
- }
61
+ void RNSkiOSPlatformContext::releaseNativeBuffer(uint64_t pointer) {
62
+ CVPixelBufferRef pixelBuffer = reinterpret_cast<CVPixelBufferRef>(pointer);
66
63
  if (pixelBuffer) {
67
64
  CFRelease(pixelBuffer);
68
65
  }
69
66
  }
70
67
 
71
- uint64_t RNSkiOSPlatformContext::makePlatformBuffer(sk_sp<SkImage> image) {
68
+ uint64_t RNSkiOSPlatformContext::makeNativeBuffer(sk_sp<SkImage> image) {
69
+ // 0. If Image is not in BGRA, convert to BGRA as only BGRA is supported.
70
+ if (image->colorType() != kBGRA_8888_SkColorType) {
71
+ // on iOS, 32_BGRA is the only supported RGB format for CVPixelBuffers.
72
+ image = image->makeColorTypeAndColorSpace(
73
+ ThreadContextHolder::ThreadSkiaMetalContext.skContext.get(),
74
+ kBGRA_8888_SkColorType, SkColorSpace::MakeSRGB());
75
+ if (image == nullptr) {
76
+ throw std::runtime_error(
77
+ "Failed to convert image to BGRA_8888 colortype! Only BGRA_8888 "
78
+ "PlatformBuffers are supported.");
79
+ }
80
+ }
81
+
82
+ // 1. Get image info
72
83
  auto bytesPerPixel = image->imageInfo().bytesPerPixel();
73
84
  int bytesPerRow = image->width() * bytesPerPixel;
74
85
  auto buf = SkData::MakeUninitialized(image->width() * image->height() *
75
86
  bytesPerPixel);
76
87
  SkImageInfo info = SkImageInfo::Make(image->width(), image->height(),
77
88
  image->colorType(), image->alphaType());
89
+ // 2. Copy pixels into our buffer
78
90
  image->readPixels(nullptr, info, const_cast<void *>(buf->data()), bytesPerRow,
79
91
  0, 0);
80
- auto pixelData = const_cast<void *>(buf->data());
81
92
 
82
- // Create a CVPixelBuffer from the raw pixel data
83
- CVPixelBufferRef pixelBuffer = nullptr;
84
- // OSType pixelFormatType = MapSkColorTypeToOSType(image->colorType());
85
-
86
- // You will need to fill in the details for creating the pixel buffer
87
- // CVPixelBufferCreateWithBytes or CVPixelBufferCreateWithPlanarBytes
88
- // Create the CVPixelBuffer with the image data
89
- void *context = static_cast<void *>(
90
- new sk_sp<SkData>(buf)); // Create a copy for the context
91
- CVReturn r = CVPixelBufferCreateWithBytes(
92
- nullptr, // allocator
93
- image->width(), image->height(), kCVPixelFormatType_32BGRA,
94
- pixelData, // pixel data
95
- bytesPerRow, // bytes per row
96
- [](void *releaseRefCon, const void *baseAddress) { // release callback
97
- auto buf = static_cast<sk_sp<SkData> *>(releaseRefCon);
98
- buf->reset(); // This effectively calls unref on the SkData object
99
- delete buf; // Cleanup the dynamically allocated context
100
- },
101
- context, // release callback context
102
- nullptr, // pixel buffer attributes
103
- &pixelBuffer // the newly created pixel buffer
104
- );
105
-
106
- if (r != kCVReturnSuccess) {
107
- return 0; // or handle error appropriately
93
+ // 3. Create an IOSurface (GPU + CPU memory)
94
+ CFMutableDictionaryRef dict = CFDictionaryCreateMutable(
95
+ kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks,
96
+ &kCFTypeDictionaryValueCallBacks);
97
+ int width = image->width();
98
+ int height = image->height();
99
+ int pitch = width * bytesPerPixel;
100
+ int size = width * height * bytesPerPixel;
101
+ OSType pixelFormat = kCVPixelFormatType_32BGRA;
102
+ CFDictionarySetValue(
103
+ dict, kIOSurfaceBytesPerRow,
104
+ CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &pitch));
105
+ CFDictionarySetValue(
106
+ dict, kIOSurfaceBytesPerElement,
107
+ CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &bytesPerPixel));
108
+ CFDictionarySetValue(
109
+ dict, kIOSurfaceWidth,
110
+ CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &width));
111
+ CFDictionarySetValue(
112
+ dict, kIOSurfaceHeight,
113
+ CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &height));
114
+ CFDictionarySetValue(
115
+ dict, kIOSurfacePixelFormat,
116
+ CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &pixelFormat));
117
+ CFDictionarySetValue(
118
+ dict, kIOSurfaceAllocSize,
119
+ CFNumberCreate(kCFAllocatorDefault, kCFNumberSInt32Type, &size));
120
+ IOSurfaceRef surface = IOSurfaceCreate(dict);
121
+ if (surface == nil) {
122
+ throw std::runtime_error("Failed to create " + std::to_string(width) + "x" +
123
+ std::to_string(height) + " IOSurface!");
108
124
  }
109
125
 
110
- // Wrap the CVPixelBuffer in a CMSampleBuffer
111
- CMSampleBufferRef sampleBuffer = nullptr;
112
-
113
- CMFormatDescriptionRef formatDescription = nullptr;
114
- CMVideoFormatDescriptionCreateForImageBuffer(kCFAllocatorDefault, pixelBuffer,
115
- &formatDescription);
126
+ // 4. Copy over the memory from the pixels into the IOSurface
127
+ IOSurfaceLock(surface, 0, nil);
128
+ void *base = IOSurfaceGetBaseAddress(surface);
129
+ memcpy(base, buf->data(), buf->size());
130
+ IOSurfaceUnlock(surface, 0, nil);
116
131
 
117
- // Assuming no specific timing is required, we initialize the timing info to
118
- // zero.
119
- CMSampleTimingInfo timingInfo = {0};
120
- timingInfo.duration = kCMTimeInvalid; // Indicate an unknown duration.
121
- timingInfo.presentationTimeStamp = kCMTimeZero; // Start at time zero.
122
- timingInfo.decodeTimeStamp = kCMTimeInvalid; // No specific decode time.
123
-
124
- // Create the sample buffer.
125
- OSStatus status = CMSampleBufferCreateReadyWithImageBuffer(
126
- kCFAllocatorDefault, pixelBuffer, formatDescription, &timingInfo,
127
- &sampleBuffer);
128
-
129
- if (status != noErr) {
130
- if (formatDescription) {
131
- CFRelease(formatDescription);
132
- }
133
- if (pixelBuffer) {
134
- CFRelease(pixelBuffer);
135
- }
136
- return 0;
132
+ // 5. Create a CVPixelBuffer from the IOSurface
133
+ CVPixelBufferRef pixelBuffer = nullptr;
134
+ CVReturn result =
135
+ CVPixelBufferCreateWithIOSurface(nil, surface, nil, &pixelBuffer);
136
+ if (result != kCVReturnSuccess) {
137
+ throw std::runtime_error(
138
+ "Failed to create CVPixelBuffer from SkImage! Return value: " +
139
+ std::to_string(result));
137
140
  }
138
141
 
139
- // Return sampleBuffer casted to uint64_t
140
- return reinterpret_cast<uint64_t>(sampleBuffer);
142
+ // 8. Return CVPixelBuffer casted to uint64_t
143
+ return reinterpret_cast<uint64_t>(pixelBuffer);
141
144
  }
142
145
 
143
146
  void RNSkiOSPlatformContext::raiseError(const std::exception &err) {
@@ -149,35 +152,9 @@ sk_sp<SkSurface> RNSkiOSPlatformContext::makeOffscreenSurface(int width,
149
152
  return SkiaMetalSurfaceFactory::makeOffscreenSurface(width, height);
150
153
  }
151
154
 
152
- sk_sp<SkImage>
153
- RNSkiOSPlatformContext::makeImageFromPlatformBuffer(void *buffer) {
154
- CMSampleBufferRef sampleBuffer = (CMSampleBufferRef)buffer;
155
- // DO the CPU transfer (debugging only)
156
- // Step 1: Extract the CVPixelBufferRef from the CMSampleBufferRef
157
- CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(sampleBuffer);
158
-
159
- // Step 2: Lock the pixel buffer to access the raw pixel data
160
- CVPixelBufferLockBaseAddress(pixelBuffer, 0);
161
-
162
- // Step 3: Get information about the image
163
- void *baseAddress = CVPixelBufferGetBaseAddress(pixelBuffer);
164
- size_t width = CVPixelBufferGetWidth(pixelBuffer);
165
- size_t height = CVPixelBufferGetHeight(pixelBuffer);
166
- size_t bytesPerRow = CVPixelBufferGetBytesPerRow(pixelBuffer);
167
-
168
- // Assuming the pixel format is 32BGRA, which is common for iOS video frames.
169
- // You might need to adjust this based on the actual pixel format.
170
- SkImageInfo info = SkImageInfo::Make(width, height, kRGBA_8888_SkColorType,
171
- kUnpremul_SkAlphaType);
172
-
173
- // Step 4: Create an SkImage from the pixel buffer
174
- sk_sp<SkData> data =
175
- SkData::MakeWithoutCopy(baseAddress, height * bytesPerRow);
176
- sk_sp<SkImage> image = SkImages::RasterFromData(info, data, bytesPerRow);
177
- auto texture = SkiaMetalSurfaceFactory::makeTextureFromImage(image);
178
- // Step 5: Unlock the pixel buffer
179
- CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
180
- return texture;
155
+ sk_sp<SkImage> RNSkiOSPlatformContext::makeImageFromNativeBuffer(void *buffer) {
156
+ CVPixelBufferRef sampleBuffer = (CVPixelBufferRef)buffer;
157
+ return SkiaMetalSurfaceFactory::makeTextureFromCVPixelBuffer(sampleBuffer);
181
158
  }
182
159
 
183
160
  sk_sp<SkFontMgr> RNSkiOSPlatformContext::createFontMgr() {
@@ -0,0 +1,119 @@
1
+ //
2
+ // SkiaCVPixelBufferUtils.h
3
+ // react-native-skia
4
+ //
5
+ // Created by Marc Rousavy on 10.04.24.
6
+ //
7
+
8
+ #pragma once
9
+
10
+ #import <vector>
11
+
12
+ #import <CoreMedia/CMSampleBuffer.h>
13
+ #import <CoreVideo/CVMetalTextureCache.h>
14
+ #import <MetalKit/MetalKit.h>
15
+
16
+ #pragma clang diagnostic push
17
+ #pragma clang diagnostic ignored "-Wdocumentation"
18
+ #import "include/core/SkColorSpace.h"
19
+ #import "include/core/SkImage.h"
20
+ #import "include/gpu/GrBackendSurface.h"
21
+ #import "include/gpu/GrYUVABackendTextures.h"
22
+ #pragma clang diagnostic pop
23
+
24
+ /**
25
+ Holds a Metal Texture.
26
+ When the `TextureHolder` is destroyed, the underlying Metal Texture
27
+ is marked as invalid and might be overwritten by the Texture Cache,
28
+ so make sure to delete the `TextureHolder` only when the `SkImage`
29
+ has been deleted.
30
+
31
+ For example, use the `releaseProc` parameter in `BorrowImageFromTexture`
32
+ to delete the `TextureHolder`.
33
+ */
34
+ class TextureHolder {
35
+ public:
36
+ /**
37
+ Create a new instance of TextureHolder which holds
38
+ the given `CVMetalTextureRef`.
39
+
40
+ The given `CVMetalTextureRef` is assumed to already be
41
+ retained with `CFRetain`, and will later be manually
42
+ released with `CFRelease`.
43
+ */
44
+ TextureHolder(CVMetalTextureRef texture);
45
+ ~TextureHolder();
46
+
47
+ /**
48
+ Converts this Texture to a Skia GrBackendTexture.
49
+ */
50
+ GrBackendTexture toGrBackendTexture();
51
+
52
+ private:
53
+ CVMetalTextureRef _texture;
54
+ };
55
+
56
+ /**
57
+ Same as `TextureHolder`, but for multiple planar textures (e.g. YUVA)
58
+ */
59
+ class MultiTexturesHolder {
60
+ public:
61
+ ~MultiTexturesHolder();
62
+ void addTexture(TextureHolder *texture);
63
+
64
+ private:
65
+ std::vector<TextureHolder *> _textures;
66
+ };
67
+
68
+ class SkiaCVPixelBufferUtils {
69
+ public:
70
+ enum class CVPixelBufferBaseFormat { rgb, yuv };
71
+
72
+ /**
73
+ Get the base format (currently only RGB) of the PixelBuffer.
74
+ Depending on the base-format, different methods have to be used to create
75
+ Skia buffers.
76
+ */
77
+ static CVPixelBufferBaseFormat
78
+ getCVPixelBufferBaseFormat(CVPixelBufferRef pixelBuffer);
79
+
80
+ class RGB {
81
+ public:
82
+ /**
83
+ Creates a GPU-backed Skia Texture (SkImage) with the given RGB
84
+ CVPixelBuffer.
85
+ */
86
+ static sk_sp<SkImage>
87
+ makeSkImageFromCVPixelBuffer(GrDirectContext *context,
88
+ CVPixelBufferRef pixelBuffer);
89
+
90
+ private:
91
+ static SkColorType getCVPixelBufferColorType(CVPixelBufferRef pixelBuffer);
92
+ };
93
+
94
+ class YUV {
95
+ public:
96
+ /**
97
+ Creates a GPU-backed Skia Texture (SkImage) with the given YUV
98
+ CVPixelBuffer.
99
+ */
100
+ static sk_sp<SkImage>
101
+ makeSkImageFromCVPixelBuffer(GrDirectContext *context,
102
+ CVPixelBufferRef pixelBuffer);
103
+
104
+ private:
105
+ static SkYUVAInfo::PlaneConfig getPlaneConfig(OSType pixelFormat);
106
+ static SkYUVAInfo::Subsampling getSubsampling(OSType pixelFormat);
107
+ static SkYUVColorSpace getColorspace(OSType pixelFormat);
108
+ static SkYUVAInfo getYUVAInfoForCVPixelBuffer(CVPixelBufferRef pixelBuffer);
109
+ };
110
+
111
+ private:
112
+ static CVMetalTextureCacheRef getTextureCache();
113
+ static TextureHolder *
114
+ getSkiaTextureForCVPixelBufferPlane(CVPixelBufferRef pixelBuffer,
115
+ size_t planeIndex);
116
+ static MTLPixelFormat
117
+ getMTLPixelFormatForCVPixelBufferPlane(CVPixelBufferRef pixelBuffer,
118
+ size_t planeIndex);
119
+ };