@shopify/react-native-skia 2.5.1 → 2.5.3

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 (138) hide show
  1. package/android/CMakeLists.txt +8 -6
  2. package/android/build.gradle +5 -32
  3. package/android/cpp/jni/JniWebGPUView.cpp +67 -0
  4. package/android/cpp/rnskia-android/OpenGLContext.h +9 -2
  5. package/android/cpp/rnskia-android/RNSkAndroidPlatformContext.h +6 -3
  6. package/android/cpp/rnskia-android/SkiaPlatformContext.h +26 -0
  7. package/android/src/main/java/com/shopify/reactnative/skia/RNSkiaPackage.java +4 -1
  8. package/android/src/main/java/com/shopify/reactnative/skia/WebGPUSurfaceView.java +41 -0
  9. package/android/src/main/java/com/shopify/reactnative/skia/WebGPUTextureView.java +44 -0
  10. package/android/src/main/java/com/shopify/reactnative/skia/WebGPUView.java +95 -0
  11. package/android/src/main/java/com/shopify/reactnative/skia/WebGPUViewAPI.java +14 -0
  12. package/android/src/main/java/com/shopify/reactnative/skia/WebGPUViewManager.java +58 -0
  13. package/apple/MetalContext.h +10 -2
  14. package/apple/MetalWindowContext.h +1 -0
  15. package/apple/MetalWindowContext.mm +8 -1
  16. package/apple/RNSkApplePlatformContext.h +2 -1
  17. package/apple/RNSkApplePlatformContext.mm +6 -4
  18. package/apple/RNSkUIKit.h +13 -0
  19. package/apple/SkiaPictureView.mm +3 -0
  20. package/apple/SkiaPlatformContext.h +20 -0
  21. package/apple/SkiaPlatformContext.mm +21 -0
  22. package/apple/WebGPUMetalView.h +12 -0
  23. package/apple/WebGPUMetalView.mm +93 -0
  24. package/apple/WebGPUView.h +20 -0
  25. package/apple/WebGPUView.mm +77 -0
  26. package/cpp/api/JsiSkImage.h +76 -0
  27. package/cpp/api/JsiSkSurfaceFactory.h +12 -1
  28. package/cpp/jsi2/JSIConverter.h +11 -0
  29. package/cpp/rnskia/RNDawnContext.h +24 -16
  30. package/cpp/rnskia/RNDawnUtils.h +12 -0
  31. package/cpp/rnskia/RNSkManager.cpp +11 -4
  32. package/cpp/rnskia/RNSkPlatformContext.h +3 -1
  33. package/cpp/rnwgpu/Canvas.h +45 -0
  34. package/cpp/rnwgpu/PlatformContext.h +18 -0
  35. package/cpp/rnwgpu/SurfaceRegistry.h +229 -0
  36. package/cpp/rnwgpu/api/GPUAdapter.cpp +26 -0
  37. package/cpp/rnwgpu/api/GPUCanvasContext.cpp +64 -0
  38. package/cpp/rnwgpu/api/GPUCanvasContext.h +65 -0
  39. package/cpp/rnwgpu/api/GPUDevice.cpp +52 -0
  40. package/cpp/rnwgpu/api/GPUDevice.h +62 -1
  41. package/cpp/rnwgpu/api/GPUUncapturedErrorEvent.h +61 -0
  42. package/cpp/rnwgpu/api/RNWebGPU.h +62 -0
  43. package/cpp/rnwgpu/api/descriptors/GPUBindGroupEntry.h +4 -0
  44. package/cpp/rnwgpu/api/descriptors/GPUCanvasConfiguration.h +76 -0
  45. package/lib/commonjs/external/reanimated/useVideo.js +1 -4
  46. package/lib/commonjs/external/reanimated/useVideo.js.map +1 -1
  47. package/lib/commonjs/mock/index.js +1 -0
  48. package/lib/commonjs/mock/index.js.map +1 -1
  49. package/lib/commonjs/skia/types/Surface/SurfaceFactory.d.ts +10 -1
  50. package/lib/commonjs/skia/types/Surface/SurfaceFactory.js +5 -0
  51. package/lib/commonjs/skia/types/Surface/SurfaceFactory.js.map +1 -1
  52. package/lib/commonjs/sksg/Container.native.js +4 -0
  53. package/lib/commonjs/sksg/Container.native.js.map +1 -1
  54. package/lib/commonjs/sksg/Container.web.js +4 -0
  55. package/lib/commonjs/sksg/Container.web.js.map +1 -1
  56. package/lib/commonjs/specs/WebGPUViewNativeComponent.d.ts +8 -0
  57. package/lib/commonjs/specs/WebGPUViewNativeComponent.js +11 -0
  58. package/lib/commonjs/specs/WebGPUViewNativeComponent.js.map +1 -0
  59. package/lib/commonjs/specs/WebGPUViewNativeComponent.web.d.ts +8 -0
  60. package/lib/commonjs/specs/WebGPUViewNativeComponent.web.js +101 -0
  61. package/lib/commonjs/specs/WebGPUViewNativeComponent.web.js.map +1 -0
  62. package/lib/commonjs/specs/utils.d.ts +1 -0
  63. package/lib/commonjs/specs/utils.js +11 -0
  64. package/lib/commonjs/specs/utils.js.map +1 -0
  65. package/lib/commonjs/views/WebGPUCanvas.d.ts +32 -0
  66. package/lib/commonjs/views/WebGPUCanvas.js +66 -0
  67. package/lib/commonjs/views/WebGPUCanvas.js.map +1 -0
  68. package/lib/commonjs/views/WebGPUCanvas.web.d.ts +23 -0
  69. package/lib/commonjs/views/WebGPUCanvas.web.js +20 -0
  70. package/lib/commonjs/views/WebGPUCanvas.web.js.map +1 -0
  71. package/lib/commonjs/views/index.d.ts +1 -0
  72. package/lib/commonjs/views/index.js +11 -0
  73. package/lib/commonjs/views/index.js.map +1 -1
  74. package/lib/module/external/reanimated/useVideo.js +1 -4
  75. package/lib/module/external/reanimated/useVideo.js.map +1 -1
  76. package/lib/module/mock/index.js +1 -0
  77. package/lib/module/mock/index.js.map +1 -1
  78. package/lib/module/skia/types/Surface/SurfaceFactory.d.ts +10 -1
  79. package/lib/module/skia/types/Surface/SurfaceFactory.js +4 -1
  80. package/lib/module/skia/types/Surface/SurfaceFactory.js.map +1 -1
  81. package/lib/module/sksg/Container.native.js +5 -0
  82. package/lib/module/sksg/Container.native.js.map +1 -1
  83. package/lib/module/sksg/Container.web.js +5 -0
  84. package/lib/module/sksg/Container.web.js.map +1 -1
  85. package/lib/module/specs/WebGPUViewNativeComponent.d.ts +8 -0
  86. package/lib/module/specs/WebGPUViewNativeComponent.js +4 -0
  87. package/lib/module/specs/WebGPUViewNativeComponent.js.map +1 -0
  88. package/lib/module/specs/WebGPUViewNativeComponent.web.d.ts +8 -0
  89. package/lib/module/specs/WebGPUViewNativeComponent.web.js +94 -0
  90. package/lib/module/specs/WebGPUViewNativeComponent.web.js.map +1 -0
  91. package/lib/module/specs/utils.d.ts +1 -0
  92. package/lib/module/specs/utils.js +5 -0
  93. package/lib/module/specs/utils.js.map +1 -0
  94. package/lib/module/views/WebGPUCanvas.d.ts +32 -0
  95. package/lib/module/views/WebGPUCanvas.js +57 -0
  96. package/lib/module/views/WebGPUCanvas.js.map +1 -0
  97. package/lib/module/views/WebGPUCanvas.web.d.ts +23 -0
  98. package/lib/module/views/WebGPUCanvas.web.js +12 -0
  99. package/lib/module/views/WebGPUCanvas.web.js.map +1 -0
  100. package/lib/module/views/index.d.ts +1 -0
  101. package/lib/module/views/index.js +1 -0
  102. package/lib/module/views/index.js.map +1 -1
  103. package/lib/typescript/lib/commonjs/mock/index.d.ts +1 -0
  104. package/lib/typescript/lib/commonjs/skia/types/Surface/SurfaceFactory.d.ts +4 -0
  105. package/lib/typescript/lib/commonjs/specs/WebGPUViewNativeComponent.d.ts +3 -0
  106. package/lib/typescript/lib/commonjs/specs/WebGPUViewNativeComponent.web.d.ts +3 -0
  107. package/lib/typescript/lib/commonjs/specs/utils.d.ts +2 -0
  108. package/lib/typescript/lib/commonjs/views/WebGPUCanvas.d.ts +6 -0
  109. package/lib/typescript/lib/commonjs/views/WebGPUCanvas.web.d.ts +6 -0
  110. package/lib/typescript/lib/module/mock/index.d.ts +7 -1
  111. package/lib/typescript/lib/module/skia/types/Surface/SurfaceFactory.d.ts +4 -1
  112. package/lib/typescript/lib/module/specs/WebGPUViewNativeComponent.d.ts +2 -0
  113. package/lib/typescript/lib/module/specs/WebGPUViewNativeComponent.web.d.ts +2 -0
  114. package/lib/typescript/lib/module/specs/utils.d.ts +1 -0
  115. package/lib/typescript/lib/module/views/WebGPUCanvas.d.ts +7 -0
  116. package/lib/typescript/lib/module/views/WebGPUCanvas.web.d.ts +8 -0
  117. package/lib/typescript/lib/module/views/index.d.ts +1 -0
  118. package/lib/typescript/src/skia/types/Surface/SurfaceFactory.d.ts +10 -1
  119. package/lib/typescript/src/specs/WebGPUViewNativeComponent.d.ts +8 -0
  120. package/lib/typescript/src/specs/WebGPUViewNativeComponent.web.d.ts +8 -0
  121. package/lib/typescript/src/specs/utils.d.ts +1 -0
  122. package/lib/typescript/src/views/WebGPUCanvas.d.ts +32 -0
  123. package/lib/typescript/src/views/WebGPUCanvas.web.d.ts +23 -0
  124. package/lib/typescript/src/views/index.d.ts +1 -0
  125. package/package.json +7 -3
  126. package/react-native-skia.podspec +16 -83
  127. package/scripts/install-libs.js +131 -0
  128. package/src/external/reanimated/useVideo.ts +1 -4
  129. package/src/mock/index.ts +1 -0
  130. package/src/skia/types/Surface/SurfaceFactory.ts +17 -1
  131. package/src/sksg/Container.native.ts +3 -0
  132. package/src/sksg/Container.web.ts +3 -0
  133. package/src/specs/WebGPUViewNativeComponent.ts +11 -0
  134. package/src/specs/WebGPUViewNativeComponent.web.ts +108 -0
  135. package/src/specs/utils.ts +4 -0
  136. package/src/views/WebGPUCanvas.tsx +109 -0
  137. package/src/views/WebGPUCanvas.web.tsx +36 -0
  138. package/src/views/index.ts +1 -0
