@shopify/react-native-skia 2.5.2 → 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 (115) hide show
  1. package/android/CMakeLists.txt +4 -0
  2. package/android/cpp/jni/JniWebGPUView.cpp +67 -0
  3. package/android/cpp/rnskia-android/SkiaPlatformContext.h +26 -0
  4. package/android/src/main/java/com/shopify/reactnative/skia/RNSkiaPackage.java +4 -1
  5. package/android/src/main/java/com/shopify/reactnative/skia/WebGPUSurfaceView.java +41 -0
  6. package/android/src/main/java/com/shopify/reactnative/skia/WebGPUTextureView.java +44 -0
  7. package/android/src/main/java/com/shopify/reactnative/skia/WebGPUView.java +95 -0
  8. package/android/src/main/java/com/shopify/reactnative/skia/WebGPUViewAPI.java +14 -0
  9. package/android/src/main/java/com/shopify/reactnative/skia/WebGPUViewManager.java +58 -0
  10. package/apple/RNSkUIKit.h +13 -0
  11. package/apple/SkiaPlatformContext.h +20 -0
  12. package/apple/SkiaPlatformContext.mm +21 -0
  13. package/apple/WebGPUMetalView.h +12 -0
  14. package/apple/WebGPUMetalView.mm +93 -0
  15. package/apple/WebGPUView.h +20 -0
  16. package/apple/WebGPUView.mm +77 -0
  17. package/cpp/jsi2/JSIConverter.h +11 -0
  18. package/cpp/rnskia/RNSkManager.cpp +11 -4
  19. package/cpp/rnwgpu/Canvas.h +45 -0
  20. package/cpp/rnwgpu/PlatformContext.h +18 -0
  21. package/cpp/rnwgpu/SurfaceRegistry.h +229 -0
  22. package/cpp/rnwgpu/api/GPUAdapter.cpp +26 -0
  23. package/cpp/rnwgpu/api/GPUCanvasContext.cpp +64 -0
  24. package/cpp/rnwgpu/api/GPUCanvasContext.h +65 -0
  25. package/cpp/rnwgpu/api/GPUDevice.cpp +52 -0
  26. package/cpp/rnwgpu/api/GPUDevice.h +62 -1
  27. package/cpp/rnwgpu/api/GPUUncapturedErrorEvent.h +61 -0
  28. package/cpp/rnwgpu/api/RNWebGPU.h +62 -0
  29. package/cpp/rnwgpu/api/descriptors/GPUBindGroupEntry.h +4 -0
  30. package/cpp/rnwgpu/api/descriptors/GPUCanvasConfiguration.h +76 -0
  31. package/lib/commonjs/external/reanimated/useVideo.js +1 -4
  32. package/lib/commonjs/external/reanimated/useVideo.js.map +1 -1
  33. package/lib/commonjs/mock/index.js +1 -0
  34. package/lib/commonjs/mock/index.js.map +1 -1
  35. package/lib/commonjs/skia/types/Surface/SurfaceFactory.js.map +1 -1
  36. package/lib/commonjs/sksg/Container.native.js +4 -0
  37. package/lib/commonjs/sksg/Container.native.js.map +1 -1
  38. package/lib/commonjs/sksg/Container.web.js +4 -0
  39. package/lib/commonjs/sksg/Container.web.js.map +1 -1
  40. package/lib/commonjs/specs/WebGPUViewNativeComponent.d.ts +8 -0
  41. package/lib/commonjs/specs/WebGPUViewNativeComponent.js +11 -0
  42. package/lib/commonjs/specs/WebGPUViewNativeComponent.js.map +1 -0
  43. package/lib/commonjs/specs/WebGPUViewNativeComponent.web.d.ts +8 -0
  44. package/lib/commonjs/specs/WebGPUViewNativeComponent.web.js +101 -0
  45. package/lib/commonjs/specs/WebGPUViewNativeComponent.web.js.map +1 -0
  46. package/lib/commonjs/specs/utils.d.ts +1 -0
  47. package/lib/commonjs/specs/utils.js +11 -0
  48. package/lib/commonjs/specs/utils.js.map +1 -0
  49. package/lib/commonjs/views/WebGPUCanvas.d.ts +32 -0
  50. package/lib/commonjs/views/WebGPUCanvas.js +66 -0
  51. package/lib/commonjs/views/WebGPUCanvas.js.map +1 -0
  52. package/lib/commonjs/views/WebGPUCanvas.web.d.ts +23 -0
  53. package/lib/commonjs/views/WebGPUCanvas.web.js +20 -0
  54. package/lib/commonjs/views/WebGPUCanvas.web.js.map +1 -0
  55. package/lib/commonjs/views/index.d.ts +1 -0
  56. package/lib/commonjs/views/index.js +11 -0
  57. package/lib/commonjs/views/index.js.map +1 -1
  58. package/lib/module/external/reanimated/useVideo.js +1 -4
  59. package/lib/module/external/reanimated/useVideo.js.map +1 -1
  60. package/lib/module/mock/index.js +1 -0
  61. package/lib/module/mock/index.js.map +1 -1
  62. package/lib/module/skia/types/Surface/SurfaceFactory.js.map +1 -1
  63. package/lib/module/sksg/Container.native.js +5 -0
  64. package/lib/module/sksg/Container.native.js.map +1 -1
  65. package/lib/module/sksg/Container.web.js +5 -0
  66. package/lib/module/sksg/Container.web.js.map +1 -1
  67. package/lib/module/specs/WebGPUViewNativeComponent.d.ts +8 -0
  68. package/lib/module/specs/WebGPUViewNativeComponent.js +4 -0
  69. package/lib/module/specs/WebGPUViewNativeComponent.js.map +1 -0
  70. package/lib/module/specs/WebGPUViewNativeComponent.web.d.ts +8 -0
  71. package/lib/module/specs/WebGPUViewNativeComponent.web.js +94 -0
  72. package/lib/module/specs/WebGPUViewNativeComponent.web.js.map +1 -0
  73. package/lib/module/specs/utils.d.ts +1 -0
  74. package/lib/module/specs/utils.js +5 -0
  75. package/lib/module/specs/utils.js.map +1 -0
  76. package/lib/module/views/WebGPUCanvas.d.ts +32 -0
  77. package/lib/module/views/WebGPUCanvas.js +57 -0
  78. package/lib/module/views/WebGPUCanvas.js.map +1 -0
  79. package/lib/module/views/WebGPUCanvas.web.d.ts +23 -0
  80. package/lib/module/views/WebGPUCanvas.web.js +12 -0
  81. package/lib/module/views/WebGPUCanvas.web.js.map +1 -0
  82. package/lib/module/views/index.d.ts +1 -0
  83. package/lib/module/views/index.js +1 -0
  84. package/lib/module/views/index.js.map +1 -1
  85. package/lib/typescript/lib/commonjs/mock/index.d.ts +1 -0
  86. package/lib/typescript/lib/commonjs/specs/WebGPUViewNativeComponent.d.ts +3 -0
  87. package/lib/typescript/lib/commonjs/specs/WebGPUViewNativeComponent.web.d.ts +3 -0
  88. package/lib/typescript/lib/commonjs/specs/utils.d.ts +2 -0
  89. package/lib/typescript/lib/commonjs/views/WebGPUCanvas.d.ts +6 -0
  90. package/lib/typescript/lib/commonjs/views/WebGPUCanvas.web.d.ts +6 -0
  91. package/lib/typescript/lib/module/mock/index.d.ts +3 -1
  92. package/lib/typescript/lib/module/specs/WebGPUViewNativeComponent.d.ts +2 -0
  93. package/lib/typescript/lib/module/specs/WebGPUViewNativeComponent.web.d.ts +2 -0
  94. package/lib/typescript/lib/module/specs/utils.d.ts +1 -0
  95. package/lib/typescript/lib/module/views/WebGPUCanvas.d.ts +7 -0
  96. package/lib/typescript/lib/module/views/WebGPUCanvas.web.d.ts +8 -0
  97. package/lib/typescript/lib/module/views/index.d.ts +1 -0
  98. package/lib/typescript/src/specs/WebGPUViewNativeComponent.d.ts +8 -0
  99. package/lib/typescript/src/specs/WebGPUViewNativeComponent.web.d.ts +8 -0
  100. package/lib/typescript/src/specs/utils.d.ts +1 -0
  101. package/lib/typescript/src/views/WebGPUCanvas.d.ts +32 -0
  102. package/lib/typescript/src/views/WebGPUCanvas.web.d.ts +23 -0
  103. package/lib/typescript/src/views/index.d.ts +1 -0
  104. package/package.json +3 -2
  105. package/src/external/reanimated/useVideo.ts +1 -4
  106. package/src/mock/index.ts +1 -0
  107. package/src/skia/types/Surface/SurfaceFactory.ts +5 -1
  108. package/src/sksg/Container.native.ts +3 -0
  109. package/src/sksg/Container.web.ts +3 -0
  110. package/src/specs/WebGPUViewNativeComponent.ts +11 -0
  111. package/src/specs/WebGPUViewNativeComponent.web.ts +108 -0
  112. package/src/specs/utils.ts +4 -0
  113. package/src/views/WebGPUCanvas.tsx +109 -0
  114. package/src/views/WebGPUCanvas.web.tsx +36 -0
  115. package/src/views/index.ts +1 -0
