SDL_image: cmake: add support for building vendored dav1d library

From d42d109b3624ad1ef899d5f24ef6ed9139ec82be Mon Sep 17 00:00:00 2001
From: Anonymous Maarten <[EMAIL REDACTED]>
Date: Sun, 10 Sep 2023 22:15:13 +0200
Subject: [PATCH] cmake: add support for building vendored dav1d library

---
 .github/workflows/main.yml      | 19 ++++++++--------
 CMakeLists.txt                  | 40 +++++++++++++++++++++++++++++----
 cmake/PrivateSdlFunctions.cmake | 12 ++++++----
 external/dav1d                  |  2 +-
 external/libavif                |  2 +-
 5 files changed, 56 insertions(+), 19 deletions(-)

diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml
index bb7d8ef5..8d29a103 100644
--- a/.github/workflows/main.yml
+++ b/.github/workflows/main.yml
@@ -18,9 +18,9 @@ jobs:
         - { name: Windows (MSVC),    os: windows-latest, shell: sh,  vendored: true, cmake: '-GNinja', msvc: 1, shared: 1, static: 0 }
         - { name: Windows (mingw64), os: windows-latest, shell: 'msys2 {0}', vendored: false, msystem: mingw64, msys-env: mingw-w64-x86_64, shared: 1, static: 0,
             cmake: '-DSDL3IMAGE_BACKEND_STB=OFF -DSDL3IMAGE_BACKEND_WIC=OFF  -DSDL3IMAGE_AVIF=ON -G "Ninja Multi-Config"' }
-        - { name: Linux,             os: ubuntu-latest,  shell: sh,  vendored: false, cmake: '-DSDL3IMAGE_AVIF=ON -GNinja', shared: 1, static: 0, nojxl: true }
+        - { name: Linux,             os: ubuntu-latest,  shell: sh,  vendored: false, cmake: '-GNinja', shared: 1, static: 0, nojxl: true }
         - { name: 'Linux (static)',  os: ubuntu-latest,  shell: sh,  vendored: true, cmake: '-DBUILD_SHARED_LIBS=OFF -GNinja', shared: 0, static: 1 }
-        - { name: Macos,             os: macos-latest,   shell: sh,  vendored: false, cmake: '-DSDL3IMAGE_AVIF=ON -GNinja', shared: 1, static: 0 }
+        - { name: Macos,             os: macos-latest,   shell: sh,  vendored: false, cmake: '-GNinja', shared: 1, static: 0 }
 
     steps:
 
@@ -37,14 +37,15 @@ jobs:
         install: >-
           ${{ matrix.platform.msys-env }}-cmake
           ${{ matrix.platform.msys-env }}-gcc
+          ${{ matrix.platform.msys-env }}-ninja
+          ${{ matrix.platform.msys-env }}-pkg-config
+          ${{ matrix.platform.msys-env }}-nasm
           ${{ matrix.platform.msys-env }}-libavif
           ${{ matrix.platform.msys-env }}-libjpeg-turbo
           ${{ matrix.platform.msys-env }}-libjxl
           ${{ matrix.platform.msys-env }}-libpng
           ${{ matrix.platform.msys-env }}-libtiff
           ${{ matrix.platform.msys-env }}-libwebp
-          ${{ matrix.platform.msys-env }}-ninja
-          ${{ matrix.platform.msys-env }}-pkg-config
           ${{ matrix.platform.msys-env }}-zlib
     - name: Install Ninja
       uses: turtlesec-no/get-ninja@main
@@ -65,8 +66,6 @@ jobs:
           libavif \
           libpng \
           libtiff \
-          ninja \
-          pkg-config \
           webp \
           zlib \
           ${NULL+}
@@ -80,10 +79,11 @@ jobs:
           libpng-dev \
           libtiff-dev \
           libwebp-dev \
-          ninja-build \
-          pkg-config \
           zlib1g-dev \
           ${NULL+}