@@ -4,7 +4,7 @@ cmake_minimum_required(VERSION 3.4.1)
4
4
  set (CMAKE_VERBOSE_MAKEFILE ON)
5
5
  set (CMAKE_CXX_STANDARD 20)
6
6
 
7
- # SKIA_LIBS_PATH is passed from Gradle (resolved via Node.js package resolution)
7
+ # SKIA_LIBS_PATH is passed from Gradle (pointing to libs/android/, populated by npm postinstall)
8
8
  # Append the ABI to get the full path
9
9
  set (SKIA_LIBS_PATH "${SKIA_LIBS_PATH}/${ANDROID_ABI}")
10
10
 
@@ -17,14 +17,12 @@ if(NOT EXISTS "${SKIA_LIBS_PATH}/libskia.a")
17
17
  message("│ │")
18
18
  message("│ Could not find libskia.a at: ${SKIA_LIBS_PATH} │")
19
19
  message("│ │")
20
- message("│ Make sure react-native-skia-android is installed: │")
21
- message("│ yarn add react-native-skia-android │")
22
- message("│ │")
23
- message("│ See: https://shopify.github.io/react-native-skia/docs/getting-started/installation │")
20
+ message("│ Run the following command to install them: │")
21
+ message("│ npx install-skia │")
24
22
  message("│ │")
