@shopify/react-native-skia 1.2.0 → 1.2.2

Sign up to get free protection for your applications and to get access to all the features.
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
+ };