mirror of
https://github.com/webmproject/libwebp.git
synced 2024-12-26 13:48:21 +01:00
ed665a15e8
This builds on the work on portable-intrinsics branch: - define WEBP_ENABLE_WASM_SIMD to enable WebAssembly optimizations, this defines a constant (WEBP_USE_WASM_SIMD) that we can use in the future to enable Wasm SIMD intrinsics - build dwebp with JS build - add a placeholder dec_wasm.c file, we don't do any special initialization so it will fall back to c functions - add Wasm to cpu checks, it needs to come before all checks since the Emscripten toolchain will emulate x86 systems Change-Id: I12de720304ff19fff82c8d100defbc60353787a9
169 lines
6.6 KiB
CMake
169 lines
6.6 KiB
CMake
# Copyright (c) 2021 Google LLC.
|
|
#
|
|
# Use of this source code is governed by a BSD-style license
|
|
# that can be found in the LICENSE file in the root of the source
|
|
# tree. An additional intellectual property rights grant can be found
|
|
# in the file PATENTS. All contributing project authors may
|
|
# be found in the AUTHORS file in the root of the source tree.
|
|
|
|
# Check for SIMD extensions.
|
|
include(CMakePushCheckState)
|
|
|
|
function(webp_check_compiler_flag WEBP_SIMD_FLAG ENABLE_SIMD)
|
|
if(NOT ENABLE_SIMD)
|
|
message(STATUS "Disabling ${WEBP_SIMD_FLAG} optimization.")
|
|
set(WEBP_HAVE_${WEBP_SIMD_FLAG} 0 PARENT_SCOPE)
|
|
return()
|
|
endif()
|
|
unset(WEBP_HAVE_FLAG_${WEBP_SIMD_FLAG} CACHE)
|
|
cmake_push_check_state()
|
|
set(CMAKE_REQUIRED_INCLUDES ${CMAKE_CURRENT_SOURCE_DIR})
|
|
check_c_source_compiles("
|
|
#include \"${CMAKE_CURRENT_LIST_DIR}/../src/dsp/dsp.h\"
|
|
int main(void) {
|
|
#if !defined(WEBP_USE_${WEBP_SIMD_FLAG})
|
|
this is not valid code
|
|
#endif
|
|
return 0;
|
|
}
|
|
" WEBP_HAVE_FLAG_${WEBP_SIMD_FLAG})
|
|
cmake_pop_check_state()
|
|
if(WEBP_HAVE_FLAG_${WEBP_SIMD_FLAG})
|
|
set(WEBP_HAVE_${WEBP_SIMD_FLAG} 1 PARENT_SCOPE)
|
|
else()
|
|
set(WEBP_HAVE_${WEBP_SIMD_FLAG} 0 PARENT_SCOPE)
|
|
endif()
|
|
endfunction()
|
|
|
|
# those are included in the names of WEBP_USE_* in c++ code.
|
|
set(WEBP_SIMD_FLAGS "WASM_SIMD;SSE41;SSE2;MIPS32;MIPS_DSP_R2;NEON;MSA")
|
|
set(WEBP_SIMD_FILE_EXTENSIONS
|
|
"_wasm.c;_sse41.c;_sse2.c;_mips32.c;_mips_dsp_r2.c;_neon.c;_msa.c")
|
|
if(MSVC AND CMAKE_C_COMPILER_ID STREQUAL "MSVC")
|
|
# With at least Visual Studio 12 (2013)+ /arch is not necessary to build SSE2
|
|
# or SSE4 code unless a lesser /arch is forced. MSVC does not have a SSE4
|
|
# flag, but an AVX one. Using that with SSE4 code risks generating illegal
|
|
# instructions when used on machines with SSE4 only. The flags are left for
|
|
# older (untested) versions to avoid any potential compatibility issues.
|
|
if(MSVC_VERSION GREATER_EQUAL 1800 AND NOT CMAKE_C_FLAGS MATCHES "/arch:")
|
|
set(SIMD_ENABLE_FLAGS)
|
|
else()
|
|
set(SIMD_ENABLE_FLAGS "/arch:AVX;/arch:SSE2;;;;")
|
|
endif()
|
|
set(SIMD_DISABLE_FLAGS)
|
|
else()
|
|
set(SIMD_ENABLE_FLAGS
|
|
"-msimd128;-msse4.1;-msse2;-mips32;-mdspr2;-mfpu=neon;-mmsa")
|
|
set(SIMD_DISABLE_FLAGS
|
|
"-mno-simd128;-mno-sse4.1;-mno-sse2;;-mno-dspr2;;-mno-msa")
|
|
endif()
|
|
|
|
set(WEBP_SIMD_FILES_TO_NOT_INCLUDE)
|
|
set(WEBP_SIMD_FILES_TO_INCLUDE)
|
|
set(WEBP_SIMD_FLAGS_TO_INCLUDE)
|
|
|
|
if(${ANDROID})
|
|
if(${ANDROID_ABI} STREQUAL "armeabi-v7a")
|
|
# This is because Android studio uses the configuration "-march=armv7-a
|
|
# -mfloat-abi=softfp -mfpu=vfpv3-d16" that does not trigger neon
|
|
# optimizations but should (as this configuration does not exist anymore).
|
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -mfpu=neon ")
|
|
endif()
|
|
endif()
|
|
|
|
list(LENGTH WEBP_SIMD_FLAGS WEBP_SIMD_FLAGS_LENGTH)
|
|
math(EXPR WEBP_SIMD_FLAGS_RANGE "${WEBP_SIMD_FLAGS_LENGTH} - 1")
|
|
|
|
foreach(I_SIMD RANGE ${WEBP_SIMD_FLAGS_RANGE})
|
|
# With Emscripten 2.0.9 -msimd128 -mfpu=neon will enable NEON, but the
|
|
# source will fail to compile.
|
|
if(EMSCRIPTEN AND ${I_SIMD} GREATER_EQUAL 5)
|
|
break()
|
|
endif()
|
|
# Emscripten supports SSE via compat headers, if WEBP_ENABLED_WASM_SIMD is
|
|
# specified skip testing those (because it will succeed).
|
|
if (EMSCRIPTEN AND ${I_SIMD} GREATER_EQUAL 1 AND ${WEBP_ENABLE_WASM_SIMD})
|
|
break()
|
|
endif()
|
|
|
|
list(GET WEBP_SIMD_FLAGS ${I_SIMD} WEBP_SIMD_FLAG)
|
|
|
|
# First try with no extra flag added as the compiler might have default flags
|
|
# (especially on Android).
|
|
unset(WEBP_HAVE_${WEBP_SIMD_FLAG} CACHE)
|
|
cmake_push_check_state()
|
|
set(CMAKE_REQUIRED_FLAGS)
|
|
webp_check_compiler_flag(${WEBP_SIMD_FLAG} ${WEBP_ENABLE_SIMD})
|
|
if(NOT WEBP_HAVE_${WEBP_SIMD_FLAG})
|
|
list(GET SIMD_ENABLE_FLAGS ${I_SIMD} SIMD_COMPILE_FLAG)
|
|
# This enables using Emscripten's SSE compatibility headers.
|
|
if(EMSCRIPTEN)
|
|
set(SIMD_COMPILE_FLAG "-msimd128 ${SIMD_COMPILE_FLAG}")
|
|
endif()
|
|
set(CMAKE_REQUIRED_FLAGS ${SIMD_COMPILE_FLAG})
|
|
webp_check_compiler_flag(${WEBP_SIMD_FLAG} ${WEBP_ENABLE_SIMD})
|
|
else()
|
|
if(MSVC AND SIMD_ENABLE_FLAGS)
|
|
# The detection for SSE2/SSE4 support under MSVC is based on the compiler
|
|
# version so e.g., clang-cl will require flags to enable the assembly.
|
|
list(GET SIMD_ENABLE_FLAGS ${I_SIMD} SIMD_COMPILE_FLAG)
|
|
else()
|
|
set(SIMD_COMPILE_FLAG " ")
|
|
endif()
|
|
endif()
|
|
# Check which files we should include or not.
|
|
list(GET WEBP_SIMD_FILE_EXTENSIONS ${I_SIMD} WEBP_SIMD_FILE_EXTENSION)
|
|
file(GLOB SIMD_FILES "${CMAKE_CURRENT_LIST_DIR}/../"
|
|
"src/dsp/*${WEBP_SIMD_FILE_EXTENSION}")
|
|
if(WEBP_HAVE_${WEBP_SIMD_FLAG})
|
|
# Memorize the file and flags.
|
|
foreach(FILE ${SIMD_FILES})
|
|
list(APPEND WEBP_SIMD_FILES_TO_INCLUDE ${FILE})
|
|
list(APPEND WEBP_SIMD_FLAGS_TO_INCLUDE ${SIMD_COMPILE_FLAG})
|
|
endforeach()
|
|
else()
|
|
# Remove the file from the list.
|
|
foreach(FILE ${SIMD_FILES})
|
|
list(APPEND WEBP_SIMD_FILES_NOT_TO_INCLUDE ${FILE})
|
|
endforeach()
|
|
# Explicitly disable SIMD.
|
|
if(SIMD_DISABLE_FLAGS)
|
|
list(GET SIMD_DISABLE_FLAGS ${I_SIMD} SIMD_COMPILE_FLAG)
|
|
include(CheckCCompilerFlag)
|
|
if(SIMD_COMPILE_FLAG)
|
|
# Between 3.17.0 and 3.18.2 check_cxx_compiler_flag() sets a normal
|
|
# variable at parent scope while check_cxx_source_compiles() continues
|
|
# to set an internal cache variable, so we unset both to avoid the
|
|
# failure / success state persisting between checks. See
|
|
# https://gitlab.kitware.com/cmake/cmake/-/issues/21207.
|
|
unset(HAS_COMPILE_FLAG)
|
|
unset(HAS_COMPILE_FLAG CACHE)
|
|
check_c_compiler_flag(${SIMD_COMPILE_FLAG} HAS_COMPILE_FLAG)
|
|
if(HAS_COMPILE_FLAG)
|
|
# Do one more check for Clang to circumvent CMake issue 13194.
|
|
if(COMMAND check_compiler_flag_common_patterns)
|
|
# Only in CMake 3.0 and above.
|
|
check_compiler_flag_common_patterns(COMMON_PATTERNS)
|
|
else()
|
|
set(COMMON_PATTERNS)
|
|
endif()
|
|
set(CMAKE_REQUIRED_DEFINITIONS ${SIMD_COMPILE_FLAG})
|
|
check_c_source_compiles("int main(void) {return 0;}"
|
|
FLAG_${SIMD_COMPILE_FLAG}
|
|
FAIL_REGEX
|
|
"warning: argument unused during compilation:"
|
|
${COMMON_PATTERNS})
|
|
if(NOT FLAG_${SIMD_COMPILE_FLAG})
|
|
unset(HAS_COMPILE_FLAG)
|
|
unset(HAS_COMPILE_FLAG CACHE)
|
|
endif()
|
|
endif()
|
|
if(HAS_COMPILE_FLAG)
|
|
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${SIMD_COMPILE_FLAG}")
|
|
endif()
|
|
endif()
|
|
endif()
|
|
endif()
|
|
cmake_pop_check_state()
|
|
endforeach()
|