25
23
  message("└─────────────────────────────────────────────────────────────────────────────┘")
26
24
  message("")
27
- message(FATAL_ERROR "Skia prebuilt binaries not found at ${SKIA_LIBS_PATH}")
25
+ message(FATAL_ERROR "Skia prebuilt binaries not found. Run `npx install-skia` to fix this.")
28
26
  endif()
29
27
 
30
28
  # Import libskia
@@ -130,6 +128,7 @@ if(SK_GRAPHITE)
130
128
  "${PROJECT_SOURCE_DIR}/../cpp/rnwgpu/api/GPUAdapter.cpp"
131
129
  "${PROJECT_SOURCE_DIR}/../cpp/rnwgpu/api/GPUBindGroup.cpp"
132
130
  "${PROJECT_SOURCE_DIR}/../cpp/rnwgpu/api/GPUBuffer.cpp"
131
+ "${PROJECT_SOURCE_DIR}/../cpp/rnwgpu/api/GPUCanvasContext.cpp"
133
132
  "${PROJECT_SOURCE_DIR}/../cpp/rnwgpu/api/GPUCommandEncoder.cpp"
134
133
  "${PROJECT_SOURCE_DIR}/../cpp/rnwgpu/api/GPUComputePassEncoder.cpp"
135
134
  "${PROJECT_SOURCE_DIR}/../cpp/rnwgpu/api/GPUComputePipeline.cpp"
@@ -143,6 +142,9 @@ if(SK_GRAPHITE)
143
142
  "${PROJECT_SOURCE_DIR}/../cpp/rnwgpu/api/GPUShaderModule.cpp"
144
143
  "${PROJECT_SOURCE_DIR}/../cpp/rnwgpu/api/GPUSupportedLimits.cpp"
145
144
  "${PROJECT_SOURCE_DIR}/../cpp/rnwgpu/api/GPUTexture.cpp"
145
+
146
+ # WebGPU Canvas JNI bindings
147
+ "${PROJECT_SOURCE_DIR}/cpp/jni/JniWebGPUView.cpp"
146
148
  )
147
149
  endif()
148
150
 
@@ -56,41 +56,15 @@ static def findNodeModules(baseDir) {
56
56
  throw new GradleException("React-Native-Skia: Failed to find node_modules/ path!")
57
57
  }
58
58
 