@@ -0,0 +1,57 @@
1
+ function _extends() { return _extends = Object.assign ? Object.assign.bind() : function (n) { for (var e = 1; e < arguments.length; e++) { var t = arguments[e]; for (var r in t) ({}).hasOwnProperty.call(t, r) && (n[r] = t[r]); } return n; }, _extends.apply(null, arguments); }
2
+ import React, { useImperativeHandle, useRef, useState } from "react";
3
+ import { View, Platform } from "react-native";
4
+ import WebGPUNativeView from "../specs/WebGPUViewNativeComponent";
5
+ let CONTEXT_COUNTER = 1;
6
+ function generateContextId() {
7
+ return CONTEXT_COUNTER++;
8
+ }
9
+ export const WebGPUCanvas = ({
10
+ transparent,
11
+ ref,
12
+ ...props
13
+ }) => {
14
+ const viewRef = useRef(null);
15
+ const [contextId] = useState(() => generateContextId());
16
+ useImperativeHandle(ref, () => ({
17
+ getContextId: () => contextId,
18
+ getNativeSurface: () => {
19
+ if (typeof RNWebGPU === "undefined") {
20
+ throw new Error("[WebGPU] RNWebGPU is not available. Make sure SK_GRAPHITE is enabled.");
21
+ }
22
+ return RNWebGPU.getNativeSurface(contextId);
23
+ },
24
+ getContext(contextName) {
25
+ if (contextName !== "webgpu") {
26
+ throw new Error(`[WebGPU] Unsupported context: ${contextName}`);
27
+ }
28
+ if (!viewRef.current) {
29
+ throw new Error("[WebGPU] Cannot get context before mount");
30
+ }
31
+ if (typeof RNWebGPU === "undefined") {
32
+ throw new Error("[WebGPU] RNWebGPU is not available. Make sure SK_GRAPHITE is enabled.");
33
+ }
34
+ // getBoundingClientRect became stable in RN 0.83
35
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
36
+ const view = viewRef.current;
37
+ const size = "getBoundingClientRect" in view ? view.getBoundingClientRect() : view.unstable_getBoundingClientRect();
38
+ return RNWebGPU.MakeWebGPUCanvasContext(contextId, size.width, size.height);
39
+ }
40
+ }));
41
+
42
+ // WebGPU Canvas is not supported on web
43
+ if (Platform.OS === "web") {
44
+ return /*#__PURE__*/React.createElement(View, props);
45
+ }
46
+ return /*#__PURE__*/React.createElement(View, _extends({
47
+ collapsable: false,
48
+ ref: viewRef
49
+ }, props), /*#__PURE__*/React.createElement(WebGPUNativeView, {
50
+ style: {
51
+ flex: 1
52
+ },
53
+ contextId: contextId,
54
+ transparent: !!transparent
55
+ }));
56
+ };
57
+ //# sourceMappingURL=WebGPUCanvas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["React","useImperativeHandle","useRef","useState","View","Platform","WebGPUNativeView","CONTEXT_COUNTER","generateContextId","WebGPUCanvas","transparent","ref","props","viewRef","contextId","getContextId","getNativeSurface","RNWebGPU","Error","getContext","contextName","current","view","size","getBoundingClientRect","unstable_getBoundingClientRect","MakeWebGPUCanvasContext","width","height","OS","createElement","_extends","collapsable","style","flex"],"sources":["WebGPUCanvas.tsx"],"sourcesContent":["import React, { useImperativeHandle, useRef, useState } from \"react\";\nimport type { ViewProps } from \"react-native\";\nimport { View, Platform } from \"react-native\";\n\nimport WebGPUNativeView from \"../specs/WebGPUViewNativeComponent\";\n\nlet CONTEXT_COUNTER = 1;\nfunction generateContextId() {\n return CONTEXT_COUNTER++;\n}\n\ndeclare global {\n var RNWebGPU: {\n gpu: GPU;\n fabric: boolean;\n getNativeSurface: (contextId: number) => NativeCanvas;\n MakeWebGPUCanvasContext: (\n contextId: number,\n width: number,\n height: number\n ) => RNCanvasContext;\n };\n}\n\ntype SurfacePointer = bigint;\n\nexport interface NativeCanvas {\n surface: SurfacePointer;\n width: number;\n height: number;\n clientWidth: number;\n clientHeight: number;\n}\n\nexport type RNCanvasContext = GPUCanvasContext & {\n present: () => void;\n};\n\nexport interface WebGPUCanvasRef {\n getContextId: () => number;\n getContext(contextName: \"webgpu\"): RNCanvasContext | null;\n getNativeSurface: () => NativeCanvas;\n}\n\ninterface WebGPUCanvasProps extends ViewProps {\n transparent?: boolean;\n ref?: React.Ref<WebGPUCanvasRef>;\n}\n\nexport const WebGPUCanvas = ({\n transparent,\n ref,\n ...props\n}: WebGPUCanvasProps) => {\n const viewRef = useRef(null);\n const [contextId] = useState(() => generateContextId());\n\n useImperativeHandle(ref, () => ({\n getContextId: () => contextId,\n getNativeSurface: () => {\n if (typeof RNWebGPU === \"undefined\") {\n throw new Error(\n \"[WebGPU] RNWebGPU is not available. Make sure SK_GRAPHITE is enabled.\"\n );\n }\n return RNWebGPU.getNativeSurface(contextId);\n },\n getContext(contextName: \"webgpu\"): RNCanvasContext | null {\n if (contextName !== \"webgpu\") {\n throw new Error(`[WebGPU] Unsupported context: ${contextName}`);\n }\n if (!viewRef.current) {\n throw new Error(\"[WebGPU] Cannot get context before mount\");\n }\n if (typeof RNWebGPU === \"undefined\") {\n throw new Error(\n \"[WebGPU] RNWebGPU is not available. Make sure SK_GRAPHITE is enabled.\"\n );\n }\n // getBoundingClientRect became stable in RN 0.83\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const view = viewRef.current as any;\n const size =\n \"getBoundingClientRect\" in view\n ? view.getBoundingClientRect()\n : view.unstable_getBoundingClientRect();\n return RNWebGPU.MakeWebGPUCanvasContext(\n contextId,\n size.width,\n size.height\n );\n },\n }));\n\n // WebGPU Canvas is not supported on web\n if (Platform.OS === \"web\") {\n return <View {...props} />;\n }\n\n return (\n <View collapsable={false} ref={viewRef} {...props}>\n <WebGPUNativeView\n style={{ flex: 1 }}\n contextId={contextId}\n transparent={!!transparent}\n />\n </View>\n );\n};\n"],"mappings":";AAAA,OAAOA,KAAK,IAAIC,mBAAmB,EAAEC,MAAM,EAAEC,QAAQ,QAAQ,OAAO;AAEpE,SAASC,IAAI,EAAEC,QAAQ,QAAQ,cAAc;AAE7C,OAAOC,gBAAgB,MAAM,oCAAoC;AAEjE,IAAIC,eAAe,GAAG,CAAC;AACvB,SAASC,iBAAiBA,CAAA,EAAG;EAC3B,OAAOD,eAAe,EAAE;AAC1B;AAwCA,OAAO,MAAME,YAAY,GAAGA,CAAC;EAC3BC,WAAW;EACXC,GAAG;EACH,GAAGC;AACc,CAAC,KAAK;EACvB,MAAMC,OAAO,GAAGX,MAAM,CAAC,IAAI,CAAC;EAC5B,MAAM,CAACY,SAAS,CAAC,GAAGX,QAAQ,CAAC,MAAMK,iBAAiB,CAAC,CAAC,CAAC;EAEvDP,mBAAmB,CAACU,GAAG,EAAE,OAAO;IAC9BI,YAAY,EAAEA,CAAA,KAAMD,SAAS;IAC7BE,gBAAgB,EAAEA,CAAA,KAAM;MACtB,IAAI,OAAOC,QAAQ,KAAK,WAAW,EAAE;QACnC,MAAM,IAAIC,KAAK,CACb,uEACF,CAAC;MACH;MACA,OAAOD,QAAQ,CAACD,gBAAgB,CAACF,SAAS,CAAC;IAC7C,CAAC;IACDK,UAAUA,CAACC,WAAqB,EAA0B;MACxD,IAAIA,WAAW,KAAK,QAAQ,EAAE;QAC5B,MAAM,IAAIF,KAAK,CAAC,iCAAiCE,WAAW,EAAE,CAAC;MACjE;MACA,IAAI,CAACP,OAAO,CAACQ,OAAO,EAAE;QACpB,MAAM,IAAIH,KAAK,CAAC,0CAA0C,CAAC;MAC7D;MACA,IAAI,OAAOD,QAAQ,KAAK,WAAW,EAAE;QACnC,MAAM,IAAIC,KAAK,CACb,uEACF,CAAC;MACH;MACA;MACA;MACA,MAAMI,IAAI,GAAGT,OAAO,CAACQ,OAAc;MACnC,MAAME,IAAI,GACR,uBAAuB,IAAID,IAAI,GAC3BA,IAAI,CAACE,qBAAqB,CAAC,CAAC,GAC5BF,IAAI,CAACG,8BAA8B,CAAC,CAAC;MAC3C,OAAOR,QAAQ,CAACS,uBAAuB,CACrCZ,SAAS,EACTS,IAAI,CAACI,KAAK,EACVJ,IAAI,CAACK,MACP,CAAC;IACH;EACF,CAAC,CAAC,CAAC;;EAEH;EACA,IAAIvB,QAAQ,CAACwB,EAAE,KAAK,KAAK,EAAE;IACzB,oBAAO7B,KAAA,CAAA8B,aAAA,CAAC1B,IAAI,EAAKQ,KAAQ,CAAC;EAC5B;EAEA,oBACEZ,KAAA,CAAA8B,aAAA,CAAC1B,IAAI,EAAA2B,QAAA;IAACC,WAAW,EAAE,KAAM;IAACrB,GAAG,EAAEE;EAAQ,GAAKD,KAAK,gBAC/CZ,KAAA,CAAA8B,aAAA,CAACxB,gBAAgB;IACf2B,KAAK,EAAE;MAAEC,IAAI,EAAE;IAAE,CAAE;IACnBpB,SAAS,EAAEA,SAAU;IACrBJ,WAAW,EAAE,CAAC,CAACA;EAAY,CAC5B,CACG,CAAC;AAEX,CAAC","ignoreList":[]}
@@ -0,0 +1,23 @@
1
+ import React from "react";
2
+ import type { ViewProps } from "react-native";
3
+ export interface NativeCanvas {
4
+ surface: bigint;
5
+ width: number;
6
+ height: number;
7
+ clientWidth: number;
8
+ clientHeight: number;
9
+ }
10
+ export type RNCanvasContext = GPUCanvasContext & {
11
+ present: () => void;
12
+ };
13
+ export interface WebGPUCanvasRef {
14
+ getContextId: () => number;
15
+ getContext(contextName: "webgpu"): RNCanvasContext | null;
16
+ getNativeSurface: () => NativeCanvas;
17
+ }
18
+ interface WebGPUCanvasProps extends ViewProps {
19
+ transparent?: boolean;
20
+ ref?: React.Ref<WebGPUCanvasRef>;
21
+ }
22
+ export declare const WebGPUCanvas: ({ transparent: _transparent, ref: _ref, ...props }: WebGPUCanvasProps) => React.JSX.Element;
23
+ export {};
@@ -0,0 +1,12 @@
1
+ import React from "react";
2
+ // WebGPU Canvas is not supported on web
3
+ export const WebGPUCanvas = ({
4
+ transparent: _transparent,
5
+ ref: _ref,
6
+ ...props
7
+ }) => {
8
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
9
+ // @ts-expect-error
10
+ return /*#__PURE__*/React.createElement("div", props);
11
+ };
12
+ //# sourceMappingURL=WebGPUCanvas.web.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["React","WebGPUCanvas","transparent","_transparent","ref","_ref","props","createElement"],"sources":["WebGPUCanvas.web.tsx"],"sourcesContent":["import React from \"react\";\nimport type { ViewProps } from \"react-native\";\n\nexport interface NativeCanvas {\n surface: bigint;\n width: number;\n height: number;\n clientWidth: number;\n clientHeight: number;\n}\n\nexport type RNCanvasContext = GPUCanvasContext & {\n present: () => void;\n};\n\nexport interface WebGPUCanvasRef {\n getContextId: () => number;\n getContext(contextName: \"webgpu\"): RNCanvasContext | null;\n getNativeSurface: () => NativeCanvas;\n}\n\ninterface WebGPUCanvasProps extends ViewProps {\n transparent?: boolean;\n ref?: React.Ref<WebGPUCanvasRef>;\n}\n\n// WebGPU Canvas is not supported on web\nexport const WebGPUCanvas = ({\n transparent: _transparent,\n ref: _ref,\n ...props\n}: WebGPUCanvasProps) => {\n // eslint-disable-next-line @typescript-eslint/ban-ts-comment\n // @ts-expect-error\n return <div {...props} />;\n};\n"],"mappings":"AAAA,OAAOA,KAAK,MAAM,OAAO;AA0BzB;AACA,OAAO,MAAMC,YAAY,GAAGA,CAAC;EAC3BC,WAAW,EAAEC,YAAY;EACzBC,GAAG,EAAEC,IAAI;EACT,GAAGC;AACc,CAAC,KAAK;EACvB;EACA;EACA,oBAAON,KAAA,CAAAO,aAAA,QAASD,KAAQ,CAAC;AAC3B,CAAC","ignoreList":[]}
@@ -1,2 +1,3 @@
1
1
  export * from "./SkiaPictureView";
