@shopify/react-native-skia 1.6.0 → 1.7.0

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 (93) hide show
  1. package/android/cpp/jni/include/JniSkiaBaseView.h +0 -1
  2. package/android/cpp/jni/include/JniSkiaManager.h +2 -2
  3. package/android/cpp/rnskia-android/MainThreadDispatcher.h +2 -4
  4. package/android/cpp/rnskia-android/OpenGLContext.h +13 -5
  5. package/android/cpp/rnskia-android/OpenGLWindowContext.h +2 -2
  6. package/android/cpp/rnskia-android/RNSkAndroidPlatformContext.h +61 -3
  7. package/android/cpp/rnskia-android/RNSkAndroidView.h +0 -4
  8. package/android/cpp/rnskia-android/gl/Display.h +2 -0
  9. package/cpp/api/JsiSkContourMeasure.h +1 -5
  10. package/cpp/api/JsiSkImage.h +11 -0
  11. package/cpp/api/JsiSkImageFactory.h +14 -0
  12. package/cpp/api/JsiSkPicture.h +2 -0
  13. package/cpp/api/JsiSkSurface.h +7 -0
  14. package/cpp/api/JsiTextureInfo.h +53 -0
  15. package/cpp/jsi/ViewProperty.h +48 -0
  16. package/cpp/rnskia/RNSkDomView.h +4 -7
  17. package/cpp/rnskia/RNSkJsiViewApi.h +3 -3
  18. package/cpp/rnskia/RNSkPictureView.h +8 -18
  19. package/cpp/rnskia/RNSkPlatformContext.h +18 -12
  20. package/cpp/rnskia/RNSkView.h +2 -8
  21. package/ios/RNSkia-iOS/MetalContext.h +101 -15
  22. package/ios/RNSkia-iOS/MetalContext.mm +9 -8
  23. package/ios/RNSkia-iOS/MetalWindowContext.h +39 -0
  24. package/ios/RNSkia-iOS/MetalWindowContext.mm +60 -0
  25. package/ios/RNSkia-iOS/RNSkiOSPlatformContext.h +13 -25
  26. package/ios/RNSkia-iOS/RNSkiOSPlatformContext.mm +88 -2
  27. package/ios/RNSkia-iOS/SkiaCVPixelBufferUtils.mm +17 -6
  28. package/ios/RNSkia-iOS/SkiaManager.mm +1 -2
  29. package/ios/RNSkia-iOS/SkiaUIView.mm +17 -15
  30. package/lib/commonjs/skia/types/Image/Image.d.ts +10 -0
  31. package/lib/commonjs/skia/types/Image/Image.js.map +1 -1
  32. package/lib/commonjs/skia/types/Image/ImageFactory.d.ts +18 -0
  33. package/lib/commonjs/skia/types/Image/ImageFactory.js.map +1 -1
  34. package/lib/commonjs/skia/types/Matrix4.d.ts +6 -0
  35. package/lib/commonjs/skia/types/Matrix4.js +69 -1
  36. package/lib/commonjs/skia/types/Matrix4.js.map +1 -1
  37. package/lib/commonjs/skia/types/Surface/Surface.d.ts +11 -0
  38. package/lib/commonjs/skia/types/Surface/Surface.js.map +1 -1
  39. package/lib/commonjs/skia/web/JsiSkImage.d.ts +1 -0
  40. package/lib/commonjs/skia/web/JsiSkImage.js +4 -0
  41. package/lib/commonjs/skia/web/JsiSkImage.js.map +1 -1
  42. package/lib/commonjs/skia/web/JsiSkImageFactory.d.ts +1 -0
  43. package/lib/commonjs/skia/web/JsiSkImageFactory.js +3 -0
  44. package/lib/commonjs/skia/web/JsiSkImageFactory.js.map +1 -1
  45. package/lib/commonjs/skia/web/JsiSkSurface.d.ts +1 -0
  46. package/lib/commonjs/skia/web/JsiSkSurface.js +4 -0
  47. package/lib/commonjs/skia/web/JsiSkSurface.js.map +1 -1
  48. package/lib/module/skia/types/Image/Image.d.ts +10 -0
  49. package/lib/module/skia/types/Image/Image.js.map +1 -1
  50. package/lib/module/skia/types/Image/ImageFactory.d.ts +18 -0
  51. package/lib/module/skia/types/Image/ImageFactory.js.map +1 -1
  52. package/lib/module/skia/types/Matrix4.d.ts +6 -0
  53. package/lib/module/skia/types/Matrix4.js +67 -0
  54. package/lib/module/skia/types/Matrix4.js.map +1 -1
  55. package/lib/module/skia/types/Surface/Surface.d.ts +11 -0
  56. package/lib/module/skia/types/Surface/Surface.js.map +1 -1
  57. package/lib/module/skia/web/JsiSkImage.d.ts +1 -0
  58. package/lib/module/skia/web/JsiSkImage.js +4 -0
  59. package/lib/module/skia/web/JsiSkImage.js.map +1 -1
  60. package/lib/module/skia/web/JsiSkImageFactory.d.ts +1 -0
  61. package/lib/module/skia/web/JsiSkImageFactory.js +3 -0
  62. package/lib/module/skia/web/JsiSkImageFactory.js.map +1 -1
  63. package/lib/module/skia/web/JsiSkSurface.d.ts +1 -0
  64. package/lib/module/skia/web/JsiSkSurface.js +4 -0
  65. package/lib/module/skia/web/JsiSkSurface.js.map +1 -1
  66. package/lib/typescript/lib/commonjs/skia/types/Matrix4.d.ts +6 -0
  67. package/lib/typescript/lib/commonjs/skia/web/JsiSkImage.d.ts +1 -0
  68. package/lib/typescript/lib/commonjs/skia/web/JsiSkImageFactory.d.ts +1 -0
  69. package/lib/typescript/lib/commonjs/skia/web/JsiSkSurface.d.ts +1 -0
  70. package/lib/typescript/lib/module/mock/index.d.ts +1 -0
  71. package/lib/typescript/lib/module/skia/types/Matrix4.d.ts +1 -0
  72. package/lib/typescript/lib/module/skia/web/JsiSkImage.d.ts +1 -0
  73. package/lib/typescript/lib/module/skia/web/JsiSkImageFactory.d.ts +1 -0
  74. package/lib/typescript/lib/module/skia/web/JsiSkSurface.d.ts +1 -0
  75. package/lib/typescript/src/skia/types/Image/Image.d.ts +10 -0
  76. package/lib/typescript/src/skia/types/Image/ImageFactory.d.ts +18 -0
  77. package/lib/typescript/src/skia/types/Matrix4.d.ts +6 -0
  78. package/lib/typescript/src/skia/types/Surface/Surface.d.ts +11 -0
  79. package/lib/typescript/src/skia/web/JsiSkImage.d.ts +1 -0
  80. package/lib/typescript/src/skia/web/JsiSkImageFactory.d.ts +1 -0
  81. package/lib/typescript/src/skia/web/JsiSkSurface.d.ts +1 -0
  82. package/package.json +1 -1
  83. package/src/renderer/__tests__/e2e/Matrix4.spec.tsx +93 -0
  84. package/src/skia/types/Image/Image.ts +11 -0
  85. package/src/skia/types/Image/ImageFactory.ts +24 -0
  86. package/src/skia/types/Matrix4.ts +101 -0
  87. package/src/skia/types/Surface/Surface.ts +12 -0
  88. package/src/skia/web/JsiSkImage.ts +5 -0
  89. package/src/skia/web/JsiSkImageFactory.ts +4 -0
  90. package/src/skia/web/JsiSkSurface.ts +5 -0
  91. package/cpp/jsi/JsiValueWrapper.h +0 -164
  92. package/ios/RNSkia-iOS/SkiaMetalSurfaceFactory.h +0 -128
  93. package/ios/RNSkia-iOS/SkiaMetalSurfaceFactory.mm +0 -92
