diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3c759bb0..fc77b962 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -9,66 +9,8 @@ on: types: [published] jobs: - prebuild_linux_aarch64_3rd_party: - name: Build skia bundled 3rd-party on linux/aarch64 - runs-on: ubuntu-22.04 - steps: - - uses: actions/checkout@v4 - with: - submodules: true - - uses: actions/cache@v4 - id: cache-skia - with: - path: | - gn - skia - key: linux-aarch64-skia-${{ github.sha }}-3rd-party - - name: Pre-fetch skia deps - if: ${{ steps.cache-skia.outputs.cache-hit != 'true' }} - run: git config --global core.compression 0 && cd skia && patch -p1 -i ../patch/skia-m136-minimize-download.patch && python tools/git-sync-deps && patch -p1 -R -i ../patch/skia-m136-minimize-download.patch - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - name: Build skia 3rd-Party - # Taken from https://github.com/pypa/cibuildwheel/blob/v2.19.2/cibuildwheel/resources/pinned_docker_images.cfg - uses: docker://quay.io/pypa/manylinux_2_28_aarch64:2024.07.02-0 - if: ${{ steps.cache-skia.outputs.cache-hit != 'true' }} - with: - args: bash -c "git config --global --add safe.directory '*' && - bash scripts/build_Linux.sh && - chmod a+rwx -R skia" - - prebuild_linux_aarch64: - name: Build skia on linux/aarch64 - needs: prebuild_linux_aarch64_3rd_party - runs-on: ubuntu-22.04 - steps: - - uses: actions/checkout@v4 - with: - submodules: true - - uses: actions/cache@v4 - id: cache-skia - with: - path: | - gn - skia - key: linux-aarch64-skia-${{ github.sha }} - - uses: actions/cache/restore@v4 - with: - path: | - gn - skia - key: linux-aarch64-skia-${{ github.sha }}-3rd-party - - name: Set up QEMU - uses: docker/setup-qemu-action@v3 - - name: Build Skia Proper - uses: docker://quay.io/pypa/manylinux_2_28_aarch64:2024.07.02-0 - with: - args: bash -c "git config --global --add safe.directory '*' && - bash scripts/build_Linux.sh - build_wheels: name: Build wheels on ${{ matrix.os }} (${{ matrix.arch }}) for ${{ matrix.cp }} - needs: prebuild_linux_aarch64 runs-on: ${{ matrix.os }} strategy: fail-fast: false @@ -80,38 +22,54 @@ jobs: - os: macos-13 arch: arm64 cp: "cp3{10,11,12,13}" - # aarch64 is emulated and takes longer, build one wheel per job - - os: ubuntu-22.04 + - os: ubuntu-22.04-arm arch: aarch64 - cp: cp310 - - os: ubuntu-22.04 - arch: aarch64 - cp: cp311 - - os: ubuntu-22.04 - arch: aarch64 - cp: cp312 - - os: ubuntu-22.04 - arch: aarch64 - cp: cp313 + cp: "cp3{10,11,12,13}" steps: - uses: actions/checkout@v4 with: submodules: true - - uses: actions/cache/restore@v4 - if: runner.os == 'Linux' && matrix.arch == 'aarch64' + - name: Build wheels + uses: pypa/cibuildwheel@v2.21.3 + env: + CIBW_MANYLINUX_X86_64_IMAGE: manylinux_2_28 + CIBW_MANYLINUX_AARCH64_IMAGE: manylinux_2_28 + CIBW_BUILD: "${{ matrix.cp }}-*" + CIBW_SKIP: "*musllinux*" + CIBW_ARCHS: ${{ matrix.arch }} + CIBW_ENVIRONMENT_MACOS: TARGET_ARCH=${{ matrix.arch }} MACOSX_DEPLOYMENT_TARGET=11.0 + CIBW_BEFORE_ALL: bash scripts/build_${{ runner.os }}.sh + CIBW_BEFORE_BUILD: pip install pybind11 numpy + CIBW_TEST_REQUIRES: pytest pillow glfw + CIBW_TEST_REQUIRES_LINUX: pytest pillow glfw moderngl + CIBW_TEST_REQUIRES_MACOS: pytest pillow pyopengl + CIBW_TEST_COMMAND: python -m pytest {project}/tests + CIBW_TEST_COMMAND_LINUX: > + xvfb-run -s "-screen 0 640x480x24" python -m pytest {project}/tests + CIBW_REPAIR_WHEEL_COMMAND_LINUX: "auditwheel repair --exclude libEGL.so.1 -w {dest_dir} {wheel}" + CIBW_TEST_SKIP: "*-macosx_arm64" + + - uses: actions/upload-artifact@v4 with: - path: | - gn - skia - key: linux-aarch64-skia-${{ github.sha }} - - - name: Set up QEMU - if: runner.os == 'Linux' && matrix.arch == 'aarch64' - uses: docker/setup-qemu-action@v3 + name: wheel-${{ matrix.os }}-${{ matrix.arch }}-${{ matrix.cp }} + path: ./wheelhouse/*.whl + + build_wheels_armwindows: + name: Build wheels on ${{ matrix.os }} (${{ matrix.arch }}) for ${{ matrix.cp }} + runs-on: ${{ matrix.os }} + strategy: + fail-fast: false + matrix: + os: [windows-11-arm] + arch: [ARM64] + cp: ["cp3{11,12,13}"] + + steps: + - uses: actions/checkout@v4 with: - platforms: ${{ matrix.arch }} + submodules: true - name: Build wheels uses: pypa/cibuildwheel@v2.21.3 @@ -124,6 +82,7 @@ jobs: CIBW_ENVIRONMENT_MACOS: TARGET_ARCH=${{ matrix.arch }} MACOSX_DEPLOYMENT_TARGET=11.0 CIBW_BEFORE_ALL: bash scripts/build_${{ runner.os }}.sh CIBW_BEFORE_BUILD: pip install pybind11 numpy + CIBW_BEFORE_BUILD_WINDOWS: pip install pybind11 "numpy >= 2.3.0rc1" CIBW_TEST_REQUIRES: pytest pillow glfw CIBW_TEST_REQUIRES_MACOS: pytest pillow pyopengl CIBW_TEST_COMMAND: python -m pytest {project}/tests @@ -139,7 +98,6 @@ jobs: # identical to "build_wheels", except with the older pypa/cibuildwheel@v2.19.2 build_wheels_old: name: Build wheels on ${{ matrix.os }} (${{ matrix.arch }}) for ${{ matrix.cp }} - needs: prebuild_linux_aarch64 runs-on: ${{ matrix.os }} strategy: fail-fast: false @@ -151,33 +109,15 @@ jobs: - os: macos-13 arch: arm64 cp: "cp3{8,9}" - # aarch64 is emulated and takes longer, build one wheel per job - - os: ubuntu-22.04 + - os: ubuntu-22.04-arm arch: aarch64 - cp: cp38 - - os: ubuntu-22.04 - arch: aarch64 - cp: cp39 + cp: "cp3{8,9}" steps: - uses: actions/checkout@v4 with: submodules: true - - uses: actions/cache/restore@v4 - if: runner.os == 'Linux' && matrix.arch == 'aarch64' - with: - path: | - gn - skia - key: linux-aarch64-skia-${{ github.sha }} - - - name: Set up QEMU - if: runner.os == 'Linux' && matrix.arch == 'aarch64' - uses: docker/setup-qemu-action@v3 - with: - platforms: ${{ matrix.arch }} - - name: Build wheels uses: pypa/cibuildwheel@v2.19.2 env: @@ -190,10 +130,12 @@ jobs: CIBW_BEFORE_ALL: bash scripts/build_${{ runner.os }}.sh CIBW_BEFORE_BUILD: pip install pybind11 numpy CIBW_TEST_REQUIRES: pytest pillow glfw + CIBW_TEST_REQUIRES_LINUX: pytest pillow glfw moderngl CIBW_TEST_REQUIRES_MACOS: pytest pillow pyopengl CIBW_TEST_COMMAND: python -m pytest {project}/tests CIBW_TEST_COMMAND_LINUX: > xvfb-run -s "-screen 0 640x480x24" python -m pytest {project}/tests + CIBW_REPAIR_WHEEL_COMMAND_LINUX: "auditwheel repair --exclude libEGL.so.1 -w {dest_dir} {wheel}" CIBW_TEST_SKIP: "*-macosx_arm64" - uses: actions/upload-artifact@v4 @@ -248,3 +190,28 @@ jobs: path: dist - uses: pypa/gh-action-pypi-publish@release/v1 + + build_and_test_on_Fedora: + runs-on: ubuntu-24.04 + container: fedora:42 + permissions: write-all + steps: + - run: dnf install -y dnf-utils git gcc-c++ libstdc++-devel libstdc++-static + - run: dnf install -y python3-build python3-devel python3-pytest python3-pillow python3-glfw + - run: dnf install -y egl-utils glx-utils + - run: dnf install -y patch + - run: dnf install -y expat-devel fontconfig-devel + - run: dnf install -y libxml2-devel vulkan-headers + - run: dnf install -y gn ninja-build + - uses: actions/checkout@v4 + with: + submodules: recursive + - run: bash scripts/build_Linux.sh + - run: python -m build --wheel + - run: python -m pip install dist/*.whl + - run: python -m pip install moderngl + - run: python -c 'import moderngl; moderngl_context = moderngl.create_standalone_context(backend="egl"); import skia; interface = skia.GrGLInterface.MakeEGL() ; assert isinstance(skia.GrDirectContext.MakeGL(interface), skia.GrContext) ; print("Success3")' + - run: eglinfo || /bin/true + - run: xvfb-run -s "-screen 0 640x480x24" glxinfo + # The below also run that 3 lines above but under X, but allows it to fail there. + - run: xvfb-run -s "-screen 0 640x480x24" pytest diff --git a/patch/0001-Disable-OpenGL-for-Windows-on-ARM64.patch b/patch/0001-Disable-OpenGL-for-Windows-on-ARM64.patch new file mode 100644 index 00000000..287d13b8 --- /dev/null +++ b/patch/0001-Disable-OpenGL-for-Windows-on-ARM64.patch @@ -0,0 +1,143 @@ +From 0c75727f0148cafc6653d7d94b3633889ffde7db Mon Sep 17 00:00:00 2001 +From: Brian Osman +Date: Mon, 10 Dec 2018 10:27:26 -0500 +Subject: [PATCH] Disable OpenGL for Windows-on-ARM64 + +Bug: skia:8569 +Change-Id: I4f526c8918a9a4aae4b6cd6d7c803b12e90e82ed +Reviewed-on: https://skia-review.googlesource.com/c/175984 +Reviewed-by: Mike Klein +Reviewed-by: Brian Salomon +Commit-Queue: Brian Osman +--- + BUILD.gn | 12 +++++++----- + src/gpu/gl/win/GrGLMakeNativeInterface_win.cpp | 8 ++++++++ + src/utils/win/SkWGL_win.cpp | 2 +- + .../gpu/gl/win/CreatePlatformGLTestContext_win.cpp | 11 +++++++++++ + tools/sk_app/win/GLWindowContext_win.cpp | 14 ++++++++++++++ + 5 files changed, 41 insertions(+), 6 deletions(-) + +diff --git b/BUILD.gn a/BUILD.gn +index ef913e9..33f3208 100644 +--- b/BUILD.gn ++++ a/BUILD.gn +@@ -1031,7 +1031,9 @@ optional("gpu") { + "src/gpu/ganesh/gl/win/GrGLMakeNativeInterface_win.cpp", + "src/gpu/ganesh/gl/win/GrGLMakeWinInterface.cpp", + ] +- libs += [ "OpenGL32.lib" ] ++ if (target_cpu != "arm64") { ++ libs += [ "OpenGL32.lib" ] ++ } + } else { + sources += [ "src/gpu/ganesh/gl/GrGLMakeNativeInterface_none.cpp" ] + } +@@ -2185,10 +2187,10 @@ if (skia_enable_tools) { + "tools/gpu/gl/win/SkWGL.h", + "tools/gpu/gl/win/SkWGL_win.cpp", + ] +- libs += [ +- "Gdi32.lib", +- "OpenGL32.lib", +- ] ++ libs += [ "Gdi32.lib" ] ++ if (target_cpu != "arm64") { ++ libs += [ "OpenGL32.lib" ] ++ } + } + } + +diff --git b/src/gpu/ganesh/gl/win/GrGLMakeNativeInterface_win.cpp a/src/gpu/ganesh/gl/win/GrGLMakeNativeInterface_win.cpp +index f33f2e1..da3cbe2 100644 +--- b/src/gpu/ganesh/gl/win/GrGLMakeNativeInterface_win.cpp ++++ a/src/gpu/ganesh/gl/win/GrGLMakeNativeInterface_win.cpp +@@ -11,6 +11,11 @@ + #include "include/gpu/ganesh/gl/GrGLInterface.h" + #include "include/gpu/ganesh/gl/win/GrGLMakeWinInterface.h" + ++#if defined(_M_ARM64) ++ ++sk_sp GrGLMakeNativeInterface() { return nullptr; } ++ ++#else + /* + * Windows makes the GL funcs all be __stdcall instead of __cdecl :( + * This implementation will only work if GR_GL_FUNCTION_TYPE is __stdcall. +@@ -20,4 +25,6 @@ sk_sp GrGLMakeNativeInterface() { + return GrGLInterfaces::MakeWin(); + } + ++#endif // ARM64 ++ + #endif // SK_DISABLE_LEGACY_GL_MAKE_NATIVE_INTERFACE +diff --git b/tools/gpu/gl/win/SkWGL_win.cpp a/tools/gpu/gl/win/SkWGL_win.cpp +index 4cb462b..ac2d700 100644 +--- b/tools/gpu/gl/win/SkWGL_win.cpp ++++ a/tools/gpu/gl/win/SkWGL_win.cpp +@@ -6,7 +6,7 @@ + */ + + #include "include/core/SkTypes.h" +-#if defined(SK_BUILD_FOR_WIN) && !defined(WINUWP) ++#if defined(SK_BUILD_FOR_WIN) && !defined(_M_ARM64) && !defined(WINUWP) + + #include "tools/gpu/gl/win/SkWGL.h" + +diff --git b/tools/gpu/gl/win/CreatePlatformGLTestContext_win.cpp a/tools/gpu/gl/win/CreatePlatformGLTestContext_win.cpp +index cb62daf..0d29da7 100644 +--- b/tools/gpu/gl/win/CreatePlatformGLTestContext_win.cpp ++++ a/tools/gpu/gl/win/CreatePlatformGLTestContext_win.cpp +@@ -8,6 +8,16 @@ + + #include "tools/gpu/gl/GLTestContext.h" + ++#if defined(_M_ARM64) ++ ++namespace sk_gpu_test { ++ ++GLTestContext* CreatePlatformGLTestContext(GrGLStandard, GLTestContext*) { return nullptr; } ++ ++} // namespace sk_gpu_test ++ ++#else ++ + #include + #include + #include "tools/gpu/gl/win/SkWGL.h" +@@ -221,3 +231,4 @@ GLTestContext* CreatePlatformGLTestContext(GrGLStandard forcedGpuAPI, + } + } // namespace sk_gpu_test + ++#endif +diff --git b/tools/window/win/GLWindowContext_win.cpp a/tools/window/win/GLWindowContext_win.cpp +index c018549..dca99ae 100644 +--- b/tools/window/win/GLWindowContext_win.cpp ++++ a/tools/window/win/GLWindowContext_win.cpp +@@ -17,6 +17,18 @@ + using skwindow::DisplayParams; + using skwindow::internal::GLWindowContext; + ++#if defined(_M_ARM64) ++ ++namespace skwindow { ++ ++std::unique_ptr MakeGLForWin(HWND, std::unique_ptr) { ++ return nullptr; ++} ++ ++} // namespace skwindow ++ ++#else ++ + namespace { + + class GLWindowContext_win : public GLWindowContext { +@@ -141,3 +153,5 @@ std::unique_ptr MakeGLForWin(HWND wnd, std::unique_ptr +Date: Tue, 27 May 2025 16:32:19 -0400 +Subject: [PATCH] [gn] Remove msvc env setting + +SetEnv.cmd has long been removed but kept alive by Skia packaging of +MSVC. Older MSVC compilers and Windows SDKs relied on a large number of +environment variables to be set when cross compiling, but this should no +longer be necessary. + +In addition, the MSVC ARM toolchains are now complete and no longer +require the host toolchain to be on the path. + +These improvements mean that it is no longer necessary to use `cmd.exe +/c` as a "compiler wrapper" to set up the environment. Because it is not +generally possible to properly escape such command lines this has caused +issues with any arguments which would require proper escaping such as +paths with spaces and special characters. + +This change drops support for building Skia for x86 or ARM64 with MSVC +from before VS2022, with the benefit of building for x86 or ARM64 +without extemely odd, undocumented, and limiting restrictions. + +Also add support for detecting MSVC 2022 before looking for 2019 or +2017. + +Bug: 420271794, 376381591 +Change-Id: I8591636aec31095b13db6dc1a376abfa23199ebd +Reviewed-on: https://skia-review.googlesource.com/c/skia/+/999356 +Reviewed-by: Kaylee Lubick +--- + gn/find_msvc.py | 17 ++++++++++------- + gn/toolchain/BUILD.gn | 24 ++++++++---------------- + 2 files changed, 18 insertions(+), 23 deletions(-) + +diff --git a/gn/find_msvc.py b/gn/find_msvc.py +index 108d576139..281a738900 100755 +--- a/gn/find_msvc.py ++++ b/gn/find_msvc.py +@@ -10,16 +10,19 @@ import subprocess + ''' + Look for the first match in the format + C:\\Program Files (x86)\\Microsoft Visual Studio\\${RELEASE}\\${VERSION}\\VC ++ C:\\Program Files\\Microsoft Visual Studio\\${RELEASE}\\${VERSION}\\VC ++If not found, use vswhere.exe. + ''' + def find_msvc(): + if sys.platform.startswith('win'): +- default_dir = r'C:\Program Files (x86)\Microsoft Visual Studio' +- for release in ['2019', '2017']: +- for version in ['Enterprise', 'Professional', 'Community', 'BuildTools', 'Preview']: +- path = os.path.join(default_dir, release, version, 'VC') +- if os.path.isdir(path): +- return path +- ++ default_dirs = [r'C:\Program Files\Microsoft Visual Studio', ++ r'C:\Program Files (x86)\Microsoft Visual Studio'] ++ for default_dir in default_dirs: ++ for release in ['2022', '2019', '2017']: ++ for version in ['Enterprise', 'Professional', 'Community', 'BuildTools', 'Preview']: ++ path = os.path.join(default_dir, release, version, 'VC') ++ if os.path.isdir(path): ++ return path + # Fall back to vswhere.exe to determine non-standard installation paths + # Fixed location, https://github.com/Microsoft/vswhere/wiki/Installing + vswhere = os.path.join(os.getenv('ProgramFiles(x86)'), +diff --git a/gn/toolchain/BUILD.gn b/gn/toolchain/BUILD.gn +index 4d4abc952f..85858b5a01 100644 +--- a/gn/toolchain/BUILD.gn ++++ b/gn/toolchain/BUILD.gn +@@ -87,16 +87,6 @@ template("msvc_toolchain") { + + bin = "$win_vc/Tools/MSVC/$win_toolchain_version/bin/HostX64/$toolchain_target_cpu" + +- env_setup = "" +- if (toolchain_target_cpu == "x86") { +- # Toolchain asset includes a script that configures for x86 building. +- # We don't support x86 builds with local MSVC installations. +- env_setup = "$shell $win_sdk/bin/SetEnv.cmd /x86 && " +- } else if (toolchain_target_cpu == "arm64") { +- # ARM64 compiler is incomplete - it relies on DLLs located in the host toolchain directory. +- env_setup = "$shell set \"PATH=%PATH%;$win_vc\\Tools\\MSVC\\$win_toolchain_version\\bin\\HostX64\\x64\" && " +- } +- + cl_m32_flag = "" + + if (clang_win != "") { +@@ -126,7 +116,8 @@ template("msvc_toolchain") { + if (toolchain_target_cpu == "x64") { + _ml += "64" + } +- command = "$env_setup \"$bin/$_ml.exe\" {{asmflags}} /nologo /c /Fo {{output}} {{source}}" ++ command = ++ "\"$bin/$_ml.exe\" {{asmflags}} /nologo /c /Fo {{output}} {{source}}" + outputs = [ + "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.obj", + ] +@@ -138,7 +129,7 @@ template("msvc_toolchain") { + pdbname = "{{target_out_dir}}/{{label_name}}_c.pdb" + + # Label names may have spaces so pdbname must be quoted. +- command = "$env_setup $cc_wrapper $cl /nologo /showIncludes /FC {{defines}} {{include_dirs}} {{cflags}} $cl_m32_flag {{cflags_c}} /c {{source}} /Fo{{output}} /Fd\"$pdbname\"" ++ command = "$cc_wrapper $cl /nologo /showIncludes /FC {{defines}} {{include_dirs}} {{cflags}} $cl_m32_flag {{cflags_c}} /c {{source}} /Fo{{output}} /Fd\"$pdbname\"" + depsformat = "msvc" + outputs = [ + "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.obj", +@@ -151,7 +142,7 @@ template("msvc_toolchain") { + pdbname = "{{target_out_dir}}/{{label_name}}_c.pdb" + + # Label names may have spaces so pdbname must be quoted. +- command = "$env_setup $cc_wrapper $cl /nologo /showIncludes /FC {{defines}} {{include_dirs}} {{cflags}} $cl_m32_flag {{cflags_cc}} /c {{source}} /Fo{{output}} /Fd\"$pdbname\"" ++ command = "$cc_wrapper $cl /nologo /showIncludes /FC {{defines}} {{include_dirs}} {{cflags}} $cl_m32_flag {{cflags_cc}} /c {{source}} /Fo{{output}} /Fd\"$pdbname\"" + depsformat = "msvc" + outputs = [ + "{{source_out_dir}}/{{target_output_name}}.{{source_name_part}}.obj", +@@ -162,7 +153,8 @@ template("msvc_toolchain") { + tool("alink") { + rspfile = "{{output}}.rsp" + +- command = "$env_setup $lib /nologo /ignore:4221 {{arflags}} /OUT:{{output}} @$rspfile" ++ command = ++ "$lib /nologo /ignore:4221 {{arflags}} /OUT:{{output}} @$rspfile" + outputs = [ + # Ignore {{output_extension}} and always use .lib, there's no reason to + # allow targets to override this extension on Windows. +@@ -185,7 +177,7 @@ template("msvc_toolchain") { + pdbname = "${dllname}.pdb" + rspfile = "${dllname}.rsp" + +- command = "$env_setup $link /nologo /IMPLIB:$libname /DLL /OUT:$dllname /PDB:$pdbname @$rspfile" ++ command = "$link /nologo /IMPLIB:$libname /DLL /OUT:$dllname /PDB:$pdbname @$rspfile" + outputs = [ + dllname, + libname, +@@ -217,7 +209,7 @@ template("msvc_toolchain") { + pdbname = "$exename.pdb" + rspfile = "$exename.rsp" + +- command = "$env_setup $link /nologo /OUT:$exename /PDB:$pdbname @$rspfile" ++ command = "$link /nologo /OUT:$exename /PDB:$pdbname @$rspfile" + default_output_extension = ".exe" + default_output_dir = "{{root_out_dir}}" + outputs = [ exename ] +-- +2.49.0 + diff --git a/patch/skia-m132-egl-runtime.diff b/patch/skia-m132-egl-runtime.diff new file mode 100644 index 00000000..3f7c7b66 --- /dev/null +++ b/patch/skia-m132-egl-runtime.diff @@ -0,0 +1,42 @@ +If you use cibuildwheel (which uses auditwheel repair to bundle libraries) to build, +you must NOT use the bundled "libEGL-xxxxxxxx.so.A.B.C". Look at ldd's output: + + $ ldd skia.cpython-313-x86_64-linux-gnu.so | grep GL + libEGL-48f73270.so.1.1.0 => .../skia_python.libs/libEGL-48f73270.so.1.1.0 (0x00007fd03fd31000) + libGL.so.1 => /lib64/libGL.so.1 (0x00007fd03fc71000) + libGLdispatch-64b28464.so.0.0.0 => .../skia_python.libs/libGLdispatch-64b28464.so.0.0.0 (0x00007fd03fa69000) + libGLX.so.0 => /lib64/libGLX.so.0 (0x00007fd03f369000) + libGLdispatch.so.0 => /lib64/libGLdispatch.so.0 (0x00007fd03f189000) + +(The duplicate GLdispatch entry is indirect from libEGL) + +You need to undo the effect of "auditwheel repair ..." with something like this: + + patchelf --replace-needed libEGL-e42ac8e3.so.1.1.0 libEGL.so.1.1.0 ~/.local/lib/python3.13/site-packages/skia.*.so + +Then check that libEGL.so (and libGLdispatch.so) is looked up from system locations, +and not from python3.13/site-packages/skia_python.libs/ again: + + $ ldd ~/.local/lib/python3.13/site-packages/skia.cpython-313-x86_64-linux-gnu.so | grep GL + libEGL.so.1.1.0 => /lib64/libEGL.so.1.1.0 (0x00007f8d1ea39000) + libGL.so.1 => /lib64/libGL.so.1 (0x00007f8d1e9c1000) + libGLdispatch.so.0 => /lib64/libGLdispatch.so.0 (0x00007f8d1ca69000) + libGLX.so.0 => /lib64/libGLX.so.0 (0x00007f8d1c369000) + +diff --git a/BUILD.gn b/BUILD.gn +index 20f308b..ceac00c 100644 +--- a/BUILD.gn ++++ b/BUILD.gn +@@ -1003,10 +1003,11 @@ optional("gpu") { + sources += [ "src/gpu/ganesh/gl/webgl/GrGLMakeNativeInterface_webgl.cpp" ] + } else if (is_linux && skia_use_x11) { + sources += [ ++ "src/gpu/ganesh/gl/egl/GrGLMakeEGLInterface.cpp", + "src/gpu/ganesh/gl/glx/GrGLMakeGLXInterface.cpp", + "src/gpu/ganesh/gl/glx/GrGLMakeNativeInterface_glx.cpp", + ] +- libs += [ "GL" ] ++ libs += [ "EGL", "GL" ] + } else if (is_mac) { + sources += [ "src/gpu/ganesh/gl/mac/GrGLMakeNativeInterface_mac.cpp" ] + } else if (is_ios) { diff --git a/patch/skia-m137-minimize-download.patch b/patch/skia-m137-minimize-download.patch new file mode 100644 index 00000000..380e5c2d --- /dev/null +++ b/patch/skia-m137-minimize-download.patch @@ -0,0 +1,70 @@ +diff --git a/DEPS b/DEPS +index 3c7ca04..a16b21d 100644 +--- a/DEPS ++++ b/DEPS +@@ -31,53 +31,18 @@ vars = { + # ./tools/git-sync-deps + deps = { + "buildtools" : "https://chromium.googlesource.com/chromium/src/buildtools.git@729495f2ffa69080907780591fa2a630b2556e98", +- "third_party/externals/angle2" : "https://chromium.googlesource.com/angle/angle.git@cdb34025f286a0ded80c34c4edae180539e24dc1", +- "third_party/externals/brotli" : "https://skia.googlesource.com/external/github.com/google/brotli.git@6d03dfbedda1615c4cba1211f8d81735575209c8", +- "third_party/externals/d3d12allocator" : "https://skia.googlesource.com/external/github.com/GPUOpen-LibrariesAndSDKs/D3D12MemoryAllocator.git@169895d529dfce00390a20e69c2f516066fe7a3b", +- # Dawn requires jinja2 and markupsafe for the code generator, tint for SPIRV compilation, and abseil for string formatting. +- # When the Dawn revision is updated these should be updated from the Dawn DEPS as well. +- "third_party/externals/dawn" : "https://dawn.googlesource.com/dawn.git@1a81a31c86f24b217d6396bc0a4c796590fffc43", +- "third_party/externals/jinja2" : "https://chromium.googlesource.com/chromium/src/third_party/jinja2@e2d024354e11cc6b041b0cff032d73f0c7e43a07", +- "third_party/externals/markupsafe" : "https://chromium.googlesource.com/chromium/src/third_party/markupsafe@0bad08bb207bbfc1d6f3bbc82b9242b0c50e5794", +- "third_party/externals/abseil-cpp" : "https://skia.googlesource.com/external/github.com/abseil/abseil-cpp.git@65a55c2ba891f6d2492477707f4a2e327a0b40dc", +- "third_party/externals/delaunator-cpp" : "https://skia.googlesource.com/external/github.com/skia-dev/delaunator-cpp.git@98305ef6c4e862f7d48df9cc647b690d796fec68", + "third_party/externals/dng_sdk" : "https://android.googlesource.com/platform/external/dng_sdk.git@dbe0a676450d9b8c71bf00688bb306409b779e90", +- "third_party/externals/egl-registry" : "https://skia.googlesource.com/external/github.com/KhronosGroup/EGL-Registry@b055c9b483e70ecd57b3cf7204db21f5a06f9ffe", +- "third_party/externals/emsdk" : "https://skia.googlesource.com/external/github.com/emscripten-core/emsdk.git@a896e3d066448b3530dbcaa48869fafefd738f57", + "third_party/externals/expat" : "https://chromium.googlesource.com/external/github.com/libexpat/libexpat.git@624da0f593bb8d7e146b9f42b06d8e6c80d032a3", + "third_party/externals/freetype" : "https://chromium.googlesource.com/chromium/src/third_party/freetype2.git@5d4e649f740c675426fbe4cdaffc53ee2a4cb954", + "third_party/externals/harfbuzz" : "https://chromium.googlesource.com/external/github.com/harfbuzz/harfbuzz.git@ca3cd48fa3e06fa81d7c8a3f716cca44ed2de26a", +- "third_party/externals/highway" : "https://chromium.googlesource.com/external/github.com/google/highway.git@424360251cdcfc314cfc528f53c872ecd63af0f0", + "third_party/externals/icu" : "https://chromium.googlesource.com/chromium/deps/icu.git@364118a1d9da24bb5b770ac3d762ac144d6da5a4", +- "third_party/externals/icu4x" : "https://chromium.googlesource.com/external/github.com/unicode-org/icu4x.git@bcf4f7198d4dc5f3127e84a6ca657c88e7d07a13", +- "third_party/externals/imgui" : "https://skia.googlesource.com/external/github.com/ocornut/imgui.git@55d35d8387c15bf0cfd71861df67af8cfbda7456", +- "third_party/externals/libavif" : "https://skia.googlesource.com/external/github.com/AOMediaCodec/libavif.git@55aab4ac0607ab651055d354d64c4615cf3d8000", +- "third_party/externals/libgav1" : "https://chromium.googlesource.com/codecs/libgav1.git@5cf722e659014ebaf2f573a6dd935116d36eadf1", +- "third_party/externals/libgrapheme" : "https://skia.googlesource.com/external/github.com/FRIGN/libgrapheme/@c0cab63c5300fa12284194fbef57aa2ed62a94c0", + "third_party/externals/libjpeg-turbo" : "https://chromium.googlesource.com/chromium/deps/libjpeg_turbo.git@e14cbfaa85529d47f9f55b0f104a579c1061f9ad", +- "third_party/externals/libjxl" : "https://chromium.googlesource.com/external/gitlab.com/wg1/jpeg-xl.git@a205468bc5d3a353fb15dae2398a101dff52f2d3", + "third_party/externals/libpng" : "https://skia.googlesource.com/third_party/libpng.git@ed217e3e601d8e462f7fd1e04bed43ac42212429", + "third_party/externals/libwebp" : "https://chromium.googlesource.com/webm/libwebp.git@845d5476a866141ba35ac133f856fa62f0b7445f", +- "third_party/externals/libyuv" : "https://chromium.googlesource.com/libyuv/libyuv.git@d248929c059ff7629a85333699717d7a677d8d96", +- "third_party/externals/oboe" : "https://chromium.googlesource.com/external/github.com/google/oboe.git@b02a12d1dd821118763debec6b83d00a8a0ee419", +- "third_party/externals/opengl-registry" : "https://skia.googlesource.com/external/github.com/KhronosGroup/OpenGL-Registry@14b80ebeab022b2c78f84a573f01028c96075553", +- "third_party/externals/partition_alloc" : "https://chromium.googlesource.com/chromium/src/base/allocator/partition_allocator.git@ce13777cb731e0a60c606d1741091fd11a0574d7", +- "third_party/externals/perfetto" : "https://android.googlesource.com/platform/external/perfetto@93885509be1c9240bc55fa515ceb34811e54a394", + "third_party/externals/piex" : "https://android.googlesource.com/platform/external/piex.git@bb217acdca1cc0c16b704669dd6f91a1b509c406", +- "third_party/externals/swiftshader" : "https://swiftshader.googlesource.com/SwiftShader@7905fa19e456df5aa8e2233a7ec5832c9c6c287b", + "third_party/externals/vulkanmemoryallocator" : "https://chromium.googlesource.com/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator@a6bfc237255a6bac1513f7c1ebde6d8aed6b5191", +- # vulkan-deps is a meta-repo containing several interdependent Khronos Vulkan repositories. +- # When the vulkan-deps revision is updated, those repos (spirv-*, vulkan-*) should be updated as well. + "third_party/externals/vulkan-deps" : "https://chromium.googlesource.com/vulkan-deps@95177446886dc95356c1662dbdc6e545233b3174", +- "third_party/externals/spirv-cross" : "https://chromium.googlesource.com/external/github.com/KhronosGroup/SPIRV-Cross@b8fcf307f1f347089e3c46eb4451d27f32ebc8d3", + "third_party/externals/spirv-headers" : "https://skia.googlesource.com/external/github.com/KhronosGroup/SPIRV-Headers.git@bab63ff679c41eb75fc67dac76e1dc44426101e1", +- "third_party/externals/spirv-tools" : "https://skia.googlesource.com/external/github.com/KhronosGroup/SPIRV-Tools.git@783d7033613cedaa7147d0700b517abc5c32312d", +- "third_party/externals/vello" : "https://skia.googlesource.com/external/github.com/linebender/vello.git@3ee3bea02164c5a816fe6c16ef4e3a810edb7620", +- "third_party/externals/vulkan-headers" : "https://chromium.googlesource.com/external/github.com/KhronosGroup/Vulkan-Headers@e2e53a724677f6eba8ff0ce1ccb64ee321785cbd", +- "third_party/externals/vulkan-tools" : "https://chromium.googlesource.com/external/github.com/KhronosGroup/Vulkan-Tools@682e42f7ae70a8fadf374199c02de737daa5c70d", +- "third_party/externals/vulkan-utility-libraries": "https://chromium.googlesource.com/external/github.com/KhronosGroup/Vulkan-Utility-Libraries@4e246c56ec5afb5ad66b9b04374d39ac04675c8e", +- "third_party/externals/unicodetools" : "https://chromium.googlesource.com/external/github.com/unicode-org/unicodetools@66a3fa9dbdca3b67053a483d130564eabc5fe095", +- #"third_party/externals/v8" : "https://chromium.googlesource.com/v8/v8.git@5f1ae66d5634e43563b2d25ea652dfb94c31a3b4", + "third_party/externals/wuffs" : "https://skia.googlesource.com/external/github.com/google/wuffs-mirror-release-c.git@e3f919ccfe3ef542cfc983a82146070258fb57f8", + "third_party/externals/zlib" : "https://chromium.googlesource.com/chromium/src/third_party/zlib@646b7f569718921d7d4b5b8e22572ff6c76f2596", + +diff --git a/bin/activate-emsdk b/bin/activate-emsdk +index 687ca9f..7167d8d 100755 +--- a/bin/activate-emsdk ++++ b/bin/activate-emsdk +@@ -17,6 +17,7 @@ EMSDK_PATH = os.path.join(EMSDK_ROOT, 'emsdk.py') + EMSDK_VERSION = '3.1.44' + + def main(): ++ return + if sysconfig.get_platform() in ['linux-aarch64', 'linux-arm64']: + # This platform cannot install emsdk at the provided version. See + # https://github.com/emscripten-core/emsdk/blob/main/emscripten-releases-tags.json#L5 diff --git a/patch/skia-m138-minimize-download.patch b/patch/skia-m138-minimize-download.patch new file mode 100644 index 00000000..68ffe207 --- /dev/null +++ b/patch/skia-m138-minimize-download.patch @@ -0,0 +1,70 @@ +diff --git a/DEPS b/DEPS +index 178d30b..a16b21d 100644 +--- a/DEPS ++++ b/DEPS +@@ -31,53 +31,18 @@ vars = { + # ./tools/git-sync-deps + deps = { + "buildtools" : "https://chromium.googlesource.com/chromium/src/buildtools.git@729495f2ffa69080907780591fa2a630b2556e98", +- "third_party/externals/angle2" : "https://chromium.googlesource.com/angle/angle.git@ec4d8f8e4d3f1a9e64430abd8b6b436253732adf", +- "third_party/externals/brotli" : "https://skia.googlesource.com/external/github.com/google/brotli.git@6d03dfbedda1615c4cba1211f8d81735575209c8", +- "third_party/externals/d3d12allocator" : "https://skia.googlesource.com/external/github.com/GPUOpen-LibrariesAndSDKs/D3D12MemoryAllocator.git@169895d529dfce00390a20e69c2f516066fe7a3b", +- # Dawn requires jinja2 and markupsafe for the code generator, tint for SPIRV compilation, and abseil for string formatting. +- # When the Dawn revision is updated these should be updated from the Dawn DEPS as well. +- "third_party/externals/dawn" : "https://dawn.googlesource.com/dawn.git@30e8f3c65d1708b5bfec3a6290c2b58a792d1899", +- "third_party/externals/jinja2" : "https://chromium.googlesource.com/chromium/src/third_party/jinja2@e2d024354e11cc6b041b0cff032d73f0c7e43a07", +- "third_party/externals/markupsafe" : "https://chromium.googlesource.com/chromium/src/third_party/markupsafe@0bad08bb207bbfc1d6f3bbc82b9242b0c50e5794", +- "third_party/externals/abseil-cpp" : "https://chromium.googlesource.com/chromium/src/third_party/abseil-cpp@04dc59d2c83238cb1fcb49083e5e416643a899ce", +- "third_party/externals/delaunator-cpp" : "https://skia.googlesource.com/external/github.com/skia-dev/delaunator-cpp.git@98305ef6c4e862f7d48df9cc647b690d796fec68", + "third_party/externals/dng_sdk" : "https://android.googlesource.com/platform/external/dng_sdk.git@dbe0a676450d9b8c71bf00688bb306409b779e90", +- "third_party/externals/egl-registry" : "https://skia.googlesource.com/external/github.com/KhronosGroup/EGL-Registry@b055c9b483e70ecd57b3cf7204db21f5a06f9ffe", +- "third_party/externals/emsdk" : "https://skia.googlesource.com/external/github.com/emscripten-core/emsdk.git@a896e3d066448b3530dbcaa48869fafefd738f57", + "third_party/externals/expat" : "https://chromium.googlesource.com/external/github.com/libexpat/libexpat.git@8e49998f003d693213b538ef765814c7d21abada", + "third_party/externals/freetype" : "https://chromium.googlesource.com/chromium/src/third_party/freetype2.git@702e4a1d32e4b911e85cc7df84b3ba395c28dab3", + "third_party/externals/harfbuzz" : "https://chromium.googlesource.com/external/github.com/harfbuzz/harfbuzz.git@08b52ae2e44931eef163dbad71697f911fadc323", +- "third_party/externals/highway" : "https://chromium.googlesource.com/external/github.com/google/highway.git@424360251cdcfc314cfc528f53c872ecd63af0f0", + "third_party/externals/icu" : "https://chromium.googlesource.com/chromium/deps/icu.git@364118a1d9da24bb5b770ac3d762ac144d6da5a4", +- "third_party/externals/icu4x" : "https://chromium.googlesource.com/external/github.com/unicode-org/icu4x.git@bcf4f7198d4dc5f3127e84a6ca657c88e7d07a13", +- "third_party/externals/imgui" : "https://skia.googlesource.com/external/github.com/ocornut/imgui.git@55d35d8387c15bf0cfd71861df67af8cfbda7456", +- "third_party/externals/libavif" : "https://skia.googlesource.com/external/github.com/AOMediaCodec/libavif.git@55aab4ac0607ab651055d354d64c4615cf3d8000", +- "third_party/externals/libgav1" : "https://chromium.googlesource.com/codecs/libgav1.git@5cf722e659014ebaf2f573a6dd935116d36eadf1", +- "third_party/externals/libgrapheme" : "https://skia.googlesource.com/external/github.com/FRIGN/libgrapheme/@c0cab63c5300fa12284194fbef57aa2ed62a94c0", + "third_party/externals/libjpeg-turbo" : "https://chromium.googlesource.com/chromium/deps/libjpeg_turbo.git@e14cbfaa85529d47f9f55b0f104a579c1061f9ad", +- "third_party/externals/libjxl" : "https://chromium.googlesource.com/external/gitlab.com/wg1/jpeg-xl.git@a205468bc5d3a353fb15dae2398a101dff52f2d3", + "third_party/externals/libpng" : "https://skia.googlesource.com/third_party/libpng.git@ed217e3e601d8e462f7fd1e04bed43ac42212429", + "third_party/externals/libwebp" : "https://chromium.googlesource.com/webm/libwebp.git@845d5476a866141ba35ac133f856fa62f0b7445f", +- "third_party/externals/libyuv" : "https://chromium.googlesource.com/libyuv/libyuv.git@d248929c059ff7629a85333699717d7a677d8d96", +- "third_party/externals/oboe" : "https://chromium.googlesource.com/external/github.com/google/oboe.git@b02a12d1dd821118763debec6b83d00a8a0ee419", +- "third_party/externals/opengl-registry" : "https://skia.googlesource.com/external/github.com/KhronosGroup/OpenGL-Registry@14b80ebeab022b2c78f84a573f01028c96075553", +- "third_party/externals/partition_alloc" : "https://chromium.googlesource.com/chromium/src/base/allocator/partition_allocator.git@ce13777cb731e0a60c606d1741091fd11a0574d7", +- "third_party/externals/perfetto" : "https://android.googlesource.com/platform/external/perfetto@93885509be1c9240bc55fa515ceb34811e54a394", + "third_party/externals/piex" : "https://android.googlesource.com/platform/external/piex.git@bb217acdca1cc0c16b704669dd6f91a1b509c406", +- "third_party/externals/swiftshader" : "https://swiftshader.googlesource.com/SwiftShader@a8133cbb3c8969e3c1e6b3cea2c02ec8312ef9ca", + "third_party/externals/vulkanmemoryallocator" : "https://chromium.googlesource.com/external/github.com/GPUOpen-LibrariesAndSDKs/VulkanMemoryAllocator@a6bfc237255a6bac1513f7c1ebde6d8aed6b5191", +- # vulkan-deps is a meta-repo containing several interdependent Khronos Vulkan repositories. +- # When the vulkan-deps revision is updated, those repos (spirv-*, vulkan-*) should be updated as well. + "third_party/externals/vulkan-deps" : "https://chromium.googlesource.com/vulkan-deps@d5a5fd31a4fe219410e13c93c8f3c0b237df65fc", +- "third_party/externals/spirv-cross" : "https://chromium.googlesource.com/external/github.com/KhronosGroup/SPIRV-Cross@b8fcf307f1f347089e3c46eb4451d27f32ebc8d3", + "third_party/externals/spirv-headers" : "https://skia.googlesource.com/external/github.com/KhronosGroup/SPIRV-Headers.git@c9aad99f9276817f18f72a4696239237c83cb775", +- "third_party/externals/spirv-tools" : "https://skia.googlesource.com/external/github.com/KhronosGroup/SPIRV-Tools.git@01021466b5e71deaac9054f56082566c782bfd51", +- "third_party/externals/vello" : "https://skia.googlesource.com/external/github.com/linebender/vello.git@3ee3bea02164c5a816fe6c16ef4e3a810edb7620", +- "third_party/externals/vulkan-headers" : "https://chromium.googlesource.com/external/github.com/KhronosGroup/Vulkan-Headers@75ad707a587e1469fb53a901b9b68fe9f6fbc11f", +- "third_party/externals/vulkan-tools" : "https://chromium.googlesource.com/external/github.com/KhronosGroup/Vulkan-Tools@60b640cb931814fcc6dabe4fc61f4738c56579f6", +- "third_party/externals/vulkan-utility-libraries": "https://chromium.googlesource.com/external/github.com/KhronosGroup/Vulkan-Utility-Libraries@ae56bd6e65d9faa731150e931cb35f0d895223bc", +- "third_party/externals/unicodetools" : "https://chromium.googlesource.com/external/github.com/unicode-org/unicodetools@66a3fa9dbdca3b67053a483d130564eabc5fe095", +- #"third_party/externals/v8" : "https://chromium.googlesource.com/v8/v8.git@5f1ae66d5634e43563b2d25ea652dfb94c31a3b4", + "third_party/externals/wuffs" : "https://skia.googlesource.com/external/github.com/google/wuffs-mirror-release-c.git@e3f919ccfe3ef542cfc983a82146070258fb57f8", + "third_party/externals/zlib" : "https://chromium.googlesource.com/chromium/src/third_party/zlib@646b7f569718921d7d4b5b8e22572ff6c76f2596", + +diff --git a/bin/activate-emsdk b/bin/activate-emsdk +index 687ca9f..7167d8d 100755 +--- a/bin/activate-emsdk ++++ b/bin/activate-emsdk +@@ -17,6 +17,7 @@ EMSDK_PATH = os.path.join(EMSDK_ROOT, 'emsdk.py') + EMSDK_VERSION = '3.1.44' + + def main(): ++ return + if sysconfig.get_platform() in ['linux-aarch64', 'linux-arm64']: + # This platform cannot install emsdk at the provided version. See + # https://github.com/emscripten-core/emsdk/blob/main/emscripten-releases-tags.json#L5 diff --git a/scripts/build_Linux.sh b/scripts/build_Linux.sh index c70ca4ed..461724a0 100644 --- a/scripts/build_Linux.sh +++ b/scripts/build_Linux.sh @@ -1,69 +1,29 @@ #!/usr/bin/env bash -export PATH=${PWD}/depot_tools:$PATH - -EXTRA_CFLAGS="" - -export CC=gcc -export CXX=g++ -export AR=ar -export CFLAGS="-Wno-deprecated-copy" -export LDFLAGS="-lrt" - # Install system dependencies if [[ $EUID -eq 0 ]]; then + if [[ ! -e "/etc/fedora-release" ]] ; then yum -y install epel-release ; fi yum install -y \ python3 \ + ninja-build gn \ fontconfig-devel \ mesa-libGL-devel \ + mesa-libEGL-devel libglvnd-devel mesa-libGLES-devel libglvnd mesa-libGLES mesa-libEGL libglvnd-egl \ xorg-x11-server-Xvfb \ mesa-dri-drivers && \ yum clean all && \ + mv depot_tools/ninja depot_tools/ninja.bak && \ + mv depot_tools/gn depot_tools/gn.bak && \ rm -rf /var/cache/yum fi -# Wheel-building needs fontconfig-devel from above. -# Simply quit, if it looks like a previous run was successful: -if [[ -f "skia/out/Release/libskia.a" ]] ; then - exit 0 -fi - -if [[ $(uname -m) == "aarch64" ]]; then - # Install ninja for aarch64 - yum -y install epel-release && \ - yum repolist && \ - yum install -y ninja-build && \ - mv depot_tools/ninja depot_tools/ninja.bak -fi - -# libicu.a is the largest 3rd-party; if it already exists, we run ninja -# a 2nd time and exit. -# Running ninja a 2nd-time is safe - it is no-ops if skia is already built too. -# The 3rd-party libraries below are built in size-order; we built libicu last to signal -# having built most of them. -if [[ -f "skia/out/Release/libicu.a" ]] ; then - cd skia && \ - ninja -C out/Release && \ - cd .. - exit $? -fi -### 2nd round<->1st round ### - -# Build gn -git clone https://gn.googlesource.com/gn && \ - cd gn && \ - git checkout fe330c0ae1ec29db30b6f830e50771a335e071fb && \ - python3 build/gen.py && \ - ninja -C out gn && \ - cd .. - # Build skia cd skia && \ - patch -p1 < ../patch/skia-m136-minimize-download.patch && \ + patch -p1 < ../patch/skia-m138-minimize-download.patch && \ patch -p1 < ../patch/skia-m132-colrv1-freetype.diff && \ + patch -p1 < ../patch/skia-m132-egl-runtime.diff && \ python3 tools/git-sync-deps && \ - cp -f ../gn/out/gn bin/gn && \ - bin/gn gen out/Release --args=" + gn gen out/Release --args=" is_official_build=true skia_enable_svg=true skia_use_vulkan=true @@ -76,12 +36,5 @@ skia_use_system_freetype2=false extra_cflags_cc=[\"-frtti\"] extra_ldflags=[\"-lrt\"] " && \ - ninja -C out/Release \ - third_party/freetype2 \ - third_party/libwebp \ - third_party/dng_sdk \ - third_party/harfbuzz \ - third_party/icu && \ - ( ( [[ $(uname -m) == "aarch64" ]] && echo "On aarch64 - Please run me again!" ) || \ - ninja -C out/Release ) && \ + ninja -C out/Release && \ cd .. diff --git a/scripts/build_Windows.sh b/scripts/build_Windows.sh index ec2ac468..85df523e 100644 --- a/scripts/build_Windows.sh +++ b/scripts/build_Windows.sh @@ -2,12 +2,22 @@ export PATH="${PWD}/depot_tools:$PATH" +if [[ ${RUNNER_ARCH} == "ARM64" ]]; then + EXTRA_ARGS=' +target_cpu="arm64" +' + echo "setting ARM64 Windows Skia build" +fi + + # Build skia cd skia && \ - patch -p1 < ../patch/skia-m136-minimize-download.patch && \ + patch -p1 < ../patch/skia-m138-minimize-download.patch && \ patch -p1 < ../patch/skia-m132-colrv1-freetype.diff && \ + patch -p1 -R < ../patch/0001-Disable-OpenGL-for-Windows-on-ARM64.patch && \ + patch -p1 < ../patch/0001-gn-Remove-msvc-env-setting.patch && \ python tools/git-sync-deps && \ - bin/gn gen out/Release --args=' + bin/gn gen out/Release --args=" is_official_build=true skia_enable_svg=true skia_use_vulkan=true @@ -21,7 +31,8 @@ skia_use_system_icu=false skia_use_system_harfbuzz=false skia_use_system_expat=false skia_use_system_zlib=false -extra_cflags_cc=["/GR", "/EHsc", "/MD"] -' && \ +extra_cflags_cc=[\"/GR\", \"/EHsc\", \"/MD\"] +${EXTRA_ARGS} +" && \ ninja -C out/Release && \ cd .. diff --git a/scripts/build_macOS.sh b/scripts/build_macOS.sh index 424e6324..25869913 100644 --- a/scripts/build_macOS.sh +++ b/scripts/build_macOS.sh @@ -22,7 +22,7 @@ function apply_patch { } cd skia && \ - patch -p1 < ../patch/skia-m136-minimize-download.patch && \ + patch -p1 < ../patch/skia-m138-minimize-download.patch && \ patch -p1 < ../patch/skia-m132-colrv1-freetype.diff && \ python3 tools/git-sync-deps && \ bin/gn gen out/Release --args=" diff --git a/setup.py b/setup.py index 8299fb59..c35cf83a 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ pass NAME = 'skia-python' -__version__ = '136.0b13' +__version__ = '138.0rc1' SKIA_PATH = os.getenv('SKIA_PATH', 'skia') SKIA_OUT_PATH = os.getenv( @@ -97,6 +97,7 @@ LIBRARIES = [ 'dl', 'fontconfig', + 'EGL', 'GL', 'expat', ] @@ -177,7 +178,8 @@ def build_extensions(self): ext_modules=[extension], data_files=data_files, install_requires=[ - 'numpy', + 'numpy; sys_platform != "win32" or python_version <= "3.10"', + 'numpy>=2.3.0rc1; sys_platform == "win32" and python_version >= "3.11"', 'pybind11>=2.6' ], setup_requires=['pybind11>=2.6'], diff --git a/skia b/skia index 28685d89..114d33c6 160000 --- a/skia +++ b/skia @@ -1 +1 @@ -Subproject commit 28685d899b0a35894743e2cedad4c9f525e90e1e +Subproject commit 114d33c62998ce5c16f899b9123c22000ca06ddd diff --git a/src/skia/GrContext.cpp b/src/skia/GrContext.cpp index 2c5e88fe..231fcfab 100644 --- a/src/skia/GrContext.cpp +++ b/src/skia/GrContext.cpp @@ -928,7 +928,7 @@ py::class_, GrRecordingContext>(m, "GrDi // "Enumerates all cached GPU resources and dumps their memory to " // "traceMemoryDump.") .def("supportsDistanceFieldText", &GrDirectContext::supportsDistanceFieldText) - .def("storeVkPipelineCacheData", &GrDirectContext::storeVkPipelineCacheData) + .def("storeVkPipelineCacheData", py::overload_cast<>(&GrDirectContext::storeVkPipelineCacheData)) .def_static("ComputeImageSize", [] (sk_sp image, skgpu::Mipmapped mapped, bool useNextPow2) { // REVISIT: process skgpu::Mipmapped and useNextPow2 = true diff --git a/src/skia/GrContext_gl.cpp b/src/skia/GrContext_gl.cpp index b0413997..8d20a2ca 100644 --- a/src/skia/GrContext_gl.cpp +++ b/src/skia/GrContext_gl.cpp @@ -1,6 +1,10 @@ #include "common.h" #include #include +#ifdef __linux__ +#include +#include +#endif void initGrContext_gl(py::module &m) { @@ -58,6 +62,12 @@ py::class_, SkRefCnt>( throw std::runtime_error("null pointer exception."); const GrGLInterface* ptr = interface.release(); return const_cast(ptr); - })); + })) + .def("validate", &GrGLInterface::validate) +#ifdef __linux__ + .def_static("MakeEGL", &GrGLInterfaces::MakeEGL) + .def_static("MakeGLX", &GrGLInterfaces::MakeGLX) +#endif + ; } diff --git a/src/skia/Image.cpp b/src/skia/Image.cpp index 1d987ee4..59b76f21 100644 --- a/src/skia/Image.cpp +++ b/src/skia/Image.cpp @@ -1398,7 +1398,7 @@ image :return: true if :py:class:`Image` is a GPU texture )docstring") - .def("isValid", &SkImage::isValid, + .def("isValid", py::overload_cast(&SkImage::isValid, py::const_), R"docstring( Returns true if :py:class:`Image` can be drawn on either raster surface or GPU surface. diff --git a/src/skia/RuntimeEffect.cpp b/src/skia/RuntimeEffect.cpp index ee40d27a..deffb287 100644 --- a/src/skia/RuntimeEffect.cpp +++ b/src/skia/RuntimeEffect.cpp @@ -1,21 +1,63 @@ #include #include "common.h" #include -//#include // defines SkV3, SkV4 ; M44 used in Matrix/Canvas ; Revisit. +//#include // defines SkV2, SkV3, SkV4 ; M44 used in Matrix/Canvas ; Revisit. #include +#include // for std::optional<> PYBIND11_MAKE_OPAQUE(std::vector) void initRuntimeEffect(py::module &m) { py::class_, SkRefCnt> runtime_effect(m, "RuntimeEffect"); +py::class_ runtime_effect_child(m, "RuntimeEffectChild"); py::class_ runtime_effect_childptr(m, "RuntimeEffectChildPtr"); +py::class_ runtime_effect_uniform(m, "RuntimeEffectUniform"); +py::bind_vector>(m, "VectorRuntimeEffectChild"); +py::class_> span_runtime_effect_child(m, "SpanRuntimeEffectChild"); py::bind_vector>(m, "VectorRuntimeEffectChildPtr"); py::class_> span_runtime_effect_childptr(m, "SpanRuntimeEffectChildPtr"); +py::class_> span_runtime_effect_uniform(m, "SpanRuntimeEffectUniform"); py::class_ runtime_effect_builder(m, "RuntimeEffectBuilder"); +py::enum_(runtime_effect, "ChildType") + .value("kShader", SkRuntimeEffect::ChildType::kShader) + .value("kColorFilter,", SkRuntimeEffect::ChildType::kColorFilter) + .value("kBlender", SkRuntimeEffect::ChildType::kBlender) + .export_values(); + +py::enum_(runtime_effect, "UniformType") + .value("kFloat", SkRuntimeEffect::Uniform::Type::kFloat) + .value("kFloat2", SkRuntimeEffect::Uniform::Type::kFloat2) + .value("kFloat3", SkRuntimeEffect::Uniform::Type::kFloat3) + .value("kFloat4", SkRuntimeEffect::Uniform::Type::kFloat4) + .value("kFloat2x2", SkRuntimeEffect::Uniform::Type::kFloat2x2) + .value("kFloat3x3", SkRuntimeEffect::Uniform::Type::kFloat3x3) + .value("kFloat4x4", SkRuntimeEffect::Uniform::Type::kFloat4x4) + .value("kInt", SkRuntimeEffect::Uniform::Type::kInt) + .value("kInt2", SkRuntimeEffect::Uniform::Type::kInt2) + .value("kInt3", SkRuntimeEffect::Uniform::Type::kInt3) + .value("kInt4", SkRuntimeEffect::Uniform::Type::kInt4) + .export_values(); + +py::class_(m, "V2") + .def(py::init( + [] (float x, float y) { + return SkV2{x, y}; + })) + .def(py::init( + [] (py::tuple v2) { + if (v2.size() != 2) + throw py::value_error("V2 must have exactly two elements."); + return SkV2{v2[0].cast(), v2[1].cast()}; + }), + py::arg("v2")) + ; + +py::implicitly_convertible(); + py::class_(m, "V3") .def(py::init( [] (float x, float y, float z) { @@ -53,11 +95,39 @@ py::class_(m, "RuntimeEffectResult") .def_readwrite("errorText", &SkRuntimeEffect::Result::errorText) ; +runtime_effect_child + .def(py::init<>()) + .def_property_readonly("name", + [] (const SkRuntimeEffect::Child& child) { + return child.name; + }) + .def_property_readonly("type", + [] (const SkRuntimeEffect::Child& child) { + return child.type; + }) + ; + +span_runtime_effect_child + .def("__getitem__", + [] (const SkSpan& self, size_t index) { + if (index >= self.size()) { + throw py::index_error(); + } + return self[index]; + }, py::return_value_policy::reference_internal) // SkSpan<> holds a reference but does not own + .def("__len__", + [] (const SkSpan& self) { + return self.size(); + }) + ; + + runtime_effect_childptr .def(py::init<>()) .def(py::init>()) .def(py::init>()) .def(py::init>()) + .def_property_readonly("type", &SkRuntimeEffect::ChildPtr::type) // returns std::optional ; span_runtime_effect_childptr @@ -69,6 +139,17 @@ span_runtime_effect_childptr return SkSpan(&v[0], v.size()); })) .def(py::init&>()) + .def("__getitem__", + [] (const SkSpan& self, size_t index) { + if (index >= self.size()) { + throw py::index_error(); + } + return self[index]; + }, py::return_value_policy::reference_internal) // SkSpan<> holds a reference but does not own + .def("__len__", + [] (const SkSpan& self) { + return self.size(); + }) ; py::implicitly_convertible, SkRuntimeEffect::ChildPtr>(); @@ -76,6 +157,32 @@ py::implicitly_convertible, SkRuntimeEffect::ChildPtr>(); py::implicitly_convertible, SkRuntimeEffect::ChildPtr>(); py::implicitly_convertible, SkSpan>(); +runtime_effect_uniform + .def(py::init<>()) + .def_property_readonly("name", + [] (const SkRuntimeEffect::Uniform& uniform) { + return uniform.name; + }) + .def_property_readonly("type", + [] (const SkRuntimeEffect::Uniform& uniform) { + return uniform.type; + }) + ; + +span_runtime_effect_uniform + .def("__getitem__", + [] (const SkSpan& self, size_t index) { + if (index >= self.size()) { + throw py::index_error(); + } + return self[index]; + }, py::return_value_policy::reference_internal) // SkSpan<> holds a reference but does not own + .def("__len__", + [] (const SkSpan& self) { + return self.size(); + }) + ; + /* All of these static methods check Result.effect being non-null, throw with errorText if null; they differ from upsteam c++ APIs, which asks clients to check. @@ -160,29 +267,66 @@ runtime_effect .def("makeBlender", py::overload_cast, SkSpan>(&SkRuntimeEffect::makeBlender, py::const_), py::arg("uniforms"), py::arg("children") = SkSpan{}) + .def("children", &SkRuntimeEffect::children, py::return_value_policy::reference_internal) // returns SkSpan(self.fChildren) + .def("uniforms", &SkRuntimeEffect::uniforms, py::return_value_policy::reference_internal) // returns SkSpan(self.fUniforms) ; py::class_(m, "RuntimeEffectBuilderUniform") .def(py::init<>()) + .def_property_readonly("name", + [] (const SkRuntimeEffectBuilder::BuilderUniform& uniform) -> py::object { + // return std::optional<> to allow null? requires c++17 + return (uniform.fVar) ? py::cast(uniform.fVar->name) : py::none(); + }) + .def_property_readonly("type", + [] (const SkRuntimeEffectBuilder::BuilderUniform& uniform) -> py::object { + return (uniform.fVar) ? py::cast(uniform.fVar->type) : py::none(); + }) ; py::class_(m, "RuntimeEffectBuilderChild") .def(py::init<>()) + .def_property_readonly("name", + [] (const SkRuntimeEffectBuilder::BuilderChild& child) -> py::object { + return (child.fChild) ? py::cast(child.fChild->name) : py::none(); + }) + .def_property_readonly("type", + [] (const SkRuntimeEffectBuilder::BuilderChild& child) -> py::object { + return (child.fChild) ? py::cast(child.fChild->type) : py::none(); + }) ; +/* + uniform/child/uniforms/children are probably not useful, + as effect.uniform / effect.child are much nicer. +*/ runtime_effect_builder .def(py::init>()) .def(py::init, sk_sp>()) .def("uniform", &SkRuntimeEffectBuilder::uniform, - py::arg("name")) + py::arg("name"), + py::return_value_policy::reference_internal) .def("child", &SkRuntimeEffectBuilder::child, - py::arg("name")) + py::arg("name"), + py::return_value_policy::reference_internal) .def("setUniform", [] (SkRuntimeEffectBuilder& builder, std::string_view name, int uniform) { auto v = builder.uniform(name); v = uniform; }, py::arg("name"), py::arg("uniform")) + .def("setUniform", + [] (SkRuntimeEffectBuilder& builder, std::string_view name, float uniform) { + auto v = builder.uniform(name); + v = uniform; + }, + py::arg("name"), py::arg("uniform")) + .def("setUniform", + [] (SkRuntimeEffectBuilder& builder, std::string_view name, const SkV2& uniform) { + auto v = builder.uniform(name); + v = uniform; + }, + py::arg("name"), py::arg("uniform")) .def("setUniform", [] (SkRuntimeEffectBuilder& builder, std::string_view name, const SkV3& uniform) { auto v = builder.uniform(name); @@ -197,9 +341,11 @@ runtime_effect_builder py::arg("name"), py::arg("uniform")) .def("setUniform", [] (SkRuntimeEffectBuilder& builder, std::string_view name, py::list vN) { - if (vN.size() != 3 && vN.size() != 4) - throw py::value_error("Input must have exactly three or four elements."); + if (vN.size() != 2 && vN.size() != 3 && vN.size() != 4) + throw py::value_error("Input must have exactly two, three or four elements."); auto v = builder.uniform(name); + if (vN.size() == 2) + v = SkV2{vN[0].cast(), vN[1].cast()}; if (vN.size() == 3) v = SkV3{vN[0].cast(), vN[1].cast(), vN[2].cast()}; if (vN.size() == 4) @@ -224,8 +370,12 @@ runtime_effect_builder v = child; }, py::arg("name"), py::arg("child")) - .def("uniforms", &SkRuntimeEffectBuilder::uniforms) - .def("children", &SkRuntimeEffectBuilder::children) + .def("effect", &SkRuntimeEffectBuilder::effect, + py::return_value_policy::reference_internal) // return self.fEffect.get() + .def("uniforms", &SkRuntimeEffectBuilder::uniforms, + py::return_value_policy::reference_internal) // return self.fUniforms + .def("children", &SkRuntimeEffectBuilder::children, + py::return_value_policy::reference_internal) // return self.fChildren .def("makeShader", &SkRuntimeEffectBuilder::makeShader, py::arg("localMatrix") = nullptr) .def("makeColorFilter", &SkRuntimeEffectBuilder::makeColorFilter) diff --git a/src/skia/Surface.cpp b/src/skia/Surface.cpp index d4bbc026..33d0140e 100644 --- a/src/skia/Surface.cpp +++ b/src/skia/Surface.cpp @@ -63,6 +63,8 @@ py::class_ surfaceprops(m, "SurfaceProps", R"docstring( )docstring"); py::enum_(surfaceprops, "Flags", py::arithmetic()) + .value("kDefault_Flag", + SkSurfaceProps::Flags::kDefault_Flag) .value("kUseDeviceIndependentFonts_Flag", SkSurfaceProps::Flags::kUseDeviceIndependentFonts_Flag) .value("kDynamicMSAA_Flag", @@ -246,6 +248,24 @@ surface See :py:meth:`~MakeRasterN32Premul` )docstring", py::arg("width"), py::arg("height"), py::arg("surfaceProps") = nullptr) + .def(py::init( + [] (int width, int height, SkColorType colortype, const SkSurfaceProps* surfaceProps) { + auto info = SkImageInfo::MakeN32Premul(width, height).makeColorType(colortype); + return SkSurfaces::Raster(info, surfaceProps); + }), + R"docstring( + See :py:meth:`~MakeRasterN32Premul` plus :py:class:`ImageInfo`'s :py:meth:`~makeColorType` + )docstring", + py::arg("width"), py::arg("height"), py::arg("colortype"), py::arg("surfaceProps") = nullptr) + .def(py::init( + [] (const SkImageInfo& imageinfo, size_t rowBytes, const SkSurfaceProps* surfaceProps) { + return SkSurfaces::Raster(imageinfo, rowBytes, surfaceProps); + }), + R"docstring( + See :py:meth:`~MakeRaster` + )docstring", + py::arg("imageInfo"), py::arg("rowBytes") = 0, + py::arg("surfaceProps") = nullptr) .def(py::init( [] (py::array array, SkColorType ct, SkAlphaType at, const SkColorSpace* cs, const SkSurfaceProps *surfaceProps) { @@ -1010,6 +1030,15 @@ surface Internally, sets :py:class:`ImageInfo` to width, height, native color type, and :py:attr:`AlphaType.kPremul`. + Note that the :py:class:`ImageInfo` native color type might not be what + you desire, if you intent to interact with other software expecting + specific color type order. e.g. package `wx`'s `wx.Bitmap.FromBufferRGBA`. + For that purpose, you need one of the other :py:class:`Surface` + constructors which takes an explicit appropriate matching + :py:class:`ImageInfo` input, or one that takes an explicit :py:class:`ColorType` + input. You should check the output of `surface.imageInfo().colorType()` + afterwards, in that usage. + :py:class:`Surface` is returned if width and height are greater than zero. diff --git a/tests/test_grcontext.py b/tests/test_grcontext.py index 107342c5..8784a6b9 100644 --- a/tests/test_grcontext.py +++ b/tests/test_grcontext.py @@ -540,10 +540,32 @@ def test_GrContext_ComputeImageSize(image): int) +# We want this to be followed by something that re-obtain the context +# as this one can fail, but making a broken context current. +def test_GrDirectContext_MakeGL_EGL(): + if not sys.platform.startswith("linux"): + pytest.skip("API on Linux only") + import moderngl + moderngl_context = moderngl.create_standalone_context(backend="egl") + interface = skia.GrGLInterface.MakeEGL() + import os + # The interface non-Null and validate tests don't fail under X! + if ((interface is None) or (not interface.validate())) and (os.getenv("DISPLAY") == True): + pytest.skip("Software-only X (Xvfb)") + assert isinstance(skia.GrDirectContext.MakeGL(interface), skia.GrContext) + + def test_GrDirectContext_MakeGL(context): assert isinstance(context, skia.GrContext) +# inherits the context from the last call +def test_GrDirectContext_MakeGL_GLX(): + if not sys.platform.startswith("linux"): + pytest.skip("API on Linux only") + assert isinstance(skia.GrDirectContext.MakeGL(skia.GrGLInterface.MakeGLX()), skia.GrContext) + + def test_GrDirectContext_MakeVulkan(): context = skia.GrVkBackendContext() options = skia.GrContextOptions() diff --git a/tests/test_surface.py b/tests/test_surface.py index 3bb40cc3..beaf1078 100644 --- a/tests/test_surface.py +++ b/tests/test_surface.py @@ -10,12 +10,29 @@ def check_surface(x): @pytest.mark.parametrize('args', [ (240, 320), + (240, 320, skia.SurfaceProps()), + (240, 320, skia.ColorType.kRGBA_8888_ColorType), + (240, 320, skia.ColorType.kBGRA_8888_ColorType, skia.SurfaceProps()), + (skia.ImageInfo.MakeN32Premul(240, 320),), + (skia.ImageInfo.MakeN32Premul(240, 320).makeColorType(skia.ColorType.kRGBA_8888_ColorType),), + (skia.ImageInfo.MakeN32Premul(240, 320).makeColorType(skia.ColorType.kBGRA_8888_ColorType), 0), + (skia.ImageInfo.MakeN32Premul(240, 320).makeColorType(skia.ColorType.kBGRA_8888_ColorType), 0, skia.SurfaceProps()), + (skia.ImageInfo.MakeN32Premul(240, 320), 0), + (skia.ImageInfo.MakeN32Premul(240, 320), 0, skia.SurfaceProps()), (np.zeros((240, 320, 4), dtype=np.uint8),), ]) def test_Surface_init(args): check_surface(skia.Surface(*args)) +@pytest.mark.parametrize('width, height, colortype', [ + (240, 320, skia.ColorType.kRGBA_8888_ColorType), + (240, 320, skia.ColorType.kBGRA_8888_ColorType), +]) +def test_Surface_color_init(width, height, colortype): + assert skia.Surface(width, height, colortype).imageInfo().colorType() == colortype + + def test_Surface_enter_exit(surface): with surface as canvas: assert isinstance(canvas, skia.Canvas)