2
2
  export * from "./types";
3
+ export * from "./WebGPUCanvas";
@@ -1,3 +1,4 @@
1
1
  export * from "./SkiaPictureView";
2
2
  export * from "./types";
3
+ export * from "./WebGPUCanvas";
3
4
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":[],"sources":["index.ts"],"sourcesContent":["export * from \"./SkiaPictureView\";\nexport * from \"./types\";\n"],"mappings":"AAAA,cAAc,mBAAmB;AACjC,cAAc,SAAS","ignoreList":[]}
1
+ {"version":3,"names":[],"sources":["index.ts"],"sourcesContent":["export * from \"./SkiaPictureView\";\nexport * from \"./types\";\nexport * from \"./WebGPUCanvas\";\n"],"mappings":"AAAA,cAAc,mBAAmB;AACjC,cAAc,SAAS;AACvB,cAAc,gBAAgB","ignoreList":[]}
@@ -1,6 +1,7 @@
1
1
  export const __esModule: boolean;
2
2
  export function Mock(CanvasKit: any): {
3
3
  Canvas: typeof import("react-native").View;
4
+ WebGPUCanvas: typeof import("react-native").View;
4
5
  SkiaPictureView: typeof import("react-native").View;
5
6
  JsiSkImage: typeof _JsiSkImage.JsiSkImage;
6
7
  drawAsPicture: () => undefined;
@@ -0,0 +1,3 @@
1
+ export const __esModule: boolean;
2
+ declare const _default: any;
3
+ export default _default;
@@ -0,0 +1,3 @@
1
+ export const __esModule: boolean;
2
+ export default WebGPUViewNativeComponent;
3
+ declare function WebGPUViewNativeComponent(props: any): any;
@@ -0,0 +1,2 @@
1
+ export const __esModule: boolean;
2
+ export function contextIdToId(contextId: any): string;
@@ -0,0 +1,6 @@
1
+ export const __esModule: boolean;
2
+ export function WebGPUCanvas({ transparent, ref, ...props }: {
3
+ [x: string]: any;
4
+ transparent: any;
5
+ ref: any;
6
+ }): any;
@@ -0,0 +1,6 @@
1
+ export const __esModule: boolean;
2
+ export function WebGPUCanvas({ transparent: _transparent, ref: _ref, ...props }: {
3
+ [x: string]: any;
4
+ transparent: any;
5
+ ref: any;
6
+ }): any;
@@ -1,5 +1,6 @@
1
1
  export function Mock(CanvasKit: any): {
2
2
  Canvas: typeof import("react-native").View;
3
+ WebGPUCanvas: typeof import("react-native").View;
3
4
  SkiaPictureView: typeof import("react-native").View;
4
5
  JsiSkImage: typeof JsiSkImage;
5
6
  drawAsPicture: () => undefined;
@@ -128,7 +129,8 @@ export function Mock(CanvasKit: any): {
128
129
  isEdge: (pos: any, b: any) => boolean;
129
130
  processRect: (Skia: any, def: any) => any;
130
131
  processRRect: (Skia: any, def: any) => any;
131
- inflate: (Skia: any, box: any, dx: any, dy: any, tx?: number, ty?: number) => any;
132
+ inflate: (Skia: any, box: any, dx: any, dy: any, tx?: number, // Reanimated hooks
133
+ ty?: number) => any;
132
134
  deflate: (Skia: any, box: any, dx: any, dy: any, tx?: number, ty?: number) => any;
133
135
  processRadius: (Skia: any, radius: any) => any;
134
136
  isCircleScalarDef: (def: any) => boolean;
@@ -0,0 +1,2 @@
1
+ declare const _default: import("react-native/Libraries/Utilities/codegenNativeComponent").NativeComponentType<object>;
2
+ export default _default;
@@ -0,0 +1,2 @@
1
+ export default function WebGPUViewNativeComponent(props: any): React.DetailedReactHTMLElement<any, HTMLElement>;
2
+ import React from "react";
@@ -0,0 +1 @@
1
+ export function contextIdToId(contextId: any): string;
@@ -0,0 +1,7 @@
1
+ export function WebGPUCanvas({ transparent, ref, ...props }: {
2
+ [x: string]: any;
3
+ transparent: any;
4
+ ref: any;
5
+ }): React.CElement<import("react-native").ViewProps, View>;
6
+ import { View } from "react-native";
7
+ import React from "react";
@@ -0,0 +1,8 @@
1
+ export function WebGPUCanvas({ transparent: _transparent, ref: _ref, ...props }: {
2
+ [x: string]: any;
3
+ transparent: any;
4
+ ref: any;
5
+ }): React.DetailedReactHTMLElement<{
6
+ [x: string]: any;
7
+ }, HTMLElement>;
8
+ import React from "react";
@@ -1,2 +1,3 @@
1
1
  export * from "./SkiaPictureView";
2
2
  export * from "./types";
3
+ export * from "./WebGPUCanvas";
@@ -0,0 +1,8 @@
1
+ import type { Int32 } from "react-native/Libraries/Types/CodegenTypes";
2
+ import type { ViewProps } from "react-native";
3
+ export interface NativeProps extends ViewProps {
4
+ contextId: Int32;
5
+ transparent: boolean;
6
+ }
7
+ declare const _default: import("react-native/Libraries/Utilities/codegenNativeComponent").NativeComponentType<NativeProps>;
8
+ export default _default;
@@ -0,0 +1,8 @@
1
+ import React from "react";
2
+ import type { Int32 } from "react-native/Libraries/Types/CodegenTypes";
3
+ import type { ViewProps } from "react-native";
4
+ export interface NativeProps extends ViewProps {
5
+ contextId: Int32;
6
+ transparent: boolean;
7
+ }
8
+ export default function WebGPUViewNativeComponent(props: NativeProps): React.JSX.Element;
@@ -0,0 +1 @@
1
+ export declare function contextIdToId(contextId: number): string;
@@ -0,0 +1,32 @@
1
+ import React from "react";
2
+ import type { ViewProps } from "react-native";
3
+ declare global {
4
+ var RNWebGPU: {
5
+ gpu: GPU;
6
+ fabric: boolean;
7
+ getNativeSurface: (contextId: number) => NativeCanvas;
8
+ MakeWebGPUCanvasContext: (contextId: number, width: number, height: number) => RNCanvasContext;
9
+ };
10
+ }
11
+ type SurfacePointer = bigint;
12
+ export interface NativeCanvas {
13
+ surface: SurfacePointer;
14
+ width: number;
15
+ height: number;
16
+ clientWidth: number;
17
+ clientHeight: number;
18
+ }
19
+ export type RNCanvasContext = GPUCanvasContext & {
20
+ present: () => void;
21
+ };
22
+ export interface WebGPUCanvasRef {
23
+ getContextId: () => number;
24
+ getContext(contextName: "webgpu"): RNCanvasContext | null;
25
+ getNativeSurface: () => NativeCanvas;
26
+ }
27
+ interface WebGPUCanvasProps extends ViewProps {
28
+ transparent?: boolean;
29
+ ref?: React.Ref<WebGPUCanvasRef>;
30
+ }
31
+ export declare const WebGPUCanvas: ({ transparent, ref, ...props }: WebGPUCanvasProps) => React.JSX.Element;
32
+ export {};
@@ -0,0 +1,23 @@
1
+ import React from "react";
2
+ import type { ViewProps } from "react-native";
3
+ export interface NativeCanvas {
4
+ surface: bigint;
5
+ width: number;
6
+ height: number;
7
+ clientWidth: number;
8
+ clientHeight: number;
9
+ }
10
+ export type RNCanvasContext = GPUCanvasContext & {
11
+ present: () => void;
12
+ };
13
+ export interface WebGPUCanvasRef {
14
+ getContextId: () => number;
15
+ getContext(contextName: "webgpu"): RNCanvasContext | null;
16
+ getNativeSurface: () => NativeCanvas;
17
+ }
18
+ interface WebGPUCanvasProps extends ViewProps {
19
+ transparent?: boolean;
20
+ ref?: React.Ref<WebGPUCanvasRef>;
21
+ }
22
+ export declare const WebGPUCanvas: ({ transparent: _transparent, ref: _ref, ...props }: WebGPUCanvasProps) => React.JSX.Element;
23
+ export {};
@@ -1,2 +1,3 @@
1
1
  export * from "./SkiaPictureView";
2
2
  export * from "./types";
3
+ export * from "./WebGPUCanvas";
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "setup-skia-web": "scripts/setup-canvaskit.js"
10
10
  },
11
11
  "title": "React Native Skia",
12
- "version": "2.5.2",
12
+ "version": "2.5.3",
13
13
  "description": "High-performance React Native Graphics using Skia",
14
14
  "main": "lib/module/index.js",
15
15
  "react-native": "src/index.ts",
@@ -147,7 +147,8 @@
147
147
  },
148
148
  "ios": {
149
149
  "componentProvider": {
150
- "SkiaPictureView": "SkiaPictureView"
150
+ "SkiaPictureView": "SkiaPictureView",
151
+ "WebGPUView": "WebGPUView"
151
152
  }
152
153
  }
153
154
  },