59
- // Resolve npm package path using Node.js resolution (handles monorepos, pnpm, etc.)
60
- def resolveSkiaPackage(packageName) {
61
- def cmdResult = providers.exec {
62
- commandLine "node", "-e", "console.log(require.resolve('${packageName}/package.json'))"
63
- ignoreExitValue = true
64
- }
65
-
66
- if (cmdResult.result.get().exitValue == 0) {
67
- def packageJsonPath = cmdResult.standardOutput.asText.get().trim()
68
- return new File(packageJsonPath).parent
69
- }
70
-
71
- // Fallback: walk up directories looking for node_modules
72
- def basePath = projectDir.toPath().normalize()
73
- while (basePath) {
74
- def candidate = Paths.get(basePath.toString(), "node_modules", packageName)
75
- if (candidate.toFile().exists() && new File(candidate.toString(), "package.json").exists()) {
76
- return candidate.toString()
77
- }
78
- basePath = basePath.getParent()
79
- }
80
-
81
- throw new GradleException("React-Native-Skia: Could not find ${packageName}. Make sure you have run 'yarn install' or 'npm install'.")
82
- }
83
-
84
59
  def nodeModules = findNodeModules(projectDir)
85
60
 
86
- // Resolve Skia Android package
87
- def useGraphite = System.getenv("SK_GRAPHITE") == "1" || System.getenv("SK_GRAPHITE") == "true"
88
- def skiaPackageName = useGraphite ? "react-native-skia-graphite-android" : "react-native-skia-android"
89
- def skiaAndroidPackage = resolveSkiaPackage(skiaPackageName)
90
- def skiaLibsPath = "${skiaAndroidPackage}/libs"
61
+ // Skia prebuilt libs are copied into libs/android/ by the npm postinstall script
62
+ // Graphite is detected via marker file created by install-skia-graphite
63
+ def useGraphite = file("${projectDir}/../libs/.graphite").exists()
64
+ def skiaLibsPath = "${projectDir}/../libs/android"
91
65
 
92
66
  logger.warn("react-native-skia: SK_GRAPHITE: ${useGraphite}")
93
- logger.warn("react-native-skia: Skia Android package: ${skiaAndroidPackage}")
67
+ logger.warn("react-native-skia: Skia libs: ${skiaLibsPath}")
94
68
  logger.warn("react-native-skia: node_modules/ found at: ${nodeModules}")
95
69
 
96
70
  def sourceBuild = false
@@ -292,7 +266,6 @@ repositories {
292
266
  }
293
267
  }
294
268
  google()
295
- maven { url 'https://www.jitpack.io' }
296
269
  }
297
270
 
298
271
  dependencies {
@@ -0,0 +1,67 @@
1
+ #include <jni.h>
2
+ #include <android/native_window_jni.h>
3
+
4
+ #ifdef SK_GRAPHITE
5
+ #include "webgpu/webgpu_cpp.h"
6
+ #include "rnwgpu/SurfaceRegistry.h"
7
+ #include "rnskia/RNDawnContext.h"
8
+ #endif
9
+
10
+ extern "C" JNIEXPORT void JNICALL
11
+ Java_com_shopify_reactnative_skia_WebGPUView_onSurfaceCreate(
12
+ JNIEnv *env, jobject thiz, jobject jSurface, jint contextId, jfloat width,
13
+ jfloat height) {
14
+ #ifdef SK_GRAPHITE
15
+ auto window = ANativeWindow_fromSurface(env, jSurface);
16
+ auto &registry = rnwgpu::SurfaceRegistry::getInstance();
17
+ auto &dawnContext = RNSkia::DawnContext::getInstance();
18
+ auto gpu = dawnContext.getWGPUInstance();
19
+
20
+ // Create surface from ANativeWindow
21
+ wgpu::SurfaceDescriptorFromAndroidNativeWindow androidSurfaceDesc;
22
+ androidSurfaceDesc.window = window;
23
+ wgpu::SurfaceDescriptor surfaceDescriptor;
24
+ surfaceDescriptor.nextInChain = &androidSurfaceDesc;
25
+ auto surface = gpu.CreateSurface(&surfaceDescriptor);
26
+
27
+ registry
28
+ .getSurfaceInfoOrCreate(contextId, gpu, static_cast<int>(width),
29
+ static_cast<int>(height))
30
+ ->switchToOnscreen(window, surface);
31
+ #endif
32
+ }
33
+
34
+ extern "C" JNIEXPORT void JNICALL
35
+ Java_com_shopify_reactnative_skia_WebGPUView_onSurfaceChanged(
36
+ JNIEnv *env, jobject thiz, jobject surface, jint contextId, jfloat width,
37
+ jfloat height) {
38
+ #ifdef SK_GRAPHITE
39
+ auto &registry = rnwgpu::SurfaceRegistry::getInstance();
40
+ auto surfaceInfo = registry.getSurfaceInfo(contextId);
41
+ if (surfaceInfo) {
42
+ surfaceInfo->resize(static_cast<int>(width), static_cast<int>(height));
43
+ }
44
+ #endif
45
+ }
46
+
47
+ extern "C" JNIEXPORT void JNICALL
48
+ Java_com_shopify_reactnative_skia_WebGPUView_switchToOffscreenSurface(
49
+ JNIEnv *env, jobject thiz, jint contextId) {
50
+ #ifdef SK_GRAPHITE
51
+ auto &registry = rnwgpu::SurfaceRegistry::getInstance();
52
+ auto surfaceInfo = registry.getSurfaceInfo(contextId);
53
+ if (surfaceInfo) {
54
+ surfaceInfo->switchToOffscreen();
55
+ }
56
+ #endif
57
+ }
58
+
59
+ extern "C" JNIEXPORT void JNICALL
60
+ Java_com_shopify_reactnative_skia_WebGPUView_onSurfaceDestroy(JNIEnv *env,
61
+ jobject thiz,
62
+ jint contextId) {
63
+ #ifdef SK_GRAPHITE
64
+ auto &registry = rnwgpu::SurfaceRegistry::getInstance();
65
+ registry.removeSurfaceInfo(contextId);
66
+ #endif
67
+ }
@@ -58,7 +58,8 @@ public:
58
58
  return instance;
59
59
  }
