@shopify/react-native-skia 1.5.3 → 1.5.5

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 (99) hide show
  1. package/android/CMakeLists.txt +53 -13
  2. package/android/build.gradle +3 -0
  3. package/android/cpp/rnskia-android/OpenGLContext.h +122 -11
  4. package/android/cpp/rnskia-android/OpenGLWindowContext.cpp +73 -0
  5. package/android/cpp/rnskia-android/OpenGLWindowContext.h +74 -0
  6. package/android/cpp/rnskia-android/RNSkAndroidPlatformContext.h +18 -1
  7. package/android/cpp/rnskia-android/RNSkAndroidVideo.cpp +12 -1
  8. package/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp +13 -1
  9. package/android/cpp/rnskia-android/opengl/Context.h +77 -0
  10. package/android/cpp/rnskia-android/opengl/Display.h +117 -0
  11. package/android/cpp/rnskia-android/opengl/Error.cpp +9 -0
  12. package/android/cpp/rnskia-android/opengl/Error.h +44 -0
  13. package/android/cpp/rnskia-android/opengl/Surface.h +43 -0
  14. package/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java +0 -1
  15. package/cpp/api/JsiSkImage.h +15 -2
  16. package/cpp/api/JsiSkSurface.h +18 -3
  17. package/cpp/rnskia/DawnContext.h +241 -0
  18. package/cpp/rnskia/DawnUtils.h +127 -0
  19. package/cpp/rnskia/DawnWindowContext.cpp +19 -0
  20. package/cpp/rnskia/DawnWindowContext.h +77 -0
  21. package/cpp/rnskia/ImageProvider.h +100 -0
  22. package/cpp/rnskia/RNSkView.h +6 -0
  23. package/cpp/skia/include/android/SkAnimatedImage.h +14 -0
  24. package/cpp/skia/include/codec/SkAvifDecoder.h +39 -3
  25. package/cpp/skia/include/codec/SkCodec.h +16 -0
  26. package/cpp/skia/include/config/SkUserConfig.h +3 -2
  27. package/cpp/skia/include/core/SkCanvas.h +55 -10
  28. package/cpp/skia/include/core/SkContourMeasure.h +76 -0
  29. package/cpp/skia/include/core/SkFontScanner.h +48 -0
  30. package/cpp/skia/include/core/SkMilestone.h +1 -1
  31. package/cpp/skia/include/core/SkPath.h +11 -0
  32. package/cpp/skia/include/core/SkPathEffect.h +0 -23
  33. package/cpp/skia/include/core/SkRect.h +2 -0
  34. package/cpp/skia/include/core/SkString.h +4 -0
  35. package/cpp/skia/include/core/SkTypeface.h +5 -0
  36. package/cpp/skia/include/core/SkTypes.h +8 -3
  37. package/cpp/skia/include/docs/SkPDFDocument.h +3 -3
  38. package/cpp/skia/include/effects/SkOverdrawColorFilter.h +1 -0
  39. package/cpp/skia/include/effects/SkRuntimeEffect.h +2 -1
  40. package/cpp/skia/include/encode/SkJpegEncoder.h +4 -0
  41. package/cpp/skia/include/gpu/ganesh/GrContextOptions.h +8 -1
  42. package/cpp/skia/include/gpu/ganesh/GrDirectContext.h +18 -3
  43. package/cpp/skia/include/gpu/ganesh/GrTypes.h +11 -0
  44. package/cpp/skia/include/gpu/ganesh/gl/GrGLFunctions.h +5 -1
  45. package/cpp/skia/include/gpu/ganesh/gl/GrGLInterface.h +0 -1
  46. package/cpp/skia/include/gpu/graphite/GraphiteTypes.h +8 -0
  47. package/cpp/skia/include/gpu/graphite/Recorder.h +0 -2
  48. package/cpp/skia/include/gpu/graphite/precompile/PaintOptions.h +7 -4
  49. package/cpp/skia/include/gpu/graphite/precompile/PrecompileImageFilter.h +2 -0
  50. package/cpp/skia/include/gpu/graphite/precompile/PrecompileMaskFilter.h +2 -0
  51. package/cpp/skia/include/ports/SkFontMgr_android_ndk.h +25 -0
  52. package/cpp/skia/include/ports/SkFontMgr_fontconfig.h +4 -2
  53. package/cpp/skia/include/ports/SkFontScanner_Fontations.h +15 -0
  54. package/cpp/skia/include/ports/SkFontScanner_FreeType.h +15 -0
  55. package/cpp/skia/include/private/SkExif.h +14 -0
  56. package/cpp/skia/include/private/SkPathRef.h +36 -0
  57. package/cpp/skia/include/private/base/SkFeatures.h +4 -0
  58. package/cpp/skia/include/private/base/SkSpan_impl.h +1 -3
  59. package/cpp/skia/modules/skcms/src/skcms_internals.h +3 -0
  60. package/cpp/skia/src/base/SkMathPriv.h +1 -8
  61. package/ios/RNSkia-iOS/RNSkMetalCanvasProvider.h +1 -2
  62. package/ios/RNSkia-iOS/RNSkMetalCanvasProvider.mm +25 -19
  63. package/ios/RNSkia-iOS/RNSkiOSPlatformContext.mm +23 -0
  64. package/ios/RNSkia-iOS/SkiaCVPixelBufferUtils.mm +4 -8
  65. package/ios/RNSkia-iOS/SkiaMetalSurfaceFactory.h +26 -8
  66. package/ios/RNSkia-iOS/SkiaMetalSurfaceFactory.mm +0 -20
  67. package/libs/android/arm64-v8a/libskia.a +0 -0
  68. package/libs/android/arm64-v8a/libskottie.a +0 -0
  69. package/libs/android/armeabi-v7a/libskia.a +0 -0
  70. package/libs/android/armeabi-v7a/libskottie.a +0 -0
  71. package/libs/android/x86/libskia.a +0 -0
  72. package/libs/android/x86/libskottie.a +0 -0
  73. package/libs/android/x86_64/libskia.a +0 -0
  74. package/libs/android/x86_64/libskottie.a +0 -0
  75. package/libs/ios/libskia.xcframework/ios-arm64_arm64e/libskia.a +0 -0
  76. package/libs/ios/libskia.xcframework/ios-arm64_arm64e_x86_64-simulator/libskia.a +0 -0
  77. package/libs/ios/libskottie.xcframework/ios-arm64_arm64e/libskottie.a +0 -0
  78. package/libs/ios/libskottie.xcframework/ios-arm64_arm64e_x86_64-simulator/libskottie.a +0 -0
  79. package/libs/ios/libskparagraph.xcframework/ios-arm64_arm64e/libskparagraph.a +0 -0
  80. package/libs/ios/libskparagraph.xcframework/ios-arm64_arm64e_x86_64-simulator/libskparagraph.a +0 -0
  81. package/libs/ios/libsksg.xcframework/ios-arm64_arm64e/libsksg.a +0 -0
  82. package/libs/ios/libsksg.xcframework/ios-arm64_arm64e_x86_64-simulator/libsksg.a +0 -0
  83. package/libs/ios/libskshaper.xcframework/Info.plist +5 -5
  84. package/libs/ios/libskshaper.xcframework/ios-arm64_arm64e/libskshaper.a +0 -0
  85. package/libs/ios/libskshaper.xcframework/ios-arm64_arm64e_x86_64-simulator/libskshaper.a +0 -0
  86. package/libs/ios/libskunicode_core.xcframework/Info.plist +5 -5
  87. package/libs/ios/libskunicode_core.xcframework/ios-arm64_arm64e/libskunicode_core.a +0 -0
  88. package/libs/ios/libskunicode_core.xcframework/ios-arm64_arm64e_x86_64-simulator/libskunicode_core.a +0 -0
  89. package/libs/ios/libskunicode_libgrapheme.xcframework/Info.plist +5 -5
  90. package/libs/ios/libskunicode_libgrapheme.xcframework/ios-arm64_arm64e/libskunicode_libgrapheme.a +0 -0
  91. package/libs/ios/libskunicode_libgrapheme.xcframework/ios-arm64_arm64e_x86_64-simulator/libskunicode_libgrapheme.a +0 -0
  92. package/libs/ios/libsvg.xcframework/ios-arm64_arm64e/libsvg.a +0 -0
  93. package/libs/ios/libsvg.xcframework/ios-arm64_arm64e_x86_64-simulator/libsvg.a +0 -0
  94. package/package.json +1 -1
  95. package/react-native-skia.podspec +35 -9
  96. package/src/renderer/__tests__/e2e/SVG.spec.tsx +2 -1
  97. package/android/cpp/rnskia-android/SkiaOpenGLHelper.h +0 -310
  98. package/android/cpp/rnskia-android/SkiaOpenGLSurfaceFactory.cpp +0 -188
  99. package/android/cpp/rnskia-android/SkiaOpenGLSurfaceFactory.h +0 -100