+    - name: Set up NASM
+      uses: ilammy/setup-nasm@v1
+      if: ${{ matrix.platform.vendored && !contains(matrix.platform.shell, 'msys2') }}
 
     - uses: actions/checkout@v3
       with:
@@ -109,6 +109,7 @@ jobs:
           -DSDL3IMAGE_SAMPLES=ON \
           -DSDL3IMAGE_TESTS=ON \
           -DSDL3IMAGE_TESTS_INSTALL=ON \
+          -DSDL3IMAGE_AVIF=ON \
           -DSDL3IMAGE_JXL=${{ !matrix.platform.nojxl }} \
           -DSDL3IMAGE_TIF=ON \
           -DSDL3IMAGE_WEBP=ON \
@@ -130,7 +131,7 @@ jobs:
         export LD_LIBRARY_PATH="$PWD:$LD_LIBRARY_PATH"
         set -eu
 
-        export SDL_IMAGE_TEST_REQUIRE_LOAD_AVIF=${{ (matrix.platform.vendored && '0') || '1' }}
+        export SDL_IMAGE_TEST_REQUIRE_LOAD_AVIF=1
         export SDL_IMAGE_TEST_REQUIRE_LOAD_BMP=1
         export SDL_IMAGE_TEST_REQUIRE_LOAD_CUR=1
         export SDL_IMAGE_TEST_REQUIRE_LOAD_GIF=1
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 2b69e35d..7d5150d8 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -105,6 +105,19 @@ endif()
 cmake_dependent_option(SDL3IMAGE_AVIF_SHARED "Dynamically load AVIF support (requires shared libavif)"
     ${SDL3IMAGE_DEPS_SHARED} SDL3IMAGE_AVIF OFF)
 
+if(SDL3IMAGE_AVIF_VENDORED)
+  set(SDL3IMAGE_DAV1D ON)
+  set(SDL3IMAGE_DAV1D_VENDORED ON)
+else()
+  set(SDL3IMAGE_DAV1D OFF)
+  set(SDL3IMAGE_DAV1D_VENDORED OFF)
+endif()
+if(SDL3IMAGE_AVIF_SHARED)
+  set(SDL3IMAGE_DAV1D_SHARED ON)
+else()
+  set(SDL3IMAGE_DAV1D_SHARED OFF)
+endif()
+
 if(SDL3IMAGE_VENDORED AND SDL3IMAGE_JPG AND NOT (SDL3IMAGE_BACKEND_WIC OR SDL3IMAGE_BACKEND_STB OR SDL3IMAGE_BACKEND_IMAGEIO))
     set(SDL3IMAGE_JPG_VENDORED ON)
 else()
@@ -354,20 +367,39 @@ if(SDL3IMAGE_ZLIB)
     endif()
 endif()
 
+if(SDL3IMAGE_DAV1D)
+    if(SDL3IMAGE_DAV1D_VENDORED)
+        message(STATUS "${PROJECT_NAME}: Using vendored dav1d")
+        add_subdirectory(external/dav1d)
+        set(DAV1D_LIBRARY dav1d)
+        list(APPEND INSTALL_EXTRA_TARGETS dav1d)
+    else()
+        message(FATAL_ERROR "Not implemented")
+    endif()
+endif()
+
 if(SDL3IMAGE_AVIF)
     target_compile_definitions(${sdl3_image_target_name} PRIVATE LOAD_AVIF)
     if(SDL3IMAGE_AVIF_VENDORED)
         message(STATUS "${PROJECT_NAME}: Using vendored libavif")
-        message(FATAL_ERROR "libavif is not vendored (yet)")
         sdl_check_project_in_subfolder(external/libavif libavif SDL3IMAGE_VENDORED)
         set(BUILD_SHARED_LIBS ${SDL3IMAGE_AVIF_SHARED})