60
60
 
61
- sk_sp<SkSurface> MakeOffscreen(int width, int height) {
61
+ sk_sp<SkSurface> MakeOffscreen(int width, int height,
62
+ bool useP3ColorSpace = false) {
62
63
  auto colorType = kRGBA_8888_SkColorType;
63
64
 
64
65
  SkSurfaceProps props(0, kUnknown_SkPixelGeometry);
@@ -89,10 +90,16 @@ public:
89
90
  auto releaseCtx = new ReleaseContext{.directContext = _directContext.get(),
90
91
  .texture = texture};
91
92
 
93
+ sk_sp<SkColorSpace> colorSpace =
94
+ useP3ColorSpace
95
+ ? SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB,
96
+ SkNamedGamut::kDisplayP3)
97
+ : nullptr;
98
+
92
99
  // Create a SkSurface from the GrBackendTexture
93
100
  return SkSurfaces::WrapBackendTexture(
94
101
  _directContext.get(), texture, kTopLeft_GrSurfaceOrigin, 0, colorType,
95
- nullptr, &props,
102
+ colorSpace, &props,
96
103
  [](void *addr) {
97
104
  auto releaseCtx = reinterpret_cast<ReleaseContext *>(addr);
98
105
  releaseCtx->directContext->deleteBackendTexture(releaseCtx->texture);
@@ -50,11 +50,14 @@ public:
50
50
  _jniPlatformContext->raiseError(err);
51
51
  }
52
52
 
53
- sk_sp<SkSurface> makeOffscreenSurface(int width, int height) override {
53
+ sk_sp<SkSurface> makeOffscreenSurface(int width, int height,
54
+ bool useP3ColorSpace = false) override {
54
55
  #if defined(SK_GRAPHITE)
55
- return DawnContext::getInstance().MakeOffscreen(width, height);
56
+ return DawnContext::getInstance().MakeOffscreen(width, height,
57
+ useP3ColorSpace);
56
58
  #else
57
- return OpenGLContext::getInstance().MakeOffscreen(width, height);
59
+ return OpenGLContext::getInstance().MakeOffscreen(width, height,
60
+ useP3ColorSpace);
58
61
  #endif
59
62
  }
60
63
 
@@ -0,0 +1,26 @@
1
+ #pragma once
2
+
3
+ #ifdef SK_GRAPHITE
4
+
5
+ #include "rnwgpu/PlatformContext.h"
6
+
7
+ namespace rnwgpu {
8
+
9
+ class SkiaPlatformContext : public PlatformContext {
10
+ public:
11
+ SkiaPlatformContext() = default;
12
+ ~SkiaPlatformContext() = default;
13
+
14
+ wgpu::Surface makeSurface(wgpu::Instance instance, void *surface, int width,
15
+ int height) override {
16
+ wgpu::SurfaceDescriptorFromAndroidNativeWindow androidSurfaceDesc;
17
+ androidSurfaceDesc.window = surface;
18
+ wgpu::SurfaceDescriptor surfaceDescriptor;
19
+ surfaceDescriptor.nextInChain = &androidSurfaceDesc;
20
+ return instance.CreateSurface(&surfaceDescriptor);
21
+ }
22
+ };
23
+
24
+ } // namespace rnwgpu
25
+
26
+ #endif // SK_GRAPHITE
@@ -42,7 +42,10 @@ public class RNSkiaPackage extends TurboReactPackage {
42
42
 
43
43
  @Override
44
44
  public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
45
- return Arrays.<ViewManager>asList(new SkiaPictureViewManager());
45
+ return Arrays.<ViewManager>asList(
46
+ new SkiaPictureViewManager(),
47
+ new WebGPUViewManager()
48
+ );
46
49
  }
47
50
 
48
51
  @Override
@@ -0,0 +1,41 @@
1
+ package com.shopify.reactnative.skia;
2
+
3
+ import android.annotation.SuppressLint;
4
+ import android.content.Context;
5
+ import android.view.SurfaceHolder;
6
+ import android.view.SurfaceView;
7
+
8
+ import androidx.annotation.NonNull;
9
+
10
+ @SuppressLint("ViewConstructor")
11
+ public class WebGPUSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
12
+
13
+ WebGPUViewAPI mApi;
14
+
15
+ public WebGPUSurfaceView(Context context, WebGPUViewAPI api) {
16
+ super(context);
17
+ mApi = api;
18
+ getHolder().addCallback(this);
19
+ }
20
+
21
+ @Override
22
+ protected void onDetachedFromWindow() {
23
+ super.onDetachedFromWindow();
24
+ mApi.surfaceDestroyed();
25
+ }
26
+
27
+ @Override
28
+ public void surfaceCreated(@NonNull SurfaceHolder holder) {
29
+ mApi.surfaceCreated(holder.getSurface());
30
+ }
31
+
32
+ @Override
33
+ public void surfaceChanged(@NonNull SurfaceHolder holder, int format, int width, int height) {
34
+ mApi.surfaceChanged(holder.getSurface());
35
+ }
36
+
37
+ @Override
38
+ public void surfaceDestroyed(@NonNull SurfaceHolder holder) {
39
+ mApi.surfaceOffscreen();
40
+ }
41
+ }
@@ -0,0 +1,44 @@
1
+ package com.shopify.reactnative.skia;
2
+
3
+ import android.annotation.SuppressLint;
4
+ import android.content.Context;
5
+ import android.graphics.SurfaceTexture;
6
+ import android.view.Surface;
7
+ import android.view.TextureView;
8
+ import androidx.annotation.NonNull;
9
+
10
+ @SuppressLint("ViewConstructor")
11
+ public class WebGPUTextureView extends TextureView implements TextureView.SurfaceTextureListener {
12
+
13
+ WebGPUViewAPI mApi;
14
+
15
+ public WebGPUTextureView(Context context, WebGPUViewAPI api) {
16
+ super(context);
17
+ mApi = api;
18
+ setOpaque(false);
19
+ setSurfaceTextureListener(this);
20
+ }
21
+
22
+ @Override
23
+ public void onSurfaceTextureAvailable(@NonNull SurfaceTexture surfaceTexture, int width, int height) {
24
+ Surface surface = new Surface(surfaceTexture);
25
+ mApi.surfaceCreated(surface);
26
+ }
27
+
28
+ @Override
29
+ public void onSurfaceTextureSizeChanged(@NonNull SurfaceTexture surfaceTexture, int width, int height) {
30
+ Surface surface = new Surface(surfaceTexture);
31
+ mApi.surfaceChanged(surface);
32
+ }
33
+
34
+ @Override
35
+ public boolean onSurfaceTextureDestroyed(@NonNull SurfaceTexture surfaceTexture) {
36
+ mApi.surfaceDestroyed();
37
+ return true;
38
+ }
39
+
40
+ @Override
41
+ public void onSurfaceTextureUpdated(@NonNull SurfaceTexture surfaceTexture) {
42
+ // No implementation needed
43
+ }
44
+ }
@@ -0,0 +1,95 @@
1
+ package com.shopify.reactnative.skia;
2
+
3
+ import android.content.Context;
4
+ import android.view.Surface;
5
+ import android.view.View;
6
+
7
+ import com.facebook.proguard.annotations.DoNotStrip;
8
+ import com.facebook.react.views.view.ReactViewGroup;
9
+
10
+ public class WebGPUView extends ReactViewGroup implements WebGPUViewAPI {
11
+
12
+ private int mContextId;
13
+ private boolean mTransparent = false;
14
+ private View mView = null;
15
+
16
+ WebGPUView(Context context) {
17
+ super(context);
18
+ }
19
+
20
+ public void setContextId(int contextId) {
21
+ mContextId = contextId;
22
+ }
23
+
24
+ public void setTransparent(boolean value) {
25
+ Context ctx = getContext();
26
+ if (value != mTransparent || mView == null) {
27
+ if (mView != null) {
28
+ removeView(mView);
29
+ }
30
+ mTransparent = value;
31
+ if (mTransparent) {
32
+ mView = new WebGPUTextureView(ctx, this);
33
+ } else {
34
+ mView = new WebGPUSurfaceView(ctx, this);
35
+ }
36
+ addView(mView);
37
+ }
38
+ }
39
+
40
+ @Override
41
+ protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
42
+ super.onLayout(changed, left, top, right, bottom);
43
+ if (mView != null) {
44
+ mView.layout(0, 0, this.getMeasuredWidth(), this.getMeasuredHeight());
45
+ }
46
+ }
47
+
48
+ @Override
49
+ public void surfaceCreated(Surface surface) {
50
+ float density = getResources().getDisplayMetrics().density;
51
+ float width = getWidth() / density;
52
+ float height = getHeight() / density;
53
+ onSurfaceCreate(surface, mContextId, width, height);
54
+ }
55
+
56
+ @Override
57
+ public void surfaceChanged(Surface surface) {
58
+ float density = getResources().getDisplayMetrics().density;
59
+ float width = getWidth() / density;
60
+ float height = getHeight() / density;
61
+ onSurfaceChanged(surface, mContextId, width, height);
62
+ }
63
+
64
+ @Override
65
+ public void surfaceDestroyed() {
66
+ onSurfaceDestroy(mContextId);
67
+ }
68
+
69
+ @Override
70
+ public void surfaceOffscreen() {
71
+ switchToOffscreenSurface(mContextId);
72
+ }
73
+
74
+ @DoNotStrip
75
+ private native void onSurfaceCreate(
76
+ Surface surface,
77
+ int contextId,
78
+ float width,
79
+ float height
80
+ );
81
+
82
+ @DoNotStrip
83
+ private native void onSurfaceChanged(
84
+ Surface surface,
85
+ int contextId,
86
+ float width,
87
+ float height
88
+ );
89
+
90
+ @DoNotStrip
91
+ private native void onSurfaceDestroy(int contextId);
92
+
93
+ @DoNotStrip
94
+ private native void switchToOffscreenSurface(int contextId);
95
+ }
@@ -0,0 +1,14 @@
1
+ package com.shopify.reactnative.skia;
2
+
3
+ import android.view.Surface;
4
+
5
+ public interface WebGPUViewAPI {
6
+
7
+ void surfaceCreated(Surface surface);
8
+
9
+ void surfaceChanged(Surface surface);
10
+
11
+ void surfaceDestroyed();
12
+
13
+ void surfaceOffscreen();
14
+ }
@@ -0,0 +1,58 @@
1
+ package com.shopify.reactnative.skia;
2
+
3
+ import com.facebook.react.module.annotations.ReactModule;
4
+ import com.facebook.react.uimanager.ThemedReactContext;
5
+ import com.facebook.react.uimanager.annotations.ReactProp;
6
+ import com.facebook.react.views.view.ReactViewGroup;
7
+ import com.facebook.react.views.view.ReactViewManager;
8
+ import com.facebook.react.viewmanagers.WebGPUViewManagerDelegate;
9
+ import com.facebook.react.viewmanagers.WebGPUViewManagerInterface;
10
+
11
+ import androidx.annotation.NonNull;
12
+ import androidx.annotation.Nullable;
13
+
14
+ @ReactModule(name = WebGPUViewManager.NAME)
15
+ public class WebGPUViewManager extends ReactViewManager implements WebGPUViewManagerInterface<WebGPUView> {
16
+
17
+ public static final String NAME = "WebGPUView";
18
+
19
+ protected WebGPUViewManagerDelegate mDelegate;
20
+
21
+ public WebGPUViewManager() {
22
+ mDelegate = new WebGPUViewManagerDelegate(this);
23
+ }
24
+
25
+ protected WebGPUViewManagerDelegate getDelegate() {
26
+ return mDelegate;
27
+ }
28
+
29
+ @NonNull
30
+ @Override
31
+ public String getName() {
32
+ return NAME;
33
+ }
34
+
35
+ @NonNull
36
+ @Override
37
+ public WebGPUView createViewInstance(@NonNull ThemedReactContext context) {
38
+ return new WebGPUView(context);
39
+ }
40
+
41
+ @Override
42
+ @ReactProp(name = "transparent")
43
+ public void setTransparent(WebGPUView view, boolean value) {
44
+ view.setTransparent(value);
45
+ }
46
+
47
+ @Override
48
+ @ReactProp(name = "contextId")
49
+ public void setContextId(WebGPUView view, int value) {
50
+ view.setContextId(value);
51
+ }
52
+
53
+ @Override
54
+ public void onDropViewInstance(@NonNull ReactViewGroup view) {
55
+ super.onDropViewInstance(view);
56
+ ((WebGPUView) view).surfaceDestroyed();
57
+ }
58
+ }
@@ -13,6 +13,7 @@
13
13
  #import <include/gpu/ganesh/mtl/GrMtlBackendSurface.h>
14
14
  #import <include/gpu/ganesh/mtl/GrMtlDirectContext.h>
15
15
  #import <include/gpu/ganesh/mtl/SkSurfaceMetal.h>
16
+ #include "include/core/SkColorSpace.h"
16
17
 
17
18
  struct OffscreenRenderContext {
18
19
  id<MTLTexture> texture;
@@ -44,7 +45,8 @@ public:
44
45
  return instance;
45
46
  }
46
47
 
47
- sk_sp<SkSurface> MakeOffscreen(int width, int height) {
48
+ sk_sp<SkSurface> MakeOffscreen(int width, int height,
49
+ bool useP3ColorSpace = false) {
48
50
  auto device = _device;
49
51
  auto ctx = new OffscreenRenderContext(device, _directContext, _commandQueue,
50
52
  width, height);
@@ -55,10 +57,16 @@ public:
55
57
  GrBackendTexture backendTexture =
56
58
  GrBackendTextures::MakeMtl(width, height, skgpu::Mipmapped::kNo, info);
57
59
 
60
+ sk_sp<SkColorSpace> colorSpace =
61
+ useP3ColorSpace
62
+ ? SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB,
63
+ SkNamedGamut::kDisplayP3)
64
+ : nullptr;
65
+
58
66
  // Create a SkSurface from the GrBackendTexture
59
67
  auto surface = SkSurfaces::WrapBackendTexture(
60
68
  _directContext.get(), backendTexture, kTopLeft_GrSurfaceOrigin, 0,
61
- kBGRA_8888_SkColorType, nullptr, nullptr,
69
+ kBGRA_8888_SkColorType, colorSpace, nullptr,
62
70
  [](void *addr) { delete (OffscreenRenderContext *)addr; }, ctx);
63
71
 
64
72
  return surface;
@@ -36,4 +36,5 @@ private:
36
36
  CAMetalLayer *_layer;
37
37
  #pragma clang diagnostic pop
38
38
  id<CAMetalDrawable> _currentDrawable = nil;
39
+ bool _useP3ColorSpace = false;
39
40
  };
@@ -2,6 +2,7 @@
2
2
 
3
3
  #include "MetalContext.h"
4
4
  #include "RNSkLog.h"
5
+ #include "include/core/SkColorSpace.h"
5
6
 
6
7
  MetalWindowContext::MetalWindowContext(GrDirectContext *directContext,
7
8
  id<MTLDevice> device,
@@ -46,6 +47,7 @@ MetalWindowContext::MetalWindowContext(GrDirectContext *directContext,
46
47
  CGColorSpaceCreateWithName(kCGColorSpaceDisplayP3);
47
48
  _layer.colorspace = colorSpace;
48
49
  CGColorSpaceRelease(colorSpace);
50
+ _useP3ColorSpace = true;
49
51
  }
50
52
  }
51
53
 
@@ -69,9 +71,14 @@ sk_sp<SkSurface> MetalWindowContext::getSurface() {
69
71
  GrBackendRenderTarget backendRT = GrBackendRenderTargets::MakeMtl(
70
72
  _layer.drawableSize.width, _layer.drawableSize.height, fbInfo);
71
73
 
74
+ sk_sp<SkColorSpace> skColorSpace =
75
+ _useP3ColorSpace
76
+ ? SkColorSpace::MakeRGB(SkNamedTransferFn::kSRGB,
77
+ SkNamedGamut::kDisplayP3)
78
+ : nullptr;
72
79
  _skSurface = SkSurfaces::WrapBackendRenderTarget(
73
80
  _directContext, backendRT, kTopLeft_GrSurfaceOrigin,
74
- kBGRA_8888_SkColorType, nullptr, nullptr);
81
+ kBGRA_8888_SkColorType, skColorSpace, nullptr);
75
82
 
76
83
  return _skSurface;
77
84
  }
