From 3c78d909c1ef150b4a01cbeb8488e56e8ef28605 Mon Sep 17 00:00:00 2001 From: William Candillon Date: Thu, 12 Sep 2024 08:22:28 +0200 Subject: [PATCH 1/9] :wrench: --- apps/paper/ios/Podfile.lock | 25 +++++ apps/paper/package.json | 1 + apps/paper/src/App.tsx | 9 ++ apps/paper/src/Examples/WebGPU/WebGPU.tsx | 109 ++++++++++++++++++++++ apps/paper/src/Examples/WebGPU/index.ts | 1 + apps/paper/src/Examples/index.ts | 1 + apps/paper/src/Home/HomeScreen.tsx | 5 + apps/paper/src/types.ts | 1 + yarn.lock | 11 +++ 9 files changed, 163 insertions(+) create mode 100644 apps/paper/src/Examples/WebGPU/WebGPU.tsx create mode 100644 apps/paper/src/Examples/WebGPU/index.ts diff --git a/apps/paper/ios/Podfile.lock b/apps/paper/ios/Podfile.lock index c1c0e67684..41344601be 100644 --- a/apps/paper/ios/Podfile.lock +++ b/apps/paper/ios/Podfile.lock @@ -1283,6 +1283,27 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga + - react-native-wgpu (0.1.5): + - DoubleConversion + - glog + - hermes-engine + - RCT-Folly (= 2024.01.01.00) + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-NativeModulesApple + - React-RCTFabric + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - Yoga - React-nativeconfig (0.75.2) - React-NativeModulesApple (0.75.2): - glog @@ -1697,6 +1718,7 @@ DEPENDENCIES: - react-native-safe-area-context (from `../../../node_modules/react-native-safe-area-context`) - "react-native-skia (from `../../../node_modules/@shopify/react-native-skia`)" - "react-native-slider (from `../../../node_modules/@react-native-community/slider`)" + - react-native-wgpu (from `../../../node_modules/react-native-wgpu`) - React-nativeconfig (from `../../../node_modules/react-native/ReactCommon`) - React-NativeModulesApple (from `../../../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`) - React-perflogger (from `../../../node_modules/react-native/ReactCommon/reactperflogger`) @@ -1811,6 +1833,8 @@ EXTERNAL SOURCES: :path: "../../../node_modules/@shopify/react-native-skia" react-native-slider: :path: "../../../node_modules/@react-native-community/slider" + react-native-wgpu: + :path: "../../../node_modules/react-native-wgpu" React-nativeconfig: :path: "../../../node_modules/react-native/ReactCommon" React-NativeModulesApple: @@ -1913,6 +1937,7 @@ SPEC CHECKSUMS: react-native-safe-area-context: ab8f4a3d8180913bd78ae75dd599c94cce3d5e9a react-native-skia: 94c1a75519ba65c8450f21867358739486b1992b react-native-slider: 97ce0bd921f40de79cead9754546d5e4e7ba44f8 + react-native-wgpu: 7bb28d61cf45ddc930a321b50a0bf6a73a9a508c React-nativeconfig: 57781b79e11d5af7573e6f77cbf1143b71802a6d React-NativeModulesApple: 7ff2e2cfb2e5fa5bdedcecf28ce37e696c6ef1e1 React-perflogger: 8a360ccf603de6ddbe9ff8f54383146d26e6c936 diff --git a/apps/paper/package.json b/apps/paper/package.json index 094e59ea37..4dc636ba8c 100644 --- a/apps/paper/package.json +++ b/apps/paper/package.json @@ -32,6 +32,7 @@ "react-native-safe-area-context": "^4.10.9", "react-native-screens": "^3.34.0", "react-native-svg": "^15.6.0", + "react-native-wgpu": "^0.1.5", "typescript": "^5.2.2" }, "devDependencies": { diff --git a/apps/paper/src/App.tsx b/apps/paper/src/App.tsx index 4fd9c447a9..9957c0ea6a 100644 --- a/apps/paper/src/App.tsx +++ b/apps/paper/src/App.tsx @@ -30,6 +30,7 @@ import { FrostedCard, SpeedTest, Video, + WebGPU } from "./Examples"; import { CI, Tests } from "./Tests"; import { HomeScreen } from "./Home"; @@ -108,6 +109,14 @@ const App = () => { title: "🎨 Skia", }} /> + @builtin(position) vec4f { + var pos = array( + vec2(0.0, 0.5), + vec2(-0.5, -0.5), + vec2(0.5, -0.5) + ); + + return vec4f(pos[VertexIndex], 0.0, 1.0); +}`; + +const redFragWGSL = `@fragment +fn main() -> @location(0) vec4f { + return vec4(1.0, 0.0, 0.0, 1.0); +}`; + +export function WebGPU() { + const ref = useCanvasEffect(async () => { + const adapter = await navigator.gpu.requestAdapter(); + if (!adapter) { + throw new Error("No adapter"); + } + const device = await adapter.requestDevice(); + const presentationFormat = navigator.gpu.getPreferredCanvasFormat(); + + const context = ref.current!.getContext("webgpu")!; + const canvas = context.canvas as HTMLCanvasElement; + canvas.width = canvas.clientWidth * PixelRatio.get(); + canvas.height = canvas.clientHeight * PixelRatio.get(); + + if (!context) { + throw new Error("No context"); + } + + context.configure({ + device, + format: presentationFormat, + alphaMode: "opaque", + }); + + const pipeline = device.createRenderPipeline({ + layout: "auto", + vertex: { + module: device.createShaderModule({ + code: triangleVertWGSL, + }), + entryPoint: "main", + }, + fragment: { + module: device.createShaderModule({ + code: redFragWGSL, + }), + entryPoint: "main", + targets: [ + { + format: presentationFormat, + }, + ], + }, + primitive: { + topology: "triangle-list", + }, + }); + + const commandEncoder = device.createCommandEncoder(); + + const textureView = context.getCurrentTexture().createView(); + + const renderPassDescriptor: GPURenderPassDescriptor = { + colorAttachments: [ + { + view: textureView, + clearValue: [0, 0, 0, 1], + loadOp: "clear", + storeOp: "store", + }, + ], + }; + + const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); + passEncoder.setPipeline(pipeline); + passEncoder.draw(3); + passEncoder.end(); + + device.queue.submit([commandEncoder.finish()]); + context.present(); + }); + + return ( + + + + ); +} + +const style = StyleSheet.create({ + container: { + flex: 1, + }, + webgpu: { + flex: 1, + }, +}); \ No newline at end of file diff --git a/apps/paper/src/Examples/WebGPU/index.ts b/apps/paper/src/Examples/WebGPU/index.ts new file mode 100644 index 0000000000..1bfe44838e --- /dev/null +++ b/apps/paper/src/Examples/WebGPU/index.ts @@ -0,0 +1 @@ +export * from "./WebGPU"; \ No newline at end of file diff --git a/apps/paper/src/Examples/index.ts b/apps/paper/src/Examples/index.ts index 024a807cae..7be64930a3 100644 --- a/apps/paper/src/Examples/index.ts +++ b/apps/paper/src/Examples/index.ts @@ -24,3 +24,4 @@ export * from "./Stickers"; export * from "./FrostedCard"; export * from "./SpeedTest"; export * from "./Video"; +export * from "./WebGPU"; diff --git a/apps/paper/src/Home/HomeScreen.tsx b/apps/paper/src/Home/HomeScreen.tsx index 8105ea61e9..91db7f8bf2 100644 --- a/apps/paper/src/Home/HomeScreen.tsx +++ b/apps/paper/src/Home/HomeScreen.tsx @@ -18,6 +18,11 @@ export const HomeScreen = () => { route="API" testId="API" /> + Date: Thu, 12 Sep 2024 10:08:41 +0200 Subject: [PATCH 2/9] :wrench: --- apps/paper/src/Examples/WebGPU/WebGPU.tsx | 100 ++---------------- .../RNSkAndroidPlatformContext.h | 4 + packages/skia/cpp/api/JsiSkSurfaceFactory.h | 14 ++- .../skia/cpp/rnskia/RNSkPlatformContext.h | 2 + .../src/skia/types/Surface/SurfaceFactory.ts | 2 + 5 files changed, 32 insertions(+), 90 deletions(-) diff --git a/apps/paper/src/Examples/WebGPU/WebGPU.tsx b/apps/paper/src/Examples/WebGPU/WebGPU.tsx index 72951b3d5b..9e874189e0 100644 --- a/apps/paper/src/Examples/WebGPU/WebGPU.tsx +++ b/apps/paper/src/Examples/WebGPU/WebGPU.tsx @@ -1,95 +1,17 @@ +import { Skia } from "@shopify/react-native-skia"; import React from "react"; -import { StyleSheet, View, PixelRatio } from "react-native"; +import { StyleSheet, View } from "react-native"; import { Canvas, useCanvasEffect } from "react-native-wgpu"; -const triangleVertWGSL = `@vertex -fn main( - @builtin(vertex_index) VertexIndex : u32 -) -> @builtin(position) vec4f { - var pos = array( - vec2(0.0, 0.5), - vec2(-0.5, -0.5), - vec2(0.5, -0.5) - ); - - return vec4f(pos[VertexIndex], 0.0, 1.0); -}`; - -const redFragWGSL = `@fragment -fn main() -> @location(0) vec4f { - return vec4(1.0, 0.0, 0.0, 1.0); -}`; - export function WebGPU() { - const ref = useCanvasEffect(async () => { - const adapter = await navigator.gpu.requestAdapter(); - if (!adapter) { - throw new Error("No adapter"); - } - const device = await adapter.requestDevice(); - const presentationFormat = navigator.gpu.getPreferredCanvasFormat(); - - const context = ref.current!.getContext("webgpu")!; - const canvas = context.canvas as HTMLCanvasElement; - canvas.width = canvas.clientWidth * PixelRatio.get(); - canvas.height = canvas.clientHeight * PixelRatio.get(); - - if (!context) { - throw new Error("No context"); - } - - context.configure({ - device, - format: presentationFormat, - alphaMode: "opaque", - }); - - const pipeline = device.createRenderPipeline({ - layout: "auto", - vertex: { - module: device.createShaderModule({ - code: triangleVertWGSL, - }), - entryPoint: "main", - }, - fragment: { - module: device.createShaderModule({ - code: redFragWGSL, - }), - entryPoint: "main", - targets: [ - { - format: presentationFormat, - }, - ], - }, - primitive: { - topology: "triangle-list", - }, - }); - - const commandEncoder = device.createCommandEncoder(); - - const textureView = context.getCurrentTexture().createView(); - - const renderPassDescriptor: GPURenderPassDescriptor = { - colorAttachments: [ - { - view: textureView, - clearValue: [0, 0, 0, 1], - loadOp: "clear", - storeOp: "store", - }, - ], - }; - - const passEncoder = commandEncoder.beginRenderPass(renderPassDescriptor); - passEncoder.setPipeline(pipeline); - passEncoder.draw(3); - passEncoder.end(); - - device.queue.submit([commandEncoder.finish()]); - context.present(); + const ref = useCanvasEffect(() => { + const nativeSurface = ref.current!.getNativeSurface(); + const surface = Skia.Surface.MakeFromNativeSurface( + nativeSurface.surface, + nativeSurface.width, + nativeSurface.height + ); + console.log({ surface }); }); return ( @@ -106,4 +28,4 @@ const style = StyleSheet.create({ webgpu: { flex: 1, }, -}); \ No newline at end of file +}); diff --git a/packages/skia/android/cpp/rnskia-android/RNSkAndroidPlatformContext.h b/packages/skia/android/cpp/rnskia-android/RNSkAndroidPlatformContext.h index 5cca655d12..1f29b08dd9 100644 --- a/packages/skia/android/cpp/rnskia-android/RNSkAndroidPlatformContext.h +++ b/packages/skia/android/cpp/rnskia-android/RNSkAndroidPlatformContext.h @@ -54,6 +54,10 @@ class RNSkAndroidPlatformContext : public RNSkPlatformContext { return SkiaOpenGLSurfaceFactory::makeOffscreenSurface(width, height); } + sk_sp makeSurfaceFromNativeSurface(void *surface, int width, int height) override { + return nullptr; + } + sk_sp makeImageFromNativeBuffer(void *buffer) override { return SkiaOpenGLSurfaceFactory::makeImageFromHardwareBuffer(buffer); } diff --git a/packages/skia/cpp/api/JsiSkSurfaceFactory.h b/packages/skia/cpp/api/JsiSkSurfaceFactory.h index 66d356b833..0f01f389ab 100644 --- a/packages/skia/cpp/api/JsiSkSurfaceFactory.h +++ b/packages/skia/cpp/api/JsiSkSurfaceFactory.h @@ -35,6 +35,17 @@ class JsiSkSurfaceFactory : public JsiSkHostObject { std::make_shared(getContext(), std::move(surface))); } + JSI_HOST_FUNCTION(MakeFromNativeSurface) { + jsi::BigInt pointer = arguments[0].asBigInt(runtime); + const uintptr_t nativeBufferPointer = pointer.asUint64(runtime); + void *surface = reinterpret_cast(nativeBufferPointer); + auto width = static_cast(arguments[1].asNumber()); + auto height = static_cast(arguments[2].asNumber()); + auto context = getContext(); + auto result = context->makeSurfaceFromNativeSurface(surface, width, height); + return jsi::Value::null(); + } + JSI_HOST_FUNCTION(MakeOffscreen) { auto width = static_cast(arguments[0].asNumber()); auto height = static_cast(arguments[1].asNumber()); @@ -49,7 +60,8 @@ class JsiSkSurfaceFactory : public JsiSkHostObject { } JSI_EXPORT_FUNCTIONS(JSI_EXPORT_FUNC(JsiSkSurfaceFactory, Make), - JSI_EXPORT_FUNC(JsiSkSurfaceFactory, MakeOffscreen)) + JSI_EXPORT_FUNC(JsiSkSurfaceFactory, MakeOffscreen), + JSI_EXPORT_FUNC(JsiSkSurfaceFactory, MakeFromNativeSurface)) explicit JsiSkSurfaceFactory(std::shared_ptr context) : JsiSkHostObject(std::move(context)) {} diff --git a/packages/skia/cpp/rnskia/RNSkPlatformContext.h b/packages/skia/cpp/rnskia/RNSkPlatformContext.h index 7a610693f7..2b715edbb4 100644 --- a/packages/skia/cpp/rnskia/RNSkPlatformContext.h +++ b/packages/skia/cpp/rnskia/RNSkPlatformContext.h @@ -134,6 +134,8 @@ class RNSkPlatformContext { */ virtual sk_sp makeOffscreenSurface(int width, int height) = 0; + virtual sk_sp makeSurfaceFromNativeSurface(void *surface, int width, int height) = 0; + /** * Creates an image from a native buffer. * - On iOS, this is a `CVPixelBufferRef` diff --git a/packages/skia/src/skia/types/Surface/SurfaceFactory.ts b/packages/skia/src/skia/types/Surface/SurfaceFactory.ts index 688d738404..8c059a6b37 100644 --- a/packages/skia/src/skia/types/Surface/SurfaceFactory.ts +++ b/packages/skia/src/skia/types/Surface/SurfaceFactory.ts @@ -16,4 +16,6 @@ export interface SurfaceFactory { * @param height - number of pixels of the height of the drawable area. */ MakeOffscreen: (width: number, height: number) => SkSurface | null; + + MakeFromNativeSurface(surface: bigint, width: number, height: number): SkSurface | null; } From 565bff81a26c0a4a7b69e59f8a41c357a2328a3c Mon Sep 17 00:00:00 2001 From: William Candillon Date: Thu, 12 Sep 2024 15:17:11 +0200 Subject: [PATCH 3/9] bootstrap --- apps/paper/ios/Podfile.lock | 25 ------ apps/paper/package.json | 2 +- apps/paper/src/Examples/WebGPU/WebGPU.tsx | 2 +- .../RNSkAndroidPlatformContext.h | 2 +- packages/skia/cpp/api/JsiSkApi.h | 2 + packages/skia/cpp/api/JsiSkSurfaceFactory.h | 14 +--- packages/skia/cpp/api/JsiSkiaContext.h | 77 +++++++++++++++++++ .../skia/cpp/rnskia/RNSkPlatformContext.h | 3 +- packages/skia/cpp/rnskia/SkiaContext.h | 22 ++++++ packages/skia/src/skia/types/Skia.ts | 8 +- .../src/skia/types/Surface/SurfaceFactory.ts | 2 - yarn.lock | 10 +-- 12 files changed, 119 insertions(+), 50 deletions(-) create mode 100644 packages/skia/cpp/api/JsiSkiaContext.h create mode 100644 packages/skia/cpp/rnskia/SkiaContext.h diff --git a/apps/paper/ios/Podfile.lock b/apps/paper/ios/Podfile.lock index 41344601be..c1c0e67684 100644 --- a/apps/paper/ios/Podfile.lock +++ b/apps/paper/ios/Podfile.lock @@ -1283,27 +1283,6 @@ PODS: - ReactCommon/turbomodule/bridging - ReactCommon/turbomodule/core - Yoga - - react-native-wgpu (0.1.5): - - DoubleConversion - - glog - - hermes-engine - - RCT-Folly (= 2024.01.01.00) - - RCTRequired - - RCTTypeSafety - - React-Core - - React-debug - - React-Fabric - - React-featureflags - - React-graphics - - React-ImageManager - - React-NativeModulesApple - - React-RCTFabric - - React-rendererdebug - - React-utils - - ReactCodegen - - ReactCommon/turbomodule/bridging - - ReactCommon/turbomodule/core - - Yoga - React-nativeconfig (0.75.2) - React-NativeModulesApple (0.75.2): - glog @@ -1718,7 +1697,6 @@ DEPENDENCIES: - react-native-safe-area-context (from `../../../node_modules/react-native-safe-area-context`) - "react-native-skia (from `../../../node_modules/@shopify/react-native-skia`)" - "react-native-slider (from `../../../node_modules/@react-native-community/slider`)" - - react-native-wgpu (from `../../../node_modules/react-native-wgpu`) - React-nativeconfig (from `../../../node_modules/react-native/ReactCommon`) - React-NativeModulesApple (from `../../../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`) - React-perflogger (from `../../../node_modules/react-native/ReactCommon/reactperflogger`) @@ -1833,8 +1811,6 @@ EXTERNAL SOURCES: :path: "../../../node_modules/@shopify/react-native-skia" react-native-slider: :path: "../../../node_modules/@react-native-community/slider" - react-native-wgpu: - :path: "../../../node_modules/react-native-wgpu" React-nativeconfig: :path: "../../../node_modules/react-native/ReactCommon" React-NativeModulesApple: @@ -1937,7 +1913,6 @@ SPEC CHECKSUMS: react-native-safe-area-context: ab8f4a3d8180913bd78ae75dd599c94cce3d5e9a react-native-skia: 94c1a75519ba65c8450f21867358739486b1992b react-native-slider: 97ce0bd921f40de79cead9754546d5e4e7ba44f8 - react-native-wgpu: 7bb28d61cf45ddc930a321b50a0bf6a73a9a508c React-nativeconfig: 57781b79e11d5af7573e6f77cbf1143b71802a6d React-NativeModulesApple: 7ff2e2cfb2e5fa5bdedcecf28ce37e696c6ef1e1 React-perflogger: 8a360ccf603de6ddbe9ff8f54383146d26e6c936 diff --git a/apps/paper/package.json b/apps/paper/package.json index 4dc636ba8c..1df41133db 100644 --- a/apps/paper/package.json +++ b/apps/paper/package.json @@ -32,7 +32,7 @@ "react-native-safe-area-context": "^4.10.9", "react-native-screens": "^3.34.0", "react-native-svg": "^15.6.0", - "react-native-wgpu": "^0.1.5", + "react-native-wgpu": "^0.1.6", "typescript": "^5.2.2" }, "devDependencies": { diff --git a/apps/paper/src/Examples/WebGPU/WebGPU.tsx b/apps/paper/src/Examples/WebGPU/WebGPU.tsx index 9e874189e0..101974f8ee 100644 --- a/apps/paper/src/Examples/WebGPU/WebGPU.tsx +++ b/apps/paper/src/Examples/WebGPU/WebGPU.tsx @@ -6,7 +6,7 @@ import { Canvas, useCanvasEffect } from "react-native-wgpu"; export function WebGPU() { const ref = useCanvasEffect(() => { const nativeSurface = ref.current!.getNativeSurface(); - const surface = Skia.Surface.MakeFromNativeSurface( + const surface = Skia.Context( nativeSurface.surface, nativeSurface.width, nativeSurface.height diff --git a/packages/skia/android/cpp/rnskia-android/RNSkAndroidPlatformContext.h b/packages/skia/android/cpp/rnskia-android/RNSkAndroidPlatformContext.h index 1f29b08dd9..b23b4e4733 100644 --- a/packages/skia/android/cpp/rnskia-android/RNSkAndroidPlatformContext.h +++ b/packages/skia/android/cpp/rnskia-android/RNSkAndroidPlatformContext.h @@ -54,7 +54,7 @@ class RNSkAndroidPlatformContext : public RNSkPlatformContext { return SkiaOpenGLSurfaceFactory::makeOffscreenSurface(width, height); } - sk_sp makeSurfaceFromNativeSurface(void *surface, int width, int height) override { + std::shared_ptr makeContextFromNativeSurface(void *surface, int width, int height) override { return nullptr; } diff --git a/packages/skia/cpp/api/JsiSkApi.h b/packages/skia/cpp/api/JsiSkApi.h index 59fe16cc34..cf7b716142 100644 --- a/packages/skia/cpp/api/JsiSkApi.h +++ b/packages/skia/cpp/api/JsiSkApi.h @@ -51,6 +51,7 @@ #include "JsiSkTypefaceFontProviderFactory.h" #include "JsiSkVertices.h" #include "JsiVideo.h" +#include "JsiSkiaContext.h" namespace RNSkia { @@ -69,6 +70,7 @@ class JsiSkApi : public JsiSkHostObject { // slow to do it on demand JsiSkFontMgrFactory::getFontMgr(getContext()); installFunction("Video", JsiVideo::createCtor(context)); + installFunction("Context", JsiSkiaContext::createCtor(context)); installFunction("Font", JsiSkFont::createCtor(context)); installFunction("Paint", JsiSkPaint::createCtor(context)); installFunction("RSXform", JsiSkRSXform::createCtor(context)); diff --git a/packages/skia/cpp/api/JsiSkSurfaceFactory.h b/packages/skia/cpp/api/JsiSkSurfaceFactory.h index 0f01f389ab..66d356b833 100644 --- a/packages/skia/cpp/api/JsiSkSurfaceFactory.h +++ b/packages/skia/cpp/api/JsiSkSurfaceFactory.h @@ -35,17 +35,6 @@ class JsiSkSurfaceFactory : public JsiSkHostObject { std::make_shared(getContext(), std::move(surface))); } - JSI_HOST_FUNCTION(MakeFromNativeSurface) { - jsi::BigInt pointer = arguments[0].asBigInt(runtime); - const uintptr_t nativeBufferPointer = pointer.asUint64(runtime); - void *surface = reinterpret_cast(nativeBufferPointer); - auto width = static_cast(arguments[1].asNumber()); - auto height = static_cast(arguments[2].asNumber()); - auto context = getContext(); - auto result = context->makeSurfaceFromNativeSurface(surface, width, height); - return jsi::Value::null(); - } - JSI_HOST_FUNCTION(MakeOffscreen) { auto width = static_cast(arguments[0].asNumber()); auto height = static_cast(arguments[1].asNumber()); @@ -60,8 +49,7 @@ class JsiSkSurfaceFactory : public JsiSkHostObject { } JSI_EXPORT_FUNCTIONS(JSI_EXPORT_FUNC(JsiSkSurfaceFactory, Make), - JSI_EXPORT_FUNC(JsiSkSurfaceFactory, MakeOffscreen), - JSI_EXPORT_FUNC(JsiSkSurfaceFactory, MakeFromNativeSurface)) + JSI_EXPORT_FUNC(JsiSkSurfaceFactory, MakeOffscreen)) explicit JsiSkSurfaceFactory(std::shared_ptr context) : JsiSkHostObject(std::move(context)) {} diff --git a/packages/skia/cpp/api/JsiSkiaContext.h b/packages/skia/cpp/api/JsiSkiaContext.h new file mode 100644 index 0000000000..b5a47a8d83 --- /dev/null +++ b/packages/skia/cpp/api/JsiSkiaContext.h @@ -0,0 +1,77 @@ +#pragma once + +#include +#include +#include +#include + +#include "JsiSkHostObjects.h" +#include "RNSkLog.h" +#include + +#include "JsiSkPaint.h" +#include "JsiSkPoint.h" +#include "JsiSkRect.h" +#include "JsiSkTypeface.h" + +#include "SkiaContext.h" + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdocumentation" + +#include "include/core/SkFont.h" +#include "include/core/SkFontMetrics.h" + +#pragma clang diagnostic pop + +namespace RNSkia { + +namespace jsi = facebook::jsi; + +class JsiSkiaContext : public JsiSkWrappingSharedPtrHostObject { +public: + EXPORT_JSI_API_TYPENAME(JsiSkiaContext, SkiaContext) + + JSI_HOST_FUNCTION(getSurface) { + return jsi::Value::null(); + } + + JSI_HOST_FUNCTION(present) { + return jsi::Value::undefined(); + } + + JSI_EXPORT_FUNCTIONS( + JSI_EXPORT_FUNC(JsiSkiaContext, getSurface), + JSI_EXPORT_FUNC(JsiSkiaContext, present) + ) + + JsiSkiaContext(std::shared_ptr context, + std::shared_ptr ctx) + : JsiSkWrappingSharedPtrHostObject(std::move(context), std::move(ctx)) { + } + + /** + * Creates the function for construction a new instance of the SkFont + * wrapper + * @param context Platform context + * @return A function for creating a new host object wrapper for the SkFont + * class + */ + static const jsi::HostFunctionType + createCtor(std::shared_ptr context) { + return JSI_HOST_FUNCTION_LAMBDA { + jsi::BigInt pointer = arguments[0].asBigInt(runtime); + const uintptr_t nativeBufferPointer = pointer.asUint64(runtime); + void *surface = reinterpret_cast(nativeBufferPointer); + auto width = static_cast(arguments[1].asNumber()); + auto height = static_cast(arguments[2].asNumber()); + auto result = context->makeContextFromNativeSurface(surface, width, height); + // Return the newly constructed object + return jsi::Object::createFromHostObject( + runtime, + std::make_shared(std::move(context), std::move(result))); + }; + } +}; + +} // namespace RNSkia diff --git a/packages/skia/cpp/rnskia/RNSkPlatformContext.h b/packages/skia/cpp/rnskia/RNSkPlatformContext.h index 2b715edbb4..a2bf0e731f 100644 --- a/packages/skia/cpp/rnskia/RNSkPlatformContext.h +++ b/packages/skia/cpp/rnskia/RNSkPlatformContext.h @@ -11,6 +11,7 @@ #include "RNSkDispatchQueue.h" #include "RNSkVideo.h" +#include "SkiaContext.h" #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdocumentation" @@ -134,7 +135,7 @@ class RNSkPlatformContext { */ virtual sk_sp makeOffscreenSurface(int width, int height) = 0; - virtual sk_sp makeSurfaceFromNativeSurface(void *surface, int width, int height) = 0; + virtual std::shared_ptr makeContextFromNativeSurface(void *surface, int width, int height) = 0; /** * Creates an image from a native buffer. diff --git a/packages/skia/cpp/rnskia/SkiaContext.h b/packages/skia/cpp/rnskia/SkiaContext.h new file mode 100644 index 0000000000..a58b18c8bb --- /dev/null +++ b/packages/skia/cpp/rnskia/SkiaContext.h @@ -0,0 +1,22 @@ +#pragma once + +#include + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wdocumentation" + +#include "include/core/SkImage.h" +#include "include/core/SkSurface.h" + +#pragma clang diagnostic pop + +namespace RNSkia { + +class SkiaContext { +public: + virtual ~SkiaContext() = default; + virtual sk_sp getSurface() = 0; + virtual void present() = 0; +}; + +} // namespace RNSkia diff --git a/packages/skia/src/skia/types/Skia.ts b/packages/skia/src/skia/types/Skia.ts index ca0c2edcf2..fc1099d7a2 100644 --- a/packages/skia/src/skia/types/Skia.ts +++ b/packages/skia/src/skia/types/Skia.ts @@ -21,7 +21,7 @@ import type { SkVertices, VertexMode } from "./Vertices/Vertices"; import type { DataFactory } from "./Data"; import type { SVGFactory } from "./SVG"; import type { TextBlobFactory } from "./TextBlob"; -import type { SurfaceFactory } from "./Surface"; +import type { SkSurface, SurfaceFactory } from "./Surface"; import type { SkRSXform } from "./RSXform"; import type { SkPath } from "./Path/Path"; import type { SkContourMeasureIter } from "./ContourMeasure"; @@ -33,6 +33,11 @@ import type { ParagraphBuilderFactory } from "./Paragraph/ParagraphBuilder"; import type { Video } from "./Video"; import type { NativeBufferFactory } from "./NativeBuffer"; +interface SkiaContext { + getSurface(): SkSurface; + present(): void; +} + /** * Declares the interface for the native Skia API */ @@ -97,5 +102,6 @@ export interface Skia { Surface: SurfaceFactory; ParagraphBuilder: ParagraphBuilderFactory; Video: (url: string) => Promise