@shopify/react-native-skia 2.5.2 → 2.5.4
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.
- package/android/CMakeLists.txt +11 -0
- package/android/cpp/jni/JniWebGPUView.cpp +67 -0
- package/android/cpp/rnskia-android/SkiaPlatformContext.h +26 -0
- package/android/src/main/java/com/shopify/reactnative/skia/RNSkiaPackage.java +4 -1
- package/android/src/main/java/com/shopify/reactnative/skia/WebGPUSurfaceView.java +41 -0
- package/android/src/main/java/com/shopify/reactnative/skia/WebGPUTextureView.java +44 -0
- package/android/src/main/java/com/shopify/reactnative/skia/WebGPUView.java +95 -0
- package/android/src/main/java/com/shopify/reactnative/skia/WebGPUViewAPI.java +14 -0
- package/android/src/main/java/com/shopify/reactnative/skia/WebGPUViewManager.java +58 -0
- package/apple/RNSkUIKit.h +13 -0
- package/apple/SkiaPlatformContext.h +20 -0
- package/apple/SkiaPlatformContext.mm +21 -0
- package/apple/WebGPUMetalView.h +12 -0
- package/apple/WebGPUMetalView.mm +93 -0
- package/apple/WebGPUView.h +20 -0
- package/apple/WebGPUView.mm +77 -0
- package/cpp/jsi2/JSIConverter.h +11 -0
- package/cpp/rnskia/RNDawnContext.h +2 -2
- package/cpp/rnskia/RNDawnWindowContext.h +3 -0
- package/cpp/rnskia/RNSkManager.cpp +11 -4
- package/cpp/rnwgpu/Canvas.h +50 -0
- package/cpp/rnwgpu/PlatformContext.h +18 -0
- package/cpp/rnwgpu/SurfaceRegistry.h +229 -0
- package/cpp/rnwgpu/api/GPU.cpp +12 -0
- package/cpp/rnwgpu/api/GPUAdapter.cpp +26 -0
- package/cpp/rnwgpu/api/GPUCanvasContext.cpp +64 -0
- package/cpp/rnwgpu/api/GPUCanvasContext.h +65 -0
- package/cpp/rnwgpu/api/GPUDevice.cpp +52 -0
- package/cpp/rnwgpu/api/GPUDevice.h +62 -1
- package/cpp/rnwgpu/api/GPUQueue.cpp +1 -1
- package/cpp/rnwgpu/api/GPUUncapturedErrorEvent.h +61 -0
- package/cpp/rnwgpu/api/RNWebGPU.h +62 -0
- package/cpp/rnwgpu/api/descriptors/GPUBindGroupEntry.h +4 -0
- package/cpp/rnwgpu/api/descriptors/GPUCanvasConfiguration.h +76 -0
- package/lib/commonjs/external/reanimated/useVideo.js +1 -4
- package/lib/commonjs/external/reanimated/useVideo.js.map +1 -1
- package/lib/commonjs/mock/index.js +1 -0
- package/lib/commonjs/mock/index.js.map +1 -1
- package/lib/commonjs/skia/types/Surface/SurfaceFactory.js.map +1 -1
- package/lib/commonjs/sksg/Container.native.js +4 -0
- package/lib/commonjs/sksg/Container.native.js.map +1 -1
- package/lib/commonjs/sksg/Container.web.js +4 -0
- package/lib/commonjs/sksg/Container.web.js.map +1 -1
- package/lib/commonjs/specs/WebGPUViewNativeComponent.d.ts +8 -0
- package/lib/commonjs/specs/WebGPUViewNativeComponent.js +11 -0
- package/lib/commonjs/specs/WebGPUViewNativeComponent.js.map +1 -0
- package/lib/commonjs/specs/WebGPUViewNativeComponent.web.d.ts +8 -0
- package/lib/commonjs/specs/WebGPUViewNativeComponent.web.js +101 -0
- package/lib/commonjs/specs/WebGPUViewNativeComponent.web.js.map +1 -0
- package/lib/commonjs/specs/utils.d.ts +1 -0
- package/lib/commonjs/specs/utils.js +11 -0
- package/lib/commonjs/specs/utils.js.map +1 -0
- package/lib/commonjs/views/WebGPUCanvas.d.ts +32 -0
- package/lib/commonjs/views/WebGPUCanvas.js +66 -0
- package/lib/commonjs/views/WebGPUCanvas.js.map +1 -0
- package/lib/commonjs/views/WebGPUCanvas.web.d.ts +23 -0
- package/lib/commonjs/views/WebGPUCanvas.web.js +20 -0
- package/lib/commonjs/views/WebGPUCanvas.web.js.map +1 -0
- package/lib/commonjs/views/index.d.ts +1 -0
- package/lib/commonjs/views/index.js +11 -0
- package/lib/commonjs/views/index.js.map +1 -1
- package/lib/module/external/reanimated/useVideo.js +1 -4
- package/lib/module/external/reanimated/useVideo.js.map +1 -1
- package/lib/module/mock/index.js +1 -0
- package/lib/module/mock/index.js.map +1 -1
- package/lib/module/skia/types/Surface/SurfaceFactory.js.map +1 -1
- package/lib/module/sksg/Container.native.js +5 -0
- package/lib/module/sksg/Container.native.js.map +1 -1
- package/lib/module/sksg/Container.web.js +5 -0
- package/lib/module/sksg/Container.web.js.map +1 -1
- package/lib/module/specs/WebGPUViewNativeComponent.d.ts +8 -0
- package/lib/module/specs/WebGPUViewNativeComponent.js +4 -0
- package/lib/module/specs/WebGPUViewNativeComponent.js.map +1 -0
- package/lib/module/specs/WebGPUViewNativeComponent.web.d.ts +8 -0
- package/lib/module/specs/WebGPUViewNativeComponent.web.js +94 -0
- package/lib/module/specs/WebGPUViewNativeComponent.web.js.map +1 -0
- package/lib/module/specs/utils.d.ts +1 -0
- package/lib/module/specs/utils.js +5 -0
- package/lib/module/specs/utils.js.map +1 -0
- package/lib/module/views/WebGPUCanvas.d.ts +32 -0
- package/lib/module/views/WebGPUCanvas.js +57 -0
- package/lib/module/views/WebGPUCanvas.js.map +1 -0
- package/lib/module/views/WebGPUCanvas.web.d.ts +23 -0
- package/lib/module/views/WebGPUCanvas.web.js +12 -0
- package/lib/module/views/WebGPUCanvas.web.js.map +1 -0
- package/lib/module/views/index.d.ts +1 -0
- package/lib/module/views/index.js +1 -0
- package/lib/module/views/index.js.map +1 -1
- package/lib/typescript/lib/commonjs/mock/index.d.ts +1 -0
- package/lib/typescript/lib/commonjs/specs/WebGPUViewNativeComponent.d.ts +3 -0
- package/lib/typescript/lib/commonjs/specs/WebGPUViewNativeComponent.web.d.ts +3 -0
- package/lib/typescript/lib/commonjs/specs/utils.d.ts +2 -0
- package/lib/typescript/lib/commonjs/views/WebGPUCanvas.d.ts +6 -0
- package/lib/typescript/lib/commonjs/views/WebGPUCanvas.web.d.ts +6 -0
- package/lib/typescript/lib/module/mock/index.d.ts +3 -1
- package/lib/typescript/lib/module/specs/WebGPUViewNativeComponent.d.ts +2 -0
- package/lib/typescript/lib/module/specs/WebGPUViewNativeComponent.web.d.ts +2 -0
- package/lib/typescript/lib/module/specs/utils.d.ts +1 -0
- package/lib/typescript/lib/module/views/WebGPUCanvas.d.ts +7 -0
- package/lib/typescript/lib/module/views/WebGPUCanvas.web.d.ts +8 -0
- package/lib/typescript/lib/module/views/index.d.ts +1 -0
- package/lib/typescript/src/specs/WebGPUViewNativeComponent.d.ts +8 -0
- package/lib/typescript/src/specs/WebGPUViewNativeComponent.web.d.ts +8 -0
- package/lib/typescript/src/specs/utils.d.ts +1 -0
- package/lib/typescript/src/views/WebGPUCanvas.d.ts +32 -0
- package/lib/typescript/src/views/WebGPUCanvas.web.d.ts +23 -0
- package/lib/typescript/src/views/index.d.ts +1 -0
- package/package.json +3 -2
- package/react-native-skia.podspec +3 -0
- package/scripts/install-libs.js +24 -32
- package/src/external/reanimated/useVideo.ts +1 -4
- package/src/mock/index.ts +1 -0
- package/src/skia/types/Surface/SurfaceFactory.ts +5 -1
- package/src/sksg/Container.native.ts +3 -0
- package/src/sksg/Container.web.ts +3 -0
- package/src/specs/WebGPUViewNativeComponent.ts +11 -0
- package/src/specs/WebGPUViewNativeComponent.web.ts +108 -0
- package/src/specs/utils.ts +4 -0
- package/src/views/WebGPUCanvas.tsx +109 -0
- package/src/views/WebGPUCanvas.web.tsx +36 -0
- package/src/views/index.ts +1 -0
|
@@ -12,6 +12,9 @@ import { Container, StaticContainer } from "./StaticContainer";
|
|
|
12
12
|
import "../skia/NativeSetup";
|
|
13
13
|
import "../views/api";
|
|
14
14
|
|
|
15
|
+
// create local reference for `strictGlobal` option in Worklets
|
|
16
|
+
const { SkiaViewApi } = globalThis;
|
|
17
|
+
|
|
15
18
|
const drawOnscreen = (Skia: Skia, nativeId: number, recording: Recording) => {
|
|
16
19
|
"worklet";
|
|
17
20
|
const rec = Skia.PictureRecorder();
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import codegenNativeComponent from "react-native/Libraries/Utilities/codegenNativeComponent";
|
|
2
|
+
import type { Int32 } from "react-native/Libraries/Types/CodegenTypes";
|
|
3
|
+
import type { ViewProps } from "react-native";
|
|
4
|
+
|
|
5
|
+
export interface NativeProps extends ViewProps {
|
|
6
|
+
contextId: Int32;
|
|
7
|
+
transparent: boolean;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// eslint-disable-next-line import/no-default-export
|
|
11
|
+
export default codegenNativeComponent<NativeProps>("WebGPUView");
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import React, { useEffect, useRef } from "react";
|
|
2
|
+
import { StyleSheet } from "react-native";
|
|
3
|
+
import type { Int32 } from "react-native/Libraries/Types/CodegenTypes";
|
|
4
|
+
import type { ViewProps } from "react-native";
|
|
5
|
+
|
|
6
|
+
import { contextIdToId } from "./utils";
|
|
7
|
+
|
|
8
|
+
export interface NativeProps extends ViewProps {
|
|
9
|
+
contextId: Int32;
|
|
10
|
+
transparent: boolean;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
14
|
+
function debounce<T extends (...args: any[]) => void>(
|
|
15
|
+
func: T,
|
|
16
|
+
wait: number,
|
|
17
|
+
immediate = false
|
|
18
|
+
) {
|
|
19
|
+
let timeout: ReturnType<typeof setTimeout> | undefined;
|
|
20
|
+
return function debounced(
|
|
21
|
+
this: ThisParameterType<T>,
|
|
22
|
+
...args: Parameters<T>
|
|
23
|
+
) {
|
|
24
|
+
const context = this;
|
|
25
|
+
const callNow = immediate && !timeout;
|
|
26
|
+
if (timeout) {
|
|
27
|
+
clearTimeout(timeout);
|
|
28
|
+
}
|
|
29
|
+
timeout = setTimeout(() => {
|
|
30
|
+
timeout = undefined;
|
|
31
|
+
if (!immediate) {
|
|
32
|
+
func.apply(context, args);
|
|
33
|
+
}
|
|
34
|
+
}, wait);
|
|
35
|
+
if (callNow) {
|
|
36
|
+
func.apply(context, args);
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function resizeCanvas(canvas: HTMLCanvasElement | null) {
|
|
42
|
+
if (!canvas) {
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const dpr = window.devicePixelRatio || 1;
|
|
47
|
+
|
|
48
|
+
const { height, width } = canvas.getBoundingClientRect();
|
|
49
|
+
canvas.setAttribute("height", (height * dpr).toString());
|
|
50
|
+
canvas.setAttribute("width", (width * dpr).toString());
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// eslint-disable-next-line import/no-default-export
|
|
54
|
+
export default function WebGPUViewNativeComponent(
|
|
55
|
+
props: NativeProps
|
|
56
|
+
): React.JSX.Element {
|
|
57
|
+
const { contextId, style, transparent, ...rest } = props;
|
|
58
|
+
|
|
59
|
+
const canvasElm = useRef<HTMLCanvasElement>(null);
|
|
60
|
+
|
|
61
|
+
useEffect(() => {
|
|
62
|
+
const onResize = debounce(() => resizeCanvas(canvasElm.current), 100);
|
|
63
|
+
window.addEventListener("resize", onResize);
|
|
64
|
+
return () => {
|
|
65
|
+
window.removeEventListener("resize", onResize);
|
|
66
|
+
};
|
|
67
|
+
}, []);
|
|
68
|
+
|
|
69
|
+
return React.createElement("canvas", {
|
|
70
|
+
...rest,
|
|
71
|
+
id: contextIdToId(contextId),
|
|
72
|
+
style: {
|
|
73
|
+
...styles.view,
|
|
74
|
+
...styles.flex1,
|
|
75
|
+
...(transparent === false ? { backgroundColor: "white" } : {}),
|
|
76
|
+
...(typeof style === "object" ? style : {}),
|
|
77
|
+
},
|
|
78
|
+
ref: (ref: HTMLCanvasElement) => {
|
|
79
|
+
canvasElm.current = ref;
|
|
80
|
+
if (ref) {
|
|
81
|
+
resizeCanvas(ref);
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const styles = StyleSheet.create({
|
|
88
|
+
flex1: {
|
|
89
|
+
flex: 1,
|
|
90
|
+
},
|
|
91
|
+
view: {
|
|
92
|
+
alignItems: "stretch",
|
|
93
|
+
backgroundColor: "transparent",
|
|
94
|
+
border: "0 solid black",
|
|
95
|
+
boxSizing: "border-box",
|
|
96
|
+
display: "flex",
|
|
97
|
+
flexBasis: "auto",
|
|
98
|
+
flexDirection: "column",
|
|
99
|
+
flexShrink: 0,
|
|
100
|
+
listStyle: "none",
|
|
101
|
+
margin: 0,
|
|
102
|
+
minHeight: 0,
|
|
103
|
+
minWidth: 0,
|
|
104
|
+
padding: 0,
|
|
105
|
+
position: "relative",
|
|
106
|
+
zIndex: 0,
|
|
107
|
+
},
|
|
108
|
+
});
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import React, { useImperativeHandle, useRef, useState } from "react";
|
|
2
|
+
import type { ViewProps } from "react-native";
|
|
3
|
+
import { View, Platform } from "react-native";
|
|
4
|
+
|
|
5
|
+
import WebGPUNativeView from "../specs/WebGPUViewNativeComponent";
|
|
6
|
+
|
|
7
|
+
let CONTEXT_COUNTER = 1;
|
|
8
|
+
function generateContextId() {
|
|
9
|
+
return CONTEXT_COUNTER++;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
declare global {
|
|
13
|
+
var RNWebGPU: {
|
|
14
|
+
gpu: GPU;
|
|
15
|
+
fabric: boolean;
|
|
16
|
+
getNativeSurface: (contextId: number) => NativeCanvas;
|
|
17
|
+
MakeWebGPUCanvasContext: (
|
|
18
|
+
contextId: number,
|
|
19
|
+
width: number,
|
|
20
|
+
height: number
|
|
21
|
+
) => RNCanvasContext;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
type SurfacePointer = bigint;
|
|
26
|
+
|
|
27
|
+
export interface NativeCanvas {
|
|
28
|
+
surface: SurfacePointer;
|
|
29
|
+
width: number;
|
|
30
|
+
height: number;
|
|
31
|
+
clientWidth: number;
|
|
32
|
+
clientHeight: number;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export type RNCanvasContext = GPUCanvasContext & {
|
|
36
|
+
present: () => void;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
export interface WebGPUCanvasRef {
|
|
40
|
+
getContextId: () => number;
|
|
41
|
+
getContext(contextName: "webgpu"): RNCanvasContext | null;
|
|
42
|
+
getNativeSurface: () => NativeCanvas;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
interface WebGPUCanvasProps extends ViewProps {
|
|
46
|
+
transparent?: boolean;
|
|
47
|
+
ref?: React.Ref<WebGPUCanvasRef>;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export const WebGPUCanvas = ({
|
|
51
|
+
transparent,
|
|
52
|
+
ref,
|
|
53
|
+
...props
|
|
54
|
+
}: WebGPUCanvasProps) => {
|
|
55
|
+
const viewRef = useRef(null);
|
|
56
|
+
const [contextId] = useState(() => generateContextId());
|
|
57
|
+
|
|
58
|
+
useImperativeHandle(ref, () => ({
|
|
59
|
+
getContextId: () => contextId,
|
|
60
|
+
getNativeSurface: () => {
|
|
61
|
+
if (typeof RNWebGPU === "undefined") {
|
|
62
|
+
throw new Error(
|
|
63
|
+
"[WebGPU] RNWebGPU is not available. Make sure SK_GRAPHITE is enabled."
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
return RNWebGPU.getNativeSurface(contextId);
|
|
67
|
+
},
|
|
68
|
+
getContext(contextName: "webgpu"): RNCanvasContext | null {
|
|
69
|
+
if (contextName !== "webgpu") {
|
|
70
|
+
throw new Error(`[WebGPU] Unsupported context: ${contextName}`);
|
|
71
|
+
}
|
|
72
|
+
if (!viewRef.current) {
|
|
73
|
+
throw new Error("[WebGPU] Cannot get context before mount");
|
|
74
|
+
}
|
|
75
|
+
if (typeof RNWebGPU === "undefined") {
|
|
76
|
+
throw new Error(
|
|
77
|
+
"[WebGPU] RNWebGPU is not available. Make sure SK_GRAPHITE is enabled."
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
// getBoundingClientRect became stable in RN 0.83
|
|
81
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
82
|
+
const view = viewRef.current as any;
|
|
83
|
+
const size =
|
|
84
|
+
"getBoundingClientRect" in view
|
|
85
|
+
? view.getBoundingClientRect()
|
|
86
|
+
: view.unstable_getBoundingClientRect();
|
|
87
|
+
return RNWebGPU.MakeWebGPUCanvasContext(
|
|
88
|
+
contextId,
|
|
89
|
+
size.width,
|
|
90
|
+
size.height
|
|
91
|
+
);
|
|
92
|
+
},
|
|
93
|
+
}));
|
|
94
|
+
|
|
95
|
+
// WebGPU Canvas is not supported on web
|
|
96
|
+
if (Platform.OS === "web") {
|
|
97
|
+
return <View {...props} />;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
return (
|
|
101
|
+
<View collapsable={false} ref={viewRef} {...props}>
|
|
102
|
+
<WebGPUNativeView
|
|
103
|
+
style={{ flex: 1 }}
|
|
104
|
+
contextId={contextId}
|
|
105
|
+
transparent={!!transparent}
|
|
106
|
+
/>
|
|
107
|
+
</View>
|
|
108
|
+
);
|
|
109
|
+
};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { ViewProps } from "react-native";
|
|
3
|
+
|
|
4
|
+
export interface NativeCanvas {
|
|
5
|
+
surface: bigint;
|
|
6
|
+
width: number;
|
|
7
|
+
height: number;
|
|
8
|
+
clientWidth: number;
|
|
9
|
+
clientHeight: number;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export type RNCanvasContext = GPUCanvasContext & {
|
|
13
|
+
present: () => void;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export interface WebGPUCanvasRef {
|
|
17
|
+
getContextId: () => number;
|
|
18
|
+
getContext(contextName: "webgpu"): RNCanvasContext | null;
|
|
19
|
+
getNativeSurface: () => NativeCanvas;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
interface WebGPUCanvasProps extends ViewProps {
|
|
23
|
+
transparent?: boolean;
|
|
24
|
+
ref?: React.Ref<WebGPUCanvasRef>;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// WebGPU Canvas is not supported on web
|
|
28
|
+
export const WebGPUCanvas = ({
|
|
29
|
+
transparent: _transparent,
|
|
30
|
+
ref: _ref,
|
|
31
|
+
...props
|
|
32
|
+
}: WebGPUCanvasProps) => {
|
|
33
|
+
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
|
|
34
|
+
// @ts-expect-error
|
|
35
|
+
return <div {...props} />;
|
|
36
|
+
};
|
package/src/views/index.ts
CHANGED