@@ -0,0 +1,117 @@
1
+ #pragma once
2
+
3
+ #include <memory>
4
+
5
+ #include "EGL/egl.h"
6
+ #include "GLES2/gl2.h"
7
+
8
+ #include "opengl/Context.h"
9
+ #include "opengl/Error.h"
10
+
11
+ namespace RNSkia {
12
+
13
+ class Context;
14
+ class Surface;
15
+
16
+ class Display {
17
+ public:
18
+ Display() {
19
+ EGLDisplay display = eglGetDisplay(EGL_DEFAULT_DISPLAY);
20
+
21
+ if (eglInitialize(display, nullptr, nullptr) != EGL_TRUE) {
22
+ LOG_EGL_ERROR;
23
+ return;
24
+ }
25
+ _display = display;
26
+ }
27
+
28
+ ~Display() {
29
+ if (_display != EGL_NO_DISPLAY) {
30
+ if (eglTerminate(_display) != EGL_TRUE) {
31
+ LOG_EGL_ERROR;
32
+ }
33
+ }
34
+ }
35
+
36
+ bool isValid() const { return _display != EGL_NO_DISPLAY; }
37
+
38
+ EGLConfig chooseConfig() const {
39
+
40
+ EGLint att[] = {EGL_RENDERABLE_TYPE,
41
+ EGL_OPENGL_ES2_BIT,
42
+ EGL_ALPHA_SIZE,
43
+ 8,
44
+ EGL_BLUE_SIZE,
45
+ 8,
46
+ EGL_GREEN_SIZE,
47
+ 8,
48
+ EGL_RED_SIZE,
49
+ 8,
50
+ EGL_DEPTH_SIZE,
51
+ 0,
52
+ EGL_STENCIL_SIZE,
53
+ 0,
54
+ EGL_SAMPLE_BUFFERS,
55
+ 0,
56
+ EGL_NONE};
57
+
58
+ EGLint numConfigs;
59
+ EGLConfig glConfig = 0;
60
+ if (eglChooseConfig(_display, att, &glConfig, 1, &numConfigs) != EGL_TRUE ||
61
+ numConfigs == 0) {
62
+ LOG_EGL_ERROR;
63
+ return 0;
64
+ }
65
+
66
+ return glConfig;
67
+ }
68
+
69
+ std::unique_ptr<Context> makeContext(const EGLConfig &config,
70
+ const Context *share_context) {
71
+ EGLint contextAttribs[] = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE};
72
+ auto context = eglCreateContext(
73
+ _display, config,
74
+ share_context != nullptr ? share_context->getHandle() : nullptr,
75
+ contextAttribs);
76
+
77
+ if (context == EGL_NO_CONTEXT) {
78
+ LOG_EGL_ERROR;
79
+ return nullptr;
80
+ }
81
+ return std::unique_ptr<Context>(new Context(_display, context));
82
+ }
83
+
84
+ std::unique_ptr<Surface> makeWindowSurface(const EGLConfig &config,
85
+ EGLNativeWindowType window) {
86
+ const EGLint attribs[] = {EGL_NONE};
87
+ auto surface = eglCreateWindowSurface(_display, config, window, attribs);
88
+ if (surface == EGL_NO_SURFACE) {
89
+ LOG_EGL_ERROR;
90
+ return nullptr;
91
+ }
92
+ return std::unique_ptr<Surface>(new Surface(_display, surface));
93
+ }
94
+
95
+ std::unique_ptr<Surface> makePixelBufferSurface(const EGLConfig &config,
96
+ size_t width, size_t height) {
97
+ const EGLint attribs[] = {EGL_WIDTH, static_cast<EGLint>(width), EGL_HEIGHT,
98
+ static_cast<EGLint>(height), EGL_NONE};
99
+ auto surface = eglCreatePbufferSurface(_display, config, attribs);
100
+ if (surface == EGL_NO_SURFACE) {
101
+ LOG_EGL_ERROR;
102
+ return nullptr;
103
+ }
104
+ return std::unique_ptr<Surface>(new Surface(_display, surface));
105
+ }
106
+
107
+ const EGLDisplay &getHandle() const { return _display; }
108
+
109
+ private:
110
+ EGLDisplay _display = EGL_NO_DISPLAY;
111
+
112
+ Display(const Display &) = delete;
113
+
114
+ Display &operator=(const Display &) = delete;
115
+ };
116
+
117
+ } // namespace RNSkia
@@ -0,0 +1,9 @@
1
+ #include "opengl/Error.h"
2
+
3
+ #include "RNSkLog.h"
4
+
5
+ void LogEGLError(const char *file, int line) {
6
+ const auto error = eglGetError();
7
+ RNSkia::RNSkLogger::logToConsole("EGL Error: %s (%d) in %s:%d",
8
+ EGLErrorToString(error), error, file, line);
9
+ }
@@ -0,0 +1,44 @@
1
+ #pragma once
2
+
3
+ #include "EGL/egl.h"
4
+ #include "GLES2/gl2.h"
5
+
6
+ #define LOG_EGL_ERROR LogEGLError(__FILE__, __LINE__);
7
+
8
+ static const char *EGLErrorToString(EGLint error) {
9
+ switch (error) {
10
+ case EGL_SUCCESS:
11
+ return "Success";
12
+ case EGL_NOT_INITIALIZED:
13
+ return "Not Initialized";
14
+ case EGL_BAD_ACCESS:
15
+ return "Bad Access";
16
+ case EGL_BAD_ALLOC:
17
+ return "Bad Alloc";
18
+ case EGL_BAD_ATTRIBUTE:
19
+ return "Bad Attribute";
20
+ case EGL_BAD_CONTEXT:
21
+ return "Bad Context";
22
+ case EGL_BAD_CONFIG:
23
+ return "Bad Config";
24
+ case EGL_BAD_CURRENT_SURFACE:
25
+ return "Bad Current Surface";
26
+ case EGL_BAD_DISPLAY:
27
+ return "Bad Display";
28
+ case EGL_BAD_SURFACE:
29
+ return "Bad Surface";
30
+ case EGL_BAD_MATCH:
31
+ return "Bad Match";
32
+ case EGL_BAD_PARAMETER:
33
+ return "Bad Parameter";
34
+ case EGL_BAD_NATIVE_PIXMAP:
35
+ return "Bad Native Pixmap";
36
+ case EGL_BAD_NATIVE_WINDOW:
37
+ return "Bad Native Window";
38
+ case EGL_CONTEXT_LOST:
39
+ return "Context Lost";
40
+ }
41
+ return "Unknown";
42
+ }
43
+
44
+ void LogEGLError(const char *file, int line);
@@ -0,0 +1,43 @@
1
+ #pragma once
2
+
3
+ #include "opengl/Error.h"
4
+
5
+ namespace RNSkia {
6
+
7
+ class Surface {
8
+ public:
9
+ ~Surface() {
10
+ if (_surface != EGL_NO_SURFACE) {
11
+ if (eglDestroySurface(_display, _surface) != EGL_TRUE) {
12
+ LOG_EGL_ERROR;
13
+ }
14
+ }
15
+ }
16
+
17
+ bool isValid() { return _surface != EGL_NO_SURFACE; }
18
+
19
+ const EGLSurface &getHandle() const { return _surface; }
20
+
21
+ bool Present() const {
22
+ const auto result = eglSwapBuffers(_display, _surface) == EGL_TRUE;
23
+ if (!result) {
24
+ LOG_EGL_ERROR;
25
+ }
26
+ return result;
27
+ }
28
+
29
+ private:
30
+ friend class Display;
31
+
32
+ EGLDisplay _display = EGL_NO_DISPLAY;
33
+ EGLSurface _surface = EGL_NO_SURFACE;
34
+
35
+ Surface(EGLDisplay display, EGLSurface surface)
36
+ : _display(display), _surface(surface) {}
37
+
38
+ Surface(const Surface &) = delete;
39
+
40
+ Surface &operator=(const Surface &) = delete;
41
+ };
42
+
43
+ } // Namespace RNSkia
@@ -3,7 +3,6 @@ package com.shopify.reactnative.skia;
3
3
  import android.content.Context;
