@shopify/react-native-skia 1.5.3 → 1.5.5

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