Add Chromium-only Blender WebEngine parity work
This commit is contained in:
211
blender-5.2.0/intern/cycles/cmake/external_libs.cmake
Normal file
211
blender-5.2.0/intern/cycles/cmake/external_libs.cmake
Normal file
@@ -0,0 +1,211 @@
|
||||
# SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
###########################################################################
|
||||
# CUDA
|
||||
###########################################################################
|
||||
|
||||
if(WITH_CYCLES_DEVICE_CUDA AND (WITH_CYCLES_CUDA_BINARIES OR NOT WITH_CUDA_DYNLOAD))
|
||||
find_package(CUDA) # Try to auto locate CUDA toolkit
|
||||
set_and_warn_library_found("CUDA compiler" CUDA_FOUND WITH_CYCLES_CUDA_BINARIES)
|
||||
|
||||
if(CUDA_FOUND)
|
||||
message(STATUS "Found CUDA ${CUDA_NVCC_EXECUTABLE} (${CUDA_VERSION})")
|
||||
else()
|
||||
if(NOT WITH_CUDA_DYNLOAD)
|
||||
message(STATUS "Additionally falling back to dynamic CUDA load")
|
||||
set(WITH_CUDA_DYNLOAD ON)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
###########################################################################
|
||||
# HIP
|
||||
###########################################################################
|
||||
|
||||
if(WITH_CYCLES_DEVICE_HIP)
|
||||
if(WITH_CYCLES_HIP_BINARIES)
|
||||
# Need at least HIP 5.5 to solve compiler bug affecting the kernel.
|
||||
find_package(HIP 6.0.0)
|
||||
set_and_warn_library_found("HIP compiler" HIP_FOUND WITH_CYCLES_HIP_BINARIES)
|
||||
|
||||
if(HIP_FOUND)
|
||||
message(STATUS "Found HIP ${HIP_HIPCC_EXECUTABLE} (${HIP_VERSION})")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# HIP RT
|
||||
if(WITH_CYCLES_DEVICE_HIP AND WITH_CYCLES_DEVICE_HIPRT)
|
||||
if(DEFINED LIBDIR)
|
||||
set(HIPRT_ROOT_DIR ${LIBDIR}/hiprt)
|
||||
endif()
|
||||
find_package(HIPRT)
|
||||
set_and_warn_library_found("HIP RT" HIPRT_FOUND WITH_CYCLES_DEVICE_HIPRT)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT WITH_CYCLES_DEVICE_HIP)
|
||||
set(WITH_CYCLES_DEVICE_HIPRT OFF)
|
||||
endif()
|
||||
|
||||
if(NOT WITH_HIP_DYNLOAD)
|
||||
set(WITH_HIP_DYNLOAD ON)
|
||||
endif()
|
||||
|
||||
###########################################################################
|
||||
# Metal
|
||||
###########################################################################
|
||||
|
||||
if(WITH_CYCLES_DEVICE_METAL)
|
||||
find_library(METAL_LIBRARY Metal)
|
||||
|
||||
# This file was added in the 12.0 SDK, use it as a way to detect the version.
|
||||
if(METAL_LIBRARY)
|
||||
if(EXISTS "${METAL_LIBRARY}/Headers/MTLFunctionStitching.h")
|
||||
set(METAL_FOUND ON)
|
||||
else()
|
||||
message(STATUS "Metal version too old, must be SDK 12.0 or newer")
|
||||
set(METAL_FOUND OFF)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set_and_warn_library_found("Metal" METAL_FOUND WITH_CYCLES_DEVICE_METAL)
|
||||
if(METAL_FOUND)
|
||||
message(STATUS "Found Metal: ${METAL_LIBRARY}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
###########################################################################
|
||||
# oneAPI
|
||||
###########################################################################
|
||||
|
||||
if(WITH_CYCLES_DEVICE_ONEAPI OR EMBREE_SYCL_SUPPORT)
|
||||
# Find packages for even when WITH_CYCLES_DEVICE_ONEAPI is OFF, as it's
|
||||
# needed for linking to Embree with SYCL support.
|
||||
find_package(SYCL)
|
||||
find_package(LevelZero)
|
||||
|
||||
if(WITH_CYCLES_DEVICE_ONEAPI)
|
||||
set_and_warn_library_found("oneAPI" SYCL_FOUND WITH_CYCLES_DEVICE_ONEAPI)
|
||||
set_and_warn_library_found("Level Zero" LEVEL_ZERO_FOUND WITH_CYCLES_DEVICE_ONEAPI)
|
||||
if(NOT (SYCL_FOUND AND SYCL_VERSION VERSION_GREATER_EQUAL 6.0 AND LEVEL_ZERO_FOUND))
|
||||
message(STATUS "SYCL 6.0+ or Level Zero not found, disabling WITH_CYCLES_DEVICE_ONEAPI")
|
||||
set(WITH_CYCLES_DEVICE_ONEAPI OFF)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_CYCLES_DEVICE_ONEAPI AND WITH_CYCLES_ONEAPI_BINARIES)
|
||||
# Centralized place for ocloc usage initialization
|
||||
#
|
||||
# All ocloc-related setup is done here, in one place, so that every
|
||||
# subsequent use of ocloc (validation below, device support queries
|
||||
# in oneAPI CMakeLists.txt, and the final AoT compilation command) shares
|
||||
# consistent paths and an environment to properly use ocloc.
|
||||
#
|
||||
# Six variables are established here, for later use:
|
||||
# OCLOC_INSTALL_DIR - Root directory of the ocloc installation.
|
||||
# IGC_INSTALL_DIR - Root directory of the Intel Graphics
|
||||
# Compiler (IGC) installation.
|
||||
# OCLOC_LD_LIBRARY_PATH - All library paths required to run
|
||||
# the ocloc binary (can be empty if
|
||||
# no library paths are needed).
|
||||
# OCLOC_ENV_COMMAND - The full command to set up library paths
|
||||
# with cmake -E env command
|
||||
# (can be empty if no library paths are
|
||||
# needed).
|
||||
# OCLOC_BINARY_FULL_FILEPATH - Full path to the ocloc binary.
|
||||
# OCLOC_FOUND - Indicates whether a fully working ocloc binary
|
||||
# was found.
|
||||
|
||||
# Resolve OCLOC_INSTALL_DIR if not set by user.
|
||||
# Without user-specified directory, we are expected to use precompiled
|
||||
# (Linux) / bundled (Windows) version from Blender's dependencies at
|
||||
# the path:
|
||||
# <DPCPP_ROOT_DIRECTORY>/lib/ocloc/
|
||||
if(NOT OCLOC_INSTALL_DIR)
|
||||
get_filename_component(_sycl_compiler_root ${SYCL_COMPILER} DIRECTORY)
|
||||
get_filename_component(OCLOC_INSTALL_DIR "${_sycl_compiler_root}/../lib/ocloc" ABSOLUTE)
|
||||
unset(_sycl_compiler_root)
|
||||
endif()
|
||||
|
||||
# Resolve IGC_INSTALL_DIR if not set by user.
|
||||
#
|
||||
# Ocloc at runtime searches for and loads IGC
|
||||
# (Intel Graphics Compiler) libraries (libigc.so, etc.).
|
||||
#
|
||||
# On Windows, IGC_INSTALL_DIR is identical to OCLOC_INSTALL_DIR,
|
||||
# since all shared libraries of ocloc are bundled together.
|
||||
# On Linux, we are expected to use a precompiled version from Blender's
|
||||
# dependencies at the path:
|
||||
# <DPCPP_ROOT_DIRECTORY>/lib/igc/
|
||||
if(NOT IGC_INSTALL_DIR)
|
||||
if(WIN32)
|
||||
set(IGC_INSTALL_DIR "${OCLOC_INSTALL_DIR}")
|
||||
else()
|
||||
get_filename_component(_sycl_compiler_root ${SYCL_COMPILER} DIRECTORY)
|
||||
get_filename_component(IGC_INSTALL_DIR "${_sycl_compiler_root}/../lib/igc" ABSOLUTE)
|
||||
unset(_sycl_compiler_root)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WIN32)
|
||||
set(OCLOC_BINARY_FULL_FILEPATH ${OCLOC_INSTALL_DIR}/ocloc.exe)
|
||||
else()
|
||||
set(OCLOC_BINARY_FULL_FILEPATH ${OCLOC_INSTALL_DIR}/bin/ocloc)
|
||||
endif()
|
||||
|
||||
# Build the reusable ocloc environment command prefix
|
||||
if(WIN32)
|
||||
# On Windows, it is expected to be empty, as all shared
|
||||
# libraries are expected to be located in the same directory
|
||||
# where ocloc binary is located.
|
||||
set(OCLOC_LD_LIBRARY_PATH "")
|
||||
set(OCLOC_ENV_COMMAND "")
|
||||
else()
|
||||
set(OCLOC_LD_LIBRARY_PATH "${OCLOC_INSTALL_DIR}/lib:${IGC_INSTALL_DIR}/lib")
|
||||
set(OCLOC_ENV_COMMAND
|
||||
${CMAKE_COMMAND} -E env "LD_LIBRARY_PATH=${OCLOC_LD_LIBRARY_PATH}"
|
||||
)
|
||||
endif()
|
||||
|
||||
set(OCLOC_FOUND ON)
|
||||
# Three-stage validation: directory -> binary -> execution
|
||||
if(NOT EXISTS ${OCLOC_INSTALL_DIR})
|
||||
set(OCLOC_FOUND OFF)
|
||||
set(_ocloc_missing_error_msg "oneAPI ocloc directory not found as ${OCLOC_INSTALL_DIR}.")
|
||||
elseif(NOT EXISTS ${OCLOC_BINARY_FULL_FILEPATH})
|
||||
set(OCLOC_FOUND OFF)
|
||||
set(_ocloc_missing_error_msg
|
||||
"oneAPI ocloc directory ${OCLOC_INSTALL_DIR} was found."
|
||||
"However, the ocloc binary ${OCLOC_BINARY_FULL_FILEPATH} was not found."
|
||||
)
|
||||
else()
|
||||
# Verify that the binary is functional by testing execution.
|
||||
# The --help flag is a safe way to test if the binary works properly.
|
||||
execute_process(
|
||||
COMMAND ${OCLOC_ENV_COMMAND} ${OCLOC_BINARY_FULL_FILEPATH} --help
|
||||
RESULT_VARIABLE _ocloc_retcode
|
||||
OUTPUT_QUIET
|
||||
ERROR_QUIET
|
||||
)
|
||||
|
||||
if(NOT _ocloc_retcode EQUAL 0)
|
||||
set(OCLOC_FOUND OFF)
|
||||
set(_ocloc_missing_error_msg
|
||||
"oneAPI ocloc binary ${OCLOC_BINARY_FULL_FILEPATH} was found."
|
||||
"However, it has failed to be executed with ${_ocloc_retcode} return code."
|
||||
)
|
||||
endif()
|
||||
unset(_ocloc_retcode)
|
||||
endif()
|
||||
|
||||
if(NOT OCLOC_FOUND)
|
||||
list(JOIN _ocloc_missing_error_msg " " _ocloc_missing_error_msg)
|
||||
message(STATUS "${_ocloc_missing_error_msg} A different ocloc directory can be set using OCLOC_INSTALL_DIR cmake variable.")
|
||||
set_and_warn_library_found("ocloc" OCLOC_FOUND WITH_CYCLES_ONEAPI_BINARIES)
|
||||
unset(_ocloc_missing_error_msg)
|
||||
endif()
|
||||
|
||||
endif()
|
||||
185
blender-5.2.0/intern/cycles/cmake/macros.cmake
Normal file
185
blender-5.2.0/intern/cycles/cmake/macros.cmake
Normal file
@@ -0,0 +1,185 @@
|
||||
# SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
#
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
function(cycles_set_solution_folder target)
|
||||
if(IDE_GROUP_PROJECTS_IN_FOLDERS)
|
||||
get_filename_component(folderdir ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY)
|
||||
string(REPLACE ${CMAKE_SOURCE_DIR} "" folderdir ${folderdir})
|
||||
set_target_properties(${target} PROPERTIES FOLDER ${folderdir})
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
function(cycles_add_library target library_deps)
|
||||
add_library(${target} ${ARGN})
|
||||
|
||||
# On Windows certain libraries have two sets of binaries: one for debug builds and one for
|
||||
# release builds. The root of this requirement goes into ABI, I believe, but that's outside
|
||||
# of a scope of this comment.
|
||||
#
|
||||
# CMake have a native way of dealing with this, which is specifying what build type the
|
||||
# libraries are provided for:
|
||||
#
|
||||
# target_link_libraries(target optimized|debug|general <libraries>)
|
||||
#
|
||||
# The build type is to be provided as a separate argument to the function.
|
||||
#
|
||||
# CMake's variables for libraries will contain build type in such cases. For example:
|
||||
#
|
||||
# set(FOO_LIBRARIES optimized libfoo.lib debug libfoo_d.lib)
|
||||
#
|
||||
# Complications start with a single argument for library_deps: all the elements are being
|
||||
# put to a list: "${FOO_LIBRARIES}" will become "optimized;libfoo.lib;debug;libfoo_d.lib".
|
||||
# This makes it impossible to pass it as-is to target_link_libraries since it will treat
|
||||
# this argument as a list of libraries to be linked against, causing missing libraries
|
||||
# for optimized.lib.
|
||||
#
|
||||
# What this code does it traverses library_deps and extracts information about whether
|
||||
# library is to provided as general, debug or optimized. This is a little state machine which
|
||||
# keeps track of which build type library is to provided for:
|
||||
#
|
||||
# - If "debug" or "optimized" word is found, the next element in the list is expected to be
|
||||
# a library which will be passed to target_link_libraries() under corresponding build type.
|
||||
#
|
||||
# - If there is no "debug" or "optimized" used library is specified for all build types.
|
||||
#
|
||||
# NOTE: If separated libraries for debug and release are needed every library is the list are
|
||||
# to be prefixed explicitly.
|
||||
#
|
||||
# Use: "optimized libfoo optimized libbar debug libfoo_d debug libbar_d"
|
||||
# NOT: "optimized libfoo libbar debug libfoo_d libbar_d"
|
||||
#
|
||||
# TODO(sergey): This is the same as Blender's side CMake. Find a way to avoid duplication
|
||||
# somehow in a way which allows to have Cycles standalone.
|
||||
if(NOT "${library_deps}" STREQUAL "")
|
||||
set(next_library_mode "")
|
||||
set(next_library_scope "PUBLIC")
|
||||
foreach(library ${library_deps})
|
||||
string(TOLOWER "${library}" library_lower)
|
||||
if(("${library_lower}" STREQUAL "optimized") OR
|
||||
("${library_lower}" STREQUAL "debug"))
|
||||
set(next_library_mode "${library_lower}")
|
||||
elseif(("${library}" STREQUAL "PUBLIC") OR
|
||||
("${library}" STREQUAL "PRIVATE") OR
|
||||
("${library}" STREQUAL "INTERFACE"))
|
||||
set(next_library_scope "${library}")
|
||||
else()
|
||||
if("${next_library_mode}" STREQUAL "optimized")
|
||||
target_link_libraries(${target} ${next_library_scope} optimized ${library})
|
||||
elseif("${next_library_mode}" STREQUAL "debug")
|
||||
target_link_libraries(${target} ${next_library_scope} debug ${library})
|
||||
else()
|
||||
target_link_libraries(${target} ${next_library_scope} ${library})
|
||||
endif()
|
||||
set(next_library_mode "")
|
||||
endif()
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
# On windows vcpkg goes out of its way to make its libs the preferred
|
||||
# libs, and needs to be explicitly be told not to do that.
|
||||
if(WIN32)
|
||||
set_target_properties(${target} PROPERTIES VS_GLOBAL_VcpkgEnabled "false")
|
||||
endif()
|
||||
|
||||
cycles_set_solution_folder(${target})
|
||||
endfunction()
|
||||
|
||||
# Modifies in parent scope:
|
||||
# - `${libraries}`: appended with external library dependencies.
|
||||
function(cycles_external_libraries_append libraries)
|
||||
# Dependencies with modern targets, these always exist even when optional deps are disabled.
|
||||
list(APPEND ${libraries}
|
||||
bf::dependencies::openimageio
|
||||
bf::dependencies::pthreads
|
||||
bf::dependencies::zlib
|
||||
bf::dependencies::optional::embree
|
||||
bf::dependencies::opencolorio
|
||||
bf::dependencies::openexr
|
||||
bf::dependencies::optional::openimagedenoise
|
||||
bf::dependencies::optional::openpgl
|
||||
bf::dependencies::optional::opensubdiv
|
||||
bf::dependencies::optional::openvdb
|
||||
bf::dependencies::optional::osl
|
||||
bf::dependencies::optional::pugixml
|
||||
bf::dependencies::optional::python
|
||||
${CMAKE_DL_LIBS}
|
||||
${PLATFORM_LINKLIBS}
|
||||
)
|
||||
|
||||
# Platform-specific frameworks and libraries.
|
||||
if(APPLE)
|
||||
list(APPEND ${libraries} "-framework Foundation")
|
||||
if(WITH_USD)
|
||||
list(APPEND ${libraries} "-framework CoreVideo -framework Cocoa -framework OpenGL")
|
||||
endif()
|
||||
# OpenColorIO
|
||||
list(APPEND ${libraries} "-framework IOKit")
|
||||
list(APPEND ${libraries} "-framework Carbon")
|
||||
if(WITH_OPENIMAGEDENOISE)
|
||||
if("${CMAKE_OSX_ARCHITECTURES}" STREQUAL "arm64")
|
||||
list(APPEND ${libraries} "-framework Accelerate")
|
||||
endif()
|
||||
endif()
|
||||
elseif(WIN32)
|
||||
if(WITH_USD)
|
||||
list(APPEND ${libraries} "opengl32")
|
||||
endif()
|
||||
endif()
|
||||
if(UNIX AND NOT APPLE)
|
||||
list(APPEND ${libraries} "-lm -lc -lutil")
|
||||
endif()
|
||||
|
||||
# GPU backends.
|
||||
if(WITH_CYCLES_DEVICE_CUDA OR WITH_CYCLES_DEVICE_OPTIX)
|
||||
if(WITH_CUDA_DYNLOAD)
|
||||
list(APPEND ${libraries} extern_cuew)
|
||||
else()
|
||||
list(APPEND ${libraries} ${CUDA_CUDA_LIBRARY})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(WITH_CYCLES_DEVICE_HIP AND WITH_HIP_DYNLOAD)
|
||||
list(APPEND ${libraries} extern_hipew)
|
||||
endif()
|
||||
|
||||
if(WITH_CYCLES_DEVICE_ONEAPI AND WITH_CYCLES_EMBREE AND EMBREE_SYCL_SUPPORT)
|
||||
list(APPEND ${libraries} ${SYCL_LIBRARIES})
|
||||
endif()
|
||||
|
||||
# Compatibility libraries.
|
||||
if(UNIX AND NOT APPLE)
|
||||
if(CYCLES_STANDALONE_REPOSITORY)
|
||||
list(APPEND ${libraries} extern_libc_compat)
|
||||
# Hack to solve linking order issue where external libs depend
|
||||
# on our compatibility lib.
|
||||
list(APPEND ${libraries} $<TARGET_FILE:extern_libc_compat>)
|
||||
else()
|
||||
list(APPEND ${libraries} bf_intern_libc_compat)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if(NOT CYCLES_STANDALONE_REPOSITORY)
|
||||
list(APPEND ${libraries} bf_intern_guardedalloc)
|
||||
endif()
|
||||
set(${libraries} "${${libraries}}" PARENT_SCOPE)
|
||||
endfunction()
|
||||
|
||||
function(cycles_install_libraries target)
|
||||
# Copy DLLs for dynamically linked libraries.
|
||||
if(WIN32)
|
||||
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
|
||||
install(
|
||||
FILES
|
||||
${TBB_ROOT_DIR}/bin/tbb_debug${CMAKE_SHARED_LIBRARY_SUFFIX}
|
||||
${OPENVDB_ROOT_DIR}/bin/openvdb_d${CMAKE_SHARED_LIBRARY_SUFFIX}
|
||||
DESTINATION ${CMAKE_INSTALL_PREFIX})
|
||||
else()
|
||||
install(
|
||||
FILES
|
||||
${TBB_ROOT_DIR}/bin/tbb${CMAKE_SHARED_LIBRARY_SUFFIX}
|
||||
${OPENVDB_ROOT_DIR}/bin/openvdb${CMAKE_SHARED_LIBRARY_SUFFIX}
|
||||
DESTINATION ${CMAKE_INSTALL_PREFIX})
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
26
blender-5.2.0/intern/cycles/cmake/msvc_arch_flags.c
Normal file
26
blender-5.2.0/intern/cycles/cmake/msvc_arch_flags.c
Normal file
@@ -0,0 +1,26 @@
|
||||
/* SPDX-FileCopyrightText: 2011-2022 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include <isa_availability.h>
|
||||
#include <stdio.h>
|
||||
|
||||
/* The MS CRT defines this */
|
||||
extern int __isa_available;
|
||||
|
||||
const char *get_arch_flags()
|
||||
{
|
||||
if (__isa_available >= __ISA_AVAILABLE_AVX2) {
|
||||
return "/arch:AVX2";
|
||||
}
|
||||
if (__isa_available >= __ISA_AVAILABLE_AVX) {
|
||||
return "/arch:AVX";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
printf("%s\n", get_arch_flags());
|
||||
return 0;
|
||||
}
|
||||
54
blender-5.2.0/intern/cycles/cmake/zstd_compress.cpp
Normal file
54
blender-5.2.0/intern/cycles/cmake/zstd_compress.cpp
Normal file
@@ -0,0 +1,54 @@
|
||||
/* SPDX-FileCopyrightText: 2024 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
#include <cstdint>
|
||||
#include <fstream>
|
||||
#include <vector>
|
||||
|
||||
#include <zstd.h>
|
||||
|
||||
int main(const int argc, const char **argv)
|
||||
{
|
||||
if (argc < 3) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* TODO: This might fail for non-ASCII paths on Windows... */
|
||||
std::ifstream in(argv[1], std::ios_base::binary);
|
||||
std::ofstream out(argv[2], std::ios_base::binary);
|
||||
if (!in || !out) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
in.seekg(0, std::ios_base::end);
|
||||
size_t in_size = in.tellg();
|
||||
in.seekg(0, std::ios_base::beg);
|
||||
if (!in) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::vector<char> in_data(in_size);
|
||||
in.read(in_data.data(), in_size);
|
||||
if (!in) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t out_size = ZSTD_compressBound(in_size);
|
||||
if (ZSTD_isError(out_size)) {
|
||||
return -1;
|
||||
}
|
||||
std::vector<char> out_data(out_size);
|
||||
|
||||
out_size = ZSTD_compress(out_data.data(), out_data.size(), in_data.data(), in_data.size(), 19);
|
||||
if (ZSTD_isError(out_size)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
out.write(out_data.data(), out_size);
|
||||
if (!out) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user