@@ -69,7 +69,8 @@ public:
69
69
  const std::function<void(std::unique_ptr<SkStreamAsset>)> &op) override;
70
70
 
71
71
  void raiseError(const std::exception &err) override;
72
- sk_sp<SkSurface> makeOffscreenSurface(int width, int height) override;
72
+ sk_sp<SkSurface> makeOffscreenSurface(int width, int height,
73
+ bool useP3ColorSpace = false) override;
73
74
 
74
75
  sk_sp<SkFontMgr> createFontMgr() override;
75
76
 
@@ -251,12 +251,14 @@ void RNSkApplePlatformContext::raiseError(const std::exception &err) {
251
251
  RCTFatal(RCTErrorWithMessage([NSString stringWithUTF8String:err.what()]));
252
252
  }
253
253
 
254
- sk_sp<SkSurface> RNSkApplePlatformContext::makeOffscreenSurface(int width,
255
- int height) {
254
+ sk_sp<SkSurface> RNSkApplePlatformContext::makeOffscreenSurface(
255
+ int width, int height, bool useP3ColorSpace) {
256
256
  #if defined(SK_GRAPHITE)
257
- return DawnContext::getInstance().MakeOffscreen(width, height);
257
+ return DawnContext::getInstance().MakeOffscreen(width, height,
258
+ useP3ColorSpace);
258
259
  #else
259
- return MetalContext::getInstance().MakeOffscreen(width, height);
260
+ return MetalContext::getInstance().MakeOffscreen(width, height,
261
+ useP3ColorSpace);
260
262
  #endif
261
263
  }
262
264
 
@@ -0,0 +1,13 @@
1
+ #pragma once
2
+
3
+ #if !TARGET_OS_OSX
4
+ #import <UIKit/UIKit.h>
5
+ #else
6
+ #import <Appkit/Appkit.h>
7
+ #endif
8
+
9
+ #if !TARGET_OS_OSX
10
+ typedef UIView RNSkPlatformView;
11
+ #else
12
+ typedef NSView RNSkPlatformView;
13
+ #endif
@@ -58,6 +58,9 @@ using namespace facebook::react;
58
58
  if (newProps.colorSpace == "" || newProps.colorSpace == "srgb") {
59
59
  bool useP3 = false;
60
60
  [self setUseP3ColorSpace:useP3];
61
+ } else if (newProps.colorSpace == "p3") {
62
+ bool useP3 = true;
63
+ [self setUseP3ColorSpace:useP3];
61
64
  }
62
65
  }
63
66
 
@@ -0,0 +1,20 @@
1
+ #pragma once
2
+
3
+ #ifdef SK_GRAPHITE
4
+
5
+ #include "rnwgpu/PlatformContext.h"
6
+
7
+ namespace rnwgpu {
8
+
9
+ class SkiaPlatformContext : public PlatformContext {
10
+ public:
11
+ SkiaPlatformContext() = default;
12
+ ~SkiaPlatformContext() = default;
13
+
14
+ wgpu::Surface makeSurface(wgpu::Instance instance, void *surface, int width,
15
+ int height) override;
16
+ };
17
+
18
+ } // namespace rnwgpu
19
+
20
+ #endif // SK_GRAPHITE