@@ -22,7 +22,7 @@ const copyFrameOnAndroid = (currentFrame: SharedValue<SkImage | null>) => {
22
22
  if (Platform.OS === "android") {
23
23
  const tex = currentFrame.value;
24
24
  if (tex) {
25
- currentFrame.value = tex.makeNonTextureImage();
25
+ currentFrame.value = tex; //.makeNonTextureImage();
26
26
  tex.dispose();
27
27
  }
28
28
  }
@@ -32,9 +32,6 @@ const setFrame = (video: Video, currentFrame: SharedValue<SkImage | null>) => {
32
32
  "worklet";
33
33
  const img = video.nextImage();
34
34
  if (img) {
35
- if (currentFrame.value) {
36
- currentFrame.value.dispose();
37
- }
38
35
  currentFrame.value = img;
39
36
  copyFrameOnAndroid(currentFrame);
40
37
  }
package/src/mock/index.ts CHANGED
@@ -23,6 +23,7 @@ export const Mock = (CanvasKit: CanvasKit) => {
23
23
  ...require("../dom/types"),
24
24
  ...require("../dom/nodes"),
25
25
  Canvas: require("react-native").View,
26
+ WebGPUCanvas: require("react-native").View,
26
27
  SkiaPictureView: require("react-native").View,
27
28
  JsiSkImage: JsiSkImage,
28
29
  drawAsPicture: Noop,
@@ -27,5 +27,9 @@ export interface SurfaceFactory {
27
27
  * @param height - number of pixels of the height of the drawable area.
28
28
  * @param opts - optional surface options (e.g. colorSpace: "display-p3" | "srgb").
29
29
  */
30
- MakeOffscreen: (width: number, height: number, opts?: SurfaceOptions) => SkSurface | null;
30
+ MakeOffscreen: (
31
+ width: number,
32
+ height: number,
33
+ opts?: SurfaceOptions
34
+ ) => SkSurface | null;
31
35
  }
@@ -10,6 +10,9 @@ import { visit } from "./Recorder/Visitor";
10
10
  import "../skia/NativeSetup";
11
11
  import "../views/api";
12
12
 
13
+ // create local reference for `strictGlobal` option in Worklets
14
+ const { SkiaViewApi } = globalThis;
15
+
13
16
  const nativeDrawOnscreen = (
14
17
  nativeId: number,
15
18
  recorder: JsiRecorder,
@@ -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,4 @@
1
+ // Only used on the web
2
+ export function contextIdToId(contextId: number) {
3
+ return "rnwgpu-canvas-" + contextId;
4
+ }
@@ -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
+ };