@@ -48,6 +48,17 @@ export interface SkImage extends SkJSIInstance<"Image"> {
48
48
  */
49
49
  getImageInfo(): ImageInfo;
50
50
 
51
+ /**
52
+ * Returns the backend texture of the image.
53
+ * The returned object can be used to create a Skia Image object.
54
+ * The returned object is backend specific and should be used with caution.
55
+ * It is the caller's responsibility to ensure that the texture is not used after the image is deleted.
56
+ * The returned object may be null if the image does not have a backend texture.
57
+ *
58
+ * @return backend texture of the image or null
59
+ */
60
+ getNativeTextureUnstable(): unknown;
61
+
51
62
  /**
52
63
  * Returns this image as a shader with the specified tiling. It will use cubic sampling.
53
64
  * @param tx - tile mode in the x direction.
@@ -49,6 +49,30 @@ export interface ImageFactory {
49
49
  */
50
50
  MakeImageFromNativeBuffer: (nativeBuffer: NativeBuffer) => SkImage;
51
51
 
52
+ /**
53
+ *
54
+ * Return an Image backed by a given native texture.
55
+ *
56
+ * The native texture must be a valid owning reference.
57
+ *
58
+ * This API might be used to integrate with other libraries using gpu textures,
59
+ * or to transfer images between different threads.
60
+ *
61
+ * @param texture A native texture handle
62
+ * @param width The width of the texture
63
+ * @param height The height of the texture
64
+ * @param mipmapped Whether the texture is mipmapped
65
+ * @throws Throws an error if the Image could not be created, for example when the given native texture is invalid.
66
+ *
67
+ * @returns Returns a valid SkImage, if the texture is invalid, an error is thrown.
68
+ */
69
+ MakeImageFromNativeTextureUnstable: (
70
+ texture: unknown,
71
+ width: number,
72
+ height: number,
73
+ mipmapped?: boolean
74
+ ) => SkImage;
75
+
52
76
  /**
53
77
  * Returns an image that will be a screenshot of the view represented by
54
78
  * the view tag
@@ -370,3 +370,104 @@ export const convertToAffineMatrix = (m4: Matrix4) => {
370
370
  // Returning the 6-element affine transformation matrix
371
371
  return [a, b, c, d, tx, ty];
372
372
  };
373
+
374
+ /**
375
+ * Calculates the determinant of a 3x3 matrix
376
+ * @worklet
377
+ */
378
+ const det3x3 = (
379
+ a00: number,
380
+ a01: number,
381
+ a02: number,
382
+ a10: number,
383
+ a11: number,
384
+ a12: number,
385
+ a20: number,
386
+ a21: number,
387
+ a22: number
388
+ ): number => {
389
+ "worklet";
390
+ return (
391
+ a00 * (a11 * a22 - a12 * a21) +
392
+ a01 * (a12 * a20 - a10 * a22) +
393
+ a02 * (a10 * a21 - a11 * a20)
394
+ );
395
+ };
396
+
397
+ /**
398
+ * Inverts a 4x4 matrix
399
+ * @worklet
400
+ * @returns The inverted matrix, or the identity matrix if the input is not invertible
401
+ */
402
+ export const invert4 = (m: Matrix4): Matrix4 => {
403
+ "worklet";
404
+
405
+ const a00 = m[0],
406
+ a01 = m[1],
407
+ a02 = m[2],
408
+ a03 = m[3];
409
+ const a10 = m[4],
410
+ a11 = m[5],
411
+ a12 = m[6],
412
+ a13 = m[7];
413
+ const a20 = m[8],
414
+ a21 = m[9],
415
+ a22 = m[10],
416
+ a23 = m[11];
417
+ const a30 = m[12],
418
+ a31 = m[13],
419
+ a32 = m[14],
420
+ a33 = m[15];
421
+
422
+ // Calculate cofactors
423
+ const b00 = det3x3(a11, a12, a13, a21, a22, a23, a31, a32, a33);
424
+ const b01 = -det3x3(a10, a12, a13, a20, a22, a23, a30, a32, a33);
425
+ const b02 = det3x3(a10, a11, a13, a20, a21, a23, a30, a31, a33);
426
+ const b03 = -det3x3(a10, a11, a12, a20, a21, a22, a30, a31, a32);
427
+
428
+ const b10 = -det3x3(a01, a02, a03, a21, a22, a23, a31, a32, a33);
429
+ const b11 = det3x3(a00, a02, a03, a20, a22, a23, a30, a32, a33);
430
+ const b12 = -det3x3(a00, a01, a03, a20, a21, a23, a30, a31, a33);
431
+ const b13 = det3x3(a00, a01, a02, a20, a21, a22, a30, a31, a32);
432
+
433
+ const b20 = det3x3(a01, a02, a03, a11, a12, a13, a31, a32, a33);
434
+ const b21 = -det3x3(a00, a02, a03, a10, a12, a13, a30, a32, a33);
435
+ const b22 = det3x3(a00, a01, a03, a10, a11, a13, a30, a31, a33);
436
+ const b23 = -det3x3(a00, a01, a02, a10, a11, a12, a30, a31, a32);
437
+
438
+ const b30 = -det3x3(a01, a02, a03, a11, a12, a13, a21, a22, a23);
439
+ const b31 = det3x3(a00, a02, a03, a10, a12, a13, a20, a22, a23);
440
+ const b32 = -det3x3(a00, a01, a03, a10, a11, a13, a20, a21, a23);
441
+ const b33 = det3x3(a00, a01, a02, a10, a11, a12, a20, a21, a22);
442
+
443
+ // Calculate determinant
444
+ const det = a00 * b00 + a01 * b01 + a02 * b02 + a03 * b03;
445
+
446
+ // Check if matrix is invertible
447
+ if (Math.abs(det) < 1e-8) {
448
+ // Return identity matrix if not invertible
449
+ return Matrix4();
450
+ }
451
+
452
+ const invDet = 1.0 / det;
453
+
454
+ // Calculate inverse matrix
455
+ return [
456
+ b00 * invDet,
457
+ b10 * invDet,
458
+ b20 * invDet,
459
+ b30 * invDet,
460
+ b01 * invDet,
461
+ b11 * invDet,
462
+ b21 * invDet,
463
+ b31 * invDet,
464
+ b02 * invDet,
465
+ b12 * invDet,
466
+ b22 * invDet,
467
+ b32 * invDet,
468
+ b03 * invDet,
469
+ b13 * invDet,
470
+ b23 * invDet,
471
+ b33 * invDet,
472
+ ] as Matrix4;
473
+ };
@@ -14,6 +14,18 @@ export interface SkSurface extends SkJSIInstance<"Surface"> {
14
14
  */
15
15
  getCanvas(): SkCanvas;
16
16
 
17
+ /**
18
+ * Returns the backend texture of the surface.
19
+ * The returned object can be used to create a Skia Image object.
20
+ * The returned object is backend specific and should be used with caution.
21
+ * It is the caller's responsibility to ensure that the texture is not used after the surface is deleted
22
+ * or draw operations are performed on the surface.
23
+ * The returned object may be null if the surface does not have a backend texture.
24
+ *
25
+ * @return backend texture of the surface or null
26
+ */
27
+ getNativeTextureUnstable(): unknown;
28
+
17
29
  /** Returns Image capturing Surface contents. Subsequent drawing to
18
30
  Surface contents are not captured.
19
31
 
@@ -170,4 +170,9 @@ export class JsiSkImage extends HostObject<Image, "Image"> implements SkImage {
170
170
  }
171
171
  return new JsiSkImage(this.CanvasKit, img);
172
172
  }
173
+
174
+ getNativeTextureUnstable(): unknown {
175
+ console.warn("getBackendTexture is not implemented on Web");
176
+ return null;
177
+ }
173
178
  }
@@ -75,6 +75,10 @@ export class JsiSkImageFactory extends Host implements ImageFactory {
75
75
  return new JsiSkImage(this.CanvasKit, image);
76
76
  }
77
77
 
78
+ MakeImageFromNativeTextureUnstable(): SkImage {
79
+ throw new Error("MakeImageFromNativeTexture is not implemented on web");
80
+ }
81
+
78
82
  MakeImage(info: ImageInfo, data: SkData, bytesPerRow: number) {
79
83
  // see toSkImageInfo() from canvaskit
80
84
  const image = this.CanvasKit.MakeImage(
@@ -43,4 +43,9 @@ export class JsiSkSurface
43
43
  );
44
44
  return new JsiSkImage(this.CanvasKit, image);
45
45
  }
46
+
47
+ getNativeTextureUnstable(): unknown {
48
+ console.warn("getBackendTexture is not implemented on Web");
49
+ return null;
50
+ }
46
51
  }
@@ -1,164 +0,0 @@
1
- #pragma once
2
-
3
- #include <jsi/jsi.h>
4
- #include <memory>
5
- #include <string>
6
-
7
- namespace RNJsi {
8
- namespace jsi = facebook::jsi;
9
-
10
- enum JsiWrapperValueType {
11
- NonInitialized,
12
- Undefined,
13
- Null,
14
- Bool,
15
- Number,
16
- String,
17
- Object,
18
- Function,
19
- Array,
20
- HostObject,
21
- Unknown
22
- };
23
-
24
- /**
25
- Implements a simple wrapper class for JSI values where the value can be read
26
- without asking the runtime for any assistance Meaning that we can access
27
- members without being on the JS thread.
28
- */
29
- class JsiValueWrapper {
30
- public:
31
- explicit JsiValueWrapper(jsi::Runtime &runtime)
32
- : _type(JsiWrapperValueType::Undefined) {}
33
-
34
- JsiValueWrapper(jsi::Runtime &runtime, const jsi::Value &value)
35
- : JsiValueWrapper(runtime) {
36
- setCurrent(runtime, value);
37
- }
38
-
39
- void setCurrent(jsi::Runtime &runtime, const jsi::Value &value) {
40
- if (value.isNumber()) {
41
- _type = JsiWrapperValueType::Number;
42
- _numberValue = value.asNumber();
43
- } else if (value.isBool()) {
44
- _type = JsiWrapperValueType::Bool;
45
- _boolValue = value.getBool();
46
- } else if (value.isString()) {
47
- _type = JsiWrapperValueType::String;
48
- _stringValue = value.asString(runtime).utf8(runtime);
49
- } else if (value.isUndefined()) {
50
- _type = JsiWrapperValueType::Undefined;
51
- } else if (value.isNull()) {
52
- _type = JsiWrapperValueType::Null;
53
- } else if (value.isObject()) {
54
- _type = JsiWrapperValueType::Object;
55
- _objectValue = std::make_shared<jsi::Object>(value.asObject(runtime));
56
- if (_objectValue->isFunction(runtime)) {
57
- _type = JsiWrapperValueType::Function;
58
- _functionValue =
59
- std::make_shared<jsi::Function>(_objectValue->asFunction(runtime));
60
- _objectValue = nullptr;
61
- } else if (_objectValue->isArray(runtime)) {
62
- _type = JsiWrapperValueType::Array;
63
- _arrayValue =
64
- std::make_shared<jsi::Array>(_objectValue->asArray(runtime));
65
- _objectValue = nullptr;
66
- } else if (_objectValue->isHostObject(runtime)) {
67
- _type = JsiWrapperValueType::HostObject;
68
- _hostObjectValue = _objectValue->asHostObject(runtime);
69
- _objectValue = nullptr;
70
- }
71
- } else {
72
- throw std::runtime_error("Could not store jsi::Value of provided type");
73
- }
74
- // Save in value holder as well so that we can return current
75
- if (_valueHolder == nullptr) {
76
- _valueHolder = std::make_shared<jsi::Object>(runtime);
77
- }
78
- _valueHolder->setProperty(runtime, "current", value);
79
- }
80
-
81
- jsi::Value getCurrent(jsi::Runtime &runtime) {
82
- if (_valueHolder == nullptr) {
83
- return jsi::Value::undefined();
84
- }
85
- return _valueHolder->getProperty(runtime, "current");
86
- }
87
-
88
- bool isUndefinedOrNull() { return isUndefined() || isNull(); }
89
-
90
- bool isUndefined() { return _type == JsiWrapperValueType::Undefined; }
91
-
92
- bool isNull() { return _type == JsiWrapperValueType::Null; }
93
-
94
- bool getAsBool() {
95
- assert(_type == JsiWrapperValueType::Bool);
96
- return _boolValue;
97
- }
98
-
99
- double getAsNumber() {
100
- assert(_type == JsiWrapperValueType::Number);
101
- return _numberValue;
102
- }
103
-
104
- const std::string &getAsString() {
105
- assert(_type == JsiWrapperValueType::String);
106
- return _stringValue;
107
- }
108
-
109
- std::shared_ptr<jsi::Function> getAsFunction() {
110
- assert(_type == JsiWrapperValueType::Function);
111
- return _functionValue;
112
- }
113
-
114
- std::shared_ptr<jsi::Array> getAsArray() {
115
- assert(_type == JsiWrapperValueType::Array);
116
- return _arrayValue;
117
- }
118
-
119
- std::shared_ptr<jsi::Object> getAsObject() {
120
- assert(_type == JsiWrapperValueType::Object);
121
- return _objectValue;
122
- }
123
-
124
- std::shared_ptr<jsi::HostObject> getAsHostObject() {
125
- assert(_type == JsiWrapperValueType::HostObject);
126
- return _hostObjectValue;
127
- }
128
-
129
- JsiWrapperValueType getType() { return _type; }
130
-
131
- bool equals(jsi::Runtime &runtime, const jsi::Value &value) {
132
- if (value.isNumber() && _type == JsiWrapperValueType::Number) {
133
- return _numberValue == value.asNumber();
134
- } else if (value.isBool() && _type == JsiWrapperValueType::Bool) {
135
- return _boolValue == value.getBool();
136
- } else if (value.isUndefined()) {
137
- return _type == JsiWrapperValueType::Undefined;
138
- } else if (value.isNull()) {
139
- return _type == JsiWrapperValueType::Null;
140
- } else if (value.isString()) {
141
- auto current = getCurrent(runtime);
142
- if (current.isString()) {
143
- return jsi::String::strictEquals(runtime, value.asString(runtime),
144
- current.asString(runtime));
145
- }
146
- return false;
147
- }
148
- return false;
149
- }
150
-
151
- private:
152
- std::shared_ptr<jsi::Object> _valueHolder;
153
-
154
- bool _boolValue;
155
- double _numberValue;
156
- std::string _stringValue;
157
- std::shared_ptr<jsi::Object> _objectValue;
158
- std::shared_ptr<jsi::Function> _functionValue;
159
- std::shared_ptr<jsi::Array> _arrayValue;
160
- std::shared_ptr<jsi::HostObject> _hostObjectValue;
161
-
162
- JsiWrapperValueType _type;
163
- };
164
- } // namespace RNJsi
@@ -1,128 +0,0 @@
1
- #pragma once
2
-
3
- #import <MetalKit/MetalKit.h>
4
-
5
- #include <memory>
6
-
7
- #include "RNSkLog.h"
8
- #include "WindowContext.h"
9
-
10
- #pragma clang diagnostic push
11
- #pragma clang diagnostic ignored "-Wdocumentation"
12
-
13
- #import "include/core/SkCanvas.h"
14
- #import "include/core/SkColorSpace.h"
15
-
16
- #import <CoreMedia/CMSampleBuffer.h>
17
- #import <CoreVideo/CVMetalTextureCache.h>
18
-
19
- #import <include/gpu/ganesh/GrBackendSurface.h>
20
- #import <include/gpu/ganesh/GrDirectContext.h>
21
- #import <include/gpu/ganesh/SkImageGanesh.h>
22
- #import <include/gpu/ganesh/SkSurfaceGanesh.h>
23
- #import <include/gpu/ganesh/mtl/GrMtlBackendContext.h>
24
- #import <include/gpu/ganesh/mtl/GrMtlBackendSurface.h>
25
- #import <include/gpu/ganesh/mtl/GrMtlDirectContext.h>
26
- #import <include/gpu/ganesh/mtl/SkSurfaceMetal.h>
27
-
28
- #pragma clang diagnostic pop
29
-
30
- using SkiaMetalContext = struct SkiaMetalContext {
31
- id<MTLCommandQueue> commandQueue = nullptr;
32
- sk_sp<GrDirectContext> skContext = nullptr;
33
- };
34
-
35
- class SkiaMetalSurfaceFactory {
36
- friend class IOSSkiaContext;
37
-
38
- public:
39
- static sk_sp<SkSurface> makeOffscreenSurface(id<MTLDevice> device,
40
- SkiaMetalContext *context,
41
- int width, int height);
42
-
43
- static sk_sp<SkImage>
44
- makeTextureFromCVPixelBuffer(SkiaMetalContext *context,
45
- CVPixelBufferRef pixelBuffer);
46
-
47
- static std::unique_ptr<RNSkia::WindowContext>
48
- makeContext(SkiaMetalContext *context, CALayer *texture, int width,
49
- int height);
50
- };
51
-
52
- class IOSSkiaContext : public RNSkia::WindowContext {
53
- public:
54
- IOSSkiaContext(SkiaMetalContext *context, CALayer *layer, int width,
55
- int height)
56
- : _context(context) {
57
- #pragma clang diagnostic push
58
- #pragma clang diagnostic ignored "-Wunguarded-availability-new"
59
- _layer = (CAMetalLayer *)layer;
60
- #pragma clang diagnostic pop
61
- _layer.framebufferOnly = NO;
62
- _layer.device = MTLCreateSystemDefaultDevice();
63
- _layer.opaque = false;
64
- _layer.contentsScale = [UIScreen mainScreen].scale;
65
- _layer.pixelFormat = MTLPixelFormatBGRA8Unorm;
66
- _layer.contentsGravity = kCAGravityBottomLeft;
67
- _layer.drawableSize = CGSizeMake(width, height);
68
- }
69
-
70
- ~IOSSkiaContext() {}
71
-
72
- sk_sp<SkSurface> getSurface() override {
73
- if (_skSurface) {
74
- return _skSurface;
75
- }
76
-
77
- // Get the next drawable from the CAMetalLayer
78
- _currentDrawable = [_layer nextDrawable];
79
- if (!_currentDrawable) {
80
- RNSkia::RNSkLogger::logToConsole(
81
- "Could not retrieve drawable from CAMetalLayer");
82
- return nullptr;
83
- }
84
-
85
- // Get the texture from the drawable
86
- GrMtlTextureInfo fbInfo;
87
- fbInfo.fTexture.retain((__bridge void *)_currentDrawable.texture);
88
-
89
- GrBackendRenderTarget backendRT = GrBackendRenderTargets::MakeMtl(
90
- _layer.drawableSize.width, _layer.drawableSize.height, fbInfo);
91
-
92
- _skSurface = SkSurfaces::WrapBackendRenderTarget(
93
- _context->skContext.get(), backendRT, kTopLeft_GrSurfaceOrigin,
94
- kBGRA_8888_SkColorType, nullptr, nullptr);
95
-
96
- return _skSurface;
97
- }
98
-
99
- void present() override {
100
- if (auto dContext = GrAsDirectContext(_skSurface->recordingContext())) {
101
- dContext->flushAndSubmit();
102
- }
103
-
104
- id<MTLCommandBuffer> commandBuffer([_context->commandQueue commandBuffer]);
105
- [commandBuffer presentDrawable:_currentDrawable];
106
- [commandBuffer commit];
107
- _skSurface = nullptr;
108
- }
109
-
110
- int getWidth() override {
111
- return _layer.frame.size.width * _layer.contentsScale;
112
- };
113
-
114
- int getHeight() override {
115
- return _layer.frame.size.height * _layer.contentsScale;
116
- };
117
-
118
- void resize(int width, int height) override { _skSurface = nullptr; }
119
-
120
- private:
121
- SkiaMetalContext *_context;
122
- sk_sp<SkSurface> _skSurface = nullptr;
123
- #pragma clang diagnostic push
124
- #pragma clang diagnostic ignored "-Wunguarded-availability-new"
125
- CAMetalLayer *_layer;
126
- #pragma clang diagnostic pop
127
- id<CAMetalDrawable> _currentDrawable = nil;
128
- };
@@ -1,92 +0,0 @@
1
- #import "RNSkLog.h"
2
-
3
- #import "SkiaCVPixelBufferUtils.h"
4
- #import "SkiaMetalSurfaceFactory.h"
5
-
6
- #pragma clang diagnostic push
7
- #pragma clang diagnostic ignored "-Wdocumentation"
8
-
9
- #import "include/core/SkCanvas.h"
10
- #import "include/core/SkColorSpace.h"
11
- #import "include/core/SkSurface.h"
12
-
13
- #import <include/gpu/ganesh/GrBackendSurface.h>
14
- #import <include/gpu/ganesh/GrDirectContext.h>
15
- #import <include/gpu/ganesh/SkImageGanesh.h>
16
- #import <include/gpu/ganesh/SkSurfaceGanesh.h>
17
- #import <include/gpu/ganesh/mtl/GrMtlBackendContext.h>
18
- #import <include/gpu/ganesh/mtl/GrMtlBackendSurface.h>
19
- #import <include/gpu/ganesh/mtl/GrMtlDirectContext.h>
20
- #import <include/gpu/ganesh/mtl/SkSurfaceMetal.h>
21
-
22
- #pragma clang diagnostic pop
23
-
24
- struct OffscreenRenderContext {
25
- id<MTLTexture> texture;
26
-
27
- OffscreenRenderContext(id<MTLDevice> device,
28
- sk_sp<GrDirectContext> skiaContext,
29
- id<MTLCommandQueue> commandQueue, int width,
30
- int height) {
31
- // Create a Metal texture descriptor
32
- MTLTextureDescriptor *textureDescriptor = [MTLTextureDescriptor
33
- texture2DDescriptorWithPixelFormat:MTLPixelFormatBGRA8Unorm
34
- width:width
35
- height:height
36
- mipmapped:NO];
37
- textureDescriptor.usage =
38
- MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead;
39
- texture = [device newTextureWithDescriptor:textureDescriptor];
40
- }
41
- };
42
-
43
- std::unique_ptr<RNSkia::WindowContext>
44
- SkiaMetalSurfaceFactory::makeContext(SkiaMetalContext *context,
45
- CALayer *texture, int width, int height) {
46
- return std::make_unique<IOSSkiaContext>(context, texture, width, height);
47
- }
48
-
49
- sk_sp<SkSurface> SkiaMetalSurfaceFactory::makeOffscreenSurface(
50
- id<MTLDevice> device, SkiaMetalContext *context, int width, int height) {
51
-
52
- auto ctx = new OffscreenRenderContext(device, context->skContext,
53
- context->commandQueue, width, height);
54
-
55
- // Create a GrBackendTexture from the Metal texture
56
- GrMtlTextureInfo info;
57
- info.fTexture.retain((__bridge void *)ctx->texture);
58
- GrBackendTexture backendTexture =
59
- GrBackendTextures::MakeMtl(width, height, skgpu::Mipmapped::kNo, info);
60
-
61
- // Create a SkSurface from the GrBackendTexture
62
- auto surface = SkSurfaces::WrapBackendTexture(
63
- context->skContext.get(), backendTexture, kTopLeft_GrSurfaceOrigin, 0,
64
- kBGRA_8888_SkColorType, nullptr, nullptr,
65
- [](void *addr) { delete (OffscreenRenderContext *)addr; }, ctx);
66
-
67
- return surface;
68
- }
69
-
70
- sk_sp<SkImage> SkiaMetalSurfaceFactory::makeTextureFromCVPixelBuffer(
71
- SkiaMetalContext *context, CVPixelBufferRef pixelBuffer) {
72
- SkiaCVPixelBufferUtils::CVPixelBufferBaseFormat format =
73
- SkiaCVPixelBufferUtils::getCVPixelBufferBaseFormat(pixelBuffer);
74
- switch (format) {
75
- case SkiaCVPixelBufferUtils::CVPixelBufferBaseFormat::rgb: {
76
- // CVPixelBuffer is in any RGB format, single-plane
77
- return SkiaCVPixelBufferUtils::RGB::makeSkImageFromCVPixelBuffer(
78
- context->skContext.get(), pixelBuffer);
79
- }
80
- case SkiaCVPixelBufferUtils::CVPixelBufferBaseFormat::yuv: {
81
- // CVPixelBuffer is in any YUV format, multi-plane
82
- return SkiaCVPixelBufferUtils::YUV::makeSkImageFromCVPixelBuffer(
83
- context->skContext.get(), pixelBuffer);
84
- }
85
- default:
86
- [[unlikely]] {
87
- throw std::runtime_error("Failed to convert NativeBuffer to SkImage - "
88
- "NativeBuffer has unsupported PixelFormat! " +
89
- std::to_string(static_cast<int>(format)));
90
- }
91
- }
92
- }