From fdeaeacf5fdbd6221a2e8c93c560e7116a088889 Mon Sep 17 00:00:00 2001 From: William Candillon Date: Thu, 14 Nov 2024 10:36:21 +0100 Subject: [PATCH 01/13] Add build flag for Skia Graphite --- .gitignore | 1 + packages/skia/scripts/build-skia.ts | 27 ++++---- packages/skia/scripts/skia-configuration.ts | 70 +++++++++++++++++---- 3 files changed, 70 insertions(+), 28 deletions(-) diff --git a/.gitignore b/.gitignore index 36c87658ad..b4c7f791e3 100644 --- a/.gitignore +++ b/.gitignore @@ -52,6 +52,7 @@ local.properties # Externals packages/skia/libs packages/skia/cpp/skia/ +packages/skia/cpp/dawn/ # BUCK buck-out/ diff --git a/packages/skia/scripts/build-skia.ts b/packages/skia/scripts/build-skia.ts index 96789c4907..736cad1036 100644 --- a/packages/skia/scripts/build-skia.ts +++ b/packages/skia/scripts/build-skia.ts @@ -16,7 +16,7 @@ const getOutDir = (platform: PlatformName, targetName: string) => { return `${OutFolder}/${platform}/${targetName}`; }; -const configurePlatform = ( +const configurePlatform = async ( platformName: PlatformName, configuration: Platform, targetName: string @@ -67,10 +67,7 @@ const configurePlatform = ( // eslint-disable-next-line max-len const command = `${commandline} ${options} ${targetOptions} --script-executable=python3 --args='target_os="${platformName}" target_cpu="${target.cpu}" ${common}${args}${targetArgs}'`; - console.log("Command:"); - console.log(command); - console.log("==============================="); - $(command); + await runAsync(command, "⚙️"); return true; } else { console.log( @@ -140,13 +137,15 @@ const buildXCFrameworks = () => { }; (async () => { - // Test for existence of Android SDK - if (!process.env.ANDROID_NDK) { - console.log("ANDROID_NDK not set."); - exit(1); - } else { - console.log("☑ ANDROID_NDK"); - } + ["ANDROID_NDK", "ANDROID_HOME"].forEach((name) => { + // Test for existence of Android SDK + if (!process.env[name]) { + console.log(`${name} not set.`); + exit(1); + } else { + console.log(`✅ ${name}`); + } + }); // Run glient sync console.log("Running gclient sync..."); @@ -158,9 +157,7 @@ const buildXCFrameworks = () => { for (const key of mapKeys(configurations)) { const configuration = configurations[key]; for (const target of mapKeys(configuration.targets)) { - if (!configurePlatform(key as PlatformName, configuration, target)) { - throw Error(`Error configuring platform "${key}" for cpu "${target}"`); - } + await configurePlatform(key as PlatformName, configuration, target); await buildPlatform(key as PlatformName, target); process.chdir(ProjectRoot); if (key === "android") { diff --git a/packages/skia/scripts/skia-configuration.ts b/packages/skia/scripts/skia-configuration.ts index e76699afc9..801e9d9846 100644 --- a/packages/skia/scripts/skia-configuration.ts +++ b/packages/skia/scripts/skia-configuration.ts @@ -1,15 +1,19 @@ +/* eslint-disable max-len */ import path from "path"; import { $ } from "./utils"; +const DEBUG = false; +const GRAPHITE = false; +const BUILD_WITH_PARAGRAPH = true; + export const SkiaSrc = path.join(__dirname, "../../../externals/skia"); export const ProjectRoot = path.join(__dirname, "../../.."); export const PackageRoot = path.join(__dirname, ".."); -export const OutFolder = path.join(SkiaSrc, "out"); +export const OutFolder = path.join(SkiaSrc, DEBUG ? "debug" : "out"); -const NdkDir: string = process.env.ANDROID_NDK ?? ""; +const NdkDir = process.env.ANDROID_NDK ?? ""; -export const BUILD_WITH_PARAGRAPH = true; const NoParagraphArgs = [ ["skia_use_harfbuzz", false], ["skia_use_icu", false], @@ -19,7 +23,7 @@ const NoParagraphArgs = [ // On Android: we use system ICU // On iOS: we use libgrapheme const CommonParagraphArgs = [ - ["skia_enable_paragraph", true], + ["skia_enable_skparagraph", true], ["skia_use_system_icu", false], ["skia_use_harfbuzz", true], ["skia_use_system_harfbuzz", false], @@ -49,6 +53,14 @@ const ParagraphOutputsAndroid = BUILD_WITH_PARAGRAPH ? ["libskparagraph.a", "libskunicode_core.a", "libskunicode_icu.a"] : []; +const DawnOutput = GRAPHITE + ? [ + "libdawn_native_static.a", + "libdawn_platform_static.a", + "libdawn_proc_static.a", + ] + : []; + export const commonArgs = [ ["skia_use_piex", true], ["skia_use_sfntly", false], @@ -58,14 +70,15 @@ export const commonArgs = [ ["skia_use_system_libwebp", false], ["skia_use_system_zlib", false], ["skia_enable_tools", false], - ["is_official_build", true], + ["is_official_build", !DEBUG], ["skia_enable_skottie", true], - ["is_debug", false], + ["is_debug", DEBUG], ["skia_enable_pdf", false], - ["skia_enable_flutter_defines", true], ["paragraph_tests_enabled", false], ["is_component_build", false], - // ["skia_enable_graphite", true], + ["skia_enable_ganesh", !GRAPHITE], + ["skia_enable_graphite", GRAPHITE], + ["skia_use_dawn", GRAPHITE], ]; export type PlatformName = "ios" | "android"; @@ -86,6 +99,8 @@ export type Platform = { options?: Arg[]; }; +const iosMinTarget = GRAPHITE ? '"13.0"' : '"15.1"'; + export const configurations = { android: { targets: { @@ -107,9 +122,10 @@ export const configurations = { }, }, args: [ + ...(GRAPHITE ? [["ndk_api", 26]] : []), ["ndk", `"${NdkDir}"`], ["skia_use_system_freetype2", false], - ["skia_use_gl", true], + ["skia_use_gl", !GRAPHITE], ["cc", '"clang"'], ["cxx", '"clang++"'], [ @@ -126,6 +142,7 @@ export const configurations = { "libskottie.a", "libsksg.a", ...ParagraphOutputsAndroid, + ...DawnOutput, ], }, ios: { @@ -133,7 +150,7 @@ export const configurations = { "arm64-iphoneos": { cpu: "arm64", args: [ - ["ios_min_target", '"13.0"'], + ["ios_min_target", iosMinTarget], ["extra_cflags", '["-target", "arm64-apple-ios"]'], ["extra_asmflags", '["-target", "arm64-apple-ios"]'], ["extra_ldflags", '["-target", "arm64-apple-ios"]'], @@ -142,7 +159,7 @@ export const configurations = { "arm64-iphonesimulator": { cpu: "arm64", args: [ - ["ios_min_target", '"13.0"'], + ["ios_min_target", iosMinTarget], ["extra_cflags", '["-target", "arm64-apple-ios-simulator"]'], ["extra_asmflags", '["-target", "arm64-apple-ios-simulator"]'], ["extra_ldflags", '["-target", "arm64-apple-ios-simulator"]'], @@ -152,7 +169,7 @@ export const configurations = { x64: { cpu: "x64", args: [ - ["ios_min_target", '"13.0"'], + ["ios_min_target", iosMinTarget], ["extra_cflags", '["-target", "arm64-apple-ios-simulator"]'], ["extra_asmflags", '["-target", "arm64-apple-ios-simulator"]'], ["extra_ldflags", '["-target", "arm64-apple-ios-simulator"]'], @@ -173,6 +190,7 @@ export const configurations = { "libskottie.a", "libsksg.a", ...ParagraphIOS, + ...DawnOutput, ], }, }; @@ -182,16 +200,41 @@ const copyModule = (module: string) => [ `cp -a ../../externals/skia/modules/${module}/include/. ./cpp/skia/modules/${module}/include`, ]; +const copyGraphite = () => + GRAPHITE + ? [ + "mkdir -p ./cpp/dawn/include", + "mkdir -p ./cpp/skia/src/gpu/graphite", + "cp -a ../../externals/skia/src/gpu/graphite/ContextOptionsPriv.h ./cpp/skia/src/gpu/graphite/.", + "cp -a ../../externals/skia/src/gpu/graphite/ResourceTypes.h ./cpp/skia/src/gpu/graphite/.", + "cp -a ../../externals/skia/src/gpu/graphite/TextureProxyView.h ./cpp/skia/src/gpu/graphite/.", + + "cp -a ../../externals/skia/out/android/arm/gen/third_party/externals/dawn/include/. ./cpp/dawn/include", + "cp -a ../../externals/skia/third_party/externals/dawn/include/. ./cpp/dawn/include", + "cp -a ../../externals/skia/third_party/externals/dawn/include/. ./cpp/dawn/include", + + // Remove duplicated WebGPU headers + "sed -i '' 's/#include \"dawn\\/webgpu.h\"/#include \"webgpu\\/webgpu.h\"/' ./cpp/dawn/include/dawn/dawn_proc_table.h", + "cp ./cpp/dawn/include/dawn/webgpu.h ./cpp/dawn/include/webgpu/webgpu.h", + "cp ./cpp/dawn/include/dawn/webgpu_cpp.h ./cpp/dawn/include/webgpu/webgpu_cpp.h", + "rm -rf ./cpp/dawn/include/dawn/webgpu.h", + "rm -rf ./cpp/dawn/include/dawn/webgpu_cpp.h", + "rm -rf ./cpp/dawn/include/dawn/wire", + ] + : []; + export const copyHeaders = () => { process.chdir(PackageRoot); [ "rm -rf ./cpp/skia", + "rm -rf ./cpp/dawn", - "mkdir -p ./cpp/skia", "mkdir -p ./cpp/skia/include", "mkdir -p ./cpp/skia/modules", "mkdir -p ./cpp/skia/src", + ...copyGraphite(), + "cp -a ../../externals/skia/include/. ./cpp/skia/include", ...copyModule("svg"), ...copyModule("skresources"), @@ -203,6 +246,7 @@ export const copyHeaders = () => { "cp -a ../../externals/skia/src/core/SkChecksum.h ./cpp/skia/src/core/.", "cp -a ../../externals/skia/src/core/SkTHash.h ./cpp/skia/src/core/.", + // TODO: remove ganesh "mkdir -p ./cpp/skia/src/gpu/ganesh/gl", "cp -a ../../externals/skia/src/gpu/ganesh/gl/GrGLDefines.h ./cpp/skia/src/gpu/ganesh/gl/.", From a45b5c4690e604ea52c6c76b595f57ae9415fc80 Mon Sep 17 00:00:00 2001 From: William Candillon Date: Thu, 14 Nov 2024 11:44:49 +0100 Subject: [PATCH 02/13] :green_heart: --- packages/skia/android/build.gradle | 3 ++ packages/skia/react-native-skia.podspec | 36 +++++++++++++++------ packages/skia/scripts/skia-configuration.ts | 15 +++++---- 3 files changed, 39 insertions(+), 15 deletions(-) diff --git a/packages/skia/android/build.gradle b/packages/skia/android/build.gradle index a06971b242..2b080657e5 100644 --- a/packages/skia/android/build.gradle +++ b/packages/skia/android/build.gradle @@ -330,6 +330,9 @@ if (ENABLE_PREFAB) { } else if (path.contains("skia/include") || path.contains("skia/modules") || path.contains("skia/src")) { // Skip flattening Skia dir path = path.substring("skia/".length()) + } else if (path.startsWith("dawn/include/")) { + // Flatten dawn/include/dawn and dawn/include/webgpu + path = path.substring("dawn/include/".length()) } else { // flatten anything else path = path.substring(path.lastIndexOf("/") + 1) diff --git a/packages/skia/react-native-skia.podspec b/packages/skia/react-native-skia.podspec index 60a8904303..477d0cc052 100644 --- a/packages/skia/react-native-skia.podspec +++ b/packages/skia/react-native-skia.podspec @@ -4,6 +4,29 @@ require "json" package = JSON.parse(File.read(File.join(__dir__, "package.json"))) +# Check for GRAPHITE env var +use_graphite = ENV['SK_GRAPHITE'] == '1' + +# Set preprocessor definitions based on GRAPHITE flag +preprocessor_defs = use_graphite ? + '$(inherited) SK_GRAPHITE=1' : + '$(inherited) SK_METAL=1 SK_GANESH=1' + +# Define base frameworks +base_frameworks = ['libs/ios/libskia.xcframework', +'libs/ios/libsvg.xcframework', +'libs/ios/libskshaper.xcframework', +'libs/ios/libskparagraph.xcframework', +'libs/ios/libskunicode_core.xcframework', +'libs/ios/libskunicode_libgrapheme.xcframework',] + +# Add Graphite frameworks if enabled +graphite_frameworks = [ + 'libs/ios/libdawn_native_static.xcframework', + 'libs/ios/libdawn_platform_static.xcframework', + 'libs/ios/libdawn_proc_static.xcframework' +] + Pod::Spec.new do |s| s.name = "react-native-skia" s.version = package["version"] @@ -23,7 +46,7 @@ Pod::Spec.new do |s| s.requires_arc = true s.pod_target_xcconfig = { - 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) SK_METAL=1 SK_GANESH=1', + 'GCC_PREPROCESSOR_DEFINITIONS' => preprocessor_defs, 'CLANG_CXX_LANGUAGE_STANDARD' => 'c++17', 'DEFINES_MODULE' => 'YES', "HEADER_SEARCH_PATHS" => '"$(PODS_TARGET_SRCROOT)/cpp/"/**' @@ -31,14 +54,9 @@ Pod::Spec.new do |s| s.frameworks = 'MetalKit' - s.ios.vendored_frameworks = [ - 'libs/ios/libskia.xcframework', - 'libs/ios/libsvg.xcframework', - 'libs/ios/libskshaper.xcframework', - 'libs/ios/libskparagraph.xcframework', - 'libs/ios/libskunicode_core.xcframework', - 'libs/ios/libskunicode_libgrapheme.xcframework', - ] + s.ios.vendored_frameworks = use_graphite ? + base_frameworks + graphite_frameworks : + base_frameworks # All iOS cpp/h files s.source_files = [ diff --git a/packages/skia/scripts/skia-configuration.ts b/packages/skia/scripts/skia-configuration.ts index 801e9d9846..40a4b82ceb 100644 --- a/packages/skia/scripts/skia-configuration.ts +++ b/packages/skia/scripts/skia-configuration.ts @@ -4,7 +4,7 @@ import path from "path"; import { $ } from "./utils"; const DEBUG = false; -const GRAPHITE = false; +const GRAPHITE = true; const BUILD_WITH_PARAGRAPH = true; export const SkiaSrc = path.join(__dirname, "../../../externals/skia"); @@ -76,7 +76,7 @@ export const commonArgs = [ ["skia_enable_pdf", false], ["paragraph_tests_enabled", false], ["is_component_build", false], - ["skia_enable_ganesh", !GRAPHITE], + //["skia_enable_ganesh", !GRAPHITE], ["skia_enable_graphite", GRAPHITE], ["skia_use_dawn", GRAPHITE], ]; @@ -99,7 +99,7 @@ export type Platform = { options?: Arg[]; }; -const iosMinTarget = GRAPHITE ? '"13.0"' : '"15.1"'; +const iosMinTarget = GRAPHITE ? '"15.1"' : '"13.0"'; export const configurations = { android: { @@ -246,9 +246,12 @@ export const copyHeaders = () => { "cp -a ../../externals/skia/src/core/SkChecksum.h ./cpp/skia/src/core/.", "cp -a ../../externals/skia/src/core/SkTHash.h ./cpp/skia/src/core/.", - // TODO: remove ganesh - "mkdir -p ./cpp/skia/src/gpu/ganesh/gl", - "cp -a ../../externals/skia/src/gpu/ganesh/gl/GrGLDefines.h ./cpp/skia/src/gpu/ganesh/gl/.", + ...(GRAPHITE + ? [] + : [ + "mkdir -p ./cpp/skia/src/gpu/ganesh/gl", + "cp -a ../../externals/skia/src/gpu/ganesh/gl/GrGLDefines.h ./cpp/skia/src/gpu/ganesh/gl/.", + ]), "cp -a ../../externals/skia/src/core/SkLRUCache.h ./cpp/skia/src/core/.", From 7abff28db0a77f1d74a9d96c69f79788c3144df1 Mon Sep 17 00:00:00 2001 From: William Candillon Date: Thu, 14 Nov 2024 12:02:09 +0100 Subject: [PATCH 03/13] :wrench: --- packages/skia/android/CMakeLists.txt | 64 +++++++++++++++---- .../reactnative/skia/SkiaBaseView.java | 1 - 2 files changed, 53 insertions(+), 12 deletions(-) diff --git a/packages/skia/android/CMakeLists.txt b/packages/skia/android/CMakeLists.txt index 9032c9b74e..c1db67b5c4 100644 --- a/packages/skia/android/CMakeLists.txt +++ b/packages/skia/android/CMakeLists.txt @@ -3,8 +3,8 @@ cmake_minimum_required(VERSION 3.4.1) set (CMAKE_VERBOSE_MAKEFILE ON) set (CMAKE_CXX_STANDARD 17) -set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSK_GL -DSK_GANESH -DSK_BUILD_FOR_ANDROID -DFOLLY_NO_CONFIG=1 -DFOLLY_HAVE_CLOCK_GETTIME=1 -DFOLLY_HAVE_MEMRCHR=1 -DFOLLY_USE_LIBCPP=1 -DFOLLY_MOBILE=1 -DON_ANDROID -DONANDROID") - +set(SK_GRAPHITE OFF) +set (CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DSK_BUILD_FOR_ANDROID -DFOLLY_NO_CONFIG=1 -DFOLLY_HAVE_CLOCK_GETTIME=1 -DFOLLY_HAVE_MEMRCHR=1 -DFOLLY_USE_LIBCPP=1 -DFOLLY_MOBILE=1 -DON_ANDROID -DONANDROID") set (PACKAGE_NAME "rnskia") set (SKIA_LIB "skia") set (SKIA_SVG_LIB "svg") @@ -13,6 +13,7 @@ set (SKIA_SKPARAGRAPH_LIB "skparagraph") set (SKIA_SKUNICODE_CORE_LIB "skunicode_core") set (SKIA_SKUNICODE_ICU_LIB "skunicode_icu") + # Clear some variables unset(LIBRN_DIR CACHE) unset(libfbjni_link_DIRS CACHE) @@ -30,6 +31,36 @@ message("-- LIBRN : " ${LIBRN_DIR}) link_directories(../libs/android/${ANDROID_ABI}/) +# Import prebuilt SKIA libraries +set (SKIA_LIBS_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../libs/android/${ANDROID_ABI}") + +if(SK_GRAPHITE) + add_definitions(-DSK_GRAPHITE) + set(DAWN_NATIVE_LIB "libdawn_native_static") + set(DAWN_PLATFORM_LIB "libdawn_platform_static") + set(DAWN_PROC_LIB "libdawn_proc_static") + set(BACKEND_SOURCES + "" + ) + # "${PROJECT_SOURCE_DIR}/../cpp/rnskia/DawnWindowContext.cpp" + add_library(libdawn_native_static STATIC IMPORTED) + set_property(TARGET libdawn_native_static PROPERTY IMPORTED_LOCATION "${SKIA_LIBS_PATH}/libdawn_native_static.a") + + add_library(libdawn_platform_static STATIC IMPORTED) + set_property(TARGET libdawn_platform_static PROPERTY IMPORTED_LOCATION "${SKIA_LIBS_PATH}/libdawn_platform_static.a") + + add_library(libdawn_proc_static STATIC IMPORTED) + set_property(TARGET libdawn_proc_static PROPERTY IMPORTED_LOCATION "${SKIA_LIBS_PATH}/libdawn_proc_static.a") +else() + add_definitions(-DSK_GL -DSK_GANESH) + set(BACKEND_SOURCES + "${PROJECT_SOURCE_DIR}/cpp/rnskia-android/SkiaOpenGLSurfaceFactory.cpp" + "${PROJECT_SOURCE_DIR}/cpp/rnskia-android/GrAHardwareBufferUtils.cpp" + "${PROJECT_SOURCE_DIR}/cpp/rnskia-android/AHardwareBufferUtils.cpp" + "${PROJECT_SOURCE_DIR}/cpp/rnskia-android/RNSkAndroidVideo.cpp" + ) +endif() + if(${REACT_NATIVE_VERSION} LESS 66) file( TO_CMAKE_PATH @@ -66,7 +97,7 @@ add_library( "${PROJECT_SOURCE_DIR}/../cpp/api/third_party/CSSColorParser.cpp" "${PROJECT_SOURCE_DIR}/../cpp/api/third_party/base64.cpp" - + ${BACKEND_SOURCES} ) target_include_directories( @@ -88,6 +119,7 @@ target_include_directories( # so "include/core/SkRef.h" instead of "SkRef.h", as otherwise # the prefab cannot be shipped. ../cpp/skia + ../cpp/dawn/include ../cpp/api ../cpp/jsi @@ -102,9 +134,6 @@ target_include_directories( ${libfbjni_include_DIRS} ) -# Import prebuilt SKIA libraries -set (SKIA_LIBS_PATH "${CMAKE_CURRENT_SOURCE_DIR}/../libs/android/${ANDROID_ABI}") - add_library(skia STATIC IMPORTED) set_property(TARGET skia PROPERTY IMPORTED_LOCATION "${SKIA_LIBS_PATH}/libskia.a") @@ -240,8 +269,7 @@ add_definitions(-DREACT_NATIVE_VERSION=${REACT_NATIVE_VERSION}) # Link if(${REACT_NATIVE_VERSION} GREATER_EQUAL 76) - target_link_libraries( - ${PACKAGE_NAME} + set(COMMON_LIBS ${LOG_LIB} ${REACT_LIB} ${FBJNI_LIBRARY} @@ -258,8 +286,7 @@ if(${REACT_NATIVE_VERSION} GREATER_EQUAL 76) -landroid ) else() - target_link_libraries( - ${PACKAGE_NAME} + set(COMMON_LIBS ${LOG_LIB} ${FBJNI_LIBRARY} ${REACT_LIB} @@ -278,4 +305,19 @@ else() -lEGL -landroid ) -endif() \ No newline at end of file +endif() + +if(SK_GRAPHITE) + target_link_libraries(${PACKAGE_NAME} + ${COMMON_LIBS} + ${DAWN_NATIVE_LIB} + ${DAWN_PLATFORM_LIB} + ${DAWN_PROC_LIB} + ) +else() + target_link_libraries(${PACKAGE_NAME} + ${COMMON_LIBS} + -lGLESv2 + -lEGL + ) +endif() diff --git a/packages/skia/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java b/packages/skia/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java index f3dd928a8e..af546b130b 100644 --- a/packages/skia/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java +++ b/packages/skia/android/src/main/java/com/shopify/reactnative/skia/SkiaBaseView.java @@ -3,7 +3,6 @@ import android.content.Context; import android.graphics.SurfaceTexture; import android.util.Log; -import android.view.MotionEvent; import android.view.TextureView; import com.facebook.react.views.view.ReactViewGroup; From a5a08a698b447b65a3952c984d3df3989f59ffe2 Mon Sep 17 00:00:00 2001 From: William Candillon Date: Thu, 14 Nov 2024 12:07:11 +0100 Subject: [PATCH 04/13] :green_heart: --- packages/skia/android/CMakeLists.txt | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/packages/skia/android/CMakeLists.txt b/packages/skia/android/CMakeLists.txt index c1db67b5c4..df9c491e59 100644 --- a/packages/skia/android/CMakeLists.txt +++ b/packages/skia/android/CMakeLists.txt @@ -77,10 +77,6 @@ add_library( "${PROJECT_SOURCE_DIR}/cpp/jni/JniPlatformContext.cpp" "${PROJECT_SOURCE_DIR}/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp" - "${PROJECT_SOURCE_DIR}/cpp/rnskia-android/SkiaOpenGLSurfaceFactory.cpp" - "${PROJECT_SOURCE_DIR}/cpp/rnskia-android/GrAHardwareBufferUtils.cpp" - "${PROJECT_SOURCE_DIR}/cpp/rnskia-android/AHardwareBufferUtils.cpp" - "${PROJECT_SOURCE_DIR}/cpp/rnskia-android/RNSkAndroidVideo.cpp" "${PROJECT_SOURCE_DIR}/../cpp/jsi/JsiHostObject.cpp" "${PROJECT_SOURCE_DIR}/../cpp/jsi/JsiValue.cpp" @@ -100,6 +96,7 @@ add_library( ${BACKEND_SOURCES} ) + target_include_directories( ${PACKAGE_NAME} PRIVATE From 5e342daaed8586512705156318b7bdaff0775e3c Mon Sep 17 00:00:00 2001 From: William Candillon Date: Thu, 14 Nov 2024 12:29:50 +0100 Subject: [PATCH 05/13] :wrench: --- packages/skia/android/CMakeLists.txt | 8 +- .../RNSkAndroidPlatformContext.h | 23 ++- .../cpp/rnskia-android/RNSkAndroidVideo.cpp | 13 +- .../RNSkOpenGLCanvasProvider.cpp | 14 ++ packages/skia/cpp/rnskia/DawnContext.h | 172 ++++++++++++++++++ packages/skia/cpp/rnskia/DawnUtils.h | 117 ++++++++++++ .../skia/cpp/rnskia/DawnWindowContext.cpp | 19 ++ packages/skia/cpp/rnskia/DawnWindowContext.h | 77 ++++++++ packages/skia/cpp/rnskia/ImageProvider.h | 100 ++++++++++ 9 files changed, 535 insertions(+), 8 deletions(-) create mode 100644 packages/skia/cpp/rnskia/DawnContext.h create mode 100644 packages/skia/cpp/rnskia/DawnUtils.h create mode 100644 packages/skia/cpp/rnskia/DawnWindowContext.cpp create mode 100644 packages/skia/cpp/rnskia/DawnWindowContext.h create mode 100644 packages/skia/cpp/rnskia/ImageProvider.h diff --git a/packages/skia/android/CMakeLists.txt b/packages/skia/android/CMakeLists.txt index df9c491e59..05ddb70e42 100644 --- a/packages/skia/android/CMakeLists.txt +++ b/packages/skia/android/CMakeLists.txt @@ -40,9 +40,9 @@ if(SK_GRAPHITE) set(DAWN_PLATFORM_LIB "libdawn_platform_static") set(DAWN_PROC_LIB "libdawn_proc_static") set(BACKEND_SOURCES - "" + #TODO: is this source needed to be added? + "${PROJECT_SOURCE_DIR}/../cpp/rnskia/DawnWindowContext.cpp" ) - # "${PROJECT_SOURCE_DIR}/../cpp/rnskia/DawnWindowContext.cpp" add_library(libdawn_native_static STATIC IMPORTED) set_property(TARGET libdawn_native_static PROPERTY IMPORTED_LOCATION "${SKIA_LIBS_PATH}/libdawn_native_static.a") @@ -56,8 +56,6 @@ else() set(BACKEND_SOURCES "${PROJECT_SOURCE_DIR}/cpp/rnskia-android/SkiaOpenGLSurfaceFactory.cpp" "${PROJECT_SOURCE_DIR}/cpp/rnskia-android/GrAHardwareBufferUtils.cpp" - "${PROJECT_SOURCE_DIR}/cpp/rnskia-android/AHardwareBufferUtils.cpp" - "${PROJECT_SOURCE_DIR}/cpp/rnskia-android/RNSkAndroidVideo.cpp" ) endif() @@ -77,6 +75,8 @@ add_library( "${PROJECT_SOURCE_DIR}/cpp/jni/JniPlatformContext.cpp" "${PROJECT_SOURCE_DIR}/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp" + "${PROJECT_SOURCE_DIR}/cpp/rnskia-android/AHardwareBufferUtils.cpp" + "${PROJECT_SOURCE_DIR}/cpp/rnskia-android/RNSkAndroidVideo.cpp"OpenGLContext.h "${PROJECT_SOURCE_DIR}/../cpp/jsi/JsiHostObject.cpp" "${PROJECT_SOURCE_DIR}/../cpp/jsi/JsiValue.cpp" diff --git a/packages/skia/android/cpp/rnskia-android/RNSkAndroidPlatformContext.h b/packages/skia/android/cpp/rnskia-android/RNSkAndroidPlatformContext.h index d1b9715cad..ae6a0e6435 100644 --- a/packages/skia/android/cpp/rnskia-android/RNSkAndroidPlatformContext.h +++ b/packages/skia/android/cpp/rnskia-android/RNSkAndroidPlatformContext.h @@ -9,9 +9,14 @@ #include #include +#if defined(SK_GRAPHITE) +#include "DawnContext.h" +#else +#include "OpenGLContext.h" +#endif + #include "AHardwareBufferUtils.h" #include "JniPlatformContext.h" -#include "OpenGLContext.h" #include "RNSkAndroidVideo.h" #include "RNSkPlatformContext.h" @@ -51,17 +56,29 @@ class RNSkAndroidPlatformContext : public RNSkPlatformContext { } sk_sp makeOffscreenSurface(int width, int height) override { +#if defined(SK_GRAPHITE) + return DawnContext::getInstance().MakeOffscreen(width, height); +#else return OpenGLContext::getInstance().MakeOffscreen(width, height); +#endif } std::shared_ptr makeContextFromNativeSurface(void *surface, int width, int height) override { - return OpenGLContext::getInstance().MakeWindow( +#if defined(SK_GRAPHITE) + return DawnContext::getInstance().MakeWindow(surface, width, height); +#else + return OpenGLContext::getInstance().MakeWindow( reinterpret_cast(surface), width, height); +#endif } sk_sp makeImageFromNativeBuffer(void *buffer) override { - return OpenGLContext::getInstance().MakeImageFromBuffer(buffer); +#if defined(SK_GRAPHITE) + return DawnContext::getInstance().MakeImageFromBuffer(buffer); +#else + return OpenGLContext::getInstance().MakeImageFromBuffer(buffer); +#endif } std::shared_ptr createVideo(const std::string &url) override { diff --git a/packages/skia/android/cpp/rnskia-android/RNSkAndroidVideo.cpp b/packages/skia/android/cpp/rnskia-android/RNSkAndroidVideo.cpp index 545016c883..5b3222d7d7 100644 --- a/packages/skia/android/cpp/rnskia-android/RNSkAndroidVideo.cpp +++ b/packages/skia/android/cpp/rnskia-android/RNSkAndroidVideo.cpp @@ -5,6 +5,14 @@ #include #endif +#include "RNSkLog.h" + +#if defined(SK_GRAPHITE) +#include "DawnContext.h" +#else +#include "OpenGLContext.h" +#endif + #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdocumentation" @@ -13,7 +21,6 @@ #pragma clang diagnostic pop -#include "OpenGLContext.h" #include "RNSkAndroidVideo.h" namespace RNSkia { @@ -52,7 +59,11 @@ sk_sp RNSkAndroidVideo::nextImage(double *timeStamp) { // Convert jobject to AHardwareBuffer AHardwareBuffer *buffer = AHardwareBuffer_fromHardwareBuffer(env, jHardwareBuffer); +#if defined(SK_GRAPHITE) + return DawnContext::getInstance().MakeImageFromBuffer(buffer); +#else return OpenGLContext::getInstance().MakeImageFromBuffer(buffer); +#endif #else return nullptr; #endif diff --git a/packages/skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp b/packages/skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp index 1d38df52aa..d740422bb6 100644 --- a/packages/skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp +++ b/packages/skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp @@ -1,8 +1,17 @@ #include "RNSkOpenGLCanvasProvider.h" #include +#include +#include +#include +#include "RNSkLog.h" + +#if defined(SK_GRAPHITE) +#include "DawnContext.h" +#else #include "OpenGLContext.h" +#endif #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdocumentation" @@ -89,8 +98,13 @@ void RNSkOpenGLCanvasProvider::surfaceAvailable(jobject jSurfaceTexture, env->DeleteLocalRef(jSurface); env->DeleteLocalRef(surfaceClass); env->DeleteLocalRef(surfaceTextureClass); +#if defined(SK_GRAPHITE) + _surfaceHolder = + DawnContext::getInstance().MakeWindow(window, width, height); +#else _surfaceHolder = OpenGLContext::getInstance().MakeWindow(window, width, height); +#endif // Post redraw request to ensure we paint in the next draw cycle. _requestRedraw(); diff --git a/packages/skia/cpp/rnskia/DawnContext.h b/packages/skia/cpp/rnskia/DawnContext.h new file mode 100644 index 0000000000..025cb83064 --- /dev/null +++ b/packages/skia/cpp/rnskia/DawnContext.h @@ -0,0 +1,172 @@ +#pragma once + +#include +#include + +#include "DawnUtils.h" +#include "DawnWindowContext.h" +#include "ImageProvider.h" + +#include "include/core/SkData.h" +#include "include/gpu/graphite/BackendTexture.h" +#include "include/gpu/graphite/Context.h" +#include "include/gpu/graphite/ContextOptions.h" +#include "include/gpu/graphite/GraphiteTypes.h" +#include "include/gpu/graphite/Recorder.h" +#include "include/gpu/graphite/Recording.h" +#include "include/gpu/graphite/Surface.h" +#include "include/gpu/graphite/dawn/DawnBackendContext.h" +#include "include/gpu/graphite/dawn/DawnTypes.h" +#include "include/gpu/graphite/dawn/DawnUtils.h" + +#include "src/gpu/graphite/ContextOptionsPriv.h" + +namespace RNSkia { + +struct AsyncContext { + bool fCalled = false; + std::unique_ptr fResult; +}; + +static void +async_callback(void *c, + std::unique_ptr result) { + auto context = static_cast(c); + context->fResult = std::move(result); + context->fCalled = true; +} + +class DawnContext { +public: + DawnContext(const DawnContext &) = delete; + DawnContext &operator=(const DawnContext &) = delete; + + static DawnContext &getInstance() { + static DawnContext instance; + return instance; + } + + sk_sp MakeRasterImage(sk_sp image) { + if (!image->isTextureBacked()) { + return image; + } + std::lock_guard lock(_mutex); + AsyncContext asyncContext; + fGraphiteContext->asyncRescaleAndReadPixels( + image.get(), image->imageInfo(), image->imageInfo().bounds(), + SkImage::RescaleGamma::kSrc, SkImage::RescaleMode::kNearest, + async_callback, &asyncContext); + fGraphiteContext->submit(); + while (!asyncContext.fCalled) { + tick(); + fGraphiteContext->checkAsyncWorkCompletion(); + } + auto bytesPerRow = asyncContext.fResult->rowBytes(0); + auto bufferSize = bytesPerRow * image->imageInfo().height(); + auto data = SkData::MakeWithProc( + asyncContext.fResult->data(0), bufferSize, + [](const void *ptr, void *context) { + auto *result = + reinterpret_cast(context); + delete result; + }, + reinterpret_cast(const_cast( + asyncContext.fResult.release()))); + auto rasterImage = + SkImages::RasterFromData(image->imageInfo(), data, bytesPerRow); + return rasterImage; + } + + void submitRecording( + skgpu::graphite::Recording *recording, + skgpu::graphite::SyncToCpu syncToCpu = skgpu::graphite::SyncToCpu::kNo) { + std::lock_guard lock(_mutex); + skgpu::graphite::InsertRecordingInfo info; + info.fRecording = recording; + fGraphiteContext->insertRecording(info); + fGraphiteContext->submit(syncToCpu); + } + + sk_sp MakeImageFromBuffer(void *buffer) { + // TODO: implement + return nullptr; + } + + // Create offscreen surface + sk_sp MakeOffscreen(int width, int height) { + SkImageInfo info = SkImageInfo::Make( + width, height, DawnUtils::PreferedColorType, kPremul_SkAlphaType); + sk_sp surface = SkSurfaces::RenderTarget(getRecorder(), info); + + if (!surface) { + throw std::runtime_error("Failed to create offscreen Skia surface."); + } + + return surface; + } + + // Create onscreen surface with window + std::unique_ptr MakeWindow(void *window, int width, + int height) { + // 1. Create Surface + wgpu::SurfaceDescriptor surfaceDescriptor; +#ifdef __APPLE__ + wgpu::SurfaceDescriptorFromMetalLayer metalSurfaceDesc; + metalSurfaceDesc.layer = window; + surfaceDescriptor.nextInChain = &metalSurfaceDesc; +#else + wgpu::SurfaceDescriptorFromAndroidNativeWindow androidSurfaceDesc; + androidSurfaceDesc.window = window; + surfaceDescriptor.nextInChain = &androidSurfaceDesc; +#endif + auto surface = + wgpu::Instance(instance->Get()).CreateSurface(&surfaceDescriptor); + return std::make_unique( + getRecorder(), backendContext.fDevice, surface, width, height); + } + +private: + std::unique_ptr instance; + std::unique_ptr fGraphiteContext; + skgpu::graphite::DawnBackendContext backendContext; + std::mutex _mutex; + + DawnContext() { + DawnProcTable backendProcs = dawn::native::GetProcs(); + dawnProcSetProcs(&backendProcs); + WGPUInstanceDescriptor desc{}; + desc.features.timedWaitAnyEnable = true; + instance = std::make_unique(&desc); + + backendContext = DawnUtils::createDawnBackendContext(instance.get()); + + skgpu::graphite::ContextOptions ctxOptions; + skgpu::graphite::ContextOptionsPriv contextOptionsPriv; + ctxOptions.fOptionsPriv = &contextOptionsPriv; + ctxOptions.fOptionsPriv->fStoreContextRefInRecorder = true; + fGraphiteContext = + skgpu::graphite::ContextFactory::MakeDawn(backendContext, ctxOptions); + + if (!fGraphiteContext) { + throw std::runtime_error("Failed to create graphite context"); + } + } + + void tick() { backendContext.fTick(backendContext.fInstance); } + + skgpu::graphite::Recorder *getRecorder() { + static thread_local skgpu::graphite::RecorderOptions recorderOptions; + if (!recorderOptions.fImageProvider) { + auto imageProvider = ImageProvider::Make(); + recorderOptions.fImageProvider = imageProvider; + } + static thread_local auto recorder = + fGraphiteContext->makeRecorder(recorderOptions); + if (!recorder) { + throw std::runtime_error("Failed to create graphite context"); + } + return recorder.get(); + } +}; + +} // namespace RNSkia \ No newline at end of file diff --git a/packages/skia/cpp/rnskia/DawnUtils.h b/packages/skia/cpp/rnskia/DawnUtils.h new file mode 100644 index 0000000000..a06fc1c181 --- /dev/null +++ b/packages/skia/cpp/rnskia/DawnUtils.h @@ -0,0 +1,117 @@ +#pragma once + +#include "webgpu/webgpu_cpp.h" + +#include "dawn/dawn_proc.h" +#include "dawn/native/DawnNative.h" + +#include "include/core/SkColorType.h" +#include "include/gpu/graphite/dawn/DawnBackendContext.h" + +namespace DawnUtils { + +#ifdef __APPLE__ +static const SkColorType PreferedColorType = kBGRA_8888_SkColorType; +static const wgpu::TextureFormat PreferredTextureFormat = + wgpu::TextureFormat::BGRA8Unorm; +#else +static const SkColorType PreferedColorType = kRGBA_8888_SkColorType; +static const wgpu::TextureFormat PreferredTextureFormat = + wgpu::TextureFormat::RGBA8Unorm; +#endif + +inline skgpu::graphite::DawnBackendContext +createDawnBackendContext(dawn::native::Instance *instance) { + + auto useTintIR = false; + static constexpr const char *kToggles[] = { + "allow_unsafe_apis", + "use_user_defined_labels_in_backend", + "disable_robustness", + "use_tint_ir", + }; + wgpu::DawnTogglesDescriptor togglesDesc; + togglesDesc.enabledToggleCount = std::size(kToggles) - (useTintIR ? 0 : 1); + togglesDesc.enabledToggles = kToggles; + + wgpu::RequestAdapterOptions options; +#ifdef __APPLE__ + constexpr auto kDefaultBackendType = wgpu::BackendType::Metal; +#elif __ANDROID__ + constexpr auto kDefaultBackendType = wgpu::BackendType::Vulkan; +#endif + options.backendType = kDefaultBackendType; + options.nextInChain = &togglesDesc; + + std::vector adapters = + instance->EnumerateAdapters(&options); + if (adapters.empty()) { + throw std::runtime_error("No matching adapter found"); + } + + wgpu::Adapter adapter = adapters[0].Get(); + + std::vector features; + if (adapter.HasFeature(wgpu::FeatureName::MSAARenderToSingleSampled)) { + features.push_back(wgpu::FeatureName::MSAARenderToSingleSampled); + } + if (adapter.HasFeature(wgpu::FeatureName::TransientAttachments)) { + features.push_back(wgpu::FeatureName::TransientAttachments); + } + if (adapter.HasFeature(wgpu::FeatureName::Unorm16TextureFormats)) { + features.push_back(wgpu::FeatureName::Unorm16TextureFormats); + } + if (adapter.HasFeature(wgpu::FeatureName::DualSourceBlending)) { + features.push_back(wgpu::FeatureName::DualSourceBlending); + } + if (adapter.HasFeature(wgpu::FeatureName::FramebufferFetch)) { + features.push_back(wgpu::FeatureName::FramebufferFetch); + } + if (adapter.HasFeature(wgpu::FeatureName::BufferMapExtendedUsages)) { + features.push_back(wgpu::FeatureName::BufferMapExtendedUsages); + } + if (adapter.HasFeature(wgpu::FeatureName::TextureCompressionETC2)) { + features.push_back(wgpu::FeatureName::TextureCompressionETC2); + } + if (adapter.HasFeature(wgpu::FeatureName::TextureCompressionBC)) { + features.push_back(wgpu::FeatureName::TextureCompressionBC); + } + if (adapter.HasFeature(wgpu::FeatureName::R8UnormStorage)) { + features.push_back(wgpu::FeatureName::R8UnormStorage); + } + if (adapter.HasFeature(wgpu::FeatureName::DawnLoadResolveTexture)) { + features.push_back(wgpu::FeatureName::DawnLoadResolveTexture); + } + if (adapter.HasFeature(wgpu::FeatureName::DawnPartialLoadResolveTexture)) { + features.push_back(wgpu::FeatureName::DawnPartialLoadResolveTexture); + } + + wgpu::DeviceDescriptor desc; + desc.requiredFeatureCount = features.size(); + desc.requiredFeatures = features.data(); + desc.nextInChain = &togglesDesc; + desc.SetDeviceLostCallback( + wgpu::CallbackMode::AllowSpontaneous, + [](const wgpu::Device &, wgpu::DeviceLostReason reason, + const char *message) { + if (reason != wgpu::DeviceLostReason::Destroyed) { + SK_ABORT("Device lost: %s\n", message); + } + }); + desc.SetUncapturedErrorCallback( + [](const wgpu::Device &, wgpu::ErrorType, const char *message) { + SkDebugf("Device error: %s\n", message); + }); + + wgpu::Device device = adapter.CreateDevice(&desc); + SkASSERT(device); + + skgpu::graphite::DawnBackendContext backendContext; + backendContext.fInstance = wgpu::Instance(instance->Get()); + backendContext.fDevice = device; + backendContext.fQueue = device.GetQueue(); + + return backendContext; +} + +} // namespace DawnUtils \ No newline at end of file diff --git a/packages/skia/cpp/rnskia/DawnWindowContext.cpp b/packages/skia/cpp/rnskia/DawnWindowContext.cpp new file mode 100644 index 0000000000..d84780a5fe --- /dev/null +++ b/packages/skia/cpp/rnskia/DawnWindowContext.cpp @@ -0,0 +1,19 @@ +#include "DawnWindowContext.h" + +#include "DawnContext.h" + +namespace RNSkia { + +void DawnWindowContext::present() { + auto recording = _recorder->snap(); + if (!recording) { + throw std::runtime_error("Failed to create graphite recording"); + } + DawnContext::getInstance().submitRecording(recording.get()); +#ifdef __APPLE__ + dawn::native::metal::WaitForCommandsToBeScheduled(_device.Get()); +#endif + _surface.Present(); +} + +} // namespace RNSkia \ No newline at end of file diff --git a/packages/skia/cpp/rnskia/DawnWindowContext.h b/packages/skia/cpp/rnskia/DawnWindowContext.h new file mode 100644 index 0000000000..b93e8c8aa2 --- /dev/null +++ b/packages/skia/cpp/rnskia/DawnWindowContext.h @@ -0,0 +1,77 @@ +#pragma once + +#include "DawnUtils.h" +#include "WindowContext.h" + +#include "dawn/native/MetalBackend.h" +#include "webgpu/webgpu_cpp.h" + +#include "include/core/SkColorSpace.h" + +#include "include/gpu/graphite/BackendTexture.h" +#include "include/gpu/graphite/Context.h" +#include "include/gpu/graphite/ContextOptions.h" +#include "include/gpu/graphite/GraphiteTypes.h" +#include "include/gpu/graphite/Recorder.h" +#include "include/gpu/graphite/Recording.h" +#include "include/gpu/graphite/Surface.h" +#include "include/gpu/graphite/dawn/DawnBackendContext.h" +#include "include/gpu/graphite/dawn/DawnTypes.h" +#include "include/gpu/graphite/dawn/DawnUtils.h" + +namespace RNSkia { + +class DawnWindowContext : public WindowContext { +public: + DawnWindowContext(skgpu::graphite::Recorder *recorder, wgpu::Device device, + wgpu::Surface surface, int width, int height) + : _recorder(recorder), _device(device), _surface(surface), _width(width), + _height(height) { + wgpu::SurfaceConfiguration config; + config.device = _device; + config.format = DawnUtils::PreferredTextureFormat; + config.width = _width; + config.height = _height; +#ifdef __APPLE__ + config.alphaMode = wgpu::CompositeAlphaMode::Premultiplied; +#endif + _surface.Configure(&config); + } + + sk_sp getSurface() override { + wgpu::SurfaceTexture surfaceTexture; + _surface.GetCurrentTexture(&surfaceTexture); + auto texture = surfaceTexture.texture; + skgpu::graphite::DawnTextureInfo info( + /*sampleCount=*/1, skgpu::Mipmapped::kNo, + DawnUtils::PreferredTextureFormat, texture.GetUsage(), + wgpu::TextureAspect::All); + auto backendTex = skgpu::graphite::BackendTextures::MakeDawn(texture.Get()); + sk_sp colorSpace = SkColorSpace::MakeSRGB(); + SkSurfaceProps surfaceProps; + auto surface = SkSurfaces::WrapBackendTexture(_recorder, backendTex, + DawnUtils::PreferedColorType, + colorSpace, &surfaceProps); + return surface; + } + + void present() override; + + void resize(int width, int height) override { + throw std::runtime_error("resize not implemented yet"); + } + + int getWidth() override { return _width; } + + int getHeight() override { return _height; } + +private: + skgpu::graphite::Recorder *_recorder; + // TODO: keep device in DawnContext? Do we need it for resizing? + wgpu::Device _device; + wgpu::Surface _surface; + int _width; + int _height; +}; + +} // namespace RNSkia \ No newline at end of file diff --git a/packages/skia/cpp/rnskia/ImageProvider.h b/packages/skia/cpp/rnskia/ImageProvider.h new file mode 100644 index 0000000000..b4dff20062 --- /dev/null +++ b/packages/skia/cpp/rnskia/ImageProvider.h @@ -0,0 +1,100 @@ +#pragma once + +#include "include/core/SkCanvas.h" +#include "include/core/SkImage.h" + +#include "include/core/SkTiledImageUtils.h" +#include "include/gpu/graphite/Image.h" +#include "include/gpu/graphite/ImageProvider.h" +#include "include/gpu/graphite/Recorder.h" +#include "src/core/SkLRUCache.h" + +namespace RNSkia { + +// Currently, we give each new Recorder its own ImageProvider. This means we +// don't have to deal w/ any threading issues. +// TODO: We should probably have this class generate and report some cache stats +// TODO: Hook up to listener system? +// TODO: add testing of a single ImageProvider passed to multiple recorders +class ImageProvider : public skgpu::graphite::ImageProvider { +public: + ImageProvider() : fCache(kDefaultNumCachedImages) {} + ~ImageProvider() override {} + + static sk_sp Make() { return sk_ref_sp(new ImageProvider); } + + sk_sp + findOrCreate(skgpu::graphite::Recorder *recorder, const SkImage *image, + SkImage::RequiredProperties requiredProps) override { + if (!requiredProps.fMipmapped) { + // If no mipmaps are required, check to see if we have a mipmapped version + // anyway - since it can be used in that case. + // TODO: we could get fancy and, if ever a mipmapped key eclipsed a + // non-mipmapped key, we could remove the hidden non-mipmapped key/image + // from the cache. + ImageKey mipMappedKey(image, /* mipmapped= */ true); + auto result = fCache.find(mipMappedKey); + if (result) { + return *result; + } + } + + ImageKey key(image, requiredProps.fMipmapped); + + auto result = fCache.find(key); + if (result) { + return *result; + } + + sk_sp newImage = + SkImages::TextureFromImage(recorder, image, requiredProps); + if (!newImage) { + return nullptr; + } + + result = fCache.insert(key, std::move(newImage)); + SkASSERT(result); + + return *result; + } + +private: + static constexpr int kDefaultNumCachedImages = 256; + + class ImageKey { + public: + ImageKey(const SkImage *image, bool mipmapped) { + uint32_t flags = mipmapped ? 0x1 : 0x0; + SkTiledImageUtils::GetImageKeyValues(image, &fValues[1]); + fValues[kNumValues - 1] = flags; + fValues[0] = + SkChecksum::Hash32(&fValues[1], (kNumValues - 1) * sizeof(uint32_t)); + } + + uint32_t hash() const { return fValues[0]; } + + bool operator==(const ImageKey &other) const { + for (int i = 0; i < kNumValues; ++i) { + if (fValues[i] != other.fValues[i]) { + return false; + } + } + + return true; + } + bool operator!=(const ImageKey &other) const { return !(*this == other); } + + private: + static const int kNumValues = SkTiledImageUtils::kNumImageKeyValues + 2; + + uint32_t fValues[kNumValues]; + }; + + struct ImageHash { + size_t operator()(const ImageKey &key) const { return key.hash(); } + }; + + SkLRUCache, ImageHash> fCache; +}; + +} // namespace RNSkia \ No newline at end of file From 92fd67daef47831911ac5f4a2d017cda7c07927c Mon Sep 17 00:00:00 2001 From: William Candillon Date: Thu, 14 Nov 2024 12:31:51 +0100 Subject: [PATCH 06/13] :green_heart: --- packages/skia/scripts/skia-configuration.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/skia/scripts/skia-configuration.ts b/packages/skia/scripts/skia-configuration.ts index 40a4b82ceb..a29cd2cf26 100644 --- a/packages/skia/scripts/skia-configuration.ts +++ b/packages/skia/scripts/skia-configuration.ts @@ -4,7 +4,7 @@ import path from "path"; import { $ } from "./utils"; const DEBUG = false; -const GRAPHITE = true; +const GRAPHITE = false; const BUILD_WITH_PARAGRAPH = true; export const SkiaSrc = path.join(__dirname, "../../../externals/skia"); From 1065f1e943125bc1d5601a55628dc54b74e20213 Mon Sep 17 00:00:00 2001 From: William Candillon Date: Thu, 14 Nov 2024 12:41:43 +0100 Subject: [PATCH 07/13] :green_heart: --- packages/skia/android/CMakeLists.txt | 2 +- packages/skia/scripts/skia-configuration.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/skia/android/CMakeLists.txt b/packages/skia/android/CMakeLists.txt index 05ddb70e42..e1efb49fb8 100644 --- a/packages/skia/android/CMakeLists.txt +++ b/packages/skia/android/CMakeLists.txt @@ -76,7 +76,7 @@ add_library( "${PROJECT_SOURCE_DIR}/cpp/jni/JniPlatformContext.cpp" "${PROJECT_SOURCE_DIR}/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp" "${PROJECT_SOURCE_DIR}/cpp/rnskia-android/AHardwareBufferUtils.cpp" - "${PROJECT_SOURCE_DIR}/cpp/rnskia-android/RNSkAndroidVideo.cpp"OpenGLContext.h + "${PROJECT_SOURCE_DIR}/cpp/rnskia-android/RNSkAndroidVideo.cpp" "${PROJECT_SOURCE_DIR}/../cpp/jsi/JsiHostObject.cpp" "${PROJECT_SOURCE_DIR}/../cpp/jsi/JsiValue.cpp" diff --git a/packages/skia/scripts/skia-configuration.ts b/packages/skia/scripts/skia-configuration.ts index a29cd2cf26..9781c4016e 100644 --- a/packages/skia/scripts/skia-configuration.ts +++ b/packages/skia/scripts/skia-configuration.ts @@ -4,7 +4,7 @@ import path from "path"; import { $ } from "./utils"; const DEBUG = false; -const GRAPHITE = false; +const GRAPHITE = !!process.env.SK_GRAPHITE; const BUILD_WITH_PARAGRAPH = true; export const SkiaSrc = path.join(__dirname, "../../../externals/skia"); From 243baa43251de78cceb4b7402ea332b041e6d02b Mon Sep 17 00:00:00 2001 From: William Candillon Date: Thu, 14 Nov 2024 13:25:46 +0100 Subject: [PATCH 08/13] :green_heart: --- apps/paper/ios/Podfile.lock | 2 +- packages/skia/react-native-skia.podspec | 8 ++++++++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/apps/paper/ios/Podfile.lock b/apps/paper/ios/Podfile.lock index ffc37254c4..70fbb6cc2b 100644 --- a/apps/paper/ios/Podfile.lock +++ b/apps/paper/ios/Podfile.lock @@ -1935,7 +1935,7 @@ SPEC CHECKSUMS: React-Mapbuffer: 1c08607305558666fd16678b85ef135e455d5c96 React-microtasksnativemodule: 87b8de96f937faefece8afd2cb3a518321b2ef99 react-native-safe-area-context: ab8f4a3d8180913bd78ae75dd599c94cce3d5e9a - react-native-skia: 89e0ec26e70ca4f34a7a1f7425bc955baf77c566 + react-native-skia: 1f36fe252564881d77ad424f84a8986098cc73b7 react-native-slider: 97ce0bd921f40de79cead9754546d5e4e7ba44f8 react-native-wgpu: 8d0437a304318e0e3d6ccbfed2a39880f8eae4dd React-nativeconfig: 57781b79e11d5af7573e6f77cbf1143b71802a6d diff --git a/packages/skia/react-native-skia.podspec b/packages/skia/react-native-skia.podspec index 477d0cc052..8a24dcecd3 100644 --- a/packages/skia/react-native-skia.podspec +++ b/packages/skia/react-native-skia.podspec @@ -64,6 +64,14 @@ Pod::Spec.new do |s| "cpp/**/*.{h,cpp}" ] + graphite_exclusions = [ + 'cpp/rnskia/DawnContext.h', + 'cpp/rnskia/DawnUtils.h', + 'cpp/rnskia/DawnWindowContext.h', + 'cpp/rnskia/DawnWindowContext.cpp', + 'cpp/rnskia/ImageProvider.h' + ] + s.exclude_files = graphite_exclusions unless use_graphite if defined?(install_modules_dependencies()) != nil install_modules_dependencies(s) From c79c1a6c2a54b2bbcfd348cad22e660dd6eabb6d Mon Sep 17 00:00:00 2001 From: William Candillon Date: Thu, 14 Nov 2024 14:55:14 +0100 Subject: [PATCH 09/13] =?UTF-8?q?=F0=9F=8D=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/skia/cpp/rnskia/DawnContext.h | 3 +++ .../ios/RNSkia-iOS/RNSkMetalCanvasProvider.mm | 12 ++++++++- .../ios/RNSkia-iOS/RNSkiOSPlatformContext.mm | 27 +++++++++++++++++-- 3 files changed, 39 insertions(+), 3 deletions(-) diff --git a/packages/skia/cpp/rnskia/DawnContext.h b/packages/skia/cpp/rnskia/DawnContext.h index 025cb83064..900c4ab579 100644 --- a/packages/skia/cpp/rnskia/DawnContext.h +++ b/packages/skia/cpp/rnskia/DawnContext.h @@ -38,6 +38,9 @@ async_callback(void *c, class DawnContext { public: + // TODO: remove + friend class RNSkiOSPlatformContext; + DawnContext(const DawnContext &) = delete; DawnContext &operator=(const DawnContext &) = delete; diff --git a/packages/skia/ios/RNSkia-iOS/RNSkMetalCanvasProvider.mm b/packages/skia/ios/RNSkia-iOS/RNSkMetalCanvasProvider.mm index c2f7cb889f..161c8c98e7 100644 --- a/packages/skia/ios/RNSkia-iOS/RNSkMetalCanvasProvider.mm +++ b/packages/skia/ios/RNSkia-iOS/RNSkMetalCanvasProvider.mm @@ -1,7 +1,13 @@ #import "RNSkMetalCanvasProvider.h" -#include "MetalContext.h" + #import "RNSkLog.h" +#if defined(SK_GRAPHITE) +#import "DawnContext.h" +#else +#import "MetalContext.h" +#endif + #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdocumentation" @@ -70,7 +76,11 @@ if (currentDrawable == nullptr) { return false; } +#if defined(SK_GRAPHITE) + auto ctx = RNSkia::DawnContext::getInstance().MakeWindow((__bridge void*)_layer, _width, _height); +#else auto ctx = MetalContext::getInstance().MakeWindow(_layer, _width, _height); +#endif auto skSurface = ctx->getSurface(); SkCanvas *canvas = skSurface->getCanvas(); cb(canvas); diff --git a/packages/skia/ios/RNSkia-iOS/RNSkiOSPlatformContext.mm b/packages/skia/ios/RNSkia-iOS/RNSkiOSPlatformContext.mm index cc9a1e4d0a..d998e0b8cb 100644 --- a/packages/skia/ios/RNSkia-iOS/RNSkiOSPlatformContext.mm +++ b/packages/skia/ios/RNSkia-iOS/RNSkiOSPlatformContext.mm @@ -5,7 +5,11 @@ #include #include +#if defined(SK_GRAPHITE) +#include "DawnContext.h" +#else #include "MetalContext.h" +#endif #include "RNSkiOSVideo.h" #pragma clang diagnostic push @@ -69,10 +73,17 @@ uint64_t RNSkiOSPlatformContext::makeNativeBuffer(sk_sp image) { // 0. If Image is not in BGRA, convert to BGRA as only BGRA is supported. if (image->colorType() != kBGRA_8888_SkColorType) { +#if defined(SK_GRAPHITE) + SkImage::RequiredProperties requiredProps; + image = image->makeColorTypeAndColorSpace( + DawnContext::getInstance().getRecorder(), + kBGRA_8888_SkColorType, SkColorSpace::MakeSRGB(), requiredProps); +#else // on iOS, 32_BGRA is the only supported RGB format for CVPixelBuffers. image = image->makeColorTypeAndColorSpace( MetalContext::getInstance()._context.skContext.get(), kBGRA_8888_SkColorType, SkColorSpace::MakeSRGB()); +#endif if (image == nullptr) { throw std::runtime_error( "Failed to convert image to BGRA_8888 colortype! Only BGRA_8888 " @@ -152,8 +163,12 @@ std::shared_ptr RNSkiOSPlatformContext::makeContextFromNativeSurface(void *surface, int width, int height) { +#if defined(SK_GRAPHITE) + return DawnContext::getInstance().MakeWindow(surface, width, height); +#else return MetalContext::getInstance().MakeWindow((__bridge CALayer *)surface, - width, height); + width, height); +#endif } void RNSkiOSPlatformContext::raiseError(const std::exception &err) { @@ -162,11 +177,19 @@ sk_sp RNSkiOSPlatformContext::makeOffscreenSurface(int width, int height) { +#if defined(SK_GRAPHITE) + return DawnContext::getInstance().MakeOffscreen(width, height); +#else return MetalContext::getInstance().MakeOffscreen(width, height); +#endif } sk_sp RNSkiOSPlatformContext::makeImageFromNativeBuffer(void *buffer) { - return MetalContext::getInstance().MakeImageFromBuffer(buffer); +#if defined(SK_GRAPHITE) + return DawnContext::getInstance().MakeImageFromBuffer(buffer); +#else + return MetalContext::getInstance().MakeImageFromBuffer(buffer); +#endif } sk_sp RNSkiOSPlatformContext::createFontMgr() { From 182bb7222c2c73acc30f613972c12334885e359f Mon Sep 17 00:00:00 2001 From: William Candillon Date: Thu, 14 Nov 2024 15:07:54 +0100 Subject: [PATCH 10/13] :wrench: --- apps/paper/ios/Podfile.lock | 2 +- .../RNSkAndroidPlatformContext.h | 8 +++---- .../cpp/rnskia-android/RNSkAndroidVideo.cpp | 2 +- .../RNSkOpenGLCanvasProvider.cpp | 7 +++---- packages/skia/cpp/api/JsiSkImage.h | 17 +++++++++++++-- packages/skia/cpp/api/JsiSkSurface.h | 21 ++++++++++++++++--- .../ios/RNSkia-iOS/RNSkMetalCanvasProvider.mm | 3 ++- .../ios/RNSkia-iOS/RNSkiOSPlatformContext.mm | 14 ++++++------- 8 files changed, 51 insertions(+), 23 deletions(-) diff --git a/apps/paper/ios/Podfile.lock b/apps/paper/ios/Podfile.lock index 70fbb6cc2b..fa9d40d1c2 100644 --- a/apps/paper/ios/Podfile.lock +++ b/apps/paper/ios/Podfile.lock @@ -1935,7 +1935,7 @@ SPEC CHECKSUMS: React-Mapbuffer: 1c08607305558666fd16678b85ef135e455d5c96 React-microtasksnativemodule: 87b8de96f937faefece8afd2cb3a518321b2ef99 react-native-safe-area-context: ab8f4a3d8180913bd78ae75dd599c94cce3d5e9a - react-native-skia: 1f36fe252564881d77ad424f84a8986098cc73b7 + react-native-skia: e998d464569b3c9a28b40ba256c9fe1d1a2d3e49 react-native-slider: 97ce0bd921f40de79cead9754546d5e4e7ba44f8 react-native-wgpu: 8d0437a304318e0e3d6ccbfed2a39880f8eae4dd React-nativeconfig: 57781b79e11d5af7573e6f77cbf1143b71802a6d diff --git a/packages/skia/android/cpp/rnskia-android/RNSkAndroidPlatformContext.h b/packages/skia/android/cpp/rnskia-android/RNSkAndroidPlatformContext.h index ae6a0e6435..1892fb50b5 100644 --- a/packages/skia/android/cpp/rnskia-android/RNSkAndroidPlatformContext.h +++ b/packages/skia/android/cpp/rnskia-android/RNSkAndroidPlatformContext.h @@ -66,18 +66,18 @@ class RNSkAndroidPlatformContext : public RNSkPlatformContext { std::shared_ptr makeContextFromNativeSurface(void *surface, int width, int height) override { #if defined(SK_GRAPHITE) - return DawnContext::getInstance().MakeWindow(surface, width, height); + return DawnContext::getInstance().MakeWindow(surface, width, height); #else - return OpenGLContext::getInstance().MakeWindow( + return OpenGLContext::getInstance().MakeWindow( reinterpret_cast(surface), width, height); #endif } sk_sp makeImageFromNativeBuffer(void *buffer) override { #if defined(SK_GRAPHITE) - return DawnContext::getInstance().MakeImageFromBuffer(buffer); + return DawnContext::getInstance().MakeImageFromBuffer(buffer); #else - return OpenGLContext::getInstance().MakeImageFromBuffer(buffer); + return OpenGLContext::getInstance().MakeImageFromBuffer(buffer); #endif } diff --git a/packages/skia/android/cpp/rnskia-android/RNSkAndroidVideo.cpp b/packages/skia/android/cpp/rnskia-android/RNSkAndroidVideo.cpp index 5b3222d7d7..0edafa3ca3 100644 --- a/packages/skia/android/cpp/rnskia-android/RNSkAndroidVideo.cpp +++ b/packages/skia/android/cpp/rnskia-android/RNSkAndroidVideo.cpp @@ -60,7 +60,7 @@ sk_sp RNSkAndroidVideo::nextImage(double *timeStamp) { AHardwareBuffer *buffer = AHardwareBuffer_fromHardwareBuffer(env, jHardwareBuffer); #if defined(SK_GRAPHITE) - return DawnContext::getInstance().MakeImageFromBuffer(buffer); + return DawnContext::getInstance().MakeImageFromBuffer(buffer); #else return OpenGLContext::getInstance().MakeImageFromBuffer(buffer); #endif diff --git a/packages/skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp b/packages/skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp index d740422bb6..660f9ecef9 100644 --- a/packages/skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp +++ b/packages/skia/android/cpp/rnskia-android/RNSkOpenGLCanvasProvider.cpp @@ -1,9 +1,9 @@ #include "RNSkOpenGLCanvasProvider.h" -#include +#include #include #include -#include +#include #include "RNSkLog.h" @@ -99,8 +99,7 @@ void RNSkOpenGLCanvasProvider::surfaceAvailable(jobject jSurfaceTexture, env->DeleteLocalRef(surfaceClass); env->DeleteLocalRef(surfaceTextureClass); #if defined(SK_GRAPHITE) - _surfaceHolder = - DawnContext::getInstance().MakeWindow(window, width, height); + _surfaceHolder = DawnContext::getInstance().MakeWindow(window, width, height); #else _surfaceHolder = OpenGLContext::getInstance().MakeWindow(window, width, height); diff --git a/packages/skia/cpp/api/JsiSkImage.h b/packages/skia/cpp/api/JsiSkImage.h index d12fd846fe..658700e803 100644 --- a/packages/skia/cpp/api/JsiSkImage.h +++ b/packages/skia/cpp/api/JsiSkImage.h @@ -12,6 +12,11 @@ #include "RNSkTypedArray.h" +#if defined(SK_GRAPHITE) +#include "DawnContext.h" +#include "include/gpu/graphite/Context.h" +#endif + #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdocumentation" @@ -83,9 +88,13 @@ class JsiSkImage : public JsiSkWrappingSkPtrHostObject { ? arguments[1].asNumber() : 100.0; auto image = getObject(); +#if defined(SK_GRAPHITE) if (image->isTextureBacked()) { image = image->makeNonTextureImage(); } +#else + image = DawnContext::getInstance().MakeRasterImage(image); +#endif sk_sp data; if (format == SkEncodedImageFormat::kJPEG) { @@ -181,9 +190,13 @@ class JsiSkImage : public JsiSkWrappingSkPtrHostObject { } JSI_HOST_FUNCTION(makeNonTextureImage) { - auto image = getObject()->makeNonTextureImage(); +#if defined(SK_GRAPHITE) + auto rasterImage = DawnContext::getInstance().MakeRasterImage(getObject()); +#else + auto rasterImage = getObject()->makeNonTextureImage(); +#endif return jsi::Object::createFromHostObject( - runtime, std::make_shared(getContext(), std::move(image))); + runtime, std::make_shared(getContext(), rasterImage)); } EXPORT_JSI_API_TYPENAME(JsiSkImage, Image) diff --git a/packages/skia/cpp/api/JsiSkSurface.h b/packages/skia/cpp/api/JsiSkSurface.h index 39b23866c4..30739c8337 100644 --- a/packages/skia/cpp/api/JsiSkSurface.h +++ b/packages/skia/cpp/api/JsiSkSurface.h @@ -10,6 +10,10 @@ #include "JsiSkCanvas.h" #include "JsiSkImage.h" +#if defined(SK_GRAPHITE) +#include "DawnContext.h" +#endif + #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdocumentation" @@ -44,21 +48,32 @@ class JsiSkSurface : public JsiSkWrappingSkPtrHostObject { } JSI_HOST_FUNCTION(flush) { - if (auto dContext = GrAsDirectContext(getObject()->recordingContext())) { + auto surface = getObject(); +#if defined(SK_GRAPHITE) + auto recording = surface->recorder()->snap(); + DawnContext::getInstance().submitRecording(recording.get()); +#else + if (auto dContext = GrAsDirectContext(surface->recordingContext())) { dContext->flushAndSubmit(); } +#endif return jsi::Value::undefined(); } JSI_HOST_FUNCTION(makeImageSnapshot) { + auto surface = getObject(); sk_sp image; if (count == 1) { auto rect = JsiSkRect::fromValue(runtime, arguments[0]); - image = getObject()->makeImageSnapshot(SkIRect::MakeXYWH( + image = surface->makeImageSnapshot(SkIRect::MakeXYWH( rect->x(), rect->y(), rect->width(), rect->height())); } else { - image = getObject()->makeImageSnapshot(); + image = surface->makeImageSnapshot(); } +#if defined(SK_GRAPHITE) + auto recording = surface->recorder()->snap(); + DawnContext::getInstance().submitRecording(recording.get()); +#endif return jsi::Object::createFromHostObject( runtime, std::make_shared(getContext(), std::move(image))); } diff --git a/packages/skia/ios/RNSkia-iOS/RNSkMetalCanvasProvider.mm b/packages/skia/ios/RNSkia-iOS/RNSkMetalCanvasProvider.mm index 161c8c98e7..7cba58f48c 100644 --- a/packages/skia/ios/RNSkia-iOS/RNSkMetalCanvasProvider.mm +++ b/packages/skia/ios/RNSkia-iOS/RNSkMetalCanvasProvider.mm @@ -77,7 +77,8 @@ return false; } #if defined(SK_GRAPHITE) - auto ctx = RNSkia::DawnContext::getInstance().MakeWindow((__bridge void*)_layer, _width, _height); + auto ctx = RNSkia::DawnContext::getInstance().MakeWindow( + (__bridge void *)_layer, _width, _height); #else auto ctx = MetalContext::getInstance().MakeWindow(_layer, _width, _height); #endif diff --git a/packages/skia/ios/RNSkia-iOS/RNSkiOSPlatformContext.mm b/packages/skia/ios/RNSkia-iOS/RNSkiOSPlatformContext.mm index d998e0b8cb..5588b95e31 100644 --- a/packages/skia/ios/RNSkia-iOS/RNSkiOSPlatformContext.mm +++ b/packages/skia/ios/RNSkia-iOS/RNSkiOSPlatformContext.mm @@ -74,10 +74,10 @@ // 0. If Image is not in BGRA, convert to BGRA as only BGRA is supported. if (image->colorType() != kBGRA_8888_SkColorType) { #if defined(SK_GRAPHITE) - SkImage::RequiredProperties requiredProps; - image = image->makeColorTypeAndColorSpace( - DawnContext::getInstance().getRecorder(), - kBGRA_8888_SkColorType, SkColorSpace::MakeSRGB(), requiredProps); + SkImage::RequiredProperties requiredProps; + image = image->makeColorTypeAndColorSpace( + DawnContext::getInstance().getRecorder(), kBGRA_8888_SkColorType, + SkColorSpace::MakeSRGB(), requiredProps); #else // on iOS, 32_BGRA is the only supported RGB format for CVPixelBuffers. image = image->makeColorTypeAndColorSpace( @@ -167,7 +167,7 @@ return DawnContext::getInstance().MakeWindow(surface, width, height); #else return MetalContext::getInstance().MakeWindow((__bridge CALayer *)surface, - width, height); + width, height); #endif } @@ -186,9 +186,9 @@ sk_sp RNSkiOSPlatformContext::makeImageFromNativeBuffer(void *buffer) { #if defined(SK_GRAPHITE) - return DawnContext::getInstance().MakeImageFromBuffer(buffer); + return DawnContext::getInstance().MakeImageFromBuffer(buffer); #else - return MetalContext::getInstance().MakeImageFromBuffer(buffer); + return MetalContext::getInstance().MakeImageFromBuffer(buffer); #endif } From af4be56def44358e8a2cf1fcbef7f41104da568b Mon Sep 17 00:00:00 2001 From: William Candillon Date: Thu, 14 Nov 2024 15:12:20 +0100 Subject: [PATCH 11/13] :green_heart: --- packages/skia/cpp/api/JsiSkImage.h | 8 ++++---- packages/skia/cpp/rnskia/RNSkView.h | 5 +++++ 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/packages/skia/cpp/api/JsiSkImage.h b/packages/skia/cpp/api/JsiSkImage.h index 658700e803..fddca444f5 100644 --- a/packages/skia/cpp/api/JsiSkImage.h +++ b/packages/skia/cpp/api/JsiSkImage.h @@ -89,11 +89,11 @@ class JsiSkImage : public JsiSkWrappingSkPtrHostObject { : 100.0; auto image = getObject(); #if defined(SK_GRAPHITE) - if (image->isTextureBacked()) { - image = image->makeNonTextureImage(); - } + image = DawnContext::getInstance().MakeRasterImage(image); #else - image = DawnContext::getInstance().MakeRasterImage(image); + if (image->isTextureBacked()) { + image = image->makeNonTextureImage(); + } #endif sk_sp data; diff --git a/packages/skia/cpp/rnskia/RNSkView.h b/packages/skia/cpp/rnskia/RNSkView.h index 1ec4a267bb..d6096de736 100644 --- a/packages/skia/cpp/rnskia/RNSkView.h +++ b/packages/skia/cpp/rnskia/RNSkView.h @@ -108,7 +108,12 @@ class RNSkOffscreenCanvasProvider : public RNSkCanvasProvider { } else { image = _surface->makeImageSnapshot(); } +#if defined(SK_GRAPHITE) return image->makeNonTextureImage(); +#else + DawnContext::getInstance().submitRecording(_surface->recorder()->snap().get()); + return DawnContext::getInstance().MakeRasterImage(image); +#endif } /** From d2cf812b72078fefedbd637376ad38efbcb45eae Mon Sep 17 00:00:00 2001 From: William Candillon Date: Thu, 14 Nov 2024 15:13:27 +0100 Subject: [PATCH 12/13] :green_heart: --- packages/skia/cpp/api/JsiSkImage.h | 8 ++++---- packages/skia/cpp/rnskia/RNSkView.h | 7 ++++--- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/packages/skia/cpp/api/JsiSkImage.h b/packages/skia/cpp/api/JsiSkImage.h index fddca444f5..585197cc4f 100644 --- a/packages/skia/cpp/api/JsiSkImage.h +++ b/packages/skia/cpp/api/JsiSkImage.h @@ -89,11 +89,11 @@ class JsiSkImage : public JsiSkWrappingSkPtrHostObject { : 100.0; auto image = getObject(); #if defined(SK_GRAPHITE) - image = DawnContext::getInstance().MakeRasterImage(image); + image = DawnContext::getInstance().MakeRasterImage(image); #else - if (image->isTextureBacked()) { - image = image->makeNonTextureImage(); - } + if (image->isTextureBacked()) { + image = image->makeNonTextureImage(); + } #endif sk_sp data; diff --git a/packages/skia/cpp/rnskia/RNSkView.h b/packages/skia/cpp/rnskia/RNSkView.h index d6096de736..666da6c8de 100644 --- a/packages/skia/cpp/rnskia/RNSkView.h +++ b/packages/skia/cpp/rnskia/RNSkView.h @@ -109,10 +109,11 @@ class RNSkOffscreenCanvasProvider : public RNSkCanvasProvider { image = _surface->makeImageSnapshot(); } #if defined(SK_GRAPHITE) - return image->makeNonTextureImage(); + DawnContext::getInstance().submitRecording( + _surface->recorder()->snap().get()); + return DawnContext::getInstance().MakeRasterImage(image); #else - DawnContext::getInstance().submitRecording(_surface->recorder()->snap().get()); - return DawnContext::getInstance().MakeRasterImage(image); + return image->makeNonTextureImage(); #endif } From aab1e3d1c5bd8dc02993e9a76ed615cea307204c Mon Sep 17 00:00:00 2001 From: William Candillon Date: Thu, 14 Nov 2024 15:51:49 +0100 Subject: [PATCH 13/13] =?UTF-8?q?=F0=9F=93=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 8 ++++++++ apps/docs/docs/getting-started/installation.md | 4 ++++ apps/paper/ios/Podfile.lock | 2 +- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index ffc03efeb7..41c49b80fc 100644 --- a/README.md +++ b/README.md @@ -151,3 +151,11 @@ Finally, you can use `drawOffscreen` to receive a canvas object as parameter. Yo ``` Again, since `eval`, `draw`, and `drawOffscreen` serialize the function's content, avoid any external dependencies that can't be serialized. + +## Graphite + +We have experimental support for Graphite. +To enable it, you need follow these steps: +* Build Skia using `SK_GRAPHITE=1 yarn build-skia` +* Install iOS pods using `SK_GRAPHITE=1 pod install` +* Update the Android [CMakeLists](/packages/skia/android/CMakeLists.txt) to use `set(SK_GRAPHITE ON)` \ No newline at end of file diff --git a/apps/docs/docs/getting-started/installation.md b/apps/docs/docs/getting-started/installation.md index efd3e5663c..23e11840c1 100644 --- a/apps/docs/docs/getting-started/installation.md +++ b/apps/docs/docs/getting-started/installation.md @@ -14,6 +14,10 @@ In addition you should make sure you're on at least `iOS 13` and `Android API le To use React Native Skia with the new architecture, `react-native@>=0.72` is required.
To use React Native Skia with video support, `Android API level 26` or above is required. +Skia has a new experimental backend named Graphite which runs on Vulkan and Metal. +We currently are working on a new version of React Native Skia that uses this new backend. +For Graphite to run, you will need to use `Android API level 26` and `iOS 15.1` or above. + **Install the library using yarn:** ```sh diff --git a/apps/paper/ios/Podfile.lock b/apps/paper/ios/Podfile.lock index fa9d40d1c2..70fbb6cc2b 100644 --- a/apps/paper/ios/Podfile.lock +++ b/apps/paper/ios/Podfile.lock @@ -1935,7 +1935,7 @@ SPEC CHECKSUMS: React-Mapbuffer: 1c08607305558666fd16678b85ef135e455d5c96 React-microtasksnativemodule: 87b8de96f937faefece8afd2cb3a518321b2ef99 react-native-safe-area-context: ab8f4a3d8180913bd78ae75dd599c94cce3d5e9a - react-native-skia: e998d464569b3c9a28b40ba256c9fe1d1a2d3e49 + react-native-skia: 1f36fe252564881d77ad424f84a8986098cc73b7 react-native-slider: 97ce0bd921f40de79cead9754546d5e4e7ba44f8 react-native-wgpu: 8d0437a304318e0e3d6ccbfed2a39880f8eae4dd React-nativeconfig: 57781b79e11d5af7573e6f77cbf1143b71802a6d