4
4
  import android.graphics.SurfaceTexture;
5
5
  import android.util.Log;
6
- import android.view.MotionEvent;
7
6
  import android.view.TextureView;
8
7
 
9
8
  import com.facebook.react.views.view.ReactViewGroup;
@@ -12,6 +12,11 @@
12
12
 
13
13
  #include "RNSkTypedArray.h"
14
14
 
15
+ #if defined(SK_GRAPHITE)
16
+ #include "DawnContext.h"
17
+ #include "include/gpu/graphite/Context.h"
18
+ #endif
19
+
15
20
  #pragma clang diagnostic push
16
21
  #pragma clang diagnostic ignored "-Wdocumentation"
17
22
 
@@ -83,9 +88,13 @@ public:
83
88
  ? arguments[1].asNumber()
84
89
  : 100.0;
85
90
  auto image = getObject();
91
+ #if defined(SK_GRAPHITE)
92
+ image = DawnContext::getInstance().MakeRasterImage(image);
93
+ #else
86
94
  if (image->isTextureBacked()) {
87
95
  image = image->makeNonTextureImage();
88
96
  }
97
+ #endif
89
98
  sk_sp<SkData> data;
90
99
 
91
100
  if (format == SkEncodedImageFormat::kJPEG) {
@@ -181,9 +190,13 @@ public:
181
190
  }