+        set(AVIF_CODEC_DAV1D ON CACHE BOOL "Use dav1d codec for decoding" FORCE)
+        set(AVIF_LOCAL_DAV1D OFF CACHE BOOL "Build dav1d by libaf" FORCE)
+        set(LIBAVIF_WITH_SHARPYUV_SDLIMAGE ${SDL3IMAGE_WEBP} CACHE BOOL "Build libavif with sharpyuv support (re-use sharpyuv built by libwebp)" FORCE)
         add_subdirectory(external/libavif EXCLUDE_FROM_ALL)
-        list(APPEND INSTALL_EXTRA_TARGETS libavif)
-        set_target_properties(libavif PROPERTIES EXPORT_NAME external_libavif)
-        add_library(SDL3_image::external_libavif ALIAS libavif)
+        list(APPEND INSTALL_EXTRA_TARGETS avif)
+        set_target_properties(avif PROPERTIES EXPORT_NAME external_libavif)
+        add_library(SDL3_image::external_libavif ALIAS avif)
         if(NOT SDL3IMAGE_AVIF_SHARED)
             list(APPEND PC_LIBS -l$<TARGET_FILE_BASE_NAME:avif>)
         endif()
+        if(NOT MSVC)
+          check_linker_flag(C "-Wl,--no-undefined" LINKER_SUPPORTS_WL_NO_UNDEFINED)
+          if(LINKER_SUPPORTS_WL_NO_UNDEFINED)
+            target_link_options(avif PRIVATE "-Wl,--no-undefined")
+          endif()
+        endif()
     else()
         message(STATUS "${PROJECT_NAME}: Using system libavif")
         find_package(libavif 1.0 QUIET)
diff --git a/cmake/PrivateSdlFunctions.cmake b/cmake/PrivateSdlFunctions.cmake
index 367e1719..79658971 100644
--- a/cmake/PrivateSdlFunctions.cmake
+++ b/cmake/PrivateSdlFunctions.cmake
@@ -219,12 +219,16 @@ function(target_get_dynamic_library DEST TARGET)
     set(${DEST} ${result} PARENT_SCOPE)
 endfunction()
 
-macro(sdl_check_project_in_subfolder relative_subfolder name vendored_option)
-    if(NOT EXISTS "${PROJECT_SOURCE_DIR}/${relative_subfolder}/CMakeLists.txt")
-        message(FATAL_ERROR "No cmake project for ${name} found in ${relative_subfolder}.\n"
+function(sdl_check_project_in_subfolder relative_subfolder name vendored_option)
+    cmake_parse_arguments(ARG "" "FILE" "" ${ARGN})
+    if(NOT ARG_FILE)
+        set(ARG_FILE "CMakeLists.txt")
+    endif()
+    if(NOT EXISTS "${PROJECT_SOURCE_DIR}/${relative_subfolder}/${ARG_FILE}")
+        message(FATAL_ERROR "Could not find ${ARG_FILE} for ${name} in ${relative_subfolder}.\n"
             "Run the download script in the external folder, or re-configure with -D${vendored_option}=OFF to use system packages.")
     endif()
-endmacro()
+endfunction()
 
 macro(sdl_check_linker_flag flag var)
     # FIXME: Use CheckLinkerFlag module once cmake minimum version >= 3.18
diff --git a/external/dav1d b/external/dav1d
index 7ca852b8..05cbee5f 160000
--- a/external/dav1d
+++ b/external/dav1d
@@ -1 +1 @@
-Subproject commit 7ca852b8c3d7cd41b3eef15b0db1a76392990555
+Subproject commit 05cbee5f522dff69f3a793bf9a6b8fa239b13d31
diff --git a/external/libavif b/external/libavif
index b319b1c8..dfc14a75 160000
--- a/external/libavif
+++ b/external/libavif
@@ -1 +1 @@
-Subproject commit b319b1c82406ee5c0d27b669533293825a77eec3
+Subproject commit dfc14a758cb9ad398b78fd6b60ec2144e67e9651