@shopify/react-native-skia 1.6.0 → 1.7.0

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