182
191
 
183
192
  JSI_HOST_FUNCTION(makeNonTextureImage) {
184
- auto image = getObject()->makeNonTextureImage();
193
+ #if defined(SK_GRAPHITE)
194
+ auto rasterImage = DawnContext::getInstance().MakeRasterImage(getObject());
195
+ #else
196
+ auto rasterImage = getObject()->makeNonTextureImage();
197
+ #endif
185
198
  return jsi::Object::createFromHostObject(
186
- runtime, std::make_shared<JsiSkImage>(getContext(), std::move(image)));
199
+ runtime, std::make_shared<JsiSkImage>(getContext(), rasterImage));
187
200
  }
188
201
 
189
202
  EXPORT_JSI_API_TYPENAME(JsiSkImage, Image)
@@ -10,6 +10,10 @@
10
10
  #include "JsiSkCanvas.h"
11
11
  #include "JsiSkImage.h"
12
12
 
13
+ #if defined(SK_GRAPHITE)
14
+ #include "DawnContext.h"
15
+ #endif
16
+
13
17
  #pragma clang diagnostic push
14
18
  #pragma clang diagnostic ignored "-Wdocumentation"
15
19
 
@@ -44,21 +48,32 @@ public:
44
48
  }
45
49
 
46
50
  JSI_HOST_FUNCTION(flush) {
47
- if (auto dContext = GrAsDirectContext(getObject()->recordingContext())) {
51
+ auto surface = getObject();
52
+ #if defined(SK_GRAPHITE)
53
+ auto recording = surface->recorder()->snap();
54
+ DawnContext::getInstance().submitRecording(recording.get());
55
+ #else
56
+ if (auto dContext = GrAsDirectContext(surface->recordingContext())) {
48
57
  dContext->flushAndSubmit();
49
58
  }
59
+ #endif
50
60
  return jsi::Value::undefined();
51
61
  }
52
62
 
53
63
  JSI_HOST_FUNCTION(makeImageSnapshot) {
64
+ auto surface = getObject();
54
65
  sk_sp<SkImage> image;
55
66
  if (count == 1) {
56
67
  auto rect = JsiSkRect::fromValue(runtime, arguments[0]);
57
- image = getObject()->makeImageSnapshot(SkIRect::MakeXYWH(
68
+ image = surface->makeImageSnapshot(SkIRect::MakeXYWH(
58
69
  rect->x(), rect->y(), rect->width(), rect->height()));
59
70
  } else {
60
- image = getObject()->makeImageSnapshot();
71
+ image = surface->makeImageSnapshot();
61
72
  }
73
+ #if defined(SK_GRAPHITE)
74
+ auto recording = surface->recorder()->snap();
75
+ DawnContext::getInstance().submitRecording(recording.get());
76
+ #endif
62
77
  return jsi::Object::createFromHostObject(
63
78
  runtime, std::make_shared<JsiSkImage>(getContext(), std::move(image)));
64
79
  }
@@ -0,0 +1,241 @@
1
+ #pragma once
2
+
3
+ #include <memory>
4
+ #include <mutex>
5
+
6
+ #include "DawnUtils.h"
7
+ #include "DawnWindowContext.h"
8
+ #include "ImageProvider.h"
9
+
10
+ #include "include/core/SkData.h"
11
+ #include "include/gpu/graphite/BackendTexture.h"
12
+ #include "include/gpu/graphite/Context.h"
13
+ #include "include/gpu/graphite/ContextOptions.h"
14
+ #include "include/gpu/graphite/GraphiteTypes.h"
15
+ #include "include/gpu/graphite/Recorder.h"
16
+ #include "include/gpu/graphite/Recording.h"
17
+ #include "include/gpu/graphite/Surface.h"
18
+ #include "include/gpu/graphite/dawn/DawnBackendContext.h"
19
+ #include "include/gpu/graphite/dawn/DawnTypes.h"
20
+ #include "include/gpu/graphite/dawn/DawnUtils.h"
21
+
22
+ #include "src/gpu/graphite/ContextOptionsPriv.h"
23
+
24
+ #ifdef __APPLE__
25
+ #include <CoreVideo/CVPixelBuffer.h>
26
+ #else
27
+ #include <android/hardware_buffer.h>
28
+ #include <android/hardware_buffer_jni.h>
29
+ #endif
30
+
31
+ namespace RNSkia {
32
+
33
+ struct AsyncContext {
34
+ bool fCalled = false;
35
+ std::unique_ptr<const SkSurface::AsyncReadResult> fResult;
36
+ };
37
+
38
+ struct SharedTextureContext {
39
+ wgpu::SharedTextureMemory sharedTextureMemory;
40
+ wgpu::Texture texture;
41
+ };
42
+
43
+ static void
44
+ async_callback(void *c,
45
+ std::unique_ptr<const SkImage::AsyncReadResult> result) {
46
+ auto context = static_cast<AsyncContext *>(c);
47
+ context->fResult = std::move(result);
48
+ context->fCalled = true;
49
+ }
50
+
51
+ class DawnContext {
52
+ public:
53
+ // TODO: remove
54
+ friend class RNSkiOSPlatformContext;
55
+
56
+ DawnContext(const DawnContext &) = delete;
57
+ DawnContext &operator=(const DawnContext &) = delete;
58
+
59
+ static DawnContext &getInstance() {
60
+ static DawnContext instance;
61
+ return instance;
62
+ }
63
+
64
+ sk_sp<SkImage> MakeRasterImage(sk_sp<SkImage> image) {
65
+ if (!image->isTextureBacked()) {
66
+ return image;
67
+ }
68
+ std::lock_guard<std::mutex> lock(_mutex);
69
+ AsyncContext asyncContext;
70
+ fGraphiteContext->asyncRescaleAndReadPixels(
71
+ image.get(), image->imageInfo(), image->imageInfo().bounds(),
72
+ SkImage::RescaleGamma::kSrc, SkImage::RescaleMode::kNearest,
73
+ async_callback, &asyncContext);
74
+ fGraphiteContext->submit();
75
+ while (!asyncContext.fCalled) {
76
+ tick();
77
+ fGraphiteContext->checkAsyncWorkCompletion();
78
+ }
79
+ auto bytesPerRow = asyncContext.fResult->rowBytes(0);
80
+ auto bufferSize = bytesPerRow * image->imageInfo().height();
81
+ auto data = SkData::MakeWithProc(
82
+ asyncContext.fResult->data(0), bufferSize,
83
+ [](const void *ptr, void *context) {
84
+ auto *result =
85
+ reinterpret_cast<const SkSurface::AsyncReadResult *>(context);
86
+ delete result;
87
+ },
88
+ reinterpret_cast<void *>(const_cast<SkSurface::AsyncReadResult *>(
89
+ asyncContext.fResult.release())));
90
+ auto rasterImage =
91
+ SkImages::RasterFromData(image->imageInfo(), data, bytesPerRow);
92
+ return rasterImage;
93
+ }
94
+
95
+ void submitRecording(
96
+ skgpu::graphite::Recording *recording,
97
+ skgpu::graphite::SyncToCpu syncToCpu = skgpu::graphite::SyncToCpu::kNo) {
98
+ std::lock_guard<std::mutex> lock(_mutex);
99
+ skgpu::graphite::InsertRecordingInfo info;
100
+ info.fRecording = recording;
101
+ fGraphiteContext->insertRecording(info);
102
+ fGraphiteContext->submit(syncToCpu);
103
+ }
104
+
105
+ sk_sp<SkImage> MakeImageFromBuffer(void *buffer) {
106
+ #ifdef __APPLE__
107
+ wgpu::SharedTextureMemoryIOSurfaceDescriptor platformDesc;
108
+ auto ioSurface = CVPixelBufferGetIOSurface((CVPixelBufferRef)buffer);
109
+ platformDesc.ioSurface = ioSurface;
110
+ int width = static_cast<int>(IOSurfaceGetWidth(ioSurface));
111
+ int height = static_cast<int>(IOSurfaceGetHeight(ioSurface));
112
+ #else
113
+ wgpu::SharedTextureMemoryAHardwareBufferDescriptor platformDesc;
114
+ auto ahb = (AHardwareBuffer *)buffer;
115
+ platformDesc.handle = ahb;
116
+ platformDesc.useExternalFormat = true;
117
+ AHardwareBuffer_Desc adesc;
118
+ AHardwareBuffer_describe(ahb, &adesc);
119
+ int width = adesc.width;
120
+ int height = adesc.height;
121
+ #endif
122
+
123
+ wgpu::SharedTextureMemoryDescriptor desc = {};
124
+ desc.nextInChain = &platformDesc;
125
+ wgpu::SharedTextureMemory memory =
126
+ backendContext.fDevice.ImportSharedTextureMemory(&desc);
127
+
128
+ wgpu::TextureDescriptor textureDesc;
129
+ textureDesc.format = DawnUtils::PreferredTextureFormat;
130
+ textureDesc.dimension = wgpu::TextureDimension::e2D;
131
+ textureDesc.usage =
132
+ wgpu::TextureUsage::TextureBinding | wgpu::TextureUsage::CopySrc;
133
+ textureDesc.size = {static_cast<uint32_t>(width),
134
+ static_cast<uint32_t>(height), 1};
135
+
136
+ wgpu::Texture texture = memory.CreateTexture(&textureDesc);
137
+
138
+ wgpu::SharedTextureMemoryBeginAccessDescriptor beginAccessDesc;
139
+ beginAccessDesc.initialized = true;
140
+ beginAccessDesc.fenceCount = 0;
141
+ bool success = memory.BeginAccess(texture, &beginAccessDesc);
142
+
143
+ if (success) {
144
+ skgpu::graphite::BackendTexture betFromView =
145
+ skgpu::graphite::BackendTextures::MakeDawn(texture.Get());
146
+ auto result = SkImages::WrapTexture(
147
+ getRecorder(), betFromView, DawnUtils::PreferedColorType,
148
+ kPremul_SkAlphaType, nullptr,
149
+ [](void *context) {
150
+ auto ctx = static_cast<SharedTextureContext *>(context);
151
+ wgpu::SharedTextureMemoryEndAccessState endState = {};
152
+ ctx->sharedTextureMemory.EndAccess(ctx->texture, &endState);
153
+ delete ctx;
154
+ },
155
+ new SharedTextureContext{memory, texture});
156
+ return result;
157
+ }
158
+ if (!success) {
159
+ return nullptr;
160
+ }
161
+ return nullptr;
162
+ }
163
+
164
+ // Create offscreen surface
165
+ sk_sp<SkSurface> MakeOffscreen(int width, int height) {
166
+ SkImageInfo info = SkImageInfo::Make(
167
+ width, height, DawnUtils::PreferedColorType, kPremul_SkAlphaType);
168
+ sk_sp<SkSurface> surface = SkSurfaces::RenderTarget(getRecorder(), info);
169
+
170
+ if (!surface) {
171
+ throw std::runtime_error("Failed to create offscreen Skia surface.");
172
+ }
173
+
174
+ return surface;
175
+ }
176
+
177
+ // Create onscreen surface with window
178
+ std::unique_ptr<WindowContext> MakeWindow(void *window, int width,
179
+ int height) {
180
+ // 1. Create Surface
181
+ wgpu::SurfaceDescriptor surfaceDescriptor;
182
+ #ifdef __APPLE__
183
+ wgpu::SurfaceDescriptorFromMetalLayer metalSurfaceDesc;
184
+ metalSurfaceDesc.layer = window;
185
+ surfaceDescriptor.nextInChain = &metalSurfaceDesc;
186
+ #else
187
+ wgpu::SurfaceDescriptorFromAndroidNativeWindow androidSurfaceDesc;
188
+ androidSurfaceDesc.window = window;
189
+ surfaceDescriptor.nextInChain = &androidSurfaceDesc;
190
+ #endif
191
+ auto surface =
192
+ wgpu::Instance(instance->Get()).CreateSurface(&surfaceDescriptor);
193
+ return std::make_unique<DawnWindowContext>(
194
+ getRecorder(), backendContext.fDevice, surface, width, height);
195
+ }
196
+
197
+ private:
198
+ std::unique_ptr<dawn::native::Instance> instance;
199
+ std::unique_ptr<skgpu::graphite::Context> fGraphiteContext;
200
+ skgpu::graphite::DawnBackendContext backendContext;
201
+ std::mutex _mutex;
202
+
203
+ DawnContext() {
204
+ DawnProcTable backendProcs = dawn::native::GetProcs();
205
+ dawnProcSetProcs(&backendProcs);
206
+ WGPUInstanceDescriptor desc{};
207
+ desc.features.timedWaitAnyEnable = true;
208
+ instance = std::make_unique<dawn::native::Instance>(&desc);
209
+
210
+ backendContext = DawnUtils::createDawnBackendContext(instance.get());
211
+
212
+ skgpu::graphite::ContextOptions ctxOptions;
213
+ skgpu::graphite::ContextOptionsPriv contextOptionsPriv;
214
+ ctxOptions.fOptionsPriv = &contextOptionsPriv;
215
+ ctxOptions.fOptionsPriv->fStoreContextRefInRecorder = true;
216
+ fGraphiteContext =
217
+ skgpu::graphite::ContextFactory::MakeDawn(backendContext, ctxOptions);
218
+
219
+ if (!fGraphiteContext) {
220
+ throw std::runtime_error("Failed to create graphite context");
221
+ }
222
+ }
223
+
224
+ void tick() { backendContext.fTick(backendContext.fInstance); }
225
+
226
+ skgpu::graphite::Recorder *getRecorder() {
227
+ static thread_local skgpu::graphite::RecorderOptions recorderOptions;
228
+ if (!recorderOptions.fImageProvider) {
229
+ auto imageProvider = ImageProvider::Make();
230
+ recorderOptions.fImageProvider = imageProvider;
231
+ }
232
+ static thread_local auto recorder =
233
+ fGraphiteContext->makeRecorder(recorderOptions);
234
+ if (!recorder) {
235
+ throw std::runtime_error("Failed to create graphite context");
236
+ }
237
+ return recorder.get();
238
+ }
239
+ };
240
+
241
+ } // namespace RNSkia
@@ -0,0 +1,127 @@
1
+ #pragma once
2
+
3
+ #include "webgpu/webgpu_cpp.h"
4
+
5
+ #include "dawn/dawn_proc.h"
6
+ #include "dawn/native/DawnNative.h"
7
+
8
+ #include "include/core/SkColorType.h"
9
+ #include "include/gpu/graphite/dawn/DawnBackendContext.h"
10
+
11
+ namespace DawnUtils {
12
+
13
+ #ifdef __APPLE__
14
+ static const SkColorType PreferedColorType = kBGRA_8888_SkColorType;
15
+ static const wgpu::TextureFormat PreferredTextureFormat =
16
+ wgpu::TextureFormat::BGRA8Unorm;
17
+ #else
18
+ static const SkColorType PreferedColorType = kRGBA_8888_SkColorType;
19
+ static const wgpu::TextureFormat PreferredTextureFormat =
20
+ wgpu::TextureFormat::RGBA8Unorm;
21
+ #endif
22
+
23
+ inline skgpu::graphite::DawnBackendContext
24
+ createDawnBackendContext(dawn::native::Instance *instance) {
25
+
26
+ auto useTintIR = false;
27
+ static constexpr const char *kToggles[] = {
28
+ "allow_unsafe_apis",
29
+ "use_user_defined_labels_in_backend",
30
+ "disable_robustness",
31
+ "use_tint_ir",
32
+ };
33
+ wgpu::DawnTogglesDescriptor togglesDesc;
34
+ togglesDesc.enabledToggleCount = std::size(kToggles) - (useTintIR ? 0 : 1);
35
+ togglesDesc.enabledToggles = kToggles;
36
+
37
+ wgpu::RequestAdapterOptions options;
38
+ #ifdef __APPLE__
39
+ constexpr auto kDefaultBackendType = wgpu::BackendType::Metal;
40
+ #elif __ANDROID__
41
+ constexpr auto kDefaultBackendType = wgpu::BackendType::Vulkan;
42
+ #endif
43
+ options.backendType = kDefaultBackendType;
44
+ options.nextInChain = &togglesDesc;
45
+
46
+ std::vector<dawn::native::Adapter> adapters =
47
+ instance->EnumerateAdapters(&options);
48
+ if (adapters.empty()) {
49
+ throw std::runtime_error("No matching adapter found");
50
+ }
51
+
52
+ wgpu::Adapter adapter = adapters[0].Get();
53
+
54
+ std::vector<wgpu::FeatureName> features;
55
+ if (adapter.HasFeature(wgpu::FeatureName::MSAARenderToSingleSampled)) {
56
+ features.push_back(wgpu::FeatureName::MSAARenderToSingleSampled);
57
+ }
58
+ if (adapter.HasFeature(wgpu::FeatureName::TransientAttachments)) {
59
+ features.push_back(wgpu::FeatureName::TransientAttachments);
60
+ }
61
+ if (adapter.HasFeature(wgpu::FeatureName::Unorm16TextureFormats)) {
62
+ features.push_back(wgpu::FeatureName::Unorm16TextureFormats);
63
+ }
64
+ if (adapter.HasFeature(wgpu::FeatureName::DualSourceBlending)) {
65
+ features.push_back(wgpu::FeatureName::DualSourceBlending);
66
+ }
67
+ if (adapter.HasFeature(wgpu::FeatureName::FramebufferFetch)) {
68
+ features.push_back(wgpu::FeatureName::FramebufferFetch);
69
+ }
70
+ if (adapter.HasFeature(wgpu::FeatureName::BufferMapExtendedUsages)) {
71
+ features.push_back(wgpu::FeatureName::BufferMapExtendedUsages);
72
+ }
73
+ if (adapter.HasFeature(wgpu::FeatureName::TextureCompressionETC2)) {
74
+ features.push_back(wgpu::FeatureName::TextureCompressionETC2);
75
+ }
76
+ if (adapter.HasFeature(wgpu::FeatureName::TextureCompressionBC)) {
77
+ features.push_back(wgpu::FeatureName::TextureCompressionBC);
78
+ }
79
+ if (adapter.HasFeature(wgpu::FeatureName::R8UnormStorage)) {
80
+ features.push_back(wgpu::FeatureName::R8UnormStorage);
81
+ }
82
+ if (adapter.HasFeature(wgpu::FeatureName::DawnLoadResolveTexture)) {
83
+ features.push_back(wgpu::FeatureName::DawnLoadResolveTexture);
84
+ }
85
+ if (adapter.HasFeature(wgpu::FeatureName::DawnPartialLoadResolveTexture)) {
86
+ features.push_back(wgpu::FeatureName::DawnPartialLoadResolveTexture);
87
+ }
88
+ #ifdef __APPLE__
89
+ if (adapter.HasFeature(wgpu::FeatureName::SharedTextureMemoryIOSurface)) {
90
+ features.push_back(wgpu::FeatureName::SharedTextureMemoryIOSurface);
91
+ }
92
+ #else
93
+ if (adapter.HasFeature(
94
+ wgpu::FeatureName::SharedTextureMemoryAHardwareBuffer)) {
95
+ features.push_back(wgpu::FeatureName::SharedTextureMemoryAHardwareBuffer);
96
+ }
97
+ #endif
98
+
99
+ wgpu::DeviceDescriptor desc;
100
+ desc.requiredFeatureCount = features.size();
101
+ desc.requiredFeatures = features.data();
102
+ desc.nextInChain = &togglesDesc;
103
+ desc.SetDeviceLostCallback(
104
+ wgpu::CallbackMode::AllowSpontaneous,
105
+ [](const wgpu::Device &, wgpu::DeviceLostReason reason,
106
+ const char *message) {
107
+ if (reason != wgpu::DeviceLostReason::Destroyed) {
108
+ SK_ABORT("Device lost: %s\n", message);
109
+ }
110
+ });
111
+ desc.SetUncapturedErrorCallback(
112
+ [](const wgpu::Device &, wgpu::ErrorType, const char *message) {
113
+ SkDebugf("Device error: %s\n", message);
114
+ });
115
+
116
+ wgpu::Device device = adapter.CreateDevice(&desc);
117
+ SkASSERT(device);
118
+
119
+ skgpu::graphite::DawnBackendContext backendContext;
120
+ backendContext.fInstance = wgpu::Instance(instance->Get());
121
+ backendContext.fDevice = device;
122
+ backendContext.fQueue = device.GetQueue();
123
+
124
+ return backendContext;
125
+ }
126
+
127
+ } // namespace DawnUtils
@@ -0,0 +1,19 @@
1
+ #include "DawnWindowContext.h"
2
+
3
+ #include "DawnContext.h"
4
+
5
+ namespace RNSkia {
6
+
7
+ void DawnWindowContext::present() {
8
+ auto recording = _recorder->snap();
9
+ if (!recording) {
10
+ throw std::runtime_error("Failed to create graphite recording");
11
+ }
12
+ DawnContext::getInstance().submitRecording(recording.get());
13
+ #ifdef __APPLE__
14
+ dawn::native::metal::WaitForCommandsToBeScheduled(_device.Get());
15
+ #endif
16
+ _surface.Present();
17
+ }
18
+
19
+ } // namespace RNSkia