Merge branch 'bf-blender' into main
This commit is contained in:
commit
5104519898
|
@ -760,8 +760,8 @@ endif()
|
|||
|
||||
# Unit testing
|
||||
option(WITH_GTESTS "Enable GTest unit testing" OFF)
|
||||
option(WITH_OPENGL_RENDER_TESTS "Enable OpenGL render related unit testing (Experimental)" OFF)
|
||||
option(WITH_OPENGL_DRAW_TESTS "Enable OpenGL UI drawing related unit testing (Experimental)" OFF)
|
||||
option(WITH_GPU_RENDER_TESTS "Enable GPU render related unit testing (EEVEE, Workbench and Grease Pencil)" OFF)
|
||||
option(WITH_GPU_DRAW_TESTS "Enable GPU drawing related unit testing (GPU backends and draw manager)" OFF)
|
||||
option(WITH_COMPOSITOR_REALTIME_TESTS "Enable regression testing for realtime compositor" OFF)
|
||||
if(UNIX AND NOT (APPLE OR HAIKU))
|
||||
option(WITH_UI_TESTS "\
|
||||
|
|
|
@ -17,6 +17,7 @@ ExternalProject_Add(external_ocloc
|
|||
PREFIX ${BUILD_DIR}/ocloc
|
||||
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${LIBDIR}/ocloc ${DEFAULT_CMAKE_FLAGS} ${OCLOC_EXTRA_ARGS}
|
||||
INSTALL_DIR ${LIBDIR}/ocloc
|
||||
PATCH_COMMAND ${PATCH_CMD} -p 1 -d ${BUILD_DIR}/ocloc/src/external_ocloc/ < ${PATCH_DIR}/ocloc.diff
|
||||
)
|
||||
|
||||
add_dependencies(
|
||||
|
|
|
@ -14,6 +14,7 @@ if(NOT APPLE)
|
|||
${OIDN_EXTRA_ARGS}
|
||||
-DOIDN_DEVICE_SYCL=ON
|
||||
-DOIDN_DEVICE_SYCL_AOT=OFF
|
||||
-DOIDN_DEVICE_HIP=ON
|
||||
-DLEVEL_ZERO_ROOT=${LIBDIR}/level-zero/lib
|
||||
)
|
||||
endif()
|
||||
|
|
|
@ -47,12 +47,6 @@ set(OPENVDB_EXTRA_ARGS
|
|||
)
|
||||
|
||||
set(OPENVDB_PATCH ${PATCH_CMD} -p 1 -d ${BUILD_DIR}/openvdb/src/openvdb < ${PATCH_DIR}/openvdb.diff)
|
||||
if(APPLE)
|
||||
set(OPENVDB_PATCH
|
||||
${OPENVDB_PATCH} &&
|
||||
${PATCH_CMD} -p 1 -d ${BUILD_DIR}/openvdb/src/openvdb < ${PATCH_DIR}/openvdb_metal.diff
|
||||
)
|
||||
endif()
|
||||
|
||||
ExternalProject_Add(openvdb
|
||||
URL file://${PACKAGE_DIR}/${OPENVDB_FILE}
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
diff --git a/shared/offline_compiler/source/ocloc_fatbinary.cpp b/shared/offline_compiler/source/ocloc_fatbinary.cpp
|
||||
index 98a1c0e..4d9b5b0 100644
|
||||
--- a/shared/offline_compiler/source/ocloc_fatbinary.cpp
|
||||
+++ b/shared/offline_compiler/source/ocloc_fatbinary.cpp
|
||||
@@ -286,7 +286,9 @@ int buildFatBinaryForTarget(int retVal, const std::vector<std::string> &argsCopy
|
||||
productConfig = ProductConfigHelper::parseMajorMinorRevisionValue(argHelper->productConfigHelper->getProductConfigFromDeviceName(product));
|
||||
}
|
||||
|
||||
- fatbinary.appendFileEntry(pointerSize + "." + productConfig, pCompiler->getPackedDeviceBinaryOutput());
|
||||
+ // Storing binaries under the hardware prefix instead of the full architecture version number,
|
||||
+ // as they would otherwise be ignored if they do not fully match that of the execution device.
|
||||
+ fatbinary.appendFileEntry(pointerSize + "." + NEO::hardwarePrefix[argHelper->productConfigHelper->getProductFamilyFromDeviceName(productConfig)], pCompiler->getPackedDeviceBinaryOutput());
|
||||
return retVal;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -19,7 +19,7 @@ buildbot:
|
|||
optix:
|
||||
version: '7.3.0'
|
||||
ocloc:
|
||||
version: '101.4723'
|
||||
version: '101.4723p0'
|
||||
cmake:
|
||||
default:
|
||||
version: any
|
||||
|
|
|
@ -17,8 +17,8 @@ if NOT "%1" == "" (
|
|||
shift /1
|
||||
) else if "%1" == "with_tests" (
|
||||
set TESTS_CMAKE_ARGS=%TESTS_CMAKE_ARGS% -DWITH_GTESTS=On
|
||||
) else if "%1" == "with_opengl_tests" (
|
||||
set TESTS_CMAKE_ARGS=%TESTS_CMAKE_ARGS% -DWITH_OPENGL_DRAW_TESTS=On -DWITH_OPENGL_RENDER_TESTS=On
|
||||
) else if "%1" == "with_gpu_tests" (
|
||||
set TESTS_CMAKE_ARGS=%TESTS_CMAKE_ARGS% -DWITH_GPU_DRAW_TESTS=On -DWITH_GPU_RENDER_TESTS=On
|
||||
) else if "%1" == "full" (
|
||||
set TARGET=Full
|
||||
set BUILD_CMAKE_ARGS=%BUILD_CMAKE_ARGS% ^
|
||||
|
|
|
@ -39,7 +39,7 @@ echo - doc_py ^(Generate sphinx python api docs^)
|
|||
|
||||
echo.
|
||||
echo Experimental options
|
||||
echo - with_opengl_tests ^(enable both the render and draw opengl test suites^)
|
||||
echo - with_gpu_tests ^(enable both the render and draw gpu test suites including EEVEE, Workbench, Grease Pencil, draw manager and GPU backends^)
|
||||
echo - clang ^(enable building with clang^)
|
||||
echo - asan ^(enable asan when building with clang^)
|
||||
echo - ninja ^(enable building with ninja instead of msbuild^)
|
||||
|
|
|
@ -7,4 +7,5 @@ GPL-2.0-or-later GPL-license.txt https://spdx.org/licenses/GP
|
|||
GPL-3.0-or-later GPL3-license.txt https://spdx.org/licenses/GPL-3.0-or-later.html
|
||||
LGPL-2.1-or-later LGPL2.1-license.txt https://spdx.org/licenses/LGPL-2.1-or-later.html
|
||||
MIT MIT-license.txt https://spdx.org/licenses/MIT.html
|
||||
MPL-2.0 MPL-2.0.txt https://spdx.org/licenses/MPL-2.0.html
|
||||
Zlib Zlib-license.txt https://spdx.org/licenses/Zlib.html
|
||||
|
|
|
@ -191,13 +191,6 @@ if(CXX_HAS_AVX2)
|
|||
add_definitions(-DWITH_KERNEL_AVX2)
|
||||
endif()
|
||||
|
||||
# LLVM and OSL need to build without RTTI
|
||||
if(WIN32 AND MSVC)
|
||||
set(RTTI_DISABLE_FLAGS "/GR- -DBOOST_NO_RTTI -DBOOST_NO_TYPEID")
|
||||
elseif(CMAKE_COMPILER_IS_GNUCC OR (CMAKE_C_COMPILER_ID MATCHES "Clang"))
|
||||
set(RTTI_DISABLE_FLAGS "-fno-rtti -DBOOST_NO_RTTI -DBOOST_NO_TYPEID")
|
||||
endif()
|
||||
|
||||
# Definitions and Includes
|
||||
|
||||
add_definitions(
|
||||
|
|
|
@ -2272,6 +2272,7 @@ class CYCLES_RENDER_PT_simplify_viewport(CyclesButtonsPanel, Panel):
|
|||
col.prop(rd, "simplify_child_particles", text="Child Particles")
|
||||
col.prop(cscene, "texture_limit", text="Texture Limit")
|
||||
col.prop(rd, "simplify_volumes", text="Volume Resolution")
|
||||
col.prop(rd, "use_simplify_normals", text="Normals")
|
||||
|
||||
|
||||
class CYCLES_RENDER_PT_simplify_render(CyclesButtonsPanel, Panel):
|
||||
|
|
|
@ -326,13 +326,13 @@ static void attr_create_generic(Scene *scene,
|
|||
}
|
||||
else {
|
||||
for (const int i : looptris.index_range()) {
|
||||
const MLoopTri &tri = looptris[i];
|
||||
const MLoopTri < = looptris[i];
|
||||
data[i * 3 + 0] = make_uchar4(
|
||||
src[tri.tri[0]][0], src[tri.tri[0]][1], src[tri.tri[0]][2], src[tri.tri[0]][3]);
|
||||
src[lt.tri[0]][0], src[lt.tri[0]][1], src[lt.tri[0]][2], src[lt.tri[0]][3]);
|
||||
data[i * 3 + 1] = make_uchar4(
|
||||
src[tri.tri[1]][0], src[tri.tri[1]][1], src[tri.tri[1]][2], src[tri.tri[1]][3]);
|
||||
src[lt.tri[1]][0], src[lt.tri[1]][1], src[lt.tri[1]][2], src[lt.tri[1]][3]);
|
||||
data[i * 3 + 2] = make_uchar4(
|
||||
src[tri.tri[2]][0], src[tri.tri[2]][1], src[tri.tri[2]][2], src[tri.tri[2]][3]);
|
||||
src[lt.tri[2]][0], src[lt.tri[2]][1], src[lt.tri[2]][2], src[lt.tri[2]][3]);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
@ -376,10 +376,10 @@ static void attr_create_generic(Scene *scene,
|
|||
}
|
||||
else {
|
||||
for (const int i : looptris.index_range()) {
|
||||
const MLoopTri &tri = looptris[i];
|
||||
data[i * 3 + 0] = Converter::convert(src[tri.tri[0]]);
|
||||
data[i * 3 + 1] = Converter::convert(src[tri.tri[1]]);
|
||||
data[i * 3 + 2] = Converter::convert(src[tri.tri[2]]);
|
||||
const MLoopTri < = looptris[i];
|
||||
data[i * 3 + 0] = Converter::convert(src[lt.tri[0]]);
|
||||
data[i * 3 + 1] = Converter::convert(src[lt.tri[1]]);
|
||||
data[i * 3 + 2] = Converter::convert(src[lt.tri[2]]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -469,10 +469,10 @@ static void attr_create_uv_map(Scene *scene,
|
|||
uv_name.c_str(), ATTR_DOMAIN_CORNER);
|
||||
float2 *fdata = uv_attr->data_float2();
|
||||
for (const int i : looptris.index_range()) {
|
||||
const MLoopTri &tri = looptris[i];
|
||||
fdata[i * 3 + 0] = make_float2(b_uv_map[tri.tri[0]][0], b_uv_map[tri.tri[0]][1]);
|
||||
fdata[i * 3 + 1] = make_float2(b_uv_map[tri.tri[1]][0], b_uv_map[tri.tri[1]][1]);
|
||||
fdata[i * 3 + 2] = make_float2(b_uv_map[tri.tri[2]][0], b_uv_map[tri.tri[2]][1]);
|
||||
const MLoopTri < = looptris[i];
|
||||
fdata[i * 3 + 0] = make_float2(b_uv_map[lt.tri[0]][0], b_uv_map[lt.tri[0]][1]);
|
||||
fdata[i * 3 + 1] = make_float2(b_uv_map[lt.tri[1]][0], b_uv_map[lt.tri[1]][1]);
|
||||
fdata[i * 3 + 2] = make_float2(b_uv_map[lt.tri[2]][0], b_uv_map[lt.tri[2]][1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -915,10 +915,10 @@ static void create_mesh(Scene *scene,
|
|||
|
||||
const blender::Span<MLoopTri> looptris = b_mesh.looptris();
|
||||
for (const int i : looptris.index_range()) {
|
||||
const MLoopTri &tri = looptris[i];
|
||||
triangles[i * 3 + 0] = corner_verts[tri.tri[0]];
|
||||
triangles[i * 3 + 1] = corner_verts[tri.tri[1]];
|
||||
triangles[i * 3 + 2] = corner_verts[tri.tri[2]];
|
||||
const MLoopTri < = looptris[i];
|
||||
triangles[i * 3 + 0] = corner_verts[lt.tri[0]];
|
||||
triangles[i * 3 + 1] = corner_verts[lt.tri[1]];
|
||||
triangles[i * 3 + 2] = corner_verts[lt.tri[2]];
|
||||
}
|
||||
|
||||
if (!material_indices.is_empty()) {
|
||||
|
@ -944,9 +944,9 @@ static void create_mesh(Scene *scene,
|
|||
|
||||
if (use_loop_normals && !corner_normals.is_empty()) {
|
||||
for (const int i : looptris.index_range()) {
|
||||
const MLoopTri &tri = looptris[i];
|
||||
const MLoopTri < = looptris[i];
|
||||
for (int i = 0; i < 3; i++) {
|
||||
const int corner = tri.tri[i];
|
||||
const int corner = lt.tri[i];
|
||||
const int vert = corner_verts[corner];
|
||||
const float *normal = corner_normals[corner];
|
||||
N[vert] = make_float3(normal[0], normal[1], normal[2]);
|
||||
|
|
|
@ -313,7 +313,7 @@ void CPUDevice::get_cpu_kernel_thread_globals(
|
|||
kernel_thread_globals.clear();
|
||||
void *osl_memory = get_cpu_osl_memory();
|
||||
for (int i = 0; i < info.cpu_threads; i++) {
|
||||
kernel_thread_globals.emplace_back(kernel_globals, osl_memory, profiler);
|
||||
kernel_thread_globals.emplace_back(kernel_globals, osl_memory, profiler, i);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ class CPUKernels {
|
|||
int x,
|
||||
int y,
|
||||
float threshold,
|
||||
bool reset,
|
||||
int reset,
|
||||
int offset,
|
||||
int stride)>;
|
||||
|
||||
|
|
|
@ -12,14 +12,16 @@ CCL_NAMESPACE_BEGIN
|
|||
|
||||
CPUKernelThreadGlobals::CPUKernelThreadGlobals(const KernelGlobalsCPU &kernel_globals,
|
||||
void *osl_globals_memory,
|
||||
Profiler &cpu_profiler)
|
||||
Profiler &cpu_profiler,
|
||||
const int thread_index)
|
||||
: KernelGlobalsCPU(kernel_globals), cpu_profiler_(cpu_profiler)
|
||||
{
|
||||
clear_runtime_pointers();
|
||||
|
||||
#ifdef WITH_OSL
|
||||
OSLGlobals::thread_init(this, static_cast<OSLGlobals *>(osl_globals_memory));
|
||||
OSLGlobals::thread_init(this, static_cast<OSLGlobals *>(osl_globals_memory), thread_index);
|
||||
#else
|
||||
(void)thread_index;
|
||||
(void)osl_globals_memory;
|
||||
#endif
|
||||
|
||||
|
|
|
@ -23,7 +23,8 @@ class CPUKernelThreadGlobals : public KernelGlobalsCPU {
|
|||
* without OSL support. Will avoid need to those unnamed pointers and casts. */
|
||||
CPUKernelThreadGlobals(const KernelGlobalsCPU &kernel_globals,
|
||||
void *osl_globals_memory,
|
||||
Profiler &cpu_profiler);
|
||||
Profiler &cpu_profiler,
|
||||
const int thread_index);
|
||||
|
||||
~CPUKernelThreadGlobals();
|
||||
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
# include "device/device.h"
|
||||
# include "device/hip/device_impl.h"
|
||||
|
||||
# include "integrator/denoiser_oidn_gpu.h"
|
||||
|
||||
# include "util/string.h"
|
||||
# include "util/windows.h"
|
||||
#endif /* WITH_HIP */
|
||||
|
@ -158,6 +160,11 @@ void device_hip_info(vector<DeviceInfo> &devices)
|
|||
info.has_light_tree = true;
|
||||
info.has_mnee = true;
|
||||
info.denoisers = 0;
|
||||
# if defined(WITH_OPENIMAGEDENOISE)
|
||||
if (OIDNDenoiserGPU::is_device_supported(info)) {
|
||||
info.denoisers |= DENOISER_OPENIMAGEDENOISE;
|
||||
}
|
||||
# endif
|
||||
|
||||
info.has_gpu_queue = true;
|
||||
/* Check if the device has P2P access to any other device in the system. */
|
||||
|
|
|
@ -73,7 +73,7 @@ class MetalDevice : public Device {
|
|||
/* Bindless Textures */
|
||||
bool is_texture(const TextureInfo &tex);
|
||||
device_vector<TextureInfo> texture_info;
|
||||
bool need_texture_info;
|
||||
bool need_texture_info = false;
|
||||
id<MTLArgumentEncoder> mtlTextureArgEncoder = nil;
|
||||
id<MTLArgumentEncoder> mtlBufferArgEncoder = nil;
|
||||
id<MTLBuffer> buffer_bindings_1d = nil;
|
||||
|
|
|
@ -40,7 +40,7 @@ class OneapiDeviceQueue : public DeviceQueue {
|
|||
virtual void copy_to_device(device_memory &mem) override;
|
||||
virtual void copy_from_device(device_memory &mem) override;
|
||||
|
||||
virtual bool supports_local_atomic_sort() const
|
||||
virtual bool supports_local_atomic_sort() const override
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -27,7 +27,6 @@ struct DeviceKernelArguments {
|
|||
POINTER,
|
||||
INT32,
|
||||
FLOAT32,
|
||||
BOOLEAN,
|
||||
KERNEL_FILM_CONVERT,
|
||||
};
|
||||
|
||||
|
@ -66,10 +65,6 @@ struct DeviceKernelArguments {
|
|||
{
|
||||
add(FLOAT32, value, sizeof(float));
|
||||
}
|
||||
void add(const bool *value)
|
||||
{
|
||||
add(BOOLEAN, value, 4);
|
||||
}
|
||||
void add(const Type type, const void *value, size_t size)
|
||||
{
|
||||
assert(count < MAX_ARGS);
|
||||
|
|
|
@ -27,7 +27,9 @@ unique_ptr<Denoiser> Denoiser::create(Device *path_trace_device, const DenoisePa
|
|||
#endif
|
||||
|
||||
#ifdef WITH_OPENIMAGEDENOISE
|
||||
if (params.type == DENOISER_OPENIMAGEDENOISE && path_trace_device->info.type == DEVICE_ONEAPI) {
|
||||
if (params.type == DENOISER_OPENIMAGEDENOISE && path_trace_device->info.type != DEVICE_CPU &&
|
||||
OIDNDenoiserGPU::is_device_supported(path_trace_device->info))
|
||||
{
|
||||
return make_unique<OIDNDenoiserGPU>(path_trace_device, params);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -103,7 +103,7 @@ class DenoiserGPU : public Denoiser {
|
|||
int denoised_offset;
|
||||
|
||||
int num_components;
|
||||
bool use_compositing;
|
||||
int use_compositing;
|
||||
bool use_denoising_albedo;
|
||||
};
|
||||
|
||||
|
|
|
@ -30,16 +30,48 @@ CCL_NAMESPACE_BEGIN
|
|||
|
||||
bool OIDNDenoiserGPU::is_device_supported(const DeviceInfo &device)
|
||||
{
|
||||
/* Currently falls back to checking just the device type, can be improved. */
|
||||
int device_type = OIDN_DEVICE_TYPE_DEFAULT;
|
||||
switch (device.type) {
|
||||
# ifdef OIDN_DEVICE_SYCL
|
||||
/* Assume all devices with Cycles support are also supported by OIDN2. */
|
||||
case DEVICE_ONEAPI:
|
||||
return true;
|
||||
device_type = OIDN_DEVICE_TYPE_SYCL;
|
||||
break;
|
||||
# endif
|
||||
# ifdef OIDN_DEVICE_HIP
|
||||
case DEVICE_HIP:
|
||||
device_type = OIDN_DEVICE_TYPE_HIP;
|
||||
break;
|
||||
# endif
|
||||
# ifdef OIDN_DEVICE_CUDA
|
||||
case DEVICE_CUDA:
|
||||
case DEVICE_OPTIX:
|
||||
device_type = OIDN_DEVICE_TYPE_CUDA;
|
||||
break;
|
||||
# endif
|
||||
case DEVICE_CPU:
|
||||
/* This is the GPU denoiser - CPU devices shouldn't end up here. */
|
||||
assert(0);
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Match GPUs by their PCI ID. */
|
||||
const int num_devices = oidnGetNumPhysicalDevices();
|
||||
for (int i = 0; i < num_devices; i++) {
|
||||
if (oidnGetPhysicalDeviceInt(i, "type") == device_type) {
|
||||
if (oidnGetPhysicalDeviceBool(i, "pciAddressSupported")) {
|
||||
unsigned int pci_domain = oidnGetPhysicalDeviceInt(i, "pciDomain");
|
||||
unsigned int pci_bus = oidnGetPhysicalDeviceInt(i, "pciBus");
|
||||
unsigned int pci_device = oidnGetPhysicalDeviceInt(i, "pciDevice");
|
||||
string pci_id = string_printf("%04x:%02x:%02x", pci_domain, pci_bus, pci_device);
|
||||
if (device.id.find(pci_id) != string::npos) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
OIDNDenoiserGPU::OIDNDenoiserGPU(Device *path_trace_device, const DenoiseParams ¶ms)
|
||||
|
@ -78,6 +110,9 @@ uint OIDNDenoiserGPU::get_device_type_mask() const
|
|||
uint device_mask = 0;
|
||||
# ifdef OIDN_DEVICE_SYCL
|
||||
device_mask |= DEVICE_MASK_ONEAPI;
|
||||
# endif
|
||||
# ifdef OIDN_DEVICE_HIP
|
||||
device_mask |= DEVICE_MASK_HIP;
|
||||
# endif
|
||||
return device_mask;
|
||||
}
|
||||
|
@ -122,15 +157,27 @@ bool OIDNDenoiserGPU::denoise_create_if_needed(DenoiseContext &context)
|
|||
1);
|
||||
denoiser_queue_->init_execution();
|
||||
break;
|
||||
# endif
|
||||
# if defined(OIDN_DEVICE_HIP) && defined(WITH_HIP)
|
||||
case DEVICE_HIP: {
|
||||
hipStream_t stream = nullptr;
|
||||
oidn_device_ = oidnNewHIPDevice(&denoiser_device_->info.num, &stream, 1);
|
||||
break;
|
||||
}
|
||||
# endif
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!oidn_device_) {
|
||||
denoiser_device_->set_error("Failed to create OIDN device");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (denoiser_queue_) {
|
||||
denoiser_queue_->init_execution();
|
||||
}
|
||||
|
||||
oidnCommitDevice(oidn_device_);
|
||||
|
||||
oidn_filter_ = create_filter();
|
||||
|
|
|
@ -1055,6 +1055,7 @@ int PathTraceWorkGPU::adaptive_sampling_convergence_check_count_active(float thr
|
|||
queue_->zero_to_device(num_active_pixels);
|
||||
|
||||
const int work_size = effective_buffer_params_.width * effective_buffer_params_.height;
|
||||
const int reset_int = reset; /* No bool kernel arguments. */
|
||||
|
||||
DeviceKernelArguments args(&buffers_->buffer.device_pointer,
|
||||
&effective_buffer_params_.full_x,
|
||||
|
@ -1062,7 +1063,7 @@ int PathTraceWorkGPU::adaptive_sampling_convergence_check_count_active(float thr
|
|||
&effective_buffer_params_.width,
|
||||
&effective_buffer_params_.height,
|
||||
&threshold,
|
||||
&reset,
|
||||
&reset_int,
|
||||
&effective_buffer_params_.offset,
|
||||
&effective_buffer_params_.stride,
|
||||
&num_active_pixels.device_pointer);
|
||||
|
|
|
@ -327,6 +327,7 @@ set(SRC_KERNEL_UTIL_HEADERS
|
|||
util/color.h
|
||||
util/differential.h
|
||||
util/lookup_table.h
|
||||
util/nanovdb.h
|
||||
util/profiling.h
|
||||
)
|
||||
|
||||
|
@ -483,8 +484,7 @@ if(WITH_CYCLES_CUDA_BINARIES)
|
|||
|
||||
if(WITH_NANOVDB)
|
||||
set(cuda_flags ${cuda_flags}
|
||||
-D WITH_NANOVDB
|
||||
-I "${NANOVDB_INCLUDE_DIR}")
|
||||
-D WITH_NANOVDB)
|
||||
endif()
|
||||
|
||||
if(WITH_CYCLES_DEBUG)
|
||||
|
@ -634,8 +634,7 @@ if(WITH_CYCLES_HIP_BINARIES AND WITH_CYCLES_DEVICE_HIP)
|
|||
|
||||
if(WITH_NANOVDB)
|
||||
set(hip_flags ${hip_flags}
|
||||
-D WITH_NANOVDB
|
||||
-I "${NANOVDB_INCLUDE_DIR}")
|
||||
-D WITH_NANOVDB)
|
||||
endif()
|
||||
|
||||
if(WITH_CYCLES_DEBUG)
|
||||
|
@ -755,8 +754,7 @@ if(WITH_CYCLES_DEVICE_OPTIX AND WITH_CYCLES_CUDA_BINARIES)
|
|||
|
||||
if(WITH_NANOVDB)
|
||||
set(cuda_flags ${cuda_flags}
|
||||
-D WITH_NANOVDB
|
||||
-I "${NANOVDB_INCLUDE_DIR}")
|
||||
-D WITH_NANOVDB)
|
||||
endif()
|
||||
if(WITH_CYCLES_OSL)
|
||||
set(cuda_flags ${cuda_flags}
|
||||
|
@ -936,8 +934,7 @@ if(WITH_CYCLES_DEVICE_ONEAPI)
|
|||
|
||||
if(WITH_NANOVDB)
|
||||
list(APPEND sycl_compiler_flags
|
||||
-DWITH_NANOVDB
|
||||
-I"${NANOVDB_INCLUDE_DIR}")
|
||||
-DWITH_NANOVDB)
|
||||
endif()
|
||||
|
||||
if(WITH_CYCLES_EMBREE AND EMBREE_SYCL_SUPPORT)
|
||||
|
@ -1256,16 +1253,3 @@ delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_KERNEL_SVM_HEADERS}" ${CYCLES
|
|||
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_KERNEL_TYPES_HEADERS}" ${CYCLES_INSTALL_PATH}/source/kernel)
|
||||
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_KERNEL_UTIL_HEADERS}" ${CYCLES_INSTALL_PATH}/source/kernel/util)
|
||||
delayed_install(${CMAKE_CURRENT_SOURCE_DIR} "${SRC_UTIL_HEADERS}" ${CYCLES_INSTALL_PATH}/source/util)
|
||||
|
||||
if(WITH_NANOVDB)
|
||||
set(SRC_NANOVDB_HEADERS
|
||||
nanovdb/NanoVDB.h
|
||||
nanovdb/CNanoVDB.h
|
||||
)
|
||||
set(SRC_NANOVDB_UTIL_HEADERS
|
||||
nanovdb/util/CSampleFromVoxels.h
|
||||
nanovdb/util/SampleFromVoxels.h
|
||||
)
|
||||
delayed_install(${NANOVDB_INCLUDE_DIR} "${SRC_NANOVDB_HEADERS}" ${CYCLES_INSTALL_PATH}/source/nanovdb)
|
||||
delayed_install(${NANOVDB_INCLUDE_DIR} "${SRC_NANOVDB_UTIL_HEADERS}" ${CYCLES_INSTALL_PATH}/source/nanovdb/util)
|
||||
endif()
|
||||
|
|
|
@ -49,6 +49,7 @@ typedef struct KernelGlobalsCPU {
|
|||
OSLGlobals *osl = nullptr;
|
||||
OSLShadingSystem *osl_ss = nullptr;
|
||||
OSLThreadData *osl_tdata = nullptr;
|
||||
int osl_thread_index = 0;
|
||||
#endif
|
||||
|
||||
#ifdef __PATH_GUIDING__
|
||||
|
|
|
@ -5,9 +5,7 @@
|
|||
#pragma once
|
||||
|
||||
#ifdef WITH_NANOVDB
|
||||
# define NANOVDB_USE_INTRINSICS
|
||||
# include <nanovdb/NanoVDB.h>
|
||||
# include <nanovdb/util/SampleFromVoxels.h>
|
||||
# include "kernel/util/nanovdb.h"
|
||||
#endif
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
@ -685,46 +683,59 @@ template<typename TexT, typename OutT = float4> struct TextureInterpolator {
|
|||
};
|
||||
|
||||
#ifdef WITH_NANOVDB
|
||||
template<typename TexT, typename OutT = float4> struct NanoVDBInterpolator {
|
||||
|
||||
typedef typename nanovdb::NanoGrid<TexT>::AccessorType AccessorType;
|
||||
template<typename TexT, typename OutT> struct NanoVDBInterpolator {
|
||||
|
||||
static ccl_always_inline float read(float r)
|
||||
{
|
||||
return r;
|
||||
}
|
||||
|
||||
static ccl_always_inline float4 read(nanovdb::Vec3f r)
|
||||
static ccl_always_inline float4 read(const packed_float3 r)
|
||||
{
|
||||
return make_float4(r[0], r[1], r[2], 1.0f);
|
||||
return make_float4(r.x, r.y, r.z, 1.0f);
|
||||
}
|
||||
|
||||
static ccl_always_inline OutT interp_3d_closest(const AccessorType &acc,
|
||||
float x,
|
||||
float y,
|
||||
float z)
|
||||
template<typename Acc>
|
||||
static ccl_always_inline OutT interp_3d_closest(const Acc &acc, float x, float y, float z)
|
||||
{
|
||||
const nanovdb::Vec3f xyz(x, y, z);
|
||||
return read(nanovdb::SampleFromVoxels<AccessorType, 0, false>(acc)(xyz));
|
||||
const nanovdb::Coord coord((int32_t)floorf(x), (int32_t)floorf(y), (int32_t)floorf(z));
|
||||
return read(acc.getValue(coord));
|
||||
}
|
||||
|
||||
static ccl_always_inline OutT interp_3d_linear(const AccessorType &acc,
|
||||
float x,
|
||||
float y,
|
||||
float z)
|
||||
template<typename Acc>
|
||||
static ccl_always_inline OutT interp_3d_linear(const Acc &acc, float x, float y, float z)
|
||||
{
|
||||
const nanovdb::Vec3f xyz(x - 0.5f, y - 0.5f, z - 0.5f);
|
||||
return read(nanovdb::SampleFromVoxels<AccessorType, 1, false>(acc)(xyz));
|
||||
int ix, iy, iz;
|
||||
const float tx = frac(x - 0.5f, &ix);
|
||||
const float ty = frac(y - 0.5f, &iy);
|
||||
const float tz = frac(z - 0.5f, &iz);
|
||||
|
||||
return mix(mix(mix(read(acc.getValue(nanovdb::Coord(ix, iy, iz))),
|
||||
read(acc.getValue(nanovdb::Coord(ix, iy, iz + 1))),
|
||||
tz),
|
||||
mix(read(acc.getValue(nanovdb::Coord(ix, iy + 1, iz + 1))),
|
||||
read(acc.getValue(nanovdb::Coord(ix, iy + 1, iz))),
|
||||
1.0f - tz),
|
||||
ty),
|
||||
mix(mix(read(acc.getValue(nanovdb::Coord(ix + 1, iy + 1, iz))),
|
||||
read(acc.getValue(nanovdb::Coord(ix + 1, iy + 1, iz + 1))),
|
||||
tz),
|
||||
mix(read(acc.getValue(nanovdb::Coord(ix + 1, iy, iz + 1))),
|
||||
read(acc.getValue(nanovdb::Coord(ix + 1, iy, iz))),
|
||||
1.0f - tz),
|
||||
1.0f - ty),
|
||||
tx);
|
||||
}
|
||||
|
||||
/* Tricubic b-spline interpolation. */
|
||||
template<typename Acc>
|
||||
# if defined(__GNUC__) || defined(__clang__)
|
||||
static ccl_always_inline
|
||||
# else
|
||||
static ccl_never_inline
|
||||
# endif
|
||||
OutT
|
||||
interp_3d_cubic(const AccessorType &acc, float x, float y, float z)
|
||||
interp_3d_cubic(const Acc &acc, float x, float y, float z)
|
||||
{
|
||||
int ix, iy, iz;
|
||||
int nix, niy, niz;
|
||||
|
@ -779,15 +790,20 @@ template<typename TexT, typename OutT = float4> struct NanoVDBInterpolator {
|
|||
using namespace nanovdb;
|
||||
|
||||
NanoGrid<TexT> *const grid = (NanoGrid<TexT> *)info.data;
|
||||
AccessorType acc = grid->getAccessor();
|
||||
|
||||
switch ((interp == INTERPOLATION_NONE) ? info.interpolation : interp) {
|
||||
case INTERPOLATION_CLOSEST:
|
||||
case INTERPOLATION_CLOSEST: {
|
||||
ReadAccessor<TexT> acc(grid->tree().root());
|
||||
return interp_3d_closest(acc, x, y, z);
|
||||
case INTERPOLATION_LINEAR:
|
||||
}
|
||||
case INTERPOLATION_LINEAR: {
|
||||
CachedReadAccessor<TexT> acc(grid->tree().root());
|
||||
return interp_3d_linear(acc, x, y, z);
|
||||
default:
|
||||
}
|
||||
default: {
|
||||
CachedReadAccessor<TexT> acc(grid->tree().root());
|
||||
return interp_3d_cubic(acc, x, y, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -880,7 +896,7 @@ ccl_device float4 kernel_tex_image_interp_3d(KernelGlobals kg,
|
|||
return make_float4(f, f, f, 1.0f);
|
||||
}
|
||||
case IMAGE_DATA_TYPE_NANOVDB_FLOAT3:
|
||||
return NanoVDBInterpolator<nanovdb::Vec3f>::interp_3d(info, P.x, P.y, P.z, interp);
|
||||
return NanoVDBInterpolator<packed_float3, float4>::interp_3d(info, P.x, P.y, P.z, interp);
|
||||
case IMAGE_DATA_TYPE_NANOVDB_FPN: {
|
||||
const float f = NanoVDBInterpolator<nanovdb::FpN, float>::interp_3d(
|
||||
info, P.x, P.y, P.z, interp);
|
||||
|
|
|
@ -101,7 +101,7 @@ bool KERNEL_FUNCTION_FULL_NAME(adaptive_sampling_convergence_check)(
|
|||
int x,
|
||||
int y,
|
||||
float threshold,
|
||||
bool reset,
|
||||
int reset,
|
||||
int offset,
|
||||
int stride);
|
||||
|
||||
|
|
|
@ -164,7 +164,7 @@ bool KERNEL_FUNCTION_FULL_NAME(adaptive_sampling_convergence_check)(
|
|||
int x,
|
||||
int y,
|
||||
float threshold,
|
||||
bool reset,
|
||||
int reset,
|
||||
int offset,
|
||||
int stride)
|
||||
{
|
||||
|
|
|
@ -45,6 +45,7 @@ typedef unsigned long long uint64_t;
|
|||
#define ccl_global
|
||||
#define ccl_inline_constant __constant__
|
||||
#define ccl_device_constant __constant__ __device__
|
||||
#define ccl_static_constexpr static constexpr
|
||||
#define ccl_constant const
|
||||
#define ccl_gpu_shared __shared__
|
||||
#define ccl_private
|
||||
|
|
|
@ -8,12 +8,17 @@ CCL_NAMESPACE_BEGIN
|
|||
|
||||
#if !defined __KERNEL_METAL__
|
||||
# ifdef WITH_NANOVDB
|
||||
# define NDEBUG /* Disable "assert" in device code */
|
||||
# define NANOVDB_USE_INTRINSICS
|
||||
# include "nanovdb/NanoVDB.h"
|
||||
# include "nanovdb/util/SampleFromVoxels.h"
|
||||
# include "kernel/util/nanovdb.h"
|
||||
# endif
|
||||
#endif
|
||||
|
||||
ccl_device_inline float frac(float x, ccl_private int *ix)
|
||||
{
|
||||
int i = float_to_int(x) - ((x < 0.0f) ? 1 : 0);
|
||||
*ix = i;
|
||||
return x - (float)i;
|
||||
}
|
||||
|
||||
/* w0, w1, w2, and w3 are the four cubic B-spline basis functions. */
|
||||
ccl_device float cubic_w0(float a)
|
||||
{
|
||||
|
@ -126,63 +131,121 @@ kernel_tex_image_interp_tricubic(ccl_global const TextureInfo &info, float x, fl
|
|||
}
|
||||
|
||||
#ifdef WITH_NANOVDB
|
||||
template<typename T, typename S>
|
||||
ccl_device typename nanovdb::NanoGrid<T>::ValueType kernel_tex_image_interp_tricubic_nanovdb(
|
||||
ccl_private S &s, float x, float y, float z)
|
||||
template<typename OutT, typename Acc>
|
||||
ccl_device OutT
|
||||
kernel_tex_image_interp_trilinear_nanovdb(ccl_private Acc &acc, float x, float y, float z)
|
||||
{
|
||||
float px = floorf(x);
|
||||
float py = floorf(y);
|
||||
float pz = floorf(z);
|
||||
float fx = x - px;
|
||||
float fy = y - py;
|
||||
float fz = z - pz;
|
||||
int ix, iy, iz;
|
||||
const float tx = frac(x - 0.5f, &ix);
|
||||
const float ty = frac(y - 0.5f, &iy);
|
||||
const float tz = frac(z - 0.5f, &iz);
|
||||
|
||||
float g0x = cubic_g0(fx);
|
||||
float g1x = cubic_g1(fx);
|
||||
float g0y = cubic_g0(fy);
|
||||
float g1y = cubic_g1(fy);
|
||||
float g0z = cubic_g0(fz);
|
||||
float g1z = cubic_g1(fz);
|
||||
return mix(mix(mix(OutT(acc.getValue(nanovdb::Coord(ix, iy, iz))),
|
||||
OutT(acc.getValue(nanovdb::Coord(ix, iy, iz + 1))),
|
||||
tz),
|
||||
mix(OutT(acc.getValue(nanovdb::Coord(ix, iy + 1, iz + 1))),
|
||||
OutT(acc.getValue(nanovdb::Coord(ix, iy + 1, iz))),
|
||||
1.0f - tz),
|
||||
ty),
|
||||
mix(mix(OutT(acc.getValue(nanovdb::Coord(ix + 1, iy + 1, iz))),
|
||||
OutT(acc.getValue(nanovdb::Coord(ix + 1, iy + 1, iz + 1))),
|
||||
tz),
|
||||
mix(OutT(acc.getValue(nanovdb::Coord(ix + 1, iy, iz + 1))),
|
||||
OutT(acc.getValue(nanovdb::Coord(ix + 1, iy, iz))),
|
||||
1.0f - tz),
|
||||
1.0f - ty),
|
||||
tx);
|
||||
}
|
||||
|
||||
float x0 = px + cubic_h0(fx);
|
||||
float x1 = px + cubic_h1(fx);
|
||||
float y0 = py + cubic_h0(fy);
|
||||
float y1 = py + cubic_h1(fy);
|
||||
float z0 = pz + cubic_h0(fz);
|
||||
float z1 = pz + cubic_h1(fz);
|
||||
template<typename OutT, typename Acc>
|
||||
ccl_device OutT
|
||||
kernel_tex_image_interp_tricubic_nanovdb(ccl_private Acc &acc, float x, float y, float z)
|
||||
{
|
||||
int ix, iy, iz;
|
||||
int nix, niy, niz;
|
||||
int pix, piy, piz;
|
||||
int nnix, nniy, nniz;
|
||||
|
||||
using namespace nanovdb;
|
||||
/* A -0.5 offset is used to center the cubic samples around the sample point. */
|
||||
const float tx = frac(x - 0.5f, &ix);
|
||||
const float ty = frac(y - 0.5f, &iy);
|
||||
const float tz = frac(z - 0.5f, &iz);
|
||||
|
||||
return g0z * (g0y * (g0x * s(Vec3f(x0, y0, z0)) + g1x * s(Vec3f(x1, y0, z0))) +
|
||||
g1y * (g0x * s(Vec3f(x0, y1, z0)) + g1x * s(Vec3f(x1, y1, z0)))) +
|
||||
g1z * (g0y * (g0x * s(Vec3f(x0, y0, z1)) + g1x * s(Vec3f(x1, y0, z1))) +
|
||||
g1y * (g0x * s(Vec3f(x0, y1, z1)) + g1x * s(Vec3f(x1, y1, z1))));
|
||||
pix = ix - 1;
|
||||
piy = iy - 1;
|
||||
piz = iz - 1;
|
||||
nix = ix + 1;
|
||||
niy = iy + 1;
|
||||
niz = iz + 1;
|
||||
nnix = ix + 2;
|
||||
nniy = iy + 2;
|
||||
nniz = iz + 2;
|
||||
|
||||
const int xc[4] = {pix, ix, nix, nnix};
|
||||
const int yc[4] = {piy, iy, niy, nniy};
|
||||
const int zc[4] = {piz, iz, niz, nniz};
|
||||
float u[4], v[4], w[4];
|
||||
|
||||
/* Some helper macros to keep code size reasonable.
|
||||
* Lets the compiler inline all the matrix multiplications.
|
||||
*/
|
||||
# define SET_CUBIC_SPLINE_WEIGHTS(u, t) \
|
||||
{ \
|
||||
u[0] = (((-1.0f / 6.0f) * t + 0.5f) * t - 0.5f) * t + (1.0f / 6.0f); \
|
||||
u[1] = ((0.5f * t - 1.0f) * t) * t + (2.0f / 3.0f); \
|
||||
u[2] = ((-0.5f * t + 0.5f) * t + 0.5f) * t + (1.0f / 6.0f); \
|
||||
u[3] = (1.0f / 6.0f) * t * t * t; \
|
||||
} \
|
||||
(void)0
|
||||
|
||||
# define DATA(x, y, z) (OutT(acc.getValue(nanovdb::Coord(xc[x], yc[y], zc[z]))))
|
||||
# define COL_TERM(col, row) \
|
||||
(v[col] * (u[0] * DATA(0, col, row) + u[1] * DATA(1, col, row) + u[2] * DATA(2, col, row) + \
|
||||
u[3] * DATA(3, col, row)))
|
||||
# define ROW_TERM(row) \
|
||||
(w[row] * (COL_TERM(0, row) + COL_TERM(1, row) + COL_TERM(2, row) + COL_TERM(3, row)))
|
||||
|
||||
SET_CUBIC_SPLINE_WEIGHTS(u, tx);
|
||||
SET_CUBIC_SPLINE_WEIGHTS(v, ty);
|
||||
SET_CUBIC_SPLINE_WEIGHTS(w, tz);
|
||||
|
||||
/* Actual interpolation. */
|
||||
return ROW_TERM(0) + ROW_TERM(1) + ROW_TERM(2) + ROW_TERM(3);
|
||||
|
||||
# undef COL_TERM
|
||||
# undef ROW_TERM
|
||||
# undef DATA
|
||||
# undef SET_CUBIC_SPLINE_WEIGHTS
|
||||
}
|
||||
|
||||
# if defined(__KERNEL_METAL__)
|
||||
template<typename T>
|
||||
__attribute__((noinline)) typename nanovdb::NanoGrid<T>::ValueType kernel_tex_image_interp_nanovdb(
|
||||
template<typename OutT, typename T>
|
||||
__attribute__((noinline)) OutT kernel_tex_image_interp_nanovdb(
|
||||
ccl_global const TextureInfo &info, float x, float y, float z, uint interpolation)
|
||||
# else
|
||||
template<typename T>
|
||||
ccl_device_noinline typename nanovdb::NanoGrid<T>::ValueType kernel_tex_image_interp_nanovdb(
|
||||
template<typename OutT, typename T>
|
||||
ccl_device_noinline OutT kernel_tex_image_interp_nanovdb(
|
||||
ccl_global const TextureInfo &info, float x, float y, float z, uint interpolation)
|
||||
# endif
|
||||
{
|
||||
using namespace nanovdb;
|
||||
|
||||
ccl_global NanoGrid<T> *const grid = (ccl_global NanoGrid<T> *)info.data;
|
||||
typedef typename nanovdb::NanoGrid<T>::AccessorType AccessorType;
|
||||
AccessorType acc = grid->getAccessor();
|
||||
|
||||
switch (interpolation) {
|
||||
case INTERPOLATION_CLOSEST:
|
||||
return SampleFromVoxels<AccessorType, 0, false>(acc)(Vec3f(x, y, z));
|
||||
case INTERPOLATION_LINEAR:
|
||||
return SampleFromVoxels<AccessorType, 1, false>(acc)(Vec3f(x - 0.5f, y - 0.5f, z - 0.5f));
|
||||
default:
|
||||
SampleFromVoxels<AccessorType, 1, false> s(acc);
|
||||
return kernel_tex_image_interp_tricubic_nanovdb<T>(s, x - 0.5f, y - 0.5f, z - 0.5f);
|
||||
case INTERPOLATION_CLOSEST: {
|
||||
ReadAccessor<T> acc(grid->tree().root());
|
||||
const nanovdb::Coord coord((int32_t)floorf(x), (int32_t)floorf(y), (int32_t)floorf(z));
|
||||
return OutT(acc.getValue(coord));
|
||||
}
|
||||
case INTERPOLATION_LINEAR: {
|
||||
CachedReadAccessor<T> acc(grid->tree().root());
|
||||
return kernel_tex_image_interp_trilinear_nanovdb<OutT>(acc, x, y, z);
|
||||
}
|
||||
default: {
|
||||
CachedReadAccessor<T> acc(grid->tree().root());
|
||||
return kernel_tex_image_interp_tricubic_nanovdb<OutT>(acc, x, y, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -240,20 +303,20 @@ ccl_device float4 kernel_tex_image_interp_3d(KernelGlobals kg,
|
|||
|
||||
#ifdef WITH_NANOVDB
|
||||
if (texture_type == IMAGE_DATA_TYPE_NANOVDB_FLOAT) {
|
||||
float f = kernel_tex_image_interp_nanovdb<float>(info, x, y, z, interpolation);
|
||||
float f = kernel_tex_image_interp_nanovdb<float, float>(info, x, y, z, interpolation);
|
||||
return make_float4(f, f, f, 1.0f);
|
||||
}
|
||||
if (texture_type == IMAGE_DATA_TYPE_NANOVDB_FLOAT3) {
|
||||
nanovdb::Vec3f f = kernel_tex_image_interp_nanovdb<nanovdb::Vec3f>(
|
||||
float3 f = kernel_tex_image_interp_nanovdb<float3, packed_float3>(
|
||||
info, x, y, z, interpolation);
|
||||
return make_float4(f[0], f[1], f[2], 1.0f);
|
||||
return make_float4(f.x, f.y, f.z, 1.0f);
|
||||
}
|
||||
if (texture_type == IMAGE_DATA_TYPE_NANOVDB_FPN) {
|
||||
float f = kernel_tex_image_interp_nanovdb<nanovdb::FpN>(info, x, y, z, interpolation);
|
||||
float f = kernel_tex_image_interp_nanovdb<float, nanovdb::FpN>(info, x, y, z, interpolation);
|
||||
return make_float4(f, f, f, 1.0f);
|
||||
}
|
||||
if (texture_type == IMAGE_DATA_TYPE_NANOVDB_FP16) {
|
||||
float f = kernel_tex_image_interp_nanovdb<nanovdb::Fp16>(info, x, y, z, interpolation);
|
||||
float f = kernel_tex_image_interp_nanovdb<float, nanovdb::Fp16>(info, x, y, z, interpolation);
|
||||
return make_float4(f, f, f, 1.0f);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -668,7 +668,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
|
|||
int sw,
|
||||
int sh,
|
||||
float threshold,
|
||||
bool reset,
|
||||
int reset,
|
||||
int offset,
|
||||
int stride,
|
||||
ccl_global uint *num_active_pixels)
|
||||
|
@ -1104,7 +1104,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
|
|||
int pass_denoised,
|
||||
int pass_sample_count,
|
||||
int num_components,
|
||||
bool use_compositing)
|
||||
int use_compositing)
|
||||
{
|
||||
const int work_index = ccl_gpu_global_id_x();
|
||||
const int y = work_index / width;
|
||||
|
|
|
@ -38,6 +38,7 @@ typedef unsigned long long uint64_t;
|
|||
#define ccl_global
|
||||
#define ccl_inline_constant __constant__
|
||||
#define ccl_device_constant __constant__ __device__
|
||||
#define ccl_static_constexpr static constexpr
|
||||
#define ccl_constant const
|
||||
#define ccl_gpu_shared __shared__
|
||||
#define ccl_private
|
||||
|
|
|
@ -47,6 +47,7 @@ using namespace metal::raytracing;
|
|||
#define ccl_global device
|
||||
#define ccl_inline_constant static constant constexpr
|
||||
#define ccl_device_constant constant
|
||||
#define ccl_static_constexpr static constant constexpr
|
||||
#define ccl_constant constant
|
||||
#define ccl_gpu_shared threadgroup
|
||||
#define ccl_private thread
|
||||
|
|
|
@ -5,10 +5,7 @@
|
|||
// clang-format off
|
||||
|
||||
#ifdef WITH_NANOVDB
|
||||
# define NDEBUG /* Disable "assert" in device code */
|
||||
# define NANOVDB_USE_INTRINSICS
|
||||
# include "nanovdb/NanoVDB.h"
|
||||
# include "nanovdb/util/SampleFromVoxels.h"
|
||||
# include "kernel/util/nanovdb.h"
|
||||
#endif
|
||||
|
||||
/* Open the Metal kernel context class
|
||||
|
|
|
@ -40,7 +40,8 @@
|
|||
#define ccl_device_inline inline
|
||||
#define ccl_noinline __attribute__((noinline))
|
||||
#define ccl_inline_constant const constexpr
|
||||
#define ccl_static_constant const
|
||||
#define ccl_device_constant static constexpr
|
||||
#define ccl_static_constexpr static constexpr
|
||||
#define ccl_device_forceinline __attribute__((always_inline))
|
||||
#define ccl_device_noinline ccl_device ccl_noinline
|
||||
#define ccl_device_noinline_cpu ccl_device
|
||||
|
|
|
@ -34,8 +34,7 @@ typedef struct ccl_vdb_double_t {
|
|||
} ccl_vdb_double_t;
|
||||
|
||||
# define double ccl_vdb_double_t
|
||||
# include <nanovdb/NanoVDB.h>
|
||||
# include <nanovdb/util/SampleFromVoxels.h>
|
||||
# include "kernel/util/nanovdb.h"
|
||||
# undef double
|
||||
#endif
|
||||
|
||||
|
|
|
@ -202,48 +202,64 @@ ccl_device float4 kernel_tex_image_interp(KernelGlobals, int id, float x, float
|
|||
}
|
||||
|
||||
#ifdef WITH_NANOVDB
|
||||
template<typename T> struct NanoVDBInterpolator {
|
||||
template<typename TexT, typename OutT> struct NanoVDBInterpolator {
|
||||
|
||||
typedef typename nanovdb::NanoGrid<T>::AccessorType AccessorType;
|
||||
|
||||
static ccl_always_inline float4 read(float r)
|
||||
static ccl_always_inline float read(float r)
|
||||
{
|
||||
return make_float4(r, r, r, 1.0f);
|
||||
return r;
|
||||
}
|
||||
|
||||
static ccl_always_inline float4 read(nanovdb::Vec3f r)
|
||||
static ccl_always_inline float4 read(const packed_float3 r)
|
||||
{
|
||||
return make_float4(r[0], r[1], r[2], 1.0f);
|
||||
return make_float4(r.x, r.y, r.z, 1.0f);
|
||||
}
|
||||
|
||||
static ccl_always_inline float4 interp_3d_closest(const AccessorType &acc,
|
||||
float x,
|
||||
float y,
|
||||
float z)
|
||||
template<typename Acc>
|
||||
static ccl_always_inline OutT interp_3d_closest(const Acc &acc, float x, float y, float z)
|
||||
{
|
||||
const nanovdb::Vec3f xyz(x, y, z);
|
||||
return read(nanovdb::SampleFromVoxels<AccessorType, 0, false>(acc)(xyz));
|
||||
const nanovdb::Coord coord(int32_t(rintf(x)), int32_t(rintf(y)), int32_t(rintf(z)));
|
||||
return read(acc.getValue(coord));
|
||||
}
|
||||
|
||||
static ccl_always_inline float4 interp_3d_linear(const AccessorType &acc,
|
||||
float x,
|
||||
float y,
|
||||
float z)
|
||||
template<typename Acc>
|
||||
static ccl_always_inline OutT interp_3d_linear(const Acc &acc, float x, float y, float z)
|
||||
{
|
||||
const nanovdb::Vec3f xyz(x - 0.5f, y - 0.5f, z - 0.5f);
|
||||
return read(nanovdb::SampleFromVoxels<AccessorType, 1, false>(acc)(xyz));
|
||||
int ix, iy, iz;
|
||||
const float tx = svm_image_texture_frac(x - 0.5f, &ix);
|
||||
const float ty = svm_image_texture_frac(y - 0.5f, &iy);
|
||||
const float tz = svm_image_texture_frac(z - 0.5f, &iz);
|
||||
|
||||
return mix(mix(mix(read(acc.getValue(nanovdb::Coord(ix, iy, iz))),
|
||||
read(acc.getValue(nanovdb::Coord(ix, iy, iz + 1))),
|
||||
tz),
|
||||
mix(read(acc.getValue(nanovdb::Coord(ix, iy + 1, iz + 1))),
|
||||
read(acc.getValue(nanovdb::Coord(ix, iy + 1, iz))),
|
||||
1.0f - tz),
|
||||
ty),
|
||||
mix(mix(read(acc.getValue(nanovdb::Coord(ix + 1, iy + 1, iz))),
|
||||
read(acc.getValue(nanovdb::Coord(ix + 1, iy + 1, iz + 1))),
|
||||
tz),
|
||||
mix(read(acc.getValue(nanovdb::Coord(ix + 1, iy, iz + 1))),
|
||||
read(acc.getValue(nanovdb::Coord(ix + 1, iy, iz))),
|
||||
1.0f - tz),
|
||||
1.0f - ty),
|
||||
tx);
|
||||
}
|
||||
|
||||
static float4 interp_3d_cubic(const AccessorType &acc, float x, float y, float z)
|
||||
/* Tricubic b-spline interpolation. */
|
||||
template<typename Acc>
|
||||
static ccl_always_inline OutT interp_3d_cubic(const Acc &acc, float x, float y, float z)
|
||||
{
|
||||
int ix, iy, iz;
|
||||
int nix, niy, niz;
|
||||
int pix, piy, piz;
|
||||
int nnix, nniy, nniz;
|
||||
/* Tri-cubic b-spline interpolation. */
|
||||
|
||||
/* A -0.5 offset is used to center the cubic samples around the sample point. */
|
||||
const float tx = svm_image_texture_frac(x - 0.5f, &ix);
|
||||
const float ty = svm_image_texture_frac(y - 0.5f, &iy);
|
||||
const float tz = svm_image_texture_frac(z - 0.5f, &iz);
|
||||
|
||||
pix = ix - 1;
|
||||
piy = iy - 1;
|
||||
piz = iz - 1;
|
||||
|
@ -259,8 +275,8 @@ template<typename T> struct NanoVDBInterpolator {
|
|||
const int zc[4] = {piz, iz, niz, nniz};
|
||||
float u[4], v[4], w[4];
|
||||
|
||||
/* Some helper macro to keep code reasonable size,
|
||||
* let compiler to inline all the matrix multiplications.
|
||||
/* Some helper macros to keep code size reasonable.
|
||||
* Lets the compiler inline all the matrix multiplications.
|
||||
*/
|
||||
# define DATA(x, y, z) (read(acc.getValue(nanovdb::Coord(xc[x], yc[y], zc[z]))))
|
||||
# define COL_TERM(col, row) \
|
||||
|
@ -281,21 +297,26 @@ template<typename T> struct NanoVDBInterpolator {
|
|||
# undef DATA
|
||||
}
|
||||
|
||||
static ccl_always_inline float4
|
||||
static ccl_always_inline OutT
|
||||
interp_3d(const TextureInfo &info, float x, float y, float z, int interp)
|
||||
{
|
||||
using namespace nanovdb;
|
||||
|
||||
NanoGrid<T> *const grid = (NanoGrid<T> *)info.data;
|
||||
AccessorType acc = grid->getAccessor();
|
||||
NanoGrid<TexT> *const grid = (NanoGrid<TexT> *)info.data;
|
||||
|
||||
switch ((interp == INTERPOLATION_NONE) ? info.interpolation : interp) {
|
||||
case INTERPOLATION_CLOSEST:
|
||||
switch (interp) {
|
||||
case INTERPOLATION_CLOSEST: {
|
||||
ReadAccessor<TexT> acc(grid->tree().root());
|
||||
return interp_3d_closest(acc, x, y, z);
|
||||
case INTERPOLATION_LINEAR:
|
||||
}
|
||||
case INTERPOLATION_LINEAR: {
|
||||
CachedReadAccessor<TexT> acc(grid->tree().root());
|
||||
return interp_3d_linear(acc, x, y, z);
|
||||
default:
|
||||
}
|
||||
default: {
|
||||
CachedReadAccessor<TexT> acc(grid->tree().root());
|
||||
return interp_3d_cubic(acc, x, y, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -318,16 +339,21 @@ ccl_device float4 kernel_tex_image_interp_3d(KernelGlobals, int id, float3 P, in
|
|||
|
||||
#ifdef WITH_NANOVDB
|
||||
if (info.data_type == IMAGE_DATA_TYPE_NANOVDB_FLOAT) {
|
||||
return NanoVDBInterpolator<float>::interp_3d(info, x, y, z, interpolation);
|
||||
const float f = NanoVDBInterpolator<float, float>::interp_3d(info, x, y, z, interpolation);
|
||||
return make_float4(f, f, f, 1.0f);
|
||||
}
|
||||
else if (info.data_type == IMAGE_DATA_TYPE_NANOVDB_FLOAT3) {
|
||||
return NanoVDBInterpolator<nanovdb::Vec3f>::interp_3d(info, x, y, z, interpolation);
|
||||
return NanoVDBInterpolator<packed_float3, float4>::interp_3d(info, x, y, z, interpolation);
|
||||
}
|
||||
else if (info.data_type == IMAGE_DATA_TYPE_NANOVDB_FPN) {
|
||||
return NanoVDBInterpolator<nanovdb::FpN>::interp_3d(info, x, y, z, interpolation);
|
||||
const float f = NanoVDBInterpolator<nanovdb::FpN, float>::interp_3d(
|
||||
info, x, y, z, interpolation);
|
||||
return make_float4(f, f, f, 1.0f);
|
||||
}
|
||||
else if (info.data_type == IMAGE_DATA_TYPE_NANOVDB_FP16) {
|
||||
return NanoVDBInterpolator<nanovdb::Fp16>::interp_3d(info, x, y, z, interpolation);
|
||||
const float f = NanoVDBInterpolator<nanovdb::Fp16, float>::interp_3d(
|
||||
info, x, y, z, interpolation);
|
||||
return make_float4(f, f, f, 1.0f);
|
||||
}
|
||||
#else
|
||||
if (info.data_type == IMAGE_DATA_TYPE_NANOVDB_FLOAT ||
|
||||
|
|
|
@ -45,6 +45,7 @@ typedef unsigned long long uint64_t;
|
|||
#define ccl_global
|
||||
#define ccl_inline_constant static __constant__
|
||||
#define ccl_device_constant __constant__ __device__
|
||||
#define ccl_static_constexpr static constexpr
|
||||
#define ccl_constant const
|
||||
#define ccl_gpu_shared __shared__
|
||||
#define ccl_private
|
||||
|
|
|
@ -34,7 +34,7 @@ ccl_device bool film_adaptive_sampling_convergence_check(KernelGlobals kg,
|
|||
int x,
|
||||
int y,
|
||||
float threshold,
|
||||
bool reset,
|
||||
int reset,
|
||||
int offset,
|
||||
int stride)
|
||||
{
|
||||
|
|
|
@ -36,9 +36,6 @@ set(LIB
|
|||
${LLVM_LIBRARY}
|
||||
)
|
||||
|
||||
# OSL and LLVM are built without RTTI
|
||||
string(APPEND CMAKE_CXX_FLAGS " ${RTTI_DISABLE_FLAGS}")
|
||||
|
||||
if(APPLE)
|
||||
# Disable allocation warning on macOS prior to 10.14: the OSLRenderServices
|
||||
# contains member which is 64 bytes aligned (cache inside of OIIO's
|
||||
|
|
|
@ -110,7 +110,17 @@ void osl_eval_nodes<SHADER_TYPE_SURFACE>(const KernelGlobalsCPU *kg,
|
|||
if (sd->object == OBJECT_NONE && sd->lamp == LAMP_NONE) {
|
||||
/* background */
|
||||
if (kg->osl->background_state) {
|
||||
#if OSL_LIBRARY_VERSION_CODE >= 11304
|
||||
ss->execute(*octx,
|
||||
*(kg->osl->background_state),
|
||||
kg->osl_thread_index,
|
||||
0,
|
||||
*globals,
|
||||
nullptr,
|
||||
nullptr);
|
||||
#else
|
||||
ss->execute(octx, *(kg->osl->background_state), *globals);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
@ -150,8 +160,18 @@ void osl_eval_nodes<SHADER_TYPE_SURFACE>(const KernelGlobalsCPU *kg,
|
|||
globals->dPdy = TO_VEC3(tmp_dP.dy);
|
||||
}
|
||||
|
||||
/* execute bump shader */
|
||||
/* execute bump shader */
|
||||
#if OSL_LIBRARY_VERSION_CODE >= 11304
|
||||
ss->execute(*octx,
|
||||
*(kg->osl->bump_state[shader]),
|
||||
kg->osl_thread_index,
|
||||
0,
|
||||
*globals,
|
||||
nullptr,
|
||||
nullptr);
|
||||
#else
|
||||
ss->execute(octx, *(kg->osl->bump_state[shader]), *globals);
|
||||
#endif
|
||||
|
||||
/* reset state */
|
||||
sd->P = P;
|
||||
|
@ -164,7 +184,17 @@ void osl_eval_nodes<SHADER_TYPE_SURFACE>(const KernelGlobalsCPU *kg,
|
|||
|
||||
/* surface shader */
|
||||
if (kg->osl->surface_state[shader]) {
|
||||
#if OSL_LIBRARY_VERSION_CODE >= 11304
|
||||
ss->execute(*octx,
|
||||
*(kg->osl->surface_state[shader]),
|
||||
kg->osl_thread_index,
|
||||
0,
|
||||
*globals,
|
||||
nullptr,
|
||||
nullptr);
|
||||
#else
|
||||
ss->execute(octx, *(kg->osl->surface_state[shader]), *globals);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -208,7 +238,17 @@ void osl_eval_nodes<SHADER_TYPE_VOLUME>(const KernelGlobalsCPU *kg,
|
|||
int shader = sd->shader & SHADER_MASK;
|
||||
|
||||
if (kg->osl->volume_state[shader]) {
|
||||
#if OSL_LIBRARY_VERSION_CODE >= 11304
|
||||
ss->execute(*octx,
|
||||
*(kg->osl->volume_state[shader]),
|
||||
kg->osl_thread_index,
|
||||
0,
|
||||
*globals,
|
||||
nullptr,
|
||||
nullptr);
|
||||
#else
|
||||
ss->execute(octx, *(kg->osl->volume_state[shader]), *globals);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* flatten closure tree */
|
||||
|
@ -245,7 +285,17 @@ void osl_eval_nodes<SHADER_TYPE_DISPLACEMENT>(const KernelGlobalsCPU *kg,
|
|||
int shader = sd->shader & SHADER_MASK;
|
||||
|
||||
if (kg->osl->displacement_state[shader]) {
|
||||
#if OSL_LIBRARY_VERSION_CODE >= 11304
|
||||
ss->execute(*octx,
|
||||
*(kg->osl->displacement_state[shader]),
|
||||
kg->osl_thread_index,
|
||||
0,
|
||||
*globals,
|
||||
nullptr,
|
||||
nullptr);
|
||||
#else
|
||||
ss->execute(octx, *(kg->osl->displacement_state[shader]), *globals);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* get back position */
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
void OSLGlobals::thread_init(KernelGlobalsCPU *kg, OSLGlobals *osl_globals)
|
||||
void OSLGlobals::thread_init(KernelGlobalsCPU *kg, OSLGlobals *osl_globals, const int thread_index)
|
||||
{
|
||||
/* no osl used? */
|
||||
if (!osl_globals->use) {
|
||||
|
@ -37,6 +37,7 @@ void OSLGlobals::thread_init(KernelGlobalsCPU *kg, OSLGlobals *osl_globals)
|
|||
|
||||
kg->osl_ss = (OSLShadingSystem *)ss;
|
||||
kg->osl_tdata = tdata;
|
||||
kg->osl_thread_index = thread_index;
|
||||
}
|
||||
|
||||
void OSLGlobals::thread_free(KernelGlobalsCPU *kg)
|
||||
|
|
|
@ -45,7 +45,9 @@ struct OSLGlobals {
|
|||
}
|
||||
|
||||
/* per thread data */
|
||||
static void thread_init(struct KernelGlobalsCPU *kg, OSLGlobals *osl_globals);
|
||||
static void thread_init(struct KernelGlobalsCPU *kg,
|
||||
OSLGlobals *osl_globals,
|
||||
const int thread_init);
|
||||
static void thread_free(struct KernelGlobalsCPU *kg);
|
||||
|
||||
bool use;
|
||||
|
|
|
@ -52,6 +52,11 @@ ccl_device_inline void shaderdata_to_shaderglobals(KernelGlobals kg,
|
|||
|
||||
/* shader data to be used in services callbacks */
|
||||
globals->renderstate = sd;
|
||||
#if OSL_LIBRARY_VERSION_CODE >= 11304
|
||||
globals->shadingStateUniform = nullptr;
|
||||
globals->thread_index = 0;
|
||||
globals->shade_index = 0;
|
||||
#endif
|
||||
|
||||
/* hacky, we leave it to services to fetch actual object matrix */
|
||||
globals->shader2common = sd;
|
||||
|
|
|
@ -1165,7 +1165,18 @@ bool OSLRenderServices::get_userdata(
|
|||
return false; /* disabled by lockgeom */
|
||||
}
|
||||
|
||||
#if OSL_LIBRARY_VERSION_CODE >= 11100
|
||||
#if OSL_LIBRARY_VERSION_CODE >= 11304
|
||||
TextureSystem::TextureHandle *OSLRenderServices::get_texture_handle(OSLUStringHash filename,
|
||||
OSL::ShadingContext *context,
|
||||
const TextureOpt *opt)
|
||||
{
|
||||
return get_texture_handle(to_ustring(filename), context, opt);
|
||||
}
|
||||
|
||||
TextureSystem::TextureHandle *OSLRenderServices::get_texture_handle(OSL::ustring filename,
|
||||
OSL::ShadingContext *,
|
||||
const TextureOpt *)
|
||||
#elif OSL_LIBRARY_VERSION_CODE >= 11100
|
||||
TextureSystem::TextureHandle *OSLRenderServices::get_texture_handle(OSLUStringHash filename,
|
||||
OSL::ShadingContext *)
|
||||
#else
|
||||
|
@ -1616,7 +1627,17 @@ bool OSLRenderServices::environment(OSLUStringHash filename,
|
|||
return status;
|
||||
}
|
||||
|
||||
#if OSL_LIBRARY_VERSION_CODE >= 11100
|
||||
#if OSL_LIBRARY_VERSION_CODE >= 11304
|
||||
bool OSLRenderServices::get_texture_info(OSLUStringHash filename,
|
||||
TextureHandle *texture_handle,
|
||||
TexturePerthread *texture_thread_info,
|
||||
OSL::ShaderGlobals *,
|
||||
int subimage,
|
||||
OSLUStringHash dataname,
|
||||
TypeDesc datatype,
|
||||
void *data,
|
||||
OSLUStringHash *)
|
||||
#elif OSL_LIBRARY_VERSION_CODE >= 11100
|
||||
bool OSLRenderServices::get_texture_info(OSLUStringHash filename,
|
||||
TextureHandle *texture_handle,
|
||||
TexturePerthread *texture_thread_info,
|
||||
|
@ -1627,7 +1648,7 @@ bool OSLRenderServices::get_texture_info(OSLUStringHash filename,
|
|||
void *data,
|
||||
OSLUStringHash *)
|
||||
#else
|
||||
bool OSLRenderServices::get_texture_info(OSL::ShaderGlobals *sg,
|
||||
bool OSLRenderServices::get_texture_info(OSL::ShaderGlobals *,
|
||||
OSLUStringHash filename,
|
||||
TextureHandle *texture_handle,
|
||||
int subimage,
|
||||
|
|
|
@ -189,7 +189,14 @@ class OSLRenderServices : public OSL::RendererServices {
|
|||
void *val,
|
||||
bool derivatives) override;
|
||||
|
||||
#if OSL_LIBRARY_VERSION_CODE >= 11100
|
||||
#if OSL_LIBRARY_VERSION_CODE >= 11304
|
||||
TextureSystem::TextureHandle *get_texture_handle(OSL::ustring filename,
|
||||
OSL::ShadingContext *context,
|
||||
const TextureOpt *options) override;
|
||||
TextureSystem::TextureHandle *get_texture_handle(OSLUStringHash filename,
|
||||
OSL::ShadingContext *context,
|
||||
const TextureOpt *options) override;
|
||||
#elif OSL_LIBRARY_VERSION_CODE >= 11100
|
||||
TextureSystem::TextureHandle *get_texture_handle(OSLUStringHash filename,
|
||||
OSL::ShadingContext *context) override;
|
||||
#else
|
||||
|
@ -245,7 +252,17 @@ class OSLRenderServices : public OSL::RendererServices {
|
|||
float *dresultdt,
|
||||
OSLUStringHash *errormessage) override;
|
||||
|
||||
#if OSL_LIBRARY_VERSION_CODE >= 11100
|
||||
#if OSL_LIBRARY_VERSION_CODE >= 11304
|
||||
bool get_texture_info(OSLUStringHash filename,
|
||||
TextureHandle *texture_handle,
|
||||
TexturePerthread *texture_thread_info,
|
||||
OSL::ShaderGlobals *sg,
|
||||
int subimage,
|
||||
OSLUStringHash dataname,
|
||||
TypeDesc datatype,
|
||||
void *data,
|
||||
OSLUStringHash *errormessage) override;
|
||||
#elif OSL_LIBRARY_VERSION_CODE >= 11100
|
||||
bool get_texture_info(OSLUStringHash filename,
|
||||
TextureHandle *texture_handle,
|
||||
TexturePerthread *texture_thread_info,
|
||||
|
|
|
@ -86,8 +86,10 @@ struct ShaderGlobals {
|
|||
ccl_private void *tracedata;
|
||||
ccl_private void *objdata;
|
||||
void *context;
|
||||
#if OSL_LIBRARY_VERSION_CODE >= 11302
|
||||
#if OSL_LIBRARY_VERSION_CODE >= 11304
|
||||
void *shadingStateUniform;
|
||||
int thread_index;
|
||||
int shade_index;
|
||||
#endif
|
||||
void *renderer;
|
||||
ccl_private void *object2common;
|
||||
|
|
|
@ -0,0 +1,441 @@
|
|||
/* SPDX-FileCopyrightText: 2020-2021 Contributors to the OpenVDB Project
|
||||
*
|
||||
* SPDX-License-Identifier: MPL-2.0
|
||||
*
|
||||
* This is an extract from NanoVDB.h, with minimal code needed for kernel side access to grids. The
|
||||
* original headers are not compatible with Metal due to missing address space qualifiers. */
|
||||
|
||||
#pragma once
|
||||
|
||||
CCL_NAMESPACE_BEGIN
|
||||
|
||||
#define NANOVDB_USE_SINGLE_ROOT_KEY
|
||||
#define NANOVDB_DATA_ALIGNMENT 32
|
||||
|
||||
namespace nanovdb {
|
||||
|
||||
/* Utilities */
|
||||
|
||||
template<typename DstT, typename SrcT>
|
||||
ccl_device ccl_global const DstT *PtrAdd(ccl_global const SrcT *p, int64_t offset)
|
||||
{
|
||||
return reinterpret_cast<ccl_global const DstT *>(reinterpret_cast<ccl_global const char *>(p) +
|
||||
offset);
|
||||
}
|
||||
|
||||
/* Coord */
|
||||
|
||||
struct Coord {
|
||||
int x, y, z;
|
||||
|
||||
ccl_device_inline_method explicit Coord(int32_t n) : x(n), y(n), z(n) {}
|
||||
ccl_device_inline_method Coord(int32_t x, int32_t y, int32_t z) : x(x), y(y), z(z) {}
|
||||
|
||||
ccl_device_inline_method Coord operator&(int32_t n) const
|
||||
{
|
||||
return Coord(x & n, y & n, z & n);
|
||||
}
|
||||
};
|
||||
|
||||
/* Mask */
|
||||
|
||||
template<uint32_t LOG2DIM> struct Mask {
|
||||
ccl_static_constexpr uint32_t SIZE = 1U << (3 * LOG2DIM);
|
||||
ccl_static_constexpr uint32_t WORD_COUNT = SIZE >> 6;
|
||||
uint64_t mWords[WORD_COUNT];
|
||||
|
||||
ccl_device_inline_method bool isOff(uint32_t n) const ccl_global
|
||||
{
|
||||
return 0 == (mWords[n >> 6] & (uint64_t(1) << (n & 63)));
|
||||
}
|
||||
};
|
||||
|
||||
/* Grid */
|
||||
|
||||
template<typename TreeT> struct alignas(NANOVDB_DATA_ALIGNMENT) Grid {
|
||||
ccl_static_constexpr int MaxNameSize = 256;
|
||||
uint64_t mMagic;
|
||||
uint64_t mChecksum;
|
||||
uint32_t mVersion;
|
||||
uint32_t mFlags;
|
||||
uint32_t mGridIndex;
|
||||
uint32_t mGridCount;
|
||||
uint64_t mGridSize;
|
||||
char mGridName[MaxNameSize];
|
||||
uint8_t mMap[264];
|
||||
uint8_t mWorldBBox[48]; // double[6], but no doubles in Metal
|
||||
uint8_t mVoxelSize[24]; // double[3], but no doubles in Metal
|
||||
uint32_t mGridClass;
|
||||
uint32_t mGridType;
|
||||
uint32_t mData0;
|
||||
uint64_t mData1, mData2;
|
||||
|
||||
using BuildType = typename TreeT::BuildType;
|
||||
|
||||
ccl_device_inline_method ccl_global const TreeT &tree() const ccl_global
|
||||
{
|
||||
return *reinterpret_cast<ccl_global const TreeT *>(this + 1);
|
||||
}
|
||||
};
|
||||
|
||||
/* Tree */
|
||||
|
||||
template<typename RootT> struct alignas(NANOVDB_DATA_ALIGNMENT) Tree {
|
||||
int64_t mNodeOffset[4];
|
||||
uint32_t mNodeCount[3];
|
||||
uint32_t mTileCount[3];
|
||||
uint64_t mVoxelCount;
|
||||
|
||||
using ValueType = typename RootT::ValueType;
|
||||
using BuildType = typename RootT::BuildType;
|
||||
|
||||
ccl_device_inline_method ccl_global const RootT &root() const ccl_global
|
||||
{
|
||||
return *reinterpret_cast<ccl_global const RootT *>(
|
||||
mNodeOffset[3] ? PtrAdd<uint8_t>(this, mNodeOffset[3]) : nullptr);
|
||||
}
|
||||
};
|
||||
|
||||
/* RootNode */
|
||||
|
||||
template<typename ChildT> struct alignas(NANOVDB_DATA_ALIGNMENT) RootNode {
|
||||
using ValueType = typename ChildT::ValueType;
|
||||
using BuildType = typename ChildT::BuildType;
|
||||
|
||||
#ifdef NANOVDB_USE_SINGLE_ROOT_KEY
|
||||
using KeyT = uint64_t;
|
||||
ccl_device_inline_method static uint64_t CoordToKey(const Coord ijk)
|
||||
{
|
||||
return (uint64_t(uint32_t(ijk.z) >> ChildT::TOTAL)) |
|
||||
(uint64_t(uint32_t(ijk.y) >> ChildT::TOTAL) << 21) |
|
||||
(uint64_t(uint32_t(ijk.x) >> ChildT::TOTAL) << 42);
|
||||
}
|
||||
#else
|
||||
using KeyT = Coord;
|
||||
ccl_device_inline_method static Coord CoordToKey(const CoordT ijk)
|
||||
{
|
||||
return ijk & ~ChildT::MASK;
|
||||
}
|
||||
#endif
|
||||
Coord mBBox[2];
|
||||
uint32_t mTableSize;
|
||||
|
||||
ValueType mBackground;
|
||||
ValueType mMinimum;
|
||||
ValueType mMaximum;
|
||||
float mAverage;
|
||||
float mStdDevi;
|
||||
|
||||
struct alignas(NANOVDB_DATA_ALIGNMENT) Tile {
|
||||
KeyT key;
|
||||
int64_t child;
|
||||
uint32_t state;
|
||||
ValueType value;
|
||||
};
|
||||
|
||||
ccl_device_inline_method ccl_global const Tile *probeTile(const Coord ijk) const ccl_global
|
||||
{
|
||||
const auto key = CoordToKey(ijk);
|
||||
ccl_global const Tile *p = reinterpret_cast<ccl_global const Tile *>(this + 1);
|
||||
ccl_global const Tile *q = p + mTableSize;
|
||||
for (; p < q; ++p) {
|
||||
if (p->key == key) {
|
||||
return p;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ccl_device_inline_method ccl_global const ChildT *getChild(ccl_global const Tile *tile) const
|
||||
ccl_global
|
||||
{
|
||||
return PtrAdd<ChildT>(this, tile->child);
|
||||
}
|
||||
|
||||
ccl_static_constexpr uint32_t LEVEL = 1 + ChildT::LEVEL;
|
||||
};
|
||||
|
||||
/* InternalNode */
|
||||
|
||||
template<typename ChildT, uint32_t Log2Dim = ChildT::LOG2DIM + 1>
|
||||
struct alignas(NANOVDB_DATA_ALIGNMENT) InternalNode {
|
||||
using ValueType = typename ChildT::ValueType;
|
||||
using BuildType = typename ChildT::BuildType;
|
||||
|
||||
union Tile {
|
||||
ValueType value;
|
||||
int64_t child;
|
||||
};
|
||||
|
||||
Coord mBBox[2];
|
||||
uint64_t mFlags;
|
||||
Mask<Log2Dim> mValueMask;
|
||||
Mask<Log2Dim> mChildMask;
|
||||
|
||||
ValueType mMinimum;
|
||||
ValueType mMaximum;
|
||||
float mAverage;
|
||||
float mStdDevi;
|
||||
|
||||
alignas(32) Tile mTable[1u << (3 * Log2Dim)];
|
||||
|
||||
ccl_device_inline_method ccl_global const ChildT *getChild(uint32_t n) const ccl_global
|
||||
{
|
||||
return PtrAdd<ChildT>(this, mTable[n].child);
|
||||
}
|
||||
|
||||
ccl_static_constexpr uint32_t LOG2DIM = Log2Dim;
|
||||
ccl_static_constexpr uint32_t TOTAL = LOG2DIM + ChildT::TOTAL;
|
||||
ccl_static_constexpr uint32_t DIM = 1u << TOTAL;
|
||||
ccl_static_constexpr uint32_t SIZE = 1u << (3 * LOG2DIM);
|
||||
ccl_static_constexpr uint32_t MASK = (1u << TOTAL) - 1u;
|
||||
ccl_static_constexpr uint32_t LEVEL = 1 + ChildT::LEVEL;
|
||||
|
||||
ccl_device_inline_method static uint32_t CoordToOffset(const Coord ijk)
|
||||
{
|
||||
return (((ijk.x & MASK) >> ChildT::TOTAL) << (2 * LOG2DIM)) |
|
||||
(((ijk.y & MASK) >> ChildT::TOTAL) << (LOG2DIM)) | ((ijk.z & MASK) >> ChildT::TOTAL);
|
||||
}
|
||||
};
|
||||
|
||||
/* LeafData */
|
||||
|
||||
template<typename ValueT, uint32_t LOG2DIM> struct alignas(NANOVDB_DATA_ALIGNMENT) LeafData {
|
||||
using ValueType = ValueT;
|
||||
using BuildType = ValueT;
|
||||
|
||||
Coord mBBoxMin;
|
||||
uint8_t mBBoxDif[3];
|
||||
uint8_t mFlags;
|
||||
Mask<LOG2DIM> mValueMask;
|
||||
|
||||
ValueType mMinimum;
|
||||
ValueType mMaximum;
|
||||
float mAverage;
|
||||
float mStdDevi;
|
||||
alignas(32) ValueType mValues[1u << 3 * LOG2DIM];
|
||||
|
||||
ccl_device_inline_method ValueType getValue(uint32_t i) const ccl_global
|
||||
{
|
||||
return mValues[i];
|
||||
}
|
||||
};
|
||||
|
||||
/* LeafFnBase */
|
||||
|
||||
template<uint32_t LOG2DIM> struct alignas(NANOVDB_DATA_ALIGNMENT) LeafFnBase {
|
||||
Coord mBBoxMin;
|
||||
uint8_t mBBoxDif[3];
|
||||
uint8_t mFlags;
|
||||
Mask<LOG2DIM> mValueMask;
|
||||
|
||||
float mMinimum;
|
||||
float mQuantum;
|
||||
uint16_t mMin, mMax, mAvg, mDev;
|
||||
};
|
||||
|
||||
/* LeafData<Fp16> */
|
||||
|
||||
class Fp16 {
|
||||
};
|
||||
|
||||
template<uint32_t LOG2DIM> struct alignas(NANOVDB_DATA_ALIGNMENT) LeafData<Fp16, LOG2DIM> {
|
||||
using ValueType = float;
|
||||
using BuildType = Fp16;
|
||||
|
||||
LeafFnBase<LOG2DIM> base;
|
||||
alignas(32) uint16_t mCode[1u << 3 * LOG2DIM];
|
||||
|
||||
ccl_device_inline_method float getValue(uint32_t i) const ccl_global
|
||||
{
|
||||
return mCode[i] * base.mQuantum + base.mMinimum;
|
||||
}
|
||||
};
|
||||
|
||||
/* LeafData<FpN> */
|
||||
|
||||
class FpN {
|
||||
};
|
||||
|
||||
template<uint32_t LOG2DIM> struct alignas(NANOVDB_DATA_ALIGNMENT) LeafData<FpN, LOG2DIM> {
|
||||
using ValueType = float;
|
||||
using BuildType = FpN;
|
||||
|
||||
LeafFnBase<LOG2DIM> base;
|
||||
|
||||
ccl_device_inline_method float getValue(uint32_t i) const ccl_global
|
||||
{
|
||||
const int b = base.mFlags >> 5;
|
||||
uint32_t code = reinterpret_cast<ccl_global const uint32_t *>(this + 1)[i >> (5 - b)];
|
||||
code >>= (i & ((32 >> b) - 1)) << b;
|
||||
code &= (1 << (1 << b)) - 1;
|
||||
return float(code) * base.mQuantum + base.mMinimum;
|
||||
}
|
||||
};
|
||||
|
||||
/* LeafNode */
|
||||
|
||||
template<typename BuildT, uint32_t Log2Dim = 3> struct alignas(NANOVDB_DATA_ALIGNMENT) LeafNode {
|
||||
using DataType = LeafData<BuildT, Log2Dim>;
|
||||
using ValueType = typename DataType::ValueType;
|
||||
using BuildType = typename DataType::BuildType;
|
||||
|
||||
DataType data;
|
||||
|
||||
ccl_static_constexpr uint32_t LOG2DIM = Log2Dim;
|
||||
ccl_static_constexpr uint32_t TOTAL = LOG2DIM;
|
||||
ccl_static_constexpr uint32_t DIM = 1u << TOTAL;
|
||||
ccl_static_constexpr uint32_t SIZE = 1u << 3 * LOG2DIM;
|
||||
ccl_static_constexpr uint32_t MASK = (1u << LOG2DIM) - 1u;
|
||||
ccl_static_constexpr uint32_t LEVEL = 0;
|
||||
|
||||
ccl_device_inline_method static uint32_t CoordToOffset(const Coord ijk)
|
||||
{
|
||||
return ((ijk.x & MASK) << (2 * LOG2DIM)) | ((ijk.y & MASK) << LOG2DIM) | (ijk.z & MASK);
|
||||
}
|
||||
|
||||
ccl_device_inline_method ValueType getValue(uint32_t offset) const ccl_global
|
||||
{
|
||||
return data.getValue(offset);
|
||||
}
|
||||
|
||||
ccl_device_inline_method ValueType getValue(const Coord ijk) const ccl_global
|
||||
{
|
||||
return getValue(CoordToOffset(ijk));
|
||||
}
|
||||
};
|
||||
|
||||
/* Template Specializations */
|
||||
|
||||
template<typename BuildT> using NanoLeaf = LeafNode<BuildT, 3>;
|
||||
template<typename BuildT> using NanoLower = InternalNode<NanoLeaf<BuildT>, 4>;
|
||||
template<typename BuildT> using NanoUpper = InternalNode<NanoLower<BuildT>, 5>;
|
||||
template<typename BuildT> using NanoRoot = RootNode<NanoUpper<BuildT>>;
|
||||
template<typename BuildT> using NanoTree = Tree<NanoRoot<BuildT>>;
|
||||
template<typename BuildT> using NanoGrid = Grid<NanoTree<BuildT>>;
|
||||
|
||||
/* ReadAccessor */
|
||||
|
||||
template<typename BuildT> class ReadAccessor {
|
||||
using RootT = NanoRoot<BuildT>;
|
||||
using LeafT = NanoLeaf<BuildT>;
|
||||
|
||||
mutable ccl_global const RootT *mRoot;
|
||||
|
||||
public:
|
||||
using ValueType = typename RootT::ValueType;
|
||||
|
||||
ccl_device_inline_method ReadAccessor(ccl_global const RootT &root) : mRoot(&root) {}
|
||||
|
||||
ccl_device_inline_method ValueType getValue(const Coord ijk) const
|
||||
{
|
||||
ccl_global const auto *tile = mRoot->probeTile(ijk);
|
||||
if (tile == nullptr) {
|
||||
return mRoot->mBackground;
|
||||
}
|
||||
if (tile->child == 0) {
|
||||
return tile->value;
|
||||
}
|
||||
|
||||
ccl_global const auto *upper = mRoot->getChild(tile);
|
||||
const uint32_t upper_n = upper->CoordToOffset(ijk);
|
||||
if (upper->mChildMask.isOff(upper_n)) {
|
||||
return upper->mTable[upper_n].value;
|
||||
}
|
||||
|
||||
ccl_global const auto *lower = upper->getChild(upper_n);
|
||||
const uint32_t lower_n = lower->CoordToOffset(ijk);
|
||||
if (lower->mChildMask.isOff(lower_n)) {
|
||||
return lower->mTable[lower_n].value;
|
||||
}
|
||||
|
||||
ccl_global const LeafT *leaf = lower->getChild(lower_n);
|
||||
return leaf->getValue(ijk);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename BuildT> class CachedReadAccessor {
|
||||
using RootT = NanoRoot<BuildT>;
|
||||
using UpperT = NanoUpper<BuildT>;
|
||||
using LowerT = NanoLower<BuildT>;
|
||||
using LeafT = NanoLeaf<BuildT>;
|
||||
|
||||
mutable Coord mKeys[3];
|
||||
mutable ccl_global const RootT *mRoot;
|
||||
mutable ccl_global const void *mNode[3];
|
||||
|
||||
public:
|
||||
using ValueType = typename RootT::ValueType;
|
||||
|
||||
ccl_device_inline_method CachedReadAccessor(ccl_global const RootT &root)
|
||||
: mKeys{Coord(INT_MAX), Coord(INT_MAX), Coord(INT_MAX)},
|
||||
mRoot(&root),
|
||||
mNode{nullptr, nullptr, nullptr}
|
||||
{
|
||||
}
|
||||
|
||||
template<typename NodeT> ccl_device_inline_method bool isCached(const Coord ijk) const
|
||||
{
|
||||
return (ijk.x & int32_t(~NodeT::MASK)) == mKeys[NodeT::LEVEL].x &&
|
||||
(ijk.y & int32_t(~NodeT::MASK)) == mKeys[NodeT::LEVEL].y &&
|
||||
(ijk.z & int32_t(~NodeT::MASK)) == mKeys[NodeT::LEVEL].z;
|
||||
}
|
||||
|
||||
ccl_device_inline_method ValueType getValueAndCache(ccl_global const RootT &node,
|
||||
const Coord ijk) const
|
||||
{
|
||||
if (ccl_global const auto *tile = node.probeTile(ijk)) {
|
||||
if (tile->child != 0) {
|
||||
ccl_global const auto *child = node.getChild(tile);
|
||||
insert(ijk, child);
|
||||
return getValueAndCache(*child, ijk);
|
||||
}
|
||||
return tile->value;
|
||||
}
|
||||
return node.mBackground;
|
||||
}
|
||||
|
||||
ccl_device_inline_method ValueType getValueAndCache(ccl_global const LeafT &node,
|
||||
const Coord ijk) const
|
||||
{
|
||||
return node.getValue(ijk);
|
||||
}
|
||||
|
||||
template<typename NodeT>
|
||||
ccl_device_inline_method ValueType getValueAndCache(ccl_global const NodeT &node,
|
||||
const Coord ijk) const
|
||||
{
|
||||
const uint32_t n = node.CoordToOffset(ijk);
|
||||
if (node.mChildMask.isOff(n)) {
|
||||
return node.mTable[n].value;
|
||||
}
|
||||
ccl_global const auto *child = node.getChild(n);
|
||||
insert(ijk, child);
|
||||
return getValueAndCache(*child, ijk);
|
||||
}
|
||||
|
||||
ccl_device_inline_method ValueType getValue(const Coord ijk) const
|
||||
{
|
||||
if (isCached<LeafT>(ijk)) {
|
||||
return getValueAndCache(*((ccl_global const LeafT *)mNode[0]), ijk);
|
||||
}
|
||||
else if (isCached<LowerT>(ijk)) {
|
||||
return getValueAndCache(*((ccl_global const LowerT *)mNode[1]), ijk);
|
||||
}
|
||||
else if (isCached<UpperT>(ijk)) {
|
||||
return getValueAndCache(*((ccl_global const UpperT *)mNode[2]), ijk);
|
||||
}
|
||||
return getValueAndCache(*mRoot, ijk);
|
||||
}
|
||||
|
||||
template<typename NodeT>
|
||||
ccl_device_inline_method void insert(const Coord ijk, ccl_global const NodeT *node) const
|
||||
{
|
||||
mKeys[NodeT::LEVEL] = ijk & ~NodeT::MASK;
|
||||
mNode[NodeT::LEVEL] = node;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace nanovdb
|
||||
|
||||
CCL_NAMESPACE_END
|
|
@ -108,8 +108,6 @@ if(WITH_CYCLES_OSL)
|
|||
list(APPEND LIB
|
||||
cycles_kernel_osl
|
||||
)
|
||||
|
||||
set_property(SOURCE osl.cpp PROPERTY COMPILE_FLAGS ${RTTI_DISABLE_FLAGS})
|
||||
endif()
|
||||
|
||||
if(WITH_OPENCOLORIO)
|
||||
|
|
|
@ -35,7 +35,7 @@ void curvebounds(float *lower, float *upper, float3 *p, int dim)
|
|||
float ta = -1.0f;
|
||||
float tb = -1.0f;
|
||||
|
||||
if (discroot >= 0) {
|
||||
if (discroot >= 0 && curve_coef[3] != 0.0f) {
|
||||
discroot = sqrtf(discroot);
|
||||
ta = (-curve_coef[2] - discroot) / (3 * curve_coef[3]);
|
||||
tb = (-curve_coef[2] + discroot) / (3 * curve_coef[3]);
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
# include <openvdb/tools/Dense.h>
|
||||
#endif
|
||||
#ifdef WITH_NANOVDB
|
||||
# define NANOVDB_USE_OPENVDB
|
||||
# include <nanovdb/util/OpenToNanoVDB.h>
|
||||
#endif
|
||||
|
||||
|
@ -52,23 +53,49 @@ struct ToNanoOp {
|
|||
{
|
||||
if constexpr (!std::is_same_v<GridType, openvdb::MaskGrid>) {
|
||||
try {
|
||||
FloatGridType floatgrid(*openvdb::gridConstPtrCast<GridType>(grid));
|
||||
# if NANOVDB_MAJOR_VERSION_NUMBER > 32 || \
|
||||
(NANOVDB_MAJOR_VERSION_NUMBER == 32 && NANOVDB_MINOR_VERSION_NUMBER >= 6)
|
||||
/* OpenVDB 11. */
|
||||
if constexpr (std::is_same_v<FloatGridType, openvdb::FloatGrid>) {
|
||||
openvdb::FloatGrid floatgrid(*openvdb::gridConstPtrCast<GridType>(grid));
|
||||
if (precision == 0) {
|
||||
nanogrid = nanovdb::openToNanoVDB<nanovdb::HostBuffer,
|
||||
typename FloatGridType::TreeType,
|
||||
nanovdb::FpN>(floatgrid);
|
||||
return true;
|
||||
nanogrid = nanovdb::createNanoGrid<openvdb::FloatGrid, nanovdb::FpN>(floatgrid);
|
||||
}
|
||||
else if (precision == 16) {
|
||||
nanogrid = nanovdb::openToNanoVDB<nanovdb::HostBuffer,
|
||||
typename FloatGridType::TreeType,
|
||||
nanovdb::Fp16>(floatgrid);
|
||||
return true;
|
||||
nanogrid = nanovdb::createNanoGrid<openvdb::FloatGrid, nanovdb::Fp16>(floatgrid);
|
||||
}
|
||||
else {
|
||||
nanogrid = nanovdb::createNanoGrid<openvdb::FloatGrid, float>(floatgrid);
|
||||
}
|
||||
}
|
||||
|
||||
nanogrid = nanovdb::openToNanoVDB(floatgrid);
|
||||
else if constexpr (std::is_same_v<FloatGridType, openvdb::Vec3fGrid>) {
|
||||
openvdb::Vec3fGrid floatgrid(*openvdb::gridConstPtrCast<GridType>(grid));
|
||||
nanogrid = nanovdb::createNanoGrid<openvdb::Vec3fGrid, nanovdb::Vec3f>(
|
||||
floatgrid, nanovdb::StatsMode::Disable);
|
||||
}
|
||||
# else
|
||||
/* OpenVDB 10. */
|
||||
if constexpr (std::is_same_v<FloatGridType, openvdb::FloatGrid>) {
|
||||
openvdb::FloatGrid floatgrid(*openvdb::gridConstPtrCast<GridType>(grid));
|
||||
if (precision == 0) {
|
||||
nanogrid =
|
||||
nanovdb::openToNanoVDB<nanovdb::HostBuffer, openvdb::FloatTree, nanovdb::FpN>(
|
||||
floatgrid);
|
||||
}
|
||||
else if (precision == 16) {
|
||||
nanogrid =
|
||||
nanovdb::openToNanoVDB<nanovdb::HostBuffer, openvdb::FloatTree, nanovdb::Fp16>(
|
||||
floatgrid);
|
||||
}
|
||||
else {
|
||||
nanogrid = nanovdb::openToNanoVDB(floatgrid);
|
||||
}
|
||||
}
|
||||
else if constexpr (std::is_same_v<FloatGridType, openvdb::Vec3fGrid>) {
|
||||
openvdb::Vec3fGrid floatgrid(*openvdb::gridConstPtrCast<GridType>(grid));
|
||||
nanogrid = nanovdb::openToNanoVDB(floatgrid);
|
||||
}
|
||||
# endif
|
||||
}
|
||||
catch (const std::exception &e) {
|
||||
VLOG_WARNING << "Error converting OpenVDB to NanoVDB grid: " << e.what();
|
||||
|
|
|
@ -3372,14 +3372,23 @@ PrincipledHairBsdfNode::PrincipledHairBsdfNode() : BsdfBaseNode(get_node_type())
|
|||
closure = CLOSURE_BSDF_HAIR_HUANG_ID;
|
||||
}
|
||||
|
||||
void PrincipledHairBsdfNode::attributes(Shader *shader, AttributeRequestSet *attributes)
|
||||
/* Treat hair as transparent if the hit is outside of the projected width. */
|
||||
bool PrincipledHairBsdfNode::has_surface_transparent()
|
||||
{
|
||||
if (model == NODE_PRINCIPLED_HAIR_HUANG) {
|
||||
/* Make sure we have the normal for elliptical cross section tracking. */
|
||||
if (aspect_ratio != 1.0f || input("Aspect Ratio")->link) {
|
||||
attributes->add(ATTR_STD_VERTEX_NORMAL);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void PrincipledHairBsdfNode::attributes(Shader *shader, AttributeRequestSet *attributes)
|
||||
{
|
||||
if (has_surface_transparent()) {
|
||||
/* Make sure we have the normal for elliptical cross section tracking. */
|
||||
attributes->add(ATTR_STD_VERTEX_NORMAL);
|
||||
}
|
||||
|
||||
if (!input("Random")->link) {
|
||||
/* Enable retrieving Hair Info -> Random if Random isn't linked. */
|
||||
|
|
|
@ -851,6 +851,8 @@ class PrincipledHairBsdfNode : public BsdfBaseNode {
|
|||
{
|
||||
return ShaderNode::get_feature() | KERNEL_FEATURE_NODE_PRINCIPLED_HAIR;
|
||||
}
|
||||
|
||||
bool has_surface_transparent();
|
||||
};
|
||||
|
||||
class HairBsdfNode : public BsdfNode {
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
/* Address spaces for GPU. */
|
||||
# define ccl_global
|
||||
# define ccl_inline_constant inline constexpr
|
||||
# define ccl_static_constexpr static constexpr
|
||||
# define ccl_constant const
|
||||
# define ccl_private
|
||||
# define ccl_ray_data ccl_private
|
||||
|
|
|
@ -26,7 +26,7 @@ typedef struct DualConInput {
|
|||
int co_stride;
|
||||
int totco;
|
||||
|
||||
DualConTri looptri;
|
||||
DualConTri looptris;
|
||||
int tri_stride;
|
||||
int tottri;
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ static void veccopy(float dst[3], const float src[3])
|
|||
}
|
||||
|
||||
#define GET_TRI(_mesh, _n) \
|
||||
(*(DualConTri)(((char *)(_mesh)->looptri) + ((_n) * (_mesh)->tri_stride)))
|
||||
(*(DualConTri)(((char *)(_mesh)->looptris) + ((_n) * (_mesh)->tri_stride)))
|
||||
|
||||
#define GET_CO(_mesh, _n) (*(DualConCo)(((char *)(_mesh)->co) + ((_n) * (_mesh)->co_stride)))
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include <libavcodec/avcodec.h>
|
||||
#include <libavformat/avformat.h>
|
||||
#include <libswscale/swscale.h>
|
||||
|
||||
/* Check if our ffmpeg is new enough, avoids user complaints.
|
||||
* Minimum supported version is currently 3.2.0 which mean the following library versions:
|
||||
|
@ -46,6 +47,11 @@
|
|||
# define FFMPEG_USE_OLD_CHANNEL_VARS
|
||||
#endif
|
||||
|
||||
/* Threaded sws_scale_frame was added in ffmpeg 5.0 (swscale version 6.1). */
|
||||
#if (LIBSWSCALE_VERSION_INT >= AV_VERSION_INT(6, 1, 100))
|
||||
# define FFMPEG_SWSCALE_THREADING
|
||||
#endif
|
||||
|
||||
/* AV_CODEC_CAP_AUTO_THREADS was renamed to AV_CODEC_CAP_OTHER_THREADS with
|
||||
* upstream commit
|
||||
* github.com/FFmpeg/FFmpeg/commit/7d09579190def3ef7562399489e628f3b65714ce
|
||||
|
|
|
@ -176,6 +176,13 @@ class GHOST_SystemCocoa : public GHOST_System {
|
|||
*/
|
||||
GHOST_TSuccess setCursorPosition(int32_t x, int32_t y);
|
||||
|
||||
/**
|
||||
* Get the color of the pixel at the current mouse cursor location
|
||||
* \param r_color: returned sRGB float colors
|
||||
* \return Success value (true == successful and supported by platform)
|
||||
*/
|
||||
GHOST_TSuccess getPixelAtCursor(float r_color[3]) const;
|
||||
|
||||
/***************************************************************************************
|
||||
* Access to mouse button and keyboard states.
|
||||
***************************************************************************************/
|
||||
|
@ -318,7 +325,7 @@ class GHOST_SystemCocoa : public GHOST_System {
|
|||
|
||||
/** Temporarily ignore momentum scroll events */
|
||||
bool m_ignoreMomentumScroll;
|
||||
/** Is the scroll wheel event generated by a multi-touch track-pad or mouse? */
|
||||
/** Is the scroll wheel event generated by a multi-touch trackpad or mouse? */
|
||||
bool m_multiTouchScroll;
|
||||
/** To prevent multiple warp, we store the time of the last warp event
|
||||
* and ignore mouse moved events generated before that. */
|
||||
|
|
|
@ -549,7 +549,7 @@ GHOST_SystemCocoa::GHOST_SystemCocoa()
|
|||
sysctl(mib, 2, &boottime, &len, nullptr, 0);
|
||||
m_start_time = ((boottime.tv_sec * 1000) + (boottime.tv_usec / 1000));
|
||||
|
||||
/* Detect multi-touch track-pad. */
|
||||
/* Detect multi-touch trackpad. */
|
||||
mib[0] = CTL_HW;
|
||||
mib[1] = HW_MODEL;
|
||||
sysctl(mib, 2, nullptr, &len, nullptr, 0);
|
||||
|
@ -888,6 +888,71 @@ GHOST_TSuccess GHOST_SystemCocoa::setCursorPosition(int32_t x, int32_t y)
|
|||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_SystemCocoa::getPixelAtCursor(float r_color[3]) const
|
||||
{
|
||||
/* NOTE: There are known issues/limitations at the moment:
|
||||
*
|
||||
* - User needs to allow screen capture permission for Blender.
|
||||
* - Blender has no control of the cursor outside of its window, so it is
|
||||
* not going to be the eyedropper icon.
|
||||
* - GHOST does not report click events from outside of the window, so the
|
||||
* user needs to press Enter instead.
|
||||
*
|
||||
* Ref #111303.
|
||||
*/
|
||||
|
||||
@autoreleasepool {
|
||||
/* Check for screen capture access permission early to prevent issues.
|
||||
* Without permission, macOS may capture only the Blender window, wallpaper, and taskbar.
|
||||
* This behavior could confuse users, especially when trying to pick a color from another app,
|
||||
* potentially capturing the wallpaper under that app window.
|
||||
*/
|
||||
if (@available(macOS 11.0, *)) {
|
||||
/* Although these methods are documented as available for macOS 10.15, they are not actually
|
||||
* shipped, leading to a crash if used on macOS 10.15.
|
||||
*
|
||||
* Ref: https://developer.apple.com/forums/thread/683860?answerId=684400022#684400022
|
||||
*/
|
||||
if (!CGPreflightScreenCaptureAccess()) {
|
||||
CGRequestScreenCaptureAccess();
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
}
|
||||
|
||||
CGEventRef event = CGEventCreate(nil);
|
||||
if (!event) {
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
CGPoint mouseLocation = CGEventGetLocation(event);
|
||||
CFRelease(event);
|
||||
|
||||
CGRect rect = CGRectMake(mouseLocation.x, mouseLocation.y, 1, 1);
|
||||
CGImageRef image = CGWindowListCreateImage(
|
||||
rect, kCGWindowListOptionOnScreenOnly, kCGNullWindowID, kCGWindowImageDefault);
|
||||
if (!image) {
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
NSBitmapImageRep *bitmap = [[NSBitmapImageRep alloc] initWithCGImage:image];
|
||||
CGImageRelease(image);
|
||||
|
||||
NSColor *color = [bitmap colorAtX:0 y:0];
|
||||
if (!color) {
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
NSColor *srgbColor = [color colorUsingColorSpace:[NSColorSpace sRGBColorSpace]];
|
||||
if (!srgbColor) {
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
CGFloat red = 0.0, green = 0.0, blue = 0.0;
|
||||
[color getRed:&red green:&green blue:&blue alpha:nil];
|
||||
r_color[0] = red;
|
||||
r_color[1] = green;
|
||||
r_color[2] = blue;
|
||||
}
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_SystemCocoa::setMouseCursorPosition(int32_t x, int32_t y)
|
||||
{
|
||||
float xf = (float)x, yf = (float)y;
|
||||
|
@ -953,8 +1018,6 @@ GHOST_TCapabilityFlag GHOST_SystemCocoa::getCapabilities() const
|
|||
~(
|
||||
/* Cocoa has no support for a primary selection clipboard. */
|
||||
GHOST_kCapabilityPrimaryClipboard |
|
||||
/* Cocoa has no support for sampling colors from the desktop. */
|
||||
GHOST_kCapabilityDesktopSample |
|
||||
/* This Cocoa back-end has not yet implemented image copy/paste. */
|
||||
GHOST_kCapabilityClipboardImages));
|
||||
}
|
||||
|
|
|
@ -120,6 +120,11 @@ static void gwl_seat_capability_pointer_disable(GWL_Seat *seat);
|
|||
static void gwl_seat_capability_keyboard_disable(GWL_Seat *seat);
|
||||
static void gwl_seat_capability_touch_disable(GWL_Seat *seat);
|
||||
|
||||
static void gwl_seat_cursor_anim_begin(GWL_Seat *seat);
|
||||
static void gwl_seat_cursor_anim_begin_if_needed(GWL_Seat *seat);
|
||||
static void gwl_seat_cursor_anim_end(GWL_Seat *seat);
|
||||
static void gwl_seat_cursor_anim_reset(GWL_Seat *seat);
|
||||
|
||||
static bool gwl_registry_entry_remove_by_name(GWL_Display *display,
|
||||
uint32_t name,
|
||||
int *r_interface_slot);
|
||||
|
@ -135,11 +140,6 @@ static void gwl_display_event_thread_destroy(GWL_Display *display);
|
|||
|
||||
static void ghost_wl_display_lock_without_input(wl_display *wl_display, std::mutex *server_mutex);
|
||||
|
||||
static void cursor_anim_begin_if_needed(GWL_Seat *seat);
|
||||
static void cursor_anim_begin(GWL_Seat *seat);
|
||||
static void cursor_anim_end(GWL_Seat *seat);
|
||||
static void cursor_anim_reset(GWL_Seat *seat);
|
||||
|
||||
/** Default size for pending event vector. */
|
||||
constexpr size_t events_pending_default_size = 4096 / sizeof(void *);
|
||||
|
||||
|
@ -1336,7 +1336,7 @@ static void gwl_display_destroy(GWL_Display *display)
|
|||
|
||||
/* Stop all animated cursors (freeing their #GWL_Cursor_AnimHandle). */
|
||||
for (GWL_Seat *seat : display->seats) {
|
||||
cursor_anim_end(seat);
|
||||
gwl_seat_cursor_anim_end(seat);
|
||||
}
|
||||
|
||||
/* For typical WAYLAND use this will always be set.
|
||||
|
@ -1675,6 +1675,11 @@ static void gwl_registry_entry_update_all(GWL_Display *display, const int interf
|
|||
/** \name Private Utility Functions
|
||||
* \{ */
|
||||
|
||||
static uint64_t sub_abs_u64(const uint64_t a, const uint64_t b)
|
||||
{
|
||||
return a > b ? a - b : b - a;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return milliseconds from a microsecond uint32 pair (used by some wayland functions).
|
||||
*/
|
||||
|
@ -2026,6 +2031,7 @@ static const char *ghost_wl_mime_send[] = {
|
|||
"text/plain",
|
||||
};
|
||||
|
||||
#ifdef USE_EVENT_BACKGROUND_THREAD
|
||||
static void pthread_set_min_priority(pthread_t handle)
|
||||
{
|
||||
int policy;
|
||||
|
@ -2046,6 +2052,7 @@ static void thread_set_min_priority(std::thread &thread)
|
|||
* This cast might be avoided with clever template use. */
|
||||
pthread_set_min_priority(reinterpret_cast<pthread_t>(thread.native_handle()));
|
||||
}
|
||||
#endif /* USE_EVENT_BACKGROUND_THREAD */
|
||||
|
||||
static int memfd_create_sealed(const char *name)
|
||||
{
|
||||
|
@ -2383,6 +2390,321 @@ static char *read_file_as_buffer(const int fd, const bool nil_terminate, size_t
|
|||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Private Cursor API
|
||||
* \{ */
|
||||
|
||||
static void cursor_buffer_set_surface_impl(const wl_cursor_image *wl_image,
|
||||
wl_buffer *buffer,
|
||||
wl_surface *wl_surface,
|
||||
const int scale)
|
||||
{
|
||||
const int32_t image_size_x = int32_t(wl_image->width);
|
||||
const int32_t image_size_y = int32_t(wl_image->height);
|
||||
GHOST_ASSERT((image_size_x % scale) == 0 && (image_size_y % scale) == 0,
|
||||
"The size must be a multiple of the scale!");
|
||||
|
||||
wl_surface_set_buffer_scale(wl_surface, scale);
|
||||
wl_surface_attach(wl_surface, buffer, 0, 0);
|
||||
wl_surface_damage(wl_surface, 0, 0, image_size_x, image_size_y);
|
||||
wl_surface_commit(wl_surface);
|
||||
}
|
||||
|
||||
/**
|
||||
* Needed to ensure the cursor size is always a multiple of scale.
|
||||
*/
|
||||
static int cursor_buffer_compatible_scale_from_image(const wl_cursor_image *wl_image, int scale)
|
||||
{
|
||||
const int32_t image_size_x = int32_t(wl_image->width);
|
||||
const int32_t image_size_y = int32_t(wl_image->height);
|
||||
while (scale > 1) {
|
||||
if ((image_size_x % scale) == 0 && (image_size_y % scale) == 0) {
|
||||
break;
|
||||
}
|
||||
scale -= 1;
|
||||
}
|
||||
return scale;
|
||||
}
|
||||
|
||||
static const wl_cursor *gwl_seat_cursor_find_from_shape(GWL_Seat *seat,
|
||||
const GHOST_TStandardCursor shape,
|
||||
const char **r_cursor_name)
|
||||
{
|
||||
/* Caller must lock `server_mutex`. */
|
||||
GWL_Cursor *cursor = &seat->cursor;
|
||||
wl_cursor *wl_cursor = nullptr;
|
||||
|
||||
const char *cursor_name = ghost_wl_cursors.names[shape];
|
||||
if (cursor_name[0] != '\0') {
|
||||
if (!cursor->wl.theme) {
|
||||
/* The cursor wl_surface hasn't entered an output yet. Initialize theme with scale 1. */
|
||||
cursor->wl.theme = wl_cursor_theme_load(
|
||||
cursor->theme_name.c_str(), cursor->theme_size, seat->system->wl_shm_get());
|
||||
}
|
||||
|
||||
if (cursor->wl.theme) {
|
||||
wl_cursor = wl_cursor_theme_get_cursor(cursor->wl.theme, cursor_name);
|
||||
if (!wl_cursor) {
|
||||
GHOST_PRINT("cursor '" << cursor_name << "' does not exist" << std::endl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (r_cursor_name && wl_cursor) {
|
||||
*r_cursor_name = cursor_name;
|
||||
}
|
||||
return wl_cursor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the buffer defined by #gwl_seat_cursor_buffer_set without changing anything else,
|
||||
* so #gwl_seat_cursor_buffer_hide can be used to display it again.
|
||||
*
|
||||
* The caller is responsible for setting `seat->cursor.visible`.
|
||||
*/
|
||||
static void gwl_seat_cursor_buffer_show(GWL_Seat *seat)
|
||||
{
|
||||
const GWL_Cursor *cursor = &seat->cursor;
|
||||
|
||||
if (seat->wl.pointer) {
|
||||
const int scale = cursor->is_custom ? cursor->custom_scale : seat->pointer.theme_scale;
|
||||
const int32_t hotspot_x = int32_t(cursor->wl.image.hotspot_x) / scale;
|
||||
const int32_t hotspot_y = int32_t(cursor->wl.image.hotspot_y) / scale;
|
||||
wl_pointer_set_cursor(
|
||||
seat->wl.pointer, seat->pointer.serial, cursor->wl.surface_cursor, hotspot_x, hotspot_y);
|
||||
}
|
||||
|
||||
if (!seat->wp.tablet_tools.empty()) {
|
||||
const int scale = cursor->is_custom ? cursor->custom_scale : seat->tablet.theme_scale;
|
||||
const int32_t hotspot_x = int32_t(cursor->wl.image.hotspot_x) / scale;
|
||||
const int32_t hotspot_y = int32_t(cursor->wl.image.hotspot_y) / scale;
|
||||
for (zwp_tablet_tool_v2 *zwp_tablet_tool_v2 : seat->wp.tablet_tools) {
|
||||
GWL_TabletTool *tablet_tool = static_cast<GWL_TabletTool *>(
|
||||
zwp_tablet_tool_v2_get_user_data(zwp_tablet_tool_v2));
|
||||
zwp_tablet_tool_v2_set_cursor(zwp_tablet_tool_v2,
|
||||
seat->tablet.serial,
|
||||
tablet_tool->wl.surface_cursor,
|
||||
hotspot_x,
|
||||
hotspot_y);
|
||||
#ifdef USE_KDE_TABLET_HIDDEN_CURSOR_HACK
|
||||
wl_surface_commit(tablet_tool->wl.surface_cursor);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
gwl_seat_cursor_anim_reset(seat);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide the buffer defined by #gwl_seat_cursor_buffer_set without changing anything else,
|
||||
* so #gwl_seat_cursor_buffer_show can be used to display it again.
|
||||
*
|
||||
* The caller is responsible for setting `seat->cursor.visible`.
|
||||
*/
|
||||
static void gwl_seat_cursor_buffer_hide(GWL_Seat *seat)
|
||||
{
|
||||
gwl_seat_cursor_anim_end(seat);
|
||||
|
||||
wl_pointer_set_cursor(seat->wl.pointer, seat->pointer.serial, nullptr, 0, 0);
|
||||
for (zwp_tablet_tool_v2 *zwp_tablet_tool_v2 : seat->wp.tablet_tools) {
|
||||
zwp_tablet_tool_v2_set_cursor(zwp_tablet_tool_v2, seat->tablet.serial, nullptr, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static void gwl_seat_cursor_buffer_set(const GWL_Seat *seat,
|
||||
const wl_cursor_image *wl_image,
|
||||
wl_buffer *buffer)
|
||||
{
|
||||
const GWL_Cursor *cursor = &seat->cursor;
|
||||
const bool visible = (cursor->visible && cursor->is_hardware);
|
||||
|
||||
/* This is a requirement of WAYLAND, when this isn't the case,
|
||||
* it causes Blender's window to close intermittently. */
|
||||
if (seat->wl.pointer) {
|
||||
const int scale = cursor_buffer_compatible_scale_from_image(
|
||||
wl_image, cursor->is_custom ? cursor->custom_scale : seat->pointer.theme_scale);
|
||||
const int32_t hotspot_x = int32_t(wl_image->hotspot_x) / scale;
|
||||
const int32_t hotspot_y = int32_t(wl_image->hotspot_y) / scale;
|
||||
cursor_buffer_set_surface_impl(wl_image, buffer, cursor->wl.surface_cursor, scale);
|
||||
wl_pointer_set_cursor(seat->wl.pointer,
|
||||
seat->pointer.serial,
|
||||
visible ? cursor->wl.surface_cursor : nullptr,
|
||||
hotspot_x,
|
||||
hotspot_y);
|
||||
}
|
||||
|
||||
/* Set the cursor for all tablet tools as well. */
|
||||
if (!seat->wp.tablet_tools.empty()) {
|
||||
const int scale = cursor_buffer_compatible_scale_from_image(
|
||||
wl_image, cursor->is_custom ? cursor->custom_scale : seat->tablet.theme_scale);
|
||||
const int32_t hotspot_x = int32_t(wl_image->hotspot_x) / scale;
|
||||
const int32_t hotspot_y = int32_t(wl_image->hotspot_y) / scale;
|
||||
for (zwp_tablet_tool_v2 *zwp_tablet_tool_v2 : seat->wp.tablet_tools) {
|
||||
GWL_TabletTool *tablet_tool = static_cast<GWL_TabletTool *>(
|
||||
zwp_tablet_tool_v2_get_user_data(zwp_tablet_tool_v2));
|
||||
cursor_buffer_set_surface_impl(wl_image, buffer, tablet_tool->wl.surface_cursor, scale);
|
||||
zwp_tablet_tool_v2_set_cursor(zwp_tablet_tool_v2,
|
||||
seat->tablet.serial,
|
||||
visible ? tablet_tool->wl.surface_cursor : nullptr,
|
||||
hotspot_x,
|
||||
hotspot_y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void gwl_seat_cursor_buffer_set_current(GWL_Seat *seat)
|
||||
{
|
||||
const GWL_Cursor *cursor = &seat->cursor;
|
||||
gwl_seat_cursor_anim_end(seat);
|
||||
gwl_seat_cursor_buffer_set(seat, &cursor->wl.image, cursor->wl.buffer);
|
||||
gwl_seat_cursor_anim_begin_if_needed(seat);
|
||||
}
|
||||
|
||||
enum eCursorSetMode {
|
||||
CURSOR_VISIBLE_ALWAYS_SET = 1,
|
||||
CURSOR_VISIBLE_ONLY_HIDE,
|
||||
CURSOR_VISIBLE_ONLY_SHOW,
|
||||
};
|
||||
|
||||
static void gwl_seat_cursor_visible_set(GWL_Seat *seat,
|
||||
const bool visible,
|
||||
const bool is_hardware,
|
||||
const enum eCursorSetMode set_mode)
|
||||
{
|
||||
GWL_Cursor *cursor = &seat->cursor;
|
||||
const bool was_visible = cursor->is_hardware && cursor->visible;
|
||||
const bool use_visible = is_hardware && visible;
|
||||
|
||||
if (set_mode == CURSOR_VISIBLE_ALWAYS_SET) {
|
||||
/* Pass. */
|
||||
}
|
||||
else if (set_mode == CURSOR_VISIBLE_ONLY_SHOW) {
|
||||
if (!use_visible) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (set_mode == CURSOR_VISIBLE_ONLY_HIDE) {
|
||||
if (use_visible) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (use_visible) {
|
||||
if (!was_visible) {
|
||||
gwl_seat_cursor_buffer_show(seat);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (was_visible) {
|
||||
gwl_seat_cursor_buffer_hide(seat);
|
||||
}
|
||||
}
|
||||
cursor->visible = visible;
|
||||
cursor->is_hardware = is_hardware;
|
||||
}
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Private Cursor Animation API
|
||||
* \{ */
|
||||
|
||||
#ifdef USE_EVENT_BACKGROUND_THREAD
|
||||
|
||||
static bool gwl_seat_cursor_anim_check(GWL_Seat *seat)
|
||||
{
|
||||
const wl_cursor *wl_cursor = seat->cursor.wl.theme_cursor;
|
||||
if (!wl_cursor) {
|
||||
return false;
|
||||
}
|
||||
/* NOTE: return true to stress test animated cursor,
|
||||
* to ensure (otherwise rare) issues are triggered more frequently. */
|
||||
// return true;
|
||||
|
||||
return wl_cursor->image_count > 1;
|
||||
}
|
||||
|
||||
static void gwl_seat_cursor_anim_begin(GWL_Seat *seat)
|
||||
{
|
||||
/* Caller must lock `server_mutex`. */
|
||||
GHOST_ASSERT(seat->cursor.anim_handle == nullptr, "Must be cleared");
|
||||
|
||||
/* Callback for updating the cursor animation. */
|
||||
auto cursor_anim_frame_step_fn =
|
||||
[](GWL_Seat *seat, GWL_Cursor_AnimHandle *anim_handle, int delay) {
|
||||
/* It's possible the `wl_cursor` is reloaded while the cursor is animating.
|
||||
* Don't access outside the lock, that's why the `delay` is passed in. */
|
||||
std::mutex *server_mutex = seat->system->server_mutex;
|
||||
int frame = 0;
|
||||
while (!anim_handle->exit_pending.load()) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(delay));
|
||||
if (!anim_handle->exit_pending.load()) {
|
||||
std::lock_guard lock_server_guard{*server_mutex};
|
||||
if (!anim_handle->exit_pending.load()) {
|
||||
const struct wl_cursor *wl_cursor = seat->cursor.wl.theme_cursor;
|
||||
frame = (frame + 1) % wl_cursor->image_count;
|
||||
wl_cursor_image *image = wl_cursor->images[frame];
|
||||
wl_buffer *buffer = wl_cursor_image_get_buffer(image);
|
||||
gwl_seat_cursor_buffer_set(seat, image, buffer);
|
||||
delay = wl_cursor->images[frame]->delay;
|
||||
/* Without this the cursor won't update when other processes are occupied. */
|
||||
wl_display_flush(seat->system->wl_display_get());
|
||||
}
|
||||
}
|
||||
}
|
||||
delete anim_handle;
|
||||
};
|
||||
|
||||
/* Allocate so this can be set before the thread begins. */
|
||||
GWL_Cursor_AnimHandle *anim_handle = new GWL_Cursor_AnimHandle;
|
||||
seat->cursor.anim_handle = anim_handle;
|
||||
|
||||
const int delay = seat->cursor.wl.theme_cursor->images[0]->delay;
|
||||
std::thread cursor_anim_thread(cursor_anim_frame_step_fn, seat, anim_handle, delay);
|
||||
/* Application logic should take priority. */
|
||||
thread_set_min_priority(cursor_anim_thread);
|
||||
cursor_anim_thread.detach();
|
||||
}
|
||||
|
||||
static void gwl_seat_cursor_anim_begin_if_needed(GWL_Seat *seat)
|
||||
{
|
||||
if (gwl_seat_cursor_anim_check(seat)) {
|
||||
gwl_seat_cursor_anim_begin(seat);
|
||||
}
|
||||
}
|
||||
|
||||
static void gwl_seat_cursor_anim_end(GWL_Seat *seat)
|
||||
{
|
||||
GWL_Cursor *cursor = &seat->cursor;
|
||||
if (cursor->anim_handle) {
|
||||
GWL_Cursor_AnimHandle *anim_handle = cursor->anim_handle;
|
||||
cursor->anim_handle = nullptr;
|
||||
anim_handle->exit_pending.store(true);
|
||||
}
|
||||
}
|
||||
|
||||
static void gwl_seat_cursor_anim_reset(GWL_Seat *seat)
|
||||
{
|
||||
gwl_seat_cursor_anim_end(seat);
|
||||
gwl_seat_cursor_anim_begin_if_needed(seat);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* Unfortunately cursor animation requires a background thread. */
|
||||
[[maybe_unused]] static bool gwl_seat_cursor_anim_check(GWL_Seat * /*seat*/)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
[[maybe_unused]] static void gwl_seat_cursor_anim_begin(GWL_Seat * /*seat*/) {}
|
||||
[[maybe_unused]] static void gwl_seat_cursor_anim_begin_if_needed(GWL_Seat * /*seat*/) {}
|
||||
[[maybe_unused]] static void gwl_seat_cursor_anim_end(GWL_Seat * /*seat*/) {}
|
||||
[[maybe_unused]] static void gwl_seat_cursor_anim_reset(GWL_Seat * /*seat*/) {}
|
||||
|
||||
#endif /* !USE_EVENT_BACKGROUND_THREAD */
|
||||
|
||||
/** \} */
|
||||
|
||||
/* -------------------------------------------------------------------- */
|
||||
/** \name Private Keyboard Depressed Key Tracking
|
||||
*
|
||||
|
@ -3552,7 +3874,7 @@ static void gesture_pinch_handle_begin(void *data,
|
|||
seat->pointer_gesture_pinch.rotation.factor = 5;
|
||||
|
||||
if (win) {
|
||||
/* NOTE(@ideasman42): Blender's use of track-pad coordinates is inconsistent and needs work.
|
||||
/* NOTE(@ideasman42): Blender's use of trackpad coordinates is inconsistent and needs work.
|
||||
* This isn't specific to WAYLAND, in practice they tend to work well enough in most cases.
|
||||
* Some operators scale by the UI scale, some don't.
|
||||
* Even though the window scale is correct, it doesn't account for the UI scale preference
|
||||
|
@ -7378,185 +7700,6 @@ GHOST_IWindow *GHOST_SystemWayland::createWindow(const char *title,
|
|||
return window;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the buffer defined by #cursor_buffer_set without changing anything else,
|
||||
* so #cursor_buffer_hide can be used to display it again.
|
||||
*
|
||||
* The caller is responsible for setting `seat->cursor.visible`.
|
||||
*/
|
||||
static void cursor_buffer_show(GWL_Seat *seat)
|
||||
{
|
||||
const GWL_Cursor *cursor = &seat->cursor;
|
||||
|
||||
if (seat->wl.pointer) {
|
||||
const int scale = cursor->is_custom ? cursor->custom_scale : seat->pointer.theme_scale;
|
||||
const int32_t hotspot_x = int32_t(cursor->wl.image.hotspot_x) / scale;
|
||||
const int32_t hotspot_y = int32_t(cursor->wl.image.hotspot_y) / scale;
|
||||
wl_pointer_set_cursor(
|
||||
seat->wl.pointer, seat->pointer.serial, cursor->wl.surface_cursor, hotspot_x, hotspot_y);
|
||||
}
|
||||
|
||||
if (!seat->wp.tablet_tools.empty()) {
|
||||
const int scale = cursor->is_custom ? cursor->custom_scale : seat->tablet.theme_scale;
|
||||
const int32_t hotspot_x = int32_t(cursor->wl.image.hotspot_x) / scale;
|
||||
const int32_t hotspot_y = int32_t(cursor->wl.image.hotspot_y) / scale;
|
||||
for (zwp_tablet_tool_v2 *zwp_tablet_tool_v2 : seat->wp.tablet_tools) {
|
||||
GWL_TabletTool *tablet_tool = static_cast<GWL_TabletTool *>(
|
||||
zwp_tablet_tool_v2_get_user_data(zwp_tablet_tool_v2));
|
||||
zwp_tablet_tool_v2_set_cursor(zwp_tablet_tool_v2,
|
||||
seat->tablet.serial,
|
||||
tablet_tool->wl.surface_cursor,
|
||||
hotspot_x,
|
||||
hotspot_y);
|
||||
#ifdef USE_KDE_TABLET_HIDDEN_CURSOR_HACK
|
||||
wl_surface_commit(tablet_tool->wl.surface_cursor);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
cursor_anim_reset(seat);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hide the buffer defined by #cursor_buffer_set without changing anything else,
|
||||
* so #cursor_buffer_show can be used to display it again.
|
||||
*
|
||||
* The caller is responsible for setting `seat->cursor.visible`.
|
||||
*/
|
||||
static void cursor_buffer_hide(GWL_Seat *seat)
|
||||
{
|
||||
cursor_anim_end(seat);
|
||||
|
||||
wl_pointer_set_cursor(seat->wl.pointer, seat->pointer.serial, nullptr, 0, 0);
|
||||
for (zwp_tablet_tool_v2 *zwp_tablet_tool_v2 : seat->wp.tablet_tools) {
|
||||
zwp_tablet_tool_v2_set_cursor(zwp_tablet_tool_v2, seat->tablet.serial, nullptr, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Needed to ensure the cursor size is always a multiple of scale.
|
||||
*/
|
||||
static int cursor_buffer_compatible_scale_from_image(const wl_cursor_image *wl_image, int scale)
|
||||
{
|
||||
const int32_t image_size_x = int32_t(wl_image->width);
|
||||
const int32_t image_size_y = int32_t(wl_image->height);
|
||||
while (scale > 1) {
|
||||
if ((image_size_x % scale) == 0 && (image_size_y % scale) == 0) {
|
||||
break;
|
||||
}
|
||||
scale -= 1;
|
||||
}
|
||||
return scale;
|
||||
}
|
||||
|
||||
static void cursor_buffer_set_surface_impl(const wl_cursor_image *wl_image,
|
||||
wl_buffer *buffer,
|
||||
wl_surface *wl_surface,
|
||||
const int scale)
|
||||
{
|
||||
const int32_t image_size_x = int32_t(wl_image->width);
|
||||
const int32_t image_size_y = int32_t(wl_image->height);
|
||||
GHOST_ASSERT((image_size_x % scale) == 0 && (image_size_y % scale) == 0,
|
||||
"The size must be a multiple of the scale!");
|
||||
|
||||
wl_surface_set_buffer_scale(wl_surface, scale);
|
||||
wl_surface_attach(wl_surface, buffer, 0, 0);
|
||||
wl_surface_damage(wl_surface, 0, 0, image_size_x, image_size_y);
|
||||
wl_surface_commit(wl_surface);
|
||||
}
|
||||
|
||||
static void cursor_buffer_set(const GWL_Seat *seat,
|
||||
const wl_cursor_image *wl_image,
|
||||
wl_buffer *buffer)
|
||||
{
|
||||
const GWL_Cursor *cursor = &seat->cursor;
|
||||
const bool visible = (cursor->visible && cursor->is_hardware);
|
||||
|
||||
/* This is a requirement of WAYLAND, when this isn't the case,
|
||||
* it causes Blender's window to close intermittently. */
|
||||
if (seat->wl.pointer) {
|
||||
const int scale = cursor_buffer_compatible_scale_from_image(
|
||||
wl_image, cursor->is_custom ? cursor->custom_scale : seat->pointer.theme_scale);
|
||||
const int32_t hotspot_x = int32_t(wl_image->hotspot_x) / scale;
|
||||
const int32_t hotspot_y = int32_t(wl_image->hotspot_y) / scale;
|
||||
cursor_buffer_set_surface_impl(wl_image, buffer, cursor->wl.surface_cursor, scale);
|
||||
wl_pointer_set_cursor(seat->wl.pointer,
|
||||
seat->pointer.serial,
|
||||
visible ? cursor->wl.surface_cursor : nullptr,
|
||||
hotspot_x,
|
||||
hotspot_y);
|
||||
}
|
||||
|
||||
/* Set the cursor for all tablet tools as well. */
|
||||
if (!seat->wp.tablet_tools.empty()) {
|
||||
const int scale = cursor_buffer_compatible_scale_from_image(
|
||||
wl_image, cursor->is_custom ? cursor->custom_scale : seat->tablet.theme_scale);
|
||||
const int32_t hotspot_x = int32_t(wl_image->hotspot_x) / scale;
|
||||
const int32_t hotspot_y = int32_t(wl_image->hotspot_y) / scale;
|
||||
for (zwp_tablet_tool_v2 *zwp_tablet_tool_v2 : seat->wp.tablet_tools) {
|
||||
GWL_TabletTool *tablet_tool = static_cast<GWL_TabletTool *>(
|
||||
zwp_tablet_tool_v2_get_user_data(zwp_tablet_tool_v2));
|
||||
cursor_buffer_set_surface_impl(wl_image, buffer, tablet_tool->wl.surface_cursor, scale);
|
||||
zwp_tablet_tool_v2_set_cursor(zwp_tablet_tool_v2,
|
||||
seat->tablet.serial,
|
||||
visible ? tablet_tool->wl.surface_cursor : nullptr,
|
||||
hotspot_x,
|
||||
hotspot_y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void cursor_buffer_set_from_seat(GWL_Seat *seat)
|
||||
{
|
||||
const GWL_Cursor *cursor = &seat->cursor;
|
||||
cursor_anim_end(seat);
|
||||
cursor_buffer_set(seat, &cursor->wl.image, cursor->wl.buffer);
|
||||
cursor_anim_begin_if_needed(seat);
|
||||
}
|
||||
|
||||
enum eCursorSetMode {
|
||||
CURSOR_VISIBLE_ALWAYS_SET = 1,
|
||||
CURSOR_VISIBLE_ONLY_HIDE,
|
||||
CURSOR_VISIBLE_ONLY_SHOW,
|
||||
};
|
||||
|
||||
static void cursor_visible_set(GWL_Seat *seat,
|
||||
const bool visible,
|
||||
const bool is_hardware,
|
||||
const enum eCursorSetMode set_mode)
|
||||
{
|
||||
GWL_Cursor *cursor = &seat->cursor;
|
||||
const bool was_visible = cursor->is_hardware && cursor->visible;
|
||||
const bool use_visible = is_hardware && visible;
|
||||
|
||||
if (set_mode == CURSOR_VISIBLE_ALWAYS_SET) {
|
||||
/* Pass. */
|
||||
}
|
||||
else if (set_mode == CURSOR_VISIBLE_ONLY_SHOW) {
|
||||
if (!use_visible) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (set_mode == CURSOR_VISIBLE_ONLY_HIDE) {
|
||||
if (use_visible) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (use_visible) {
|
||||
if (!was_visible) {
|
||||
cursor_buffer_show(seat);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (was_visible) {
|
||||
cursor_buffer_hide(seat);
|
||||
}
|
||||
}
|
||||
cursor->visible = visible;
|
||||
cursor->is_hardware = is_hardware;
|
||||
}
|
||||
|
||||
static bool cursor_is_software(const GHOST_TGrabCursorMode mode, const bool use_software_confine)
|
||||
{
|
||||
if (mode == GHOST_kGrabWrap) {
|
||||
|
@ -7574,114 +7717,6 @@ static bool cursor_is_software(const GHOST_TGrabCursorMode mode, const bool use_
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool cursor_anim_check(GWL_Seat *seat)
|
||||
{
|
||||
const wl_cursor *wl_cursor = seat->cursor.wl.theme_cursor;
|
||||
if (!wl_cursor) {
|
||||
return false;
|
||||
}
|
||||
/* NOTE: return true to stress test animated cursor,
|
||||
* to ensure (otherwise rare) issues are triggered more frequently. */
|
||||
// return true;
|
||||
|
||||
return wl_cursor->image_count > 1;
|
||||
}
|
||||
|
||||
static void cursor_anim_begin(GWL_Seat *seat)
|
||||
{
|
||||
/* Caller must lock `server_mutex`. */
|
||||
GHOST_ASSERT(seat->cursor.anim_handle == nullptr, "Must be cleared");
|
||||
|
||||
/* Callback for updating the cursor animation. */
|
||||
auto cursor_anim_frame_step_fn =
|
||||
[](GWL_Seat *seat, GWL_Cursor_AnimHandle *anim_handle, int delay) {
|
||||
/* It's possible the `wl_cursor` is reloaded while the cursor is animating.
|
||||
* Don't access outside the lock, that's why the `delay` is passed in. */
|
||||
std::mutex *server_mutex = seat->system->server_mutex;
|
||||
int frame = 0;
|
||||
while (!anim_handle->exit_pending.load()) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(delay));
|
||||
if (!anim_handle->exit_pending.load()) {
|
||||
std::lock_guard lock_server_guard{*server_mutex};
|
||||
if (!anim_handle->exit_pending.load()) {
|
||||
const struct wl_cursor *wl_cursor = seat->cursor.wl.theme_cursor;
|
||||
frame = (frame + 1) % wl_cursor->image_count;
|
||||
wl_cursor_image *image = wl_cursor->images[frame];
|
||||
wl_buffer *buffer = wl_cursor_image_get_buffer(image);
|
||||
cursor_buffer_set(seat, image, buffer);
|
||||
delay = wl_cursor->images[frame]->delay;
|
||||
/* Without this the cursor won't update when other processes are occupied. */
|
||||
wl_display_flush(seat->system->wl_display_get());
|
||||
}
|
||||
}
|
||||
}
|
||||
delete anim_handle;
|
||||
};
|
||||
|
||||
/* Allocate so this can be set before the thread begins. */
|
||||
GWL_Cursor_AnimHandle *anim_handle = new GWL_Cursor_AnimHandle;
|
||||
seat->cursor.anim_handle = anim_handle;
|
||||
|
||||
const int delay = seat->cursor.wl.theme_cursor->images[0]->delay;
|
||||
std::thread cursor_anim_thread(cursor_anim_frame_step_fn, seat, anim_handle, delay);
|
||||
/* Application logic should take priority. */
|
||||
thread_set_min_priority(cursor_anim_thread);
|
||||
cursor_anim_thread.detach();
|
||||
}
|
||||
|
||||
static void cursor_anim_begin_if_needed(GWL_Seat *seat)
|
||||
{
|
||||
if (cursor_anim_check(seat)) {
|
||||
cursor_anim_begin(seat);
|
||||
}
|
||||
}
|
||||
|
||||
static void cursor_anim_end(GWL_Seat *seat)
|
||||
{
|
||||
GWL_Cursor *cursor = &seat->cursor;
|
||||
if (cursor->anim_handle) {
|
||||
GWL_Cursor_AnimHandle *anim_handle = cursor->anim_handle;
|
||||
cursor->anim_handle = nullptr;
|
||||
anim_handle->exit_pending.store(true);
|
||||
}
|
||||
}
|
||||
|
||||
static void cursor_anim_reset(GWL_Seat *seat)
|
||||
{
|
||||
cursor_anim_end(seat);
|
||||
cursor_anim_begin_if_needed(seat);
|
||||
}
|
||||
|
||||
static const wl_cursor *cursor_find_from_shape(GWL_Seat *seat,
|
||||
const GHOST_TStandardCursor shape,
|
||||
const char **r_cursor_name)
|
||||
{
|
||||
/* Caller must lock `server_mutex`. */
|
||||
GWL_Cursor *cursor = &seat->cursor;
|
||||
wl_cursor *wl_cursor = nullptr;
|
||||
|
||||
const char *cursor_name = ghost_wl_cursors.names[shape];
|
||||
if (cursor_name[0] != '\0') {
|
||||
if (!cursor->wl.theme) {
|
||||
/* The cursor wl_surface hasn't entered an output yet. Initialize theme with scale 1. */
|
||||
cursor->wl.theme = wl_cursor_theme_load(
|
||||
cursor->theme_name.c_str(), cursor->theme_size, seat->system->wl_shm_get());
|
||||
}
|
||||
|
||||
if (cursor->wl.theme) {
|
||||
wl_cursor = wl_cursor_theme_get_cursor(cursor->wl.theme, cursor_name);
|
||||
if (!wl_cursor) {
|
||||
GHOST_PRINT("cursor '" << cursor_name << "' does not exist" << std::endl);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (r_cursor_name && wl_cursor) {
|
||||
*r_cursor_name = cursor_name;
|
||||
}
|
||||
return wl_cursor;
|
||||
}
|
||||
|
||||
GHOST_TSuccess GHOST_SystemWayland::cursor_shape_set(const GHOST_TStandardCursor shape)
|
||||
{
|
||||
/* Caller must lock `server_mutex`. */
|
||||
|
@ -7692,7 +7727,7 @@ GHOST_TSuccess GHOST_SystemWayland::cursor_shape_set(const GHOST_TStandardCursor
|
|||
}
|
||||
|
||||
const char *cursor_name = nullptr;
|
||||
const wl_cursor *wl_cursor = cursor_find_from_shape(seat, shape, &cursor_name);
|
||||
const wl_cursor *wl_cursor = gwl_seat_cursor_find_from_shape(seat, shape, &cursor_name);
|
||||
if (wl_cursor == nullptr) {
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
@ -7711,7 +7746,7 @@ GHOST_TSuccess GHOST_SystemWayland::cursor_shape_set(const GHOST_TStandardCursor
|
|||
cursor->wl.theme_cursor = wl_cursor;
|
||||
cursor->wl.theme_cursor_name = cursor_name;
|
||||
|
||||
cursor_buffer_set_from_seat(seat);
|
||||
gwl_seat_cursor_buffer_set_current(seat);
|
||||
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
@ -7720,7 +7755,7 @@ GHOST_TSuccess GHOST_SystemWayland::cursor_shape_check(const GHOST_TStandardCurs
|
|||
{
|
||||
/* No need to lock `server_mutex`. */
|
||||
GWL_Seat *seat = gwl_display_seat_active_get(display_);
|
||||
const wl_cursor *wl_cursor = cursor_find_from_shape(seat, cursorShape, nullptr);
|
||||
const wl_cursor *wl_cursor = gwl_seat_cursor_find_from_shape(seat, cursorShape, nullptr);
|
||||
if (wl_cursor == nullptr) {
|
||||
return GHOST_kFailure;
|
||||
}
|
||||
|
@ -7800,7 +7835,7 @@ GHOST_TSuccess GHOST_SystemWayland::cursor_shape_custom_set(const uint8_t *bitma
|
|||
cursor->wl.theme_cursor = nullptr;
|
||||
cursor->wl.theme_cursor_name = nullptr;
|
||||
|
||||
cursor_buffer_set_from_seat(seat);
|
||||
gwl_seat_cursor_buffer_set_current(seat);
|
||||
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
@ -7840,7 +7875,7 @@ GHOST_TSuccess GHOST_SystemWayland::cursor_visibility_set(const bool visible)
|
|||
return GHOST_kFailure;
|
||||
}
|
||||
|
||||
cursor_visible_set(seat, visible, seat->cursor.is_hardware, CURSOR_VISIBLE_ALWAYS_SET);
|
||||
gwl_seat_cursor_visible_set(seat, visible, seat->cursor.is_hardware, CURSOR_VISIBLE_ALWAYS_SET);
|
||||
return GHOST_kSuccess;
|
||||
}
|
||||
|
||||
|
@ -8231,15 +8266,31 @@ uint64_t GHOST_SystemWayland::ms_from_input_time(const uint32_t timestamp_as_uin
|
|||
* use `timestamp_as_uint` to calculate an offset which is applied to future events.
|
||||
* This is updated because time may have passed between generating the time-stamp and `now`.
|
||||
* The method here is used by SDL. */
|
||||
uint64_t timestamp = uint64_t(timestamp_as_uint);
|
||||
|
||||
GWL_DisplayTimeStamp &input_timestamp = display_->input_timestamp;
|
||||
if (timestamp_as_uint < input_timestamp.last) {
|
||||
/* 32-bit timer rollover, bump the offset. */
|
||||
input_timestamp.offset += uint64_t(std::numeric_limits<uint32_t>::max()) + 1;
|
||||
if (UNLIKELY(timestamp_as_uint < input_timestamp.last)) {
|
||||
/* NOTE(@ideasman42): Sometimes event times are out of order,
|
||||
* while this should _never_ happen, it occasionally does when resizing the window then
|
||||
* clicking on the window with GNOME+LIBDECOR.
|
||||
* Accept events must occur within ~25 days, out-of-order time-stamps above this time-frame
|
||||
* will be treated as a wrapped integer. */
|
||||
if (input_timestamp.last - timestamp_as_uint > std::numeric_limits<uint32_t>::max() / 2) {
|
||||
/* Finally check to avoid invalid rollover,
|
||||
* ensure the rolled over time is closer to "now" than it is currently. */
|
||||
const uint64_t offset_test = input_timestamp.offset +
|
||||
uint64_t(std::numeric_limits<uint32_t>::max()) + 1;
|
||||
const uint64_t now = getMilliSeconds();
|
||||
if (sub_abs_u64(now, timestamp + offset_test) <
|
||||
sub_abs_u64(now, timestamp + input_timestamp.offset))
|
||||
{
|
||||
/* 32-bit timer rollover, bump the offset. */
|
||||
input_timestamp.offset = offset_test;
|
||||
}
|
||||
}
|
||||
}
|
||||
input_timestamp.last = timestamp_as_uint;
|
||||
|
||||
uint64_t timestamp = uint64_t(timestamp_as_uint);
|
||||
if (input_timestamp.exact_match) {
|
||||
timestamp += input_timestamp.offset;
|
||||
}
|
||||
|
@ -8432,7 +8483,7 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod
|
|||
|
||||
/* Only hide so the cursor is not made visible before it's location is restored.
|
||||
* This function is called again at the end of this function which only shows. */
|
||||
cursor_visible_set(seat, use_visible, is_hardware_cursor, CURSOR_VISIBLE_ONLY_HIDE);
|
||||
gwl_seat_cursor_visible_set(seat, use_visible, is_hardware_cursor, CURSOR_VISIBLE_ONLY_HIDE);
|
||||
|
||||
/* Switching from one grab mode to another,
|
||||
* in this case disable the current locks as it makes logic confusing,
|
||||
|
@ -8574,7 +8625,7 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod
|
|||
}
|
||||
|
||||
/* Only show so the cursor is made visible as the last step. */
|
||||
cursor_visible_set(seat, use_visible, is_hardware_cursor, CURSOR_VISIBLE_ONLY_SHOW);
|
||||
gwl_seat_cursor_visible_set(seat, use_visible, is_hardware_cursor, CURSOR_VISIBLE_ONLY_SHOW);
|
||||
|
||||
#ifdef USE_GNOME_CONFINE_HACK
|
||||
seat->use_pointer_software_confine = use_software_confine;
|
||||
|
|
|
@ -1785,8 +1785,6 @@ GHOST_TCapabilityFlag GHOST_SystemX11::getCapabilities() const
|
|||
{
|
||||
return GHOST_TCapabilityFlag(GHOST_CAPABILITY_FLAG_ALL &
|
||||
~(
|
||||
/* No support yet for desktop sampling. */
|
||||
GHOST_kCapabilityDesktopSample |
|
||||
/* No support yet for image copy/paste. */
|
||||
GHOST_kCapabilityClipboardImages |
|
||||
/* No support yet for IME input methods. */
|
||||
|
|
|
@ -62,29 +62,37 @@ static constexpr size_t base_dpi = 96;
|
|||
#endif
|
||||
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
struct WGL_LibDecor_Window {
|
||||
struct GWL_LibDecor_Window {
|
||||
libdecor_frame *frame = nullptr;
|
||||
|
||||
/**
|
||||
* Used at startup to set the initial window size
|
||||
* (before fractional scale information is available).
|
||||
* Store the last size applied from #libdecor_frame_interface::configure
|
||||
* This is meant to be equivalent of calling:
|
||||
* `libdecor_frame_get_content_width(frame)`
|
||||
* `libdecor_frame_get_content_height(frame)`
|
||||
* However these functions are only available via the plugin API,
|
||||
* so they need to be stored somewhere.
|
||||
*/
|
||||
int scale_fractional_from_output = 0;
|
||||
struct {
|
||||
int32_t size[2] = {0, 0};
|
||||
} applied;
|
||||
|
||||
/** The window has been configured (see #xdg_surface_ack_configure). */
|
||||
bool initial_configure_seen = false;
|
||||
/** The window size has been configured. */
|
||||
bool initial_configure_seen_with_size = false;
|
||||
/** The window state has been configured. */
|
||||
bool initial_state_seen = false;
|
||||
};
|
||||
|
||||
static void gwl_libdecor_window_destroy(WGL_LibDecor_Window *decor)
|
||||
static void gwl_libdecor_window_destroy(GWL_LibDecor_Window *decor)
|
||||
{
|
||||
libdecor_frame_unref(decor->frame);
|
||||
delete decor;
|
||||
}
|
||||
#endif /* WITH_GHOST_WAYLAND_LIBDECOR */
|
||||
|
||||
struct WGL_XDG_Decor_Window {
|
||||
struct GWL_XDG_Decor_Window {
|
||||
xdg_surface *surface = nullptr;
|
||||
zxdg_toplevel_decoration_v1 *toplevel_decor = nullptr;
|
||||
xdg_toplevel *toplevel = nullptr;
|
||||
|
@ -105,7 +113,7 @@ struct WGL_XDG_Decor_Window {
|
|||
bool initial_configure_seen = false;
|
||||
};
|
||||
|
||||
static void gwl_xdg_decor_window_destroy(WGL_XDG_Decor_Window *decor)
|
||||
static void gwl_xdg_decor_window_destroy(GWL_XDG_Decor_Window *decor)
|
||||
{
|
||||
if (decor->toplevel_decor) {
|
||||
zxdg_toplevel_decoration_v1_destroy(decor->toplevel_decor);
|
||||
|
@ -295,9 +303,9 @@ struct GWL_Window {
|
|||
std::vector<GWL_Output *> outputs;
|
||||
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
WGL_LibDecor_Window *libdecor = nullptr;
|
||||
GWL_LibDecor_Window *libdecor = nullptr;
|
||||
#endif
|
||||
WGL_XDG_Decor_Window *xdg_decor = nullptr;
|
||||
GWL_XDG_Decor_Window *xdg_decor = nullptr;
|
||||
|
||||
/**
|
||||
* The current value of frame, copied from `frame_pending` when applying updates.
|
||||
|
@ -352,13 +360,13 @@ static void gwl_window_title_set(GWL_Window *win, const char *title)
|
|||
{
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
if (use_libdecor) {
|
||||
WGL_LibDecor_Window &decor = *win->libdecor;
|
||||
GWL_LibDecor_Window &decor = *win->libdecor;
|
||||
libdecor_frame_set_title(decor.frame, title);
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
WGL_XDG_Decor_Window &decor = *win->xdg_decor;
|
||||
GWL_XDG_Decor_Window &decor = *win->xdg_decor;
|
||||
xdg_toplevel_set_title(decor.toplevel, title);
|
||||
}
|
||||
|
||||
|
@ -669,16 +677,9 @@ static void gwl_window_activate(GWL_Window *win)
|
|||
/** \name Internal #GWL_Window Pending Actions
|
||||
* \{ */
|
||||
|
||||
static void gwl_window_frame_pending_fractional_scale_set(GWL_Window *win,
|
||||
bool *r_surface_needs_commit,
|
||||
bool *r_surface_needs_buffer_scale)
|
||||
static void gwl_window_frame_pending_fractional_scale_set_notest(
|
||||
GWL_Window *win, bool *r_surface_needs_commit, bool *r_surface_needs_buffer_scale)
|
||||
{
|
||||
if (win->frame_pending.fractional_scale == win->frame.fractional_scale &&
|
||||
win->frame_pending.buffer_scale == win->frame.buffer_scale)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (win->frame_pending.fractional_scale) {
|
||||
win->frame.fractional_scale = win->frame_pending.fractional_scale;
|
||||
gwl_window_viewport_set(win, r_surface_needs_commit, r_surface_needs_buffer_scale);
|
||||
|
@ -706,6 +707,19 @@ static void gwl_window_frame_pending_fractional_scale_set(GWL_Window *win,
|
|||
}
|
||||
}
|
||||
|
||||
static void gwl_window_frame_pending_fractional_scale_set(GWL_Window *win,
|
||||
bool *r_surface_needs_commit,
|
||||
bool *r_surface_needs_buffer_scale)
|
||||
{
|
||||
if (win->frame_pending.fractional_scale == win->frame.fractional_scale &&
|
||||
win->frame_pending.buffer_scale == win->frame.buffer_scale)
|
||||
{
|
||||
return;
|
||||
}
|
||||
gwl_window_frame_pending_fractional_scale_set_notest(
|
||||
win, r_surface_needs_commit, r_surface_needs_buffer_scale);
|
||||
}
|
||||
|
||||
static void gwl_window_frame_pending_size_set(GWL_Window *win,
|
||||
bool *r_surface_needs_commit,
|
||||
bool *r_surface_needs_resize_for_backend,
|
||||
|
@ -830,7 +844,7 @@ static void gwl_window_frame_update_from_pending_no_lock(GWL_Window *win)
|
|||
}
|
||||
|
||||
if (win->xdg_decor) {
|
||||
WGL_XDG_Decor_Window &decor = *win->xdg_decor;
|
||||
GWL_XDG_Decor_Window &decor = *win->xdg_decor;
|
||||
if (decor.pending.ack_configure) {
|
||||
xdg_surface_ack_configure(decor.surface, decor.pending.ack_configure_serial);
|
||||
/* The XDG spec states a commit event is required after ACK configure. */
|
||||
|
@ -885,7 +899,7 @@ static void gwl_window_frame_update_from_pending_no_lock(GWL_Window *win)
|
|||
win->frame_pending.size[1] = 0;
|
||||
}
|
||||
|
||||
static void gwl_window_frame_update_from_pending(GWL_Window *win)
|
||||
[[maybe_unused]] static void gwl_window_frame_update_from_pending(GWL_Window *win)
|
||||
{
|
||||
#ifdef USE_EVENT_BACKGROUND_THREAD
|
||||
std::lock_guard lock_frame_guard{win->frame_pending_mutex};
|
||||
|
@ -1150,20 +1164,27 @@ static void libdecor_frame_handle_configure(libdecor_frame *frame,
|
|||
}();
|
||||
# endif
|
||||
|
||||
GWL_WindowFrame *frame_pending = &static_cast<GWL_Window *>(data)->frame_pending;
|
||||
GWL_WindowFrame &frame_pending = static_cast<GWL_Window *>(data)->frame_pending;
|
||||
|
||||
/* Set the size. */
|
||||
int size_decor[2] = {
|
||||
libdecor_frame_get_content_width(frame),
|
||||
libdecor_frame_get_content_height(frame),
|
||||
};
|
||||
int size_next[2] = {0, 0};
|
||||
bool has_size = false;
|
||||
|
||||
/* Keep track the current size of window decorations (last set by this function). */
|
||||
int size_decor[2] = {0, 0};
|
||||
|
||||
{
|
||||
const GWL_Window *win = static_cast<GWL_Window *>(data);
|
||||
const GWL_LibDecor_Window &decor = *win->libdecor;
|
||||
if (decor.initial_configure_seen_with_size) {
|
||||
size_decor[0] = decor.applied.size[0];
|
||||
size_decor[1] = decor.applied.size[1];
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
GWL_Window *win = static_cast<GWL_Window *>(data);
|
||||
const int fractional_scale = win->frame.fractional_scale ?
|
||||
win->frame.fractional_scale :
|
||||
win->libdecor->scale_fractional_from_output;
|
||||
const int fractional_scale = win->frame.fractional_scale;
|
||||
/* It's important `fractional_scale` has a fractional component or rounding up will fail
|
||||
* to produce the correct whole-number scale. */
|
||||
GHOST_ASSERT((fractional_scale == 0) ||
|
||||
|
@ -1177,26 +1198,24 @@ static void libdecor_frame_handle_configure(libdecor_frame *frame,
|
|||
const int scale_as_fractional = scale * FRACTIONAL_DENOMINATOR;
|
||||
if (libdecor_configuration_get_content_size(
|
||||
configuration, frame, &size_next[0], &size_next[1])) {
|
||||
if (win->frame.fractional_scale) {
|
||||
win->frame_pending.size[0] = gwl_window_fractional_to_viewport_round(win->frame,
|
||||
size_next[0]);
|
||||
win->frame_pending.size[1] = gwl_window_fractional_to_viewport_round(win->frame,
|
||||
size_next[1]);
|
||||
if (fractional_scale) {
|
||||
frame_pending.size[0] = gwl_window_fractional_to_viewport_round(win->frame, size_next[0]);
|
||||
frame_pending.size[1] = gwl_window_fractional_to_viewport_round(win->frame, size_next[1]);
|
||||
}
|
||||
else if (fractional_scale && (fractional_scale != (scale * FRACTIONAL_DENOMINATOR))) {
|
||||
/* The windows `preferred_scale` is not yet available,
|
||||
* set the size as if fractional scale is available. */
|
||||
frame_pending->size[0] = ((size_next[0] * scale) * fractional_scale) / scale_as_fractional;
|
||||
frame_pending->size[1] = ((size_next[1] * scale) * fractional_scale) / scale_as_fractional;
|
||||
frame_pending.size[0] = ((size_next[0] * scale) * fractional_scale) / scale_as_fractional;
|
||||
frame_pending.size[1] = ((size_next[1] * scale) * fractional_scale) / scale_as_fractional;
|
||||
}
|
||||
else {
|
||||
frame_pending->size[0] = size_next[0] * scale;
|
||||
frame_pending->size[1] = size_next[1] * scale;
|
||||
frame_pending.size[0] = size_next[0] * scale;
|
||||
frame_pending.size[1] = size_next[1] * scale;
|
||||
}
|
||||
|
||||
/* Account for buffer rounding requirement, once fractional scaling is enabled
|
||||
* the buffer scale will be 1, rounding is a requirement until then. */
|
||||
gwl_round_int2_by(frame_pending->size, win->frame.buffer_scale);
|
||||
gwl_round_int2_by(frame_pending.size, win->frame.buffer_scale);
|
||||
|
||||
has_size = true;
|
||||
}
|
||||
|
@ -1218,25 +1237,15 @@ static void libdecor_frame_handle_configure(libdecor_frame *frame,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
# ifdef USE_EVENT_BACKGROUND_THREAD
|
||||
/* NOTE(@ideasman42): when running from the event handling thread,
|
||||
* don't apply the new window size back to LIBDECOR, otherwise the window content
|
||||
* (which uses a deferred update) and the window get noticeably out of sync.
|
||||
* Rely on the new `frame_pending->size` to resize the window later. */
|
||||
if (is_main_thread == false) {
|
||||
has_size = false;
|
||||
}
|
||||
# endif
|
||||
}
|
||||
|
||||
/* Set the state. */
|
||||
{
|
||||
enum libdecor_window_state window_state;
|
||||
if (libdecor_configuration_get_window_state(configuration, &window_state)) {
|
||||
frame_pending->is_maximised = window_state & LIBDECOR_WINDOW_STATE_MAXIMIZED;
|
||||
frame_pending->is_fullscreen = window_state & LIBDECOR_WINDOW_STATE_FULLSCREEN;
|
||||
frame_pending->is_active = window_state & LIBDECOR_WINDOW_STATE_ACTIVE;
|
||||
frame_pending.is_maximised = window_state & LIBDECOR_WINDOW_STATE_MAXIMIZED;
|
||||
frame_pending.is_fullscreen = window_state & LIBDECOR_WINDOW_STATE_FULLSCREEN;
|
||||
frame_pending.is_active = window_state & LIBDECOR_WINDOW_STATE_ACTIVE;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1257,18 +1266,23 @@ static void libdecor_frame_handle_configure(libdecor_frame *frame,
|
|||
/* Commit the changes. */
|
||||
{
|
||||
GWL_Window *win = static_cast<GWL_Window *>(data);
|
||||
WGL_LibDecor_Window &decor = *win->libdecor;
|
||||
GWL_LibDecor_Window &decor = *win->libdecor;
|
||||
if (has_size == false) {
|
||||
/* Keep the current decor size. */
|
||||
size_next[0] = size_decor[0];
|
||||
size_next[1] = size_decor[1];
|
||||
}
|
||||
libdecor_state *state = libdecor_state_new(UNPACK2(size_next));
|
||||
libdecor_frame_commit(frame, state, configuration);
|
||||
libdecor_state_free(state);
|
||||
else {
|
||||
/* Store the new size for later reuse. */
|
||||
decor.applied.size[0] = size_next[0];
|
||||
decor.applied.size[1] = size_next[1];
|
||||
}
|
||||
|
||||
/* Only ever use this once, after initial creation:
|
||||
* #wp_fractional_scale_v1_listener::preferred_scale provides fractional scaling values. */
|
||||
decor.scale_fractional_from_output = 0;
|
||||
if (size_next[0] && size_next[1]) {
|
||||
libdecor_state *state = libdecor_state_new(UNPACK2(size_next));
|
||||
libdecor_frame_commit(frame, state, configuration);
|
||||
libdecor_state_free(state);
|
||||
}
|
||||
|
||||
if (decor.initial_configure_seen == false) {
|
||||
decor.initial_configure_seen = true;
|
||||
|
@ -1278,6 +1292,11 @@ static void libdecor_frame_handle_configure(libdecor_frame *frame,
|
|||
decor.initial_state_seen = true;
|
||||
}
|
||||
}
|
||||
if (decor.initial_configure_seen_with_size == false) {
|
||||
if (size_next[0] && size_next[1]) {
|
||||
decor.initial_configure_seen_with_size = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1489,25 +1508,18 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
|
|||
* So leave the buffer scaled up because there is no *guarantee* the fractional scaling support
|
||||
* will run which could result in an incorrect buffer scale. */
|
||||
int scale_fractional_from_output;
|
||||
window_->frame.buffer_scale = outputs_uniform_scale_or_default(
|
||||
system_->outputs_get(), 1, &scale_fractional_from_output);
|
||||
window_->frame_pending.buffer_scale = window_->frame.buffer_scale;
|
||||
const int buffer_scale_from_output = outputs_uniform_scale_or_default(
|
||||
system_->outputs_get(), 0, &scale_fractional_from_output);
|
||||
|
||||
window_->frame.size[0] = int32_t(width);
|
||||
window_->frame.size[1] = int32_t(height);
|
||||
|
||||
/* The window surface must be rounded to the scale,
|
||||
* failing to do so causes the WAYLAND-server to close the window immediately. */
|
||||
gwl_round_int2_by(window_->frame.size, window_->frame.buffer_scale);
|
||||
|
||||
window_->is_dialog = is_dialog;
|
||||
|
||||
/* Window surfaces. */
|
||||
window_->wl.surface = wl_compositor_create_surface(system_->wl_compositor_get());
|
||||
ghost_wl_surface_tag(window_->wl.surface);
|
||||
|
||||
wl_surface_set_buffer_scale(window_->wl.surface, window_->frame.buffer_scale);
|
||||
|
||||
wl_surface_add_listener(window_->wl.surface, &wl_surface_listener, window_);
|
||||
|
||||
wp_fractional_scale_manager_v1 *fractional_scale_manager =
|
||||
|
@ -1529,8 +1541,8 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
|
|||
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
if (use_libdecor) {
|
||||
window_->libdecor = new WGL_LibDecor_Window;
|
||||
WGL_LibDecor_Window &decor = *window_->libdecor;
|
||||
window_->libdecor = new GWL_LibDecor_Window;
|
||||
GWL_LibDecor_Window &decor = *window_->libdecor;
|
||||
|
||||
/* create window decorations */
|
||||
decor.frame = libdecor_decorate(
|
||||
|
@ -1541,7 +1553,7 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
|
|||
libdecor_frame_set_app_id(decor.frame, xdg_app_id);
|
||||
|
||||
if (parentWindow) {
|
||||
WGL_LibDecor_Window &decor_parent =
|
||||
GWL_LibDecor_Window &decor_parent =
|
||||
*dynamic_cast<const GHOST_WindowWayland *>(parentWindow)->window_->libdecor;
|
||||
libdecor_frame_set_parent(decor.frame, decor_parent.frame);
|
||||
}
|
||||
|
@ -1549,8 +1561,8 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
|
|||
else
|
||||
#endif
|
||||
{
|
||||
window_->xdg_decor = new WGL_XDG_Decor_Window;
|
||||
WGL_XDG_Decor_Window &decor = *window_->xdg_decor;
|
||||
window_->xdg_decor = new GWL_XDG_Decor_Window;
|
||||
GWL_XDG_Decor_Window &decor = *window_->xdg_decor;
|
||||
decor.surface = xdg_wm_base_get_xdg_surface(system_->xdg_decor_shell_get(),
|
||||
window_->wl.surface);
|
||||
decor.toplevel = xdg_surface_get_toplevel(decor.surface);
|
||||
|
@ -1562,7 +1574,7 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
|
|||
xdg_toplevel_add_listener(decor.toplevel, &xdg_toplevel_listener, window_);
|
||||
|
||||
if (parentWindow && is_dialog) {
|
||||
WGL_XDG_Decor_Window &decor_parent =
|
||||
GWL_XDG_Decor_Window &decor_parent =
|
||||
*dynamic_cast<const GHOST_WindowWayland *>(parentWindow)->window_->xdg_decor;
|
||||
xdg_toplevel_set_parent(decor.toplevel, decor_parent.toplevel);
|
||||
}
|
||||
|
@ -1578,15 +1590,131 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
|
|||
/* Causes a glitch with `libdecor` for some reason. */
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
if (use_libdecor) {
|
||||
WGL_LibDecor_Window &decor = *window_->libdecor;
|
||||
if (fractional_scale_manager &&
|
||||
(gwl_round_int_test(scale_fractional_from_output, FRACTIONAL_DENOMINATOR) == false))
|
||||
{
|
||||
decor.scale_fractional_from_output = scale_fractional_from_output;
|
||||
/* Pass. */
|
||||
}
|
||||
else
|
||||
#endif /* WITH_GHOST_WAYLAND_LIBDECOR */
|
||||
{
|
||||
GWL_XDG_Decor_Window &decor = *window_->xdg_decor;
|
||||
|
||||
if (system_->xdg_decor_manager_get()) {
|
||||
decor.toplevel_decor = zxdg_decoration_manager_v1_get_toplevel_decoration(
|
||||
system_->xdg_decor_manager_get(), decor.toplevel);
|
||||
zxdg_toplevel_decoration_v1_add_listener(
|
||||
decor.toplevel_decor, &xdg_toplevel_decoration_v1_listener, window_);
|
||||
zxdg_toplevel_decoration_v1_set_mode(decor.toplevel_decor,
|
||||
ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
|
||||
}
|
||||
|
||||
/* Commit needed to so configure callback runs. */
|
||||
wl_surface_commit(window_->wl.surface);
|
||||
while (!decor.initial_configure_seen) {
|
||||
wl_display_flush(system->wl_display_get());
|
||||
wl_display_dispatch(system->wl_display_get());
|
||||
}
|
||||
}
|
||||
|
||||
/* If the scale is known early, setup the window scale.
|
||||
* Otherwise accept an unsightly flicker once the outputs scale can be found. */
|
||||
int early_buffer_scale = 0;
|
||||
int early_fractional_scale = 0;
|
||||
|
||||
if (const int test_fractional_scale =
|
||||
fractional_scale_manager ? (window_->frame_pending.fractional_scale_preferred ?
|
||||
window_->frame_pending.fractional_scale_preferred :
|
||||
scale_fractional_from_output) :
|
||||
0)
|
||||
{
|
||||
if (!gwl_round_int_test(test_fractional_scale, FRACTIONAL_DENOMINATOR)) {
|
||||
early_fractional_scale = test_fractional_scale;
|
||||
}
|
||||
else {
|
||||
/* Rounded, use simple integer buffer scaling. */
|
||||
early_buffer_scale = test_fractional_scale / FRACTIONAL_DENOMINATOR;
|
||||
early_fractional_scale = 0;
|
||||
}
|
||||
}
|
||||
else if (buffer_scale_from_output) {
|
||||
early_buffer_scale = buffer_scale_from_output;
|
||||
}
|
||||
|
||||
if (early_fractional_scale != 0) {
|
||||
/* Fractional scale is known. */
|
||||
|
||||
window_->frame.fractional_scale_preferred = early_fractional_scale;
|
||||
window_->frame.fractional_scale = early_fractional_scale;
|
||||
window_->frame.buffer_scale = 1;
|
||||
|
||||
window_->frame_pending.fractional_scale_preferred = early_fractional_scale;
|
||||
window_->frame_pending.fractional_scale = early_fractional_scale;
|
||||
window_->frame_pending.buffer_scale = 1;
|
||||
|
||||
/* The scale is considered initialized now. */
|
||||
window_->frame_pending.is_scale_init = true;
|
||||
|
||||
/* Always commit and set the scale. */
|
||||
bool surface_needs_commit_dummy = false, surface_needs_buffer_scale_dummy = false;
|
||||
gwl_window_frame_pending_fractional_scale_set_notest(
|
||||
window_, &surface_needs_commit_dummy, &surface_needs_buffer_scale_dummy);
|
||||
}
|
||||
else if (early_buffer_scale != 0) {
|
||||
/* Non-fractional scale is known. */
|
||||
|
||||
/* No fractional scale, simple initialization. */
|
||||
window_->frame.buffer_scale = early_buffer_scale;
|
||||
window_->frame_pending.buffer_scale = early_buffer_scale;
|
||||
|
||||
/* The scale is considered initialized now. */
|
||||
window_->frame_pending.is_scale_init = true;
|
||||
|
||||
/* The window surface must be rounded to the scale,
|
||||
* failing to do so causes the WAYLAND-server to close the window immediately. */
|
||||
gwl_round_int2_by(window_->frame.size, window_->frame.buffer_scale);
|
||||
}
|
||||
else {
|
||||
/* Scale isn't known (the windows size may flicker when #outputs_changed_update_scale runs). */
|
||||
window_->frame.buffer_scale = 1;
|
||||
window_->frame_pending.buffer_scale = 1;
|
||||
GHOST_ASSERT(window_->frame_pending.is_scale_init == false,
|
||||
"An initialized scale is not expected");
|
||||
}
|
||||
|
||||
if (window_->frame_pending.is_scale_init) {
|
||||
/* If the output scale changes here it means the scale settings were not properly set. */
|
||||
GHOST_ASSERT(outputs_changed_update_scale() == false,
|
||||
"Fractional scale was not properly initialized");
|
||||
}
|
||||
|
||||
wl_surface_set_buffer_scale(window_->wl.surface, window_->frame.buffer_scale);
|
||||
|
||||
/* Postpone binding the buffer until after it's decor has been configured:
|
||||
* - Ensure the window is sized properly (with XDG window decorations), see: #113059.
|
||||
* - Avoids flickering on startup.
|
||||
*/
|
||||
#ifdef WITH_OPENGL_BACKEND
|
||||
if (type == GHOST_kDrawingContextTypeOpenGL) {
|
||||
window_->backend.egl_window = wl_egl_window_create(
|
||||
window_->wl.surface, int(window_->frame.size[0]), int(window_->frame.size[1]));
|
||||
}
|
||||
#endif
|
||||
#ifdef WITH_VULKAN_BACKEND
|
||||
if (type == GHOST_kDrawingContextTypeVulkan) {
|
||||
window_->backend.vulkan_window_info = new GHOST_ContextVK_WindowInfo;
|
||||
window_->backend.vulkan_window_info->size[0] = window_->frame.size[0];
|
||||
window_->backend.vulkan_window_info->size[1] = window_->frame.size[1];
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Drawing context. */
|
||||
if (setDrawingContextType(type) == GHOST_kFailure) {
|
||||
GHOST_PRINT("Failed to create drawing context" << std::endl);
|
||||
}
|
||||
|
||||
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
|
||||
if (use_libdecor) {
|
||||
/* Commit needed so the top-level callbacks run (and `toplevel` can be accessed). */
|
||||
wl_surface_commit(window_->wl.surface);
|
||||
GWL_LibDecor_Window &decor = *window_->libdecor;
|
||||
|
||||
/* Additional round-trip is needed to ensure `xdg_toplevel` is set. */
|
||||
wl_display_roundtrip(system_->wl_display_get());
|
||||
|
@ -1618,53 +1746,14 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
|
|||
else
|
||||
#endif /* WITH_GHOST_WAYLAND_LIBDECOR */
|
||||
{
|
||||
WGL_XDG_Decor_Window &decor = *window_->xdg_decor;
|
||||
|
||||
if (system_->xdg_decor_manager_get()) {
|
||||
decor.toplevel_decor = zxdg_decoration_manager_v1_get_toplevel_decoration(
|
||||
system_->xdg_decor_manager_get(), decor.toplevel);
|
||||
zxdg_toplevel_decoration_v1_add_listener(
|
||||
decor.toplevel_decor, &xdg_toplevel_decoration_v1_listener, window_);
|
||||
zxdg_toplevel_decoration_v1_set_mode(decor.toplevel_decor,
|
||||
ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE);
|
||||
}
|
||||
|
||||
gwl_window_state_set(window_, state);
|
||||
|
||||
/* Commit needed to so configure callback runs. */
|
||||
wl_surface_commit(window_->wl.surface);
|
||||
while (!decor.initial_configure_seen) {
|
||||
wl_display_flush(system->wl_display_get());
|
||||
wl_display_dispatch(system->wl_display_get());
|
||||
}
|
||||
}
|
||||
|
||||
/* Postpone binding the buffer until after it's decor has been configured:
|
||||
* - Ensure the window is sized properly (with XDG window decorations), see: #113059.
|
||||
* - Avoids flickering on startup.
|
||||
*/
|
||||
#ifdef WITH_OPENGL_BACKEND
|
||||
if (type == GHOST_kDrawingContextTypeOpenGL) {
|
||||
window_->backend.egl_window = wl_egl_window_create(
|
||||
window_->wl.surface, int(window_->frame.size[0]), int(window_->frame.size[1]));
|
||||
}
|
||||
#endif
|
||||
#ifdef WITH_VULKAN_BACKEND
|
||||
if (type == GHOST_kDrawingContextTypeVulkan) {
|
||||
window_->backend.vulkan_window_info = new GHOST_ContextVK_WindowInfo;
|
||||
window_->backend.vulkan_window_info->size[0] = window_->frame.size[0];
|
||||
window_->backend.vulkan_window_info->size[1] = window_->frame.size[1];
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Commit after setting the buffer. */
|
||||
/* Commit after setting the buffer.
|
||||
* While postponing until after the buffer drawing is context is set
|
||||
* isn't essential, it reduces flickering. */
|
||||
wl_surface_commit(window_->wl.surface);
|
||||
|
||||
/* Drawing context. */
|
||||
if (setDrawingContextType(type) == GHOST_kFailure) {
|
||||
GHOST_PRINT("Failed to create drawing context" << std::endl);
|
||||
}
|
||||
|
||||
/* Set swap interval to 0 to prevent blocking. */
|
||||
setSwapInterval(0);
|
||||
}
|
||||
|
|
|
@ -51,6 +51,9 @@
|
|||
*
|
||||
* - Lock #GWL_Window.frame_pending_mutex before changing window size & frame settings,
|
||||
* this is flushed in #GHOST_WindowWayland::pending_actions_handle.
|
||||
*
|
||||
* \note Keep this define as it can be useful to disable threading when troubleshooting
|
||||
* issues with events.
|
||||
*/
|
||||
#define USE_EVENT_BACKGROUND_THREAD
|
||||
|
||||
|
|
|
@ -10,11 +10,11 @@ set(INC_SYS
|
|||
)
|
||||
|
||||
set(SRC
|
||||
opensubdiv_capi.h
|
||||
opensubdiv_capi_type.h
|
||||
opensubdiv_converter_capi.h
|
||||
opensubdiv_evaluator_capi.h
|
||||
opensubdiv_topology_refiner_capi.h
|
||||
opensubdiv_capi.hh
|
||||
opensubdiv_capi_type.hh
|
||||
opensubdiv_converter_capi.hh
|
||||
opensubdiv_evaluator_capi.hh
|
||||
opensubdiv_topology_refiner_capi.hh
|
||||
)
|
||||
|
||||
set(LIB
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#include "opensubdiv_capi.h"
|
||||
#include "opensubdiv_capi.hh"
|
||||
#include "opensubdiv/version.h"
|
||||
#ifdef _MSC_VER
|
||||
# include <iso646.h>
|
||||
|
|
|
@ -14,7 +14,7 @@
|
|||
#include <opensubdiv/sdc/options.h>
|
||||
#include <opensubdiv/sdc/types.h>
|
||||
|
||||
#include "opensubdiv_capi_type.h"
|
||||
#include "opensubdiv_capi_type.hh"
|
||||
|
||||
struct OpenSubdiv_Converter;
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
#include "internal/base/type.h"
|
||||
#include "internal/evaluator/evaluator_impl.h"
|
||||
|
||||
#include "opensubdiv_evaluator_capi.h"
|
||||
#include "opensubdiv_evaluator_capi.hh"
|
||||
|
||||
using OpenSubdiv::Far::PatchTable;
|
||||
using OpenSubdiv::Far::StencilTable;
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
|
||||
#include "internal/evaluator/eval_output_gpu.h"
|
||||
|
||||
#include "opensubdiv_evaluator_capi.h"
|
||||
#include "opensubdiv_evaluator_capi.hh"
|
||||
|
||||
using OpenSubdiv::Osd::PatchArray;
|
||||
using OpenSubdiv::Osd::PatchArrayVector;
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
|
||||
#include "internal/base/memory.h"
|
||||
|
||||
#include "opensubdiv_capi_type.h"
|
||||
#include "opensubdiv_capi_type.hh"
|
||||
|
||||
struct OpenSubdiv_EvaluatorCacheImpl {
|
||||
public:
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* Author: Sergey Sharybin. */
|
||||
|
||||
#include "opensubdiv_evaluator_capi.h"
|
||||
#include "opensubdiv_evaluator_capi.hh"
|
||||
|
||||
#include <opensubdiv/osd/glslPatchShaderSource.h>
|
||||
|
||||
|
|
|
@ -28,8 +28,8 @@
|
|||
#include "internal/evaluator/evaluator_cache_impl.h"
|
||||
#include "internal/evaluator/patch_map.h"
|
||||
#include "internal/topology/topology_refiner_impl.h"
|
||||
#include "opensubdiv_evaluator_capi.h"
|
||||
#include "opensubdiv_topology_refiner_capi.h"
|
||||
#include "opensubdiv_evaluator_capi.hh"
|
||||
#include "opensubdiv_topology_refiner_capi.hh"
|
||||
|
||||
using OpenSubdiv::Far::PatchTable;
|
||||
using OpenSubdiv::Far::PatchTableFactory;
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
|
||||
#include "internal/base/memory.h"
|
||||
|
||||
#include "opensubdiv_capi_type.h"
|
||||
#include "opensubdiv_capi_type.hh"
|
||||
|
||||
struct OpenSubdiv_Buffer;
|
||||
struct OpenSubdiv_EvaluatorCacheImpl;
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
#include "internal/base/type.h"
|
||||
|
||||
#include "opensubdiv_converter_capi.h"
|
||||
#include "opensubdiv_converter_capi.hh"
|
||||
|
||||
namespace blender {
|
||||
namespace opensubdiv {
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* Author: Sergey Sharybin. */
|
||||
|
||||
#include "opensubdiv_topology_refiner_capi.h"
|
||||
#include "opensubdiv_topology_refiner_capi.hh"
|
||||
|
||||
#include "MEM_guardedalloc.h"
|
||||
#include "internal/base/type_convert.h"
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
#include "internal/base/type_convert.h"
|
||||
#include "internal/topology/mesh_topology.h"
|
||||
|
||||
#include "opensubdiv_converter_capi.h"
|
||||
#include "opensubdiv_converter_capi.hh"
|
||||
|
||||
using blender::opensubdiv::min;
|
||||
using blender::opensubdiv::stack;
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
|
||||
#include "internal/base/memory.h"
|
||||
#include "internal/topology/mesh_topology.h"
|
||||
#include "opensubdiv_topology_refiner_capi.h"
|
||||
#include "opensubdiv_topology_refiner_capi.hh"
|
||||
|
||||
struct OpenSubdiv_Converter;
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
#include "internal/topology/mesh_topology.h"
|
||||
#include "internal/topology/topology_refiner_impl.h"
|
||||
|
||||
#include "opensubdiv_converter_capi.h"
|
||||
#include "opensubdiv_converter_capi.hh"
|
||||
|
||||
namespace blender {
|
||||
namespace opensubdiv {
|
||||
|
|
|
@ -1,28 +0,0 @@
|
|||
/* SPDX-FileCopyrightText: 2013 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*
|
||||
* Author: Sergey Sharybin. */
|
||||
|
||||
#ifndef OPENSUBDIV_CAPI_H_
|
||||
#define OPENSUBDIV_CAPI_H_
|
||||
|
||||
#include "opensubdiv_capi_type.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
// Global initialization/deinitialization.
|
||||
//
|
||||
// Supposed to be called from main thread.
|
||||
void openSubdiv_init(void);
|
||||
void openSubdiv_cleanup(void);
|
||||
|
||||
int openSubdiv_getVersionHex(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // OPENSUBDIV_CAPI_H_
|
|
@ -0,0 +1,15 @@
|
|||
/* SPDX-FileCopyrightText: 2013 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "opensubdiv_capi_type.hh"
|
||||
|
||||
// Global initialization/deinitialization.
|
||||
//
|
||||
// Supposed to be called from main thread.
|
||||
void openSubdiv_init();
|
||||
void openSubdiv_cleanup();
|
||||
|
||||
int openSubdiv_getVersionHex();
|
|
@ -1,54 +1,41 @@
|
|||
/* SPDX-FileCopyrightText: 2013 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*
|
||||
* Author: Sergey Sharybin. */
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#ifndef OPENSUBDIV_CAPI_TYPES_H_
|
||||
#define OPENSUBDIV_CAPI_TYPES_H_
|
||||
#pragma once
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum eOpenSubdivEvaluator {
|
||||
enum eOpenSubdivEvaluator {
|
||||
OPENSUBDIV_EVALUATOR_CPU = 0,
|
||||
OPENSUBDIV_EVALUATOR_GPU = 1,
|
||||
} eOpenSubdivEvaluator;
|
||||
};
|
||||
|
||||
typedef enum OpenSubdiv_SchemeType {
|
||||
enum OpenSubdiv_SchemeType {
|
||||
OSD_SCHEME_BILINEAR,
|
||||
OSD_SCHEME_CATMARK,
|
||||
OSD_SCHEME_LOOP,
|
||||
} OpenSubdiv_SchemeType;
|
||||
};
|
||||
|
||||
typedef enum OpenSubdiv_VtxBoundaryInterpolation {
|
||||
enum OpenSubdiv_VtxBoundaryInterpolation {
|
||||
// Do not interpolate boundaries
|
||||
OSD_VTX_BOUNDARY_NONE,
|
||||
// Sharpen edges.
|
||||
OSD_VTX_BOUNDARY_EDGE_ONLY,
|
||||
// sharpen edges and corners,
|
||||
OSD_VTX_BOUNDARY_EDGE_AND_CORNER,
|
||||
} OpenSubdiv_VtxBoundaryInterpolation;
|
||||
};
|
||||
|
||||
typedef enum OpenSubdiv_FVarLinearInterpolation {
|
||||
enum OpenSubdiv_FVarLinearInterpolation {
|
||||
OSD_FVAR_LINEAR_INTERPOLATION_NONE,
|
||||
OSD_FVAR_LINEAR_INTERPOLATION_CORNERS_ONLY,
|
||||
OSD_FVAR_LINEAR_INTERPOLATION_CORNERS_PLUS1,
|
||||
OSD_FVAR_LINEAR_INTERPOLATION_CORNERS_PLUS2,
|
||||
OSD_FVAR_LINEAR_INTERPOLATION_BOUNDARIES,
|
||||
OSD_FVAR_LINEAR_INTERPOLATION_ALL,
|
||||
} OpenSubdiv_FVarLinearInterpolation;
|
||||
};
|
||||
|
||||
typedef struct OpenSubdiv_PatchCoord {
|
||||
struct OpenSubdiv_PatchCoord {
|
||||
int ptex_face;
|
||||
|
||||
// Parametric location on patch.
|
||||
float u, v;
|
||||
} OpenSubdiv_PatchCoord;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // OPENSUBDIV_CAPI_TYPES_H_
|
||||
};
|
|
@ -1,27 +1,20 @@
|
|||
/* SPDX-FileCopyrightText: 2015 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*
|
||||
* Author: Sergey Sharybin. */
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#ifndef OPENSUBDIV_CONVERTER_CAPI_H_
|
||||
#define OPENSUBDIV_CONVERTER_CAPI_H_
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h> // for bool
|
||||
#include <cstdint> // for bool
|
||||
|
||||
#include "opensubdiv_capi_type.h"
|
||||
#include "opensubdiv_capi_type.hh"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct OpenSubdiv_Converter {
|
||||
OpenSubdiv_SchemeType (*getSchemeType)(const struct OpenSubdiv_Converter *converter);
|
||||
struct OpenSubdiv_Converter {
|
||||
OpenSubdiv_SchemeType (*getSchemeType)(const OpenSubdiv_Converter *converter);
|
||||
|
||||
OpenSubdiv_VtxBoundaryInterpolation (*getVtxBoundaryInterpolation)(
|
||||
const struct OpenSubdiv_Converter *converter);
|
||||
const OpenSubdiv_Converter *converter);
|
||||
OpenSubdiv_FVarLinearInterpolation (*getFVarLinearInterpolation)(
|
||||
const struct OpenSubdiv_Converter *converter);
|
||||
const OpenSubdiv_Converter *converter);
|
||||
|
||||
// Denotes whether this converter specifies full topology, which includes
|
||||
// vertices, edges, faces, vertices+edges of a face and edges/faces of a
|
||||
|
@ -32,29 +25,29 @@ typedef struct OpenSubdiv_Converter {
|
|||
// NOTE: Even if converter does not provide full topology, it still needs
|
||||
// to provide number of edges and vertices-of-edge. Those are used to assign
|
||||
// topology tags.
|
||||
bool (*specifiesFullTopology)(const struct OpenSubdiv_Converter *converter);
|
||||
bool (*specifiesFullTopology)(const OpenSubdiv_Converter *converter);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Global geometry counters.
|
||||
|
||||
// Number of faces/edges/vertices in the base mesh.
|
||||
int (*getNumFaces)(const struct OpenSubdiv_Converter *converter);
|
||||
int (*getNumEdges)(const struct OpenSubdiv_Converter *converter);
|
||||
int (*getNumVertices)(const struct OpenSubdiv_Converter *converter);
|
||||
int (*getNumFaces)(const OpenSubdiv_Converter *converter);
|
||||
int (*getNumEdges)(const OpenSubdiv_Converter *converter);
|
||||
int (*getNumVertices)(const OpenSubdiv_Converter *converter);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Face relationships.
|
||||
|
||||
// Number of vertices the face consists of.
|
||||
int (*getNumFaceVertices)(const struct OpenSubdiv_Converter *converter, const int face_index);
|
||||
int (*getNumFaceVertices)(const OpenSubdiv_Converter *converter, const int face_index);
|
||||
// Array of vertex indices the face consists of.
|
||||
void (*getFaceVertices)(const struct OpenSubdiv_Converter *converter,
|
||||
void (*getFaceVertices)(const OpenSubdiv_Converter *converter,
|
||||
const int face_index,
|
||||
int *face_vertices);
|
||||
// Array of edge indices the face consists of.
|
||||
// Aligned with the vertex indices array, edge i connects face vertex i
|
||||
// with face index i+1.
|
||||
void (*getFaceEdges)(const struct OpenSubdiv_Converter *converter,
|
||||
void (*getFaceEdges)(const OpenSubdiv_Converter *converter,
|
||||
const int face_index,
|
||||
int *face_edges);
|
||||
|
||||
|
@ -62,42 +55,38 @@ typedef struct OpenSubdiv_Converter {
|
|||
// Edge relationships.
|
||||
|
||||
// Vertices the edge consists of.
|
||||
void (*getEdgeVertices)(const struct OpenSubdiv_Converter *converter,
|
||||
void (*getEdgeVertices)(const OpenSubdiv_Converter *converter,
|
||||
const int edge_index,
|
||||
int edge_vertices[2]);
|
||||
// Number of faces which are sharing the given edge.
|
||||
int (*getNumEdgeFaces)(const struct OpenSubdiv_Converter *converter, const int edge_index);
|
||||
int (*getNumEdgeFaces)(const OpenSubdiv_Converter *converter, const int edge_index);
|
||||
// Array of face indices which are sharing the given edge.
|
||||
void (*getEdgeFaces)(const struct OpenSubdiv_Converter *converter,
|
||||
const int edge,
|
||||
int *edge_faces);
|
||||
void (*getEdgeFaces)(const OpenSubdiv_Converter *converter, const int edge, int *edge_faces);
|
||||
// Edge sharpness (aka crease).
|
||||
float (*getEdgeSharpness)(const struct OpenSubdiv_Converter *converter, const int edge_index);
|
||||
float (*getEdgeSharpness)(const OpenSubdiv_Converter *converter, const int edge_index);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Vertex relationships.
|
||||
|
||||
// Number of edges which are adjacent to the given vertex.
|
||||
int (*getNumVertexEdges)(const struct OpenSubdiv_Converter *converter, const int vertex_index);
|
||||
int (*getNumVertexEdges)(const OpenSubdiv_Converter *converter, const int vertex_index);
|
||||
// Array fo edge indices which are adjacent to the given vertex.
|
||||
void (*getVertexEdges)(const struct OpenSubdiv_Converter *converter,
|
||||
void (*getVertexEdges)(const OpenSubdiv_Converter *converter,
|
||||
const int vertex_index,
|
||||
int *vertex_edges);
|
||||
// Number of faces which are adjacent to the given vertex.
|
||||
int (*getNumVertexFaces)(const struct OpenSubdiv_Converter *converter, const int vertex_index);
|
||||
int (*getNumVertexFaces)(const OpenSubdiv_Converter *converter, const int vertex_index);
|
||||
// Array fo face indices which are adjacent to the given vertex.
|
||||
void (*getVertexFaces)(const struct OpenSubdiv_Converter *converter,
|
||||
void (*getVertexFaces)(const OpenSubdiv_Converter *converter,
|
||||
const int vertex_index,
|
||||
int *vertex_faces);
|
||||
|
||||
// Check whether vertex is to be marked as an infinite sharp.
|
||||
// This is a way to make sharp vertices which are adjacent to a loose edges.
|
||||
bool (*isInfiniteSharpVertex)(const struct OpenSubdiv_Converter *converter,
|
||||
const int vertex_index);
|
||||
bool (*isInfiniteSharpVertex)(const OpenSubdiv_Converter *converter, const int vertex_index);
|
||||
|
||||
// If vertex is not infinitely sharp, this is its actual sharpness.
|
||||
float (*getVertexSharpness)(const struct OpenSubdiv_Converter *converter,
|
||||
const int vertex_index);
|
||||
float (*getVertexSharpness)(const OpenSubdiv_Converter *converter, const int vertex_index);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Face-varying data.
|
||||
|
@ -106,7 +95,7 @@ typedef struct OpenSubdiv_Converter {
|
|||
// UV coordinates.
|
||||
|
||||
// Number of UV layers.
|
||||
int (*getNumUVLayers)(const struct OpenSubdiv_Converter *converter);
|
||||
int (*getNumUVLayers)(const OpenSubdiv_Converter *converter);
|
||||
|
||||
// We need some corner connectivity information, which might not be trivial
|
||||
// to be gathered (might require multiple matching calculations per corver
|
||||
|
@ -116,27 +105,21 @@ typedef struct OpenSubdiv_Converter {
|
|||
// complex complex-to-calculate information.
|
||||
// finish() is called after converter is done porting UV layer to OpenSubdiv,
|
||||
// allowing to free cached data.
|
||||
void (*precalcUVLayer)(const struct OpenSubdiv_Converter *converter, const int layer_index);
|
||||
void (*finishUVLayer)(const struct OpenSubdiv_Converter *converter);
|
||||
void (*precalcUVLayer)(const OpenSubdiv_Converter *converter, const int layer_index);
|
||||
void (*finishUVLayer)(const OpenSubdiv_Converter *converter);
|
||||
|
||||
// Get number of UV coordinates in the current layer (layer which was
|
||||
// specified in precalcUVLayer().
|
||||
int (*getNumUVCoordinates)(const struct OpenSubdiv_Converter *converter);
|
||||
int (*getNumUVCoordinates)(const OpenSubdiv_Converter *converter);
|
||||
// For the given face index and its corner (known as loop in Blender)
|
||||
// get corresponding UV coordinate index.
|
||||
int (*getFaceCornerUVIndex)(const struct OpenSubdiv_Converter *converter,
|
||||
int (*getFaceCornerUVIndex)(const OpenSubdiv_Converter *converter,
|
||||
const int face_index,
|
||||
const int corner_index);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// User data associated with this converter.
|
||||
|
||||
void (*freeUserData)(const struct OpenSubdiv_Converter *converter);
|
||||
void (*freeUserData)(const OpenSubdiv_Converter *converter);
|
||||
void *user_data;
|
||||
} OpenSubdiv_Converter;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* OPENSUBDIV_CONVERTER_CAPI_H_ */
|
||||
};
|
|
@ -1,51 +1,46 @@
|
|||
/* SPDX-FileCopyrightText: 2013 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*
|
||||
* Author: Sergey Sharybin. */
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#ifndef OPENSUBDIV_EVALUATOR_CAPI_H_
|
||||
#define OPENSUBDIV_EVALUATOR_CAPI_H_
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h> // for uint64_t
|
||||
#include <cstdint> // for uint64_t
|
||||
|
||||
#include "opensubdiv_capi_type.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include "opensubdiv_capi_type.hh"
|
||||
|
||||
struct OpenSubdiv_EvaluatorCacheImpl;
|
||||
struct OpenSubdiv_EvaluatorImpl;
|
||||
struct OpenSubdiv_EvaluatorInternal;
|
||||
struct OpenSubdiv_PatchCoord;
|
||||
struct OpenSubdiv_TopologyRefiner;
|
||||
|
||||
typedef struct OpenSubdiv_EvaluatorSettings {
|
||||
struct OpenSubdiv_EvaluatorSettings {
|
||||
// Number of smoothly interpolated vertex data channels.
|
||||
int num_vertex_data;
|
||||
} OpenSubdiv_EvaluatorSettings;
|
||||
};
|
||||
|
||||
// Callback type for doing input/output operations on buffers.
|
||||
// Useful to abstract GPU buffers.
|
||||
typedef struct OpenSubdiv_Buffer {
|
||||
struct OpenSubdiv_Buffer {
|
||||
// Bind the buffer to the GPU.
|
||||
void (*bind_gpu)(const struct OpenSubdiv_Buffer *buffer);
|
||||
void (*bind_gpu)(const OpenSubdiv_Buffer *buffer);
|
||||
|
||||
// Allocate the buffer directly on the host for the given size in bytes. This has to return
|
||||
// a pointer to the newly allocated memory.
|
||||
void *(*alloc)(const struct OpenSubdiv_Buffer *buffer, const unsigned int size);
|
||||
void *(*alloc)(const OpenSubdiv_Buffer *buffer, const unsigned int size);
|
||||
|
||||
// Allocate the buffer directly on the device for the given size in bytes.
|
||||
void (*device_alloc)(const struct OpenSubdiv_Buffer *buffer, const unsigned int size);
|
||||
void (*device_alloc)(const OpenSubdiv_Buffer *buffer, const unsigned int size);
|
||||
|
||||
// Update the given range of the buffer with new data.
|
||||
void (*device_update)(const struct OpenSubdiv_Buffer *buffer,
|
||||
void (*device_update)(const OpenSubdiv_Buffer *buffer,
|
||||
unsigned int start,
|
||||
unsigned int len,
|
||||
const void *data);
|
||||
|
||||
// Wrap an existing GPU buffer, given its device handle, into the client's buffer type for
|
||||
// read-only use.
|
||||
void (*wrap_device_handle)(const struct OpenSubdiv_Buffer *buffer, uint64_t device_ptr);
|
||||
void (*wrap_device_handle)(const OpenSubdiv_Buffer *buffer, uint64_t device_ptr);
|
||||
|
||||
// Offset in the buffer where the data starts, if a single buffer is used for multiple data
|
||||
// channels.
|
||||
|
@ -54,25 +49,25 @@ typedef struct OpenSubdiv_Buffer {
|
|||
// Pointer to the client buffer data, which is modified or initialized through the various
|
||||
// callbacks.
|
||||
void *data;
|
||||
} OpenSubdiv_Buffer;
|
||||
};
|
||||
|
||||
typedef struct OpenSubdiv_Evaluator {
|
||||
struct OpenSubdiv_Evaluator {
|
||||
// Set settings for data buffers used.
|
||||
void (*setSettings)(struct OpenSubdiv_Evaluator *evaluator,
|
||||
void (*setSettings)(OpenSubdiv_Evaluator *evaluator,
|
||||
const OpenSubdiv_EvaluatorSettings *settings);
|
||||
|
||||
// Set coarse positions from a continuous array of coordinates.
|
||||
void (*setCoarsePositions)(struct OpenSubdiv_Evaluator *evaluator,
|
||||
void (*setCoarsePositions)(OpenSubdiv_Evaluator *evaluator,
|
||||
const float *positions,
|
||||
const int start_vertex_index,
|
||||
const int num_vertices);
|
||||
// Set vertex data from a continuous array of coordinates.
|
||||
void (*setVertexData)(struct OpenSubdiv_Evaluator *evaluator,
|
||||
void (*setVertexData)(OpenSubdiv_Evaluator *evaluator,
|
||||
const float *data,
|
||||
const int start_vertex_index,
|
||||
const int num_vertices);
|
||||
// Set varying data from a continuous array of data.
|
||||
void (*setVaryingData)(struct OpenSubdiv_Evaluator *evaluator,
|
||||
void (*setVaryingData)(OpenSubdiv_Evaluator *evaluator,
|
||||
const float *varying_data,
|
||||
const int start_vertex_index,
|
||||
const int num_vertices);
|
||||
|
@ -80,7 +75,7 @@ typedef struct OpenSubdiv_Evaluator {
|
|||
//
|
||||
// TODO(sergey): Find a better name for vertex here. It is not the vertex of
|
||||
// geometry, but a vertex of UV map.
|
||||
void (*setFaceVaryingData)(struct OpenSubdiv_Evaluator *evaluator,
|
||||
void (*setFaceVaryingData)(OpenSubdiv_Evaluator *evaluator,
|
||||
const int face_varying_channel,
|
||||
const float *face_varying_data,
|
||||
const int start_vertex_index,
|
||||
|
@ -89,7 +84,7 @@ typedef struct OpenSubdiv_Evaluator {
|
|||
// Set coarse vertex position from a continuous memory buffer where
|
||||
// first coordinate starts at offset of `start_offset` and there is `stride`
|
||||
// bytes between adjacent vertex coordinates.
|
||||
void (*setCoarsePositionsFromBuffer)(struct OpenSubdiv_Evaluator *evaluator,
|
||||
void (*setCoarsePositionsFromBuffer)(OpenSubdiv_Evaluator *evaluator,
|
||||
const void *buffer,
|
||||
const int start_offset,
|
||||
const int stride,
|
||||
|
@ -98,7 +93,7 @@ typedef struct OpenSubdiv_Evaluator {
|
|||
// Set varying data from a continuous memory buffer where
|
||||
// first coordinate starts at offset of `start_offset` and there is `stride`
|
||||
// bytes between adjacent vertex coordinates.
|
||||
void (*setVaryingDataFromBuffer)(struct OpenSubdiv_Evaluator *evaluator,
|
||||
void (*setVaryingDataFromBuffer)(OpenSubdiv_Evaluator *evaluator,
|
||||
const void *buffer,
|
||||
const int start_offset,
|
||||
const int stride,
|
||||
|
@ -110,7 +105,7 @@ typedef struct OpenSubdiv_Evaluator {
|
|||
//
|
||||
// TODO(sergey): Find a better name for vertex here. It is not the vertex of
|
||||
// geometry, but a vertex of UV map.
|
||||
void (*setFaceVaryingDataFromBuffer)(struct OpenSubdiv_Evaluator *evaluator,
|
||||
void (*setFaceVaryingDataFromBuffer)(OpenSubdiv_Evaluator *evaluator,
|
||||
const int face_varying_channel,
|
||||
const void *buffer,
|
||||
const int start_offset,
|
||||
|
@ -119,11 +114,11 @@ typedef struct OpenSubdiv_Evaluator {
|
|||
const int num_vertices);
|
||||
|
||||
// Refine after coarse positions update.
|
||||
void (*refine)(struct OpenSubdiv_Evaluator *evaluator);
|
||||
void (*refine)(OpenSubdiv_Evaluator *evaluator);
|
||||
|
||||
// Evaluate given ptex face at given bilinear coordinate.
|
||||
// If derivatives are NULL, they will not be evaluated.
|
||||
void (*evaluateLimit)(struct OpenSubdiv_Evaluator *evaluator,
|
||||
void (*evaluateLimit)(OpenSubdiv_Evaluator *evaluator,
|
||||
const int ptex_face_index,
|
||||
float face_u,
|
||||
float face_v,
|
||||
|
@ -132,14 +127,14 @@ typedef struct OpenSubdiv_Evaluator {
|
|||
float dPdv[3]);
|
||||
|
||||
// Evaluate vertex data at a given bilinear coordinate of given ptex face.
|
||||
void (*evaluateVertexData)(struct OpenSubdiv_Evaluator *evaluator,
|
||||
void (*evaluateVertexData)(OpenSubdiv_Evaluator *evaluator,
|
||||
const int ptex_face_index,
|
||||
float face_u,
|
||||
float face_v,
|
||||
float data[]);
|
||||
|
||||
// Evaluate varying data at a given bilinear coordinate of given ptex face.
|
||||
void (*evaluateVarying)(struct OpenSubdiv_Evaluator *evaluator,
|
||||
void (*evaluateVarying)(OpenSubdiv_Evaluator *evaluator,
|
||||
const int ptex_face_index,
|
||||
float face_u,
|
||||
float face_v,
|
||||
|
@ -147,7 +142,7 @@ typedef struct OpenSubdiv_Evaluator {
|
|||
|
||||
// Evaluate face-varying data at a given bilinear coordinate of given
|
||||
// ptex face.
|
||||
void (*evaluateFaceVarying)(struct OpenSubdiv_Evaluator *evaluator,
|
||||
void (*evaluateFaceVarying)(OpenSubdiv_Evaluator *evaluator,
|
||||
const int face_varying_channel,
|
||||
const int ptex_face_index,
|
||||
float face_u,
|
||||
|
@ -160,79 +155,77 @@ typedef struct OpenSubdiv_Evaluator {
|
|||
// If derivatives are NULL, they will not be evaluated.
|
||||
//
|
||||
// NOTE: Output arrays must point to a memory of size float[3]*num_patch_coords.
|
||||
void (*evaluatePatchesLimit)(struct OpenSubdiv_Evaluator *evaluator,
|
||||
const struct OpenSubdiv_PatchCoord *patch_coords,
|
||||
void (*evaluatePatchesLimit)(OpenSubdiv_Evaluator *evaluator,
|
||||
const OpenSubdiv_PatchCoord *patch_coords,
|
||||
const int num_patch_coords,
|
||||
float *P,
|
||||
float *dPdu,
|
||||
float *dPdv);
|
||||
|
||||
// Copy the patch map to the given buffers, and output some topology information.
|
||||
void (*getPatchMap)(struct OpenSubdiv_Evaluator *evaluator,
|
||||
struct OpenSubdiv_Buffer *patch_map_handles,
|
||||
struct OpenSubdiv_Buffer *patch_map_quadtree,
|
||||
void (*getPatchMap)(OpenSubdiv_Evaluator *evaluator,
|
||||
OpenSubdiv_Buffer *patch_map_handles,
|
||||
OpenSubdiv_Buffer *patch_map_quadtree,
|
||||
int *min_patch_face,
|
||||
int *max_patch_face,
|
||||
int *max_depth,
|
||||
int *patches_are_triangular);
|
||||
|
||||
// Fill the given buffer with data from the evaluator's patch array buffer.
|
||||
void (*fillPatchArraysBuffer)(struct OpenSubdiv_Evaluator *evaluator,
|
||||
struct OpenSubdiv_Buffer *patch_array_buffer);
|
||||
void (*fillPatchArraysBuffer)(OpenSubdiv_Evaluator *evaluator,
|
||||
OpenSubdiv_Buffer *patch_array_buffer);
|
||||
|
||||
// Fill the given buffer with data from the evaluator's patch index buffer.
|
||||
void (*wrapPatchIndexBuffer)(struct OpenSubdiv_Evaluator *evaluator,
|
||||
struct OpenSubdiv_Buffer *patch_index_buffer);
|
||||
void (*wrapPatchIndexBuffer)(OpenSubdiv_Evaluator *evaluator,
|
||||
OpenSubdiv_Buffer *patch_index_buffer);
|
||||
|
||||
// Fill the given buffer with data from the evaluator's patch parameter buffer.
|
||||
void (*wrapPatchParamBuffer)(struct OpenSubdiv_Evaluator *evaluator,
|
||||
struct OpenSubdiv_Buffer *patch_param_buffer);
|
||||
void (*wrapPatchParamBuffer)(OpenSubdiv_Evaluator *evaluator,
|
||||
OpenSubdiv_Buffer *patch_param_buffer);
|
||||
|
||||
// Fill the given buffer with data from the evaluator's source buffer.
|
||||
void (*wrapSrcBuffer)(struct OpenSubdiv_Evaluator *evaluator,
|
||||
struct OpenSubdiv_Buffer *src_buffer);
|
||||
void (*wrapSrcBuffer)(OpenSubdiv_Evaluator *evaluator, OpenSubdiv_Buffer *src_buffer);
|
||||
|
||||
// Fill the given buffer with data from the evaluator's extra source buffer.
|
||||
void (*wrapSrcVertexDataBuffer)(struct OpenSubdiv_Evaluator *evaluator,
|
||||
struct OpenSubdiv_Buffer *src_buffer);
|
||||
void (*wrapSrcVertexDataBuffer)(OpenSubdiv_Evaluator *evaluator, OpenSubdiv_Buffer *src_buffer);
|
||||
|
||||
// Fill the given buffer with data from the evaluator's face varying patch array buffer.
|
||||
void (*fillFVarPatchArraysBuffer)(struct OpenSubdiv_Evaluator *evaluator,
|
||||
void (*fillFVarPatchArraysBuffer)(OpenSubdiv_Evaluator *evaluator,
|
||||
const int face_varying_channel,
|
||||
struct OpenSubdiv_Buffer *patch_array_buffer);
|
||||
OpenSubdiv_Buffer *patch_array_buffer);
|
||||
|
||||
// Fill the given buffer with data from the evaluator's face varying patch index buffer.
|
||||
void (*wrapFVarPatchIndexBuffer)(struct OpenSubdiv_Evaluator *evaluator,
|
||||
void (*wrapFVarPatchIndexBuffer)(OpenSubdiv_Evaluator *evaluator,
|
||||
const int face_varying_channel,
|
||||
struct OpenSubdiv_Buffer *patch_index_buffer);
|
||||
OpenSubdiv_Buffer *patch_index_buffer);
|
||||
|
||||
// Fill the given buffer with data from the evaluator's face varying patch parameter buffer.
|
||||
void (*wrapFVarPatchParamBuffer)(struct OpenSubdiv_Evaluator *evaluator,
|
||||
void (*wrapFVarPatchParamBuffer)(OpenSubdiv_Evaluator *evaluator,
|
||||
const int face_varying_channel,
|
||||
struct OpenSubdiv_Buffer *patch_param_buffer);
|
||||
OpenSubdiv_Buffer *patch_param_buffer);
|
||||
|
||||
// Fill the given buffer with data from the evaluator's face varying source buffer.
|
||||
void (*wrapFVarSrcBuffer)(struct OpenSubdiv_Evaluator *evaluator,
|
||||
void (*wrapFVarSrcBuffer)(OpenSubdiv_Evaluator *evaluator,
|
||||
const int face_varying_channel,
|
||||
struct OpenSubdiv_Buffer *src_buffer);
|
||||
OpenSubdiv_Buffer *src_buffer);
|
||||
|
||||
// Return true if the evaluator has source vertex data set.
|
||||
bool (*hasVertexData)(struct OpenSubdiv_Evaluator *evaluator);
|
||||
bool (*hasVertexData)(OpenSubdiv_Evaluator *evaluator);
|
||||
|
||||
// Implementation of the evaluator.
|
||||
struct OpenSubdiv_EvaluatorImpl *impl;
|
||||
OpenSubdiv_EvaluatorImpl *impl;
|
||||
|
||||
// Type of the evaluator.
|
||||
eOpenSubdivEvaluator type;
|
||||
} OpenSubdiv_Evaluator;
|
||||
};
|
||||
|
||||
typedef struct OpenSubdiv_EvaluatorCache {
|
||||
struct OpenSubdiv_EvaluatorCache {
|
||||
// Implementation of the evaluator cache.
|
||||
struct OpenSubdiv_EvaluatorCacheImpl *impl;
|
||||
} OpenSubdiv_EvaluatorCache;
|
||||
OpenSubdiv_EvaluatorCacheImpl *impl;
|
||||
};
|
||||
|
||||
OpenSubdiv_Evaluator *openSubdiv_createEvaluatorFromTopologyRefiner(
|
||||
struct OpenSubdiv_TopologyRefiner *topology_refiner,
|
||||
OpenSubdiv_TopologyRefiner *topology_refiner,
|
||||
eOpenSubdivEvaluator evaluator_type,
|
||||
OpenSubdiv_EvaluatorCache *evaluator_cache);
|
||||
|
||||
|
@ -245,9 +238,3 @@ void openSubdiv_deleteEvaluatorCache(OpenSubdiv_EvaluatorCache *evaluator_cache)
|
|||
// Return the GLSL source code from the OpenSubDiv library used for patch evaluation.
|
||||
// This function is not thread-safe.
|
||||
const char *openSubdiv_getGLSLPatchBasisSource(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // OPENSUBDIV_EVALUATOR_CAPI_H_
|
|
@ -1,19 +1,12 @@
|
|||
/* SPDX-FileCopyrightText: 2018 Blender Foundation
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*
|
||||
* Author: Sergey Sharybin. */
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later */
|
||||
|
||||
#ifndef OPENSUBDIV_TOPOLOGY_REFINER_CAPI_H_
|
||||
#define OPENSUBDIV_TOPOLOGY_REFINER_CAPI_H_
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h> // for bool
|
||||
#include <cstdint> // for bool
|
||||
|
||||
#include "opensubdiv_capi_type.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include "opensubdiv_capi_type.hh"
|
||||
|
||||
struct OpenSubdiv_Converter;
|
||||
struct OpenSubdiv_TopologyRefinerImpl;
|
||||
|
@ -23,19 +16,19 @@ struct OpenSubdiv_TopologyRefinerImpl;
|
|||
// make it possible to ensure we are not trying to abuse same OpenSubdiv's
|
||||
// topology refiner with different subdivision levels or with different
|
||||
// adaptive settings.
|
||||
typedef struct OpenSubdiv_TopologyRefinerSettings {
|
||||
struct OpenSubdiv_TopologyRefinerSettings {
|
||||
bool is_adaptive;
|
||||
int level;
|
||||
} OpenSubdiv_TopologyRefinerSettings;
|
||||
};
|
||||
|
||||
// C-style wrapper around actual topology refiner.
|
||||
//
|
||||
// The only purpose is to allow C-only code to access C++ implementation of the
|
||||
// topology refiner.
|
||||
typedef struct OpenSubdiv_TopologyRefiner {
|
||||
struct OpenSubdiv_TopologyRefiner {
|
||||
// Query subdivision level the refiner is created for.
|
||||
int (*getSubdivisionLevel)(const struct OpenSubdiv_TopologyRefiner *topology_refiner);
|
||||
bool (*getIsAdaptive)(const struct OpenSubdiv_TopologyRefiner *topology_refiner);
|
||||
int (*getSubdivisionLevel)(const OpenSubdiv_TopologyRefiner *topology_refiner);
|
||||
bool (*getIsAdaptive)(const OpenSubdiv_TopologyRefiner *topology_refiner);
|
||||
|
||||
// NOTE: All queries are querying base level.
|
||||
//
|
||||
|
@ -47,28 +40,27 @@ typedef struct OpenSubdiv_TopologyRefiner {
|
|||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Query basic topology information from base level.
|
||||
|
||||
int (*getNumVertices)(const struct OpenSubdiv_TopologyRefiner *topology_refiner);
|
||||
int (*getNumEdges)(const struct OpenSubdiv_TopologyRefiner *topology_refiner);
|
||||
int (*getNumFaces)(const struct OpenSubdiv_TopologyRefiner *topology_refiner);
|
||||
int (*getNumVertices)(const OpenSubdiv_TopologyRefiner *topology_refiner);
|
||||
int (*getNumEdges)(const OpenSubdiv_TopologyRefiner *topology_refiner);
|
||||
int (*getNumFaces)(const OpenSubdiv_TopologyRefiner *topology_refiner);
|
||||
|
||||
int (*getNumFaceVertices)(const struct OpenSubdiv_TopologyRefiner *topology_refiner,
|
||||
int (*getNumFaceVertices)(const OpenSubdiv_TopologyRefiner *topology_refiner,
|
||||
const int face_index);
|
||||
void (*getFaceVertices)(const struct OpenSubdiv_TopologyRefiner *topology_refiner,
|
||||
void (*getFaceVertices)(const OpenSubdiv_TopologyRefiner *topology_refiner,
|
||||
const int face_index,
|
||||
int *face_vertices_indices);
|
||||
|
||||
int (*getNumFaceEdges)(const struct OpenSubdiv_TopologyRefiner *topology_refiner,
|
||||
const int face_index);
|
||||
void (*getFaceEdges)(const struct OpenSubdiv_TopologyRefiner *topology_refiner,
|
||||
int (*getNumFaceEdges)(const OpenSubdiv_TopologyRefiner *topology_refiner, const int face_index);
|
||||
void (*getFaceEdges)(const OpenSubdiv_TopologyRefiner *topology_refiner,
|
||||
const int face_index,
|
||||
int *face_edges_indices);
|
||||
void (*getEdgeVertices)(const struct OpenSubdiv_TopologyRefiner *topology_refiner,
|
||||
void (*getEdgeVertices)(const OpenSubdiv_TopologyRefiner *topology_refiner,
|
||||
const int edge_index,
|
||||
int edge_vertices_indices[2]);
|
||||
|
||||
int (*getNumVertexEdges)(const struct OpenSubdiv_TopologyRefiner *topology_refiner,
|
||||
int (*getNumVertexEdges)(const OpenSubdiv_TopologyRefiner *topology_refiner,
|
||||
const int vertex_index);
|
||||
void (*getVertexEdges)(const struct OpenSubdiv_TopologyRefiner *topology_refiner,
|
||||
void (*getVertexEdges)(const OpenSubdiv_TopologyRefiner *topology_refiner,
|
||||
const int vertex_index,
|
||||
int *vertex_edges_indices);
|
||||
|
||||
|
@ -82,9 +74,9 @@ typedef struct OpenSubdiv_TopologyRefiner {
|
|||
// - Quad face consists of a single ptex face.
|
||||
// - N-gons (similar to triangle) consists of N ptex faces, ordered same
|
||||
// way as for triangle.
|
||||
int (*getNumFacePtexFaces)(const struct OpenSubdiv_TopologyRefiner *topology_refiner,
|
||||
int (*getNumFacePtexFaces)(const OpenSubdiv_TopologyRefiner *topology_refiner,
|
||||
const int face_index);
|
||||
int (*getNumPtexFaces)(const struct OpenSubdiv_TopologyRefiner *topology_refiner);
|
||||
int (*getNumPtexFaces)(const OpenSubdiv_TopologyRefiner *topology_refiner);
|
||||
|
||||
// Initialize a per-base-face offset measured in ptex face indices.
|
||||
//
|
||||
|
@ -92,25 +84,24 @@ typedef struct OpenSubdiv_TopologyRefiner {
|
|||
// faces created for bases faces [0 .. base_face_index - 1].
|
||||
//
|
||||
// The array must contain at least total number of ptex faces elements.
|
||||
void (*fillFacePtexIndexOffset)(const struct OpenSubdiv_TopologyRefiner *topology_refiner,
|
||||
void (*fillFacePtexIndexOffset)(const OpenSubdiv_TopologyRefiner *topology_refiner,
|
||||
int *face_ptex_index_offset);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Face-varying data.
|
||||
|
||||
// Number of face-varying channels (or how they are called in Blender layers).
|
||||
int (*getNumFVarChannels)(const struct OpenSubdiv_TopologyRefiner *topology_refiner);
|
||||
int (*getNumFVarChannels)(const OpenSubdiv_TopologyRefiner *topology_refiner);
|
||||
// Get face-varying interpolation type.
|
||||
OpenSubdiv_FVarLinearInterpolation (*getFVarLinearInterpolation)(
|
||||
const struct OpenSubdiv_TopologyRefiner *topology_refiner);
|
||||
const OpenSubdiv_TopologyRefiner *topology_refiner);
|
||||
// Get total number of face-varying values in a particular channel.
|
||||
int (*getNumFVarValues)(const struct OpenSubdiv_TopologyRefiner *topology_refiner,
|
||||
const int channel);
|
||||
int (*getNumFVarValues)(const OpenSubdiv_TopologyRefiner *topology_refiner, const int channel);
|
||||
// Get face-varying value indices associated with a particular face.
|
||||
//
|
||||
// This is an array of indices inside of face-varying array, array elements
|
||||
// are aligned with face corners (or loops in Blender terminology).
|
||||
const int *(*getFaceFVarValueIndices)(const struct OpenSubdiv_TopologyRefiner *topology_refiner,
|
||||
const int *(*getFaceFVarValueIndices)(const OpenSubdiv_TopologyRefiner *topology_refiner,
|
||||
const int face_index,
|
||||
const int channel);
|
||||
|
||||
|
@ -118,13 +109,13 @@ typedef struct OpenSubdiv_TopologyRefiner {
|
|||
// Internal use.
|
||||
|
||||
// Implementation of the topology refiner.
|
||||
struct OpenSubdiv_TopologyRefinerImpl *impl;
|
||||
} OpenSubdiv_TopologyRefiner;
|
||||
OpenSubdiv_TopologyRefinerImpl *impl;
|
||||
};
|
||||
|
||||
// NOTE: Will return NULL in cases of bad topology.
|
||||
// NOTE: Mesh without faces is considered a bad topology.
|
||||
OpenSubdiv_TopologyRefiner *openSubdiv_createTopologyRefinerFromConverter(
|
||||
struct OpenSubdiv_Converter *converter, const OpenSubdiv_TopologyRefinerSettings *settings);
|
||||
OpenSubdiv_Converter *converter, const OpenSubdiv_TopologyRefinerSettings *settings);
|
||||
|
||||
void openSubdiv_deleteTopologyRefiner(OpenSubdiv_TopologyRefiner *topology_refiner);
|
||||
|
||||
|
@ -135,11 +126,4 @@ void openSubdiv_deleteTopologyRefiner(OpenSubdiv_TopologyRefiner *topology_refin
|
|||
// and compare with existing refiner before going into more computationally
|
||||
// complicated parts of subdivision process.
|
||||
bool openSubdiv_topologyRefinerCompareWithConverter(
|
||||
const OpenSubdiv_TopologyRefiner *topology_refiner,
|
||||
const struct OpenSubdiv_Converter *converter);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // OPENSUBDIV_TOPOLOGY_REFINER_CAPI_H_
|
||||
const OpenSubdiv_TopologyRefiner *topology_refiner, const OpenSubdiv_Converter *converter);
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* Author: Sergey Sharybin. */
|
||||
|
||||
#include "opensubdiv_evaluator_capi.h"
|
||||
#include "opensubdiv_evaluator_capi.hh"
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* Author: Sergey Sharybin. */
|
||||
|
||||
#include "opensubdiv_capi.h"
|
||||
#include "opensubdiv_capi.hh"
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
*
|
||||
* Author: Sergey Sharybin. */
|
||||
|
||||
#include "opensubdiv_topology_refiner_capi.h"
|
||||
#include "opensubdiv_topology_refiner_capi.hh"
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
|
|
|
@ -21,8 +21,6 @@ WAYLAND_DYNLOAD_FN(libdecor_configuration_get_window_state)
|
|||
WAYLAND_DYNLOAD_FN(libdecor_decorate)
|
||||
WAYLAND_DYNLOAD_FN(libdecor_dispatch)
|
||||
WAYLAND_DYNLOAD_FN(libdecor_frame_commit)
|
||||
WAYLAND_DYNLOAD_FN(libdecor_frame_get_content_height)
|
||||
WAYLAND_DYNLOAD_FN(libdecor_frame_get_content_width)
|
||||
WAYLAND_DYNLOAD_FN(libdecor_frame_get_xdg_toplevel)
|
||||
WAYLAND_DYNLOAD_FN(libdecor_frame_map)
|
||||
WAYLAND_DYNLOAD_FN(libdecor_frame_set_app_id)
|
||||
|
@ -78,8 +76,6 @@ struct WaylandDynload_Libdecor {
|
|||
void WL_DYN_FN(libdecor_frame_commit)(struct libdecor_frame *frame,
|
||||
struct libdecor_state *state,
|
||||
struct libdecor_configuration *configuration);
|
||||
int WL_DYN_FN(libdecor_frame_get_content_width)(struct libdecor_frame *frame);
|
||||
int WL_DYN_FN(libdecor_frame_get_content_height)(struct libdecor_frame *frame);
|
||||
struct xdg_toplevel *WL_DYN_FN(libdecor_frame_get_xdg_toplevel)(struct libdecor_frame *frame);
|
||||
void WL_DYN_FN(libdecor_frame_map)(struct libdecor_frame *frame);
|
||||
void WL_DYN_FN(libdecor_frame_set_app_id)(struct libdecor_frame *frame, const char *app_id);
|
||||
|
@ -116,10 +112,6 @@ struct WaylandDynload_Libdecor {
|
|||
# define libdecor_dispatch(...) (*wayland_dynload_libdecor.libdecor_dispatch)(__VA_ARGS__)
|
||||
# define libdecor_frame_commit(...) \
|
||||
(*wayland_dynload_libdecor.libdecor_frame_commit)(__VA_ARGS__)
|
||||
# define libdecor_frame_get_content_height(...) \
|
||||
(*wayland_dynload_libdecor.libdecor_frame_get_content_height)(__VA_ARGS__)
|
||||
# define libdecor_frame_get_content_width(...) \
|
||||
(*wayland_dynload_libdecor.libdecor_frame_get_content_width)(__VA_ARGS__)
|
||||
# define libdecor_frame_get_xdg_toplevel(...) \
|
||||
(*wayland_dynload_libdecor.libdecor_frame_get_xdg_toplevel)(__VA_ARGS__)
|
||||
# define libdecor_frame_map(...) (*wayland_dynload_libdecor.libdecor_frame_map)(__VA_ARGS__)
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
8:French (Français):fr_FR
|
||||
2:Japanese (日本語):ja_JP
|
||||
47:Slovak (Slovenčina):sk_SK
|
||||
41:Vietnamese (Tiếng Việt):vi_VN
|
||||
13:Simplified Chinese (简体中文):zh_HANS
|
||||
#
|
||||
0:In Progress:
|
||||
11:Czech (Čeština):cs_CZ
|
||||
|
@ -28,15 +30,13 @@
|
|||
12:Portuguese (Português):pt_PT
|
||||
15:Russian (Русский):ru_RU
|
||||
18:Ukrainian (Українська):uk_UA
|
||||
41:Vietnamese (Tiếng Việt):vi_VN
|
||||
13:Simplified Chinese (简体中文):zh_HANS
|
||||
14:Traditional Chinese (繁體中文):zh_HANT
|
||||
#
|
||||
0:Starting:
|
||||
45:Abkhaz (Аԥсуа бызшәа):ab
|
||||
# Skipped (see IMPORT_LANGUAGES_SKIP in settings.py). #37:Amharic (አማርኛ):am_ET
|
||||
21:Arabic (ﺔﻴﺑﺮﻌﻟﺍ):ar_EG
|
||||
# Skipped (see IMPORT_LANGUAGES_SKIP in settings.py). #52:Belarusian (беларуску):be
|
||||
52:Belarusian (беларуску):be
|
||||
22:Bulgarian (Български):bg_BG
|
||||
23:Greek (Ελληνικά):el_GR
|
||||
35:Esperanto (Esperanto):eo
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Blender 4.1.0 Alpha (b'72b6c44e759b')\n"
|
||||
"Project-Id-Version: Blender 4.1.0 Alpha (b'274dc815eb35')\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"\"POT-Creation-Date: 2019-02-25 20:41:30\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Blender 4.1.0 Alpha (b'72b6c44e759b')\n"
|
||||
"Project-Id-Version: Blender 4.1.0 Alpha (b'274dc815eb35')\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-12-04 11:06:00\n"
|
||||
"POT-Creation-Date: 2023-12-11 11:18:04\n"
|
||||
"PO-Revision-Date: 2016-04-23 22:41+0300\n"
|
||||
"Last-Translator: Yousef Harfoush <bat3a@msn.com>\n"
|
||||
"Language-Team: Yousef Harfoush, Amine Moussaoui <bat3a@msn.com>\n"
|
||||
|
@ -7373,6 +7373,18 @@ msgid "Whether this path is saved in bookmarks, or generated from OS"
|
|||
msgstr "ﻡﺎﻈﻨﻟﺍ ﻦﻣ ﺓﺪﻟﻮﺘﻤﻟﺍ ﻭﺍ ﻦﻳﻭﺎﻨﻌﻟﺍ ﻲﻓ ﻅﻮﻔﺤﻣ ﺭﺎﺴﻤﻟﺍ ﺍﺬﻫ ﻥﺎﻛ ﺎﻣ ﺍﺫﺍ"
|
||||
|
||||
|
||||
msgid "File Extensions"
|
||||
msgstr "ﻒﻠﻤﻟﺍ ﺕﺎﺌﻴﻫ"
|
||||
|
||||
|
||||
msgid "Operator"
|
||||
msgstr "ﻞﻣﺎﻋ"
|
||||
|
||||
|
||||
msgid "Label"
|
||||
msgstr "ﻖﺼﻠﻣ"
|
||||
|
||||
|
||||
msgid "Animations"
|
||||
msgstr "ﺕﺎﻜﻳﺮﺤﺘﻟﺍ"
|
||||
|
||||
|
@ -11899,10 +11911,6 @@ msgid "Node tree consisting of linked nodes used for shading, textures and compo
|
|||
msgstr "ﺐﻴﻛﺮﺘﻟﺍ ﻭ ,ﺔﺠﺴﻧﻷﺍ ,ﻞﻴﻠﻈﺘﻠﻟ ﺔﻣﺪﺨﺘﺴﻤﻟﺍ ﻭ ﺔﻄﺒﺗﺮﻤﻟﺍ ﺪﻘﻌﻟﺍ ﻦﻣ ﺔﻧﻮﻜﻤﻟﺍ ﺓﺪﻘﻌﻟﺍ ﺓﺮﺠﺷ"
|
||||
|
||||
|
||||
msgid "Label"
|
||||
msgstr "ﻖﺼﻠﻣ"
|
||||
|
||||
|
||||
msgid "The node tree label"
|
||||
msgstr "ﺓﺪﻘﻌﻟﺍ ﺓﺮﺠﺷ ﻖﺼﻠﻣ"
|
||||
|
||||
|
@ -27689,10 +27697,6 @@ msgid "Falloff Type"
|
|||
msgstr "ﻲﺷﻼﺘﻟﺍ ﻉﻮﻧ"
|
||||
|
||||
|
||||
msgid "Operator"
|
||||
msgstr "ﻞﻣﺎﻋ"
|
||||
|
||||
|
||||
msgid "Sharpen"
|
||||
msgstr "ﺩﺎﺣ"
|
||||
|
||||
|
@ -29741,10 +29745,6 @@ msgid "Palette Color"
|
|||
msgstr "ﻥﻮﻠﻟﺍ ﺔﺣﻮﻟ"
|
||||
|
||||
|
||||
msgid "Refraction"
|
||||
msgstr "ﺭﺎﺴﻜﻧﻻﺍ"
|
||||
|
||||
|
||||
msgid "Integrator Presets"
|
||||
msgstr "ﻞﻣﺎﻜﻤﻠﻟ ﺔﻘﺒﺴﻤﻟﺍ ﺕﺍﺩﺍﺪﻋﻹﺍ"
|
||||
|
||||
|
@ -32822,10 +32822,6 @@ msgid "Process the render result through the compositing pipeline, if compositin
|
|||
msgstr "ﺔﻠﻌﻔﻣ ﺐﻴﻛﺮﺘﻟﺍ ﺪﻘﻋ ﺖﻧﺎﻛ ﺍﺫﺇ ،ﺐﻴﻛﺮﺘﻟﺍ ﻞﺣﺍﺮﻣ ﺮﺒﻋ ﺮﻴﻴﺼﺘﻟﺍ ﺔﺠﻴﺘﻧ ﺔﺠﻟﺎﻌﻣ"
|
||||
|
||||
|
||||
msgid "File Extensions"
|
||||
msgstr "ﻒﻠﻤﻟﺍ ﺕﺎﺌﻴﻫ"
|
||||
|
||||
|
||||
msgid "Add the file format extensions to the rendered file name (eg: filename + .jpg)"
|
||||
msgstr " (jpg. + ﻒﻠﻣ_ﻢﺳﺇ :ﻝﺎﺜﻣ) ﺮﻴّﺼﻤﻟﺍ ﻒﻠﻤﻟﺍ ﻢﺳﺇ ﻰﻟﺇ ﻒﻠﻤﻟﺍ ﺔﺌﻴﻫ ﻒﺿﺃ"
|
||||
|
||||
|
@ -35481,10 +35477,6 @@ msgid "Display vertex-per-face normals as lines"
|
|||
msgstr "ﻁﻮﻄﺨﻛ ﻪﺟﻭ-ﻞﻜﻟ-ﺔﻄﻘﻧ ﻢﻇﺍﻮﻧ ﺽﺮﻋﺇ"
|
||||
|
||||
|
||||
msgid "Stat Vis"
|
||||
msgstr "ﺔﻴﺋﺎﺼﺣﺇ ﺔﻨﻳﺎﻌﻣ"
|
||||
|
||||
|
||||
msgid "Display statistical information about the mesh"
|
||||
msgstr "ﻢﺴﺠﻤﻟﺍ ﻦﻋ ﺔﻴﺋﺎﺼﺣﺇ ﺕﺎﻣﻮﻠﻌﻣ ﺽﺮﻋﺇ"
|
||||
|
||||
|
@ -36431,6 +36423,10 @@ msgid "Auto-Step"
|
|||
msgstr "ﻲﺋﺎﻘﻠﺗ ﻡﺪﻘﺗ"
|
||||
|
||||
|
||||
msgid "Refraction"
|
||||
msgstr "ﺭﺎﺴﻜﻧﻻﺍ"
|
||||
|
||||
|
||||
msgid "Paths:"
|
||||
msgstr ":ﺕﺍﺭﺎﺴﻤﻟﺍ"
|
||||
|
||||
|
|
|
@ -0,0 +1,360 @@
|
|||
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Blender 4.1.0 Alpha (b'274dc815eb35')\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-12-11 11:18:04\n"
|
||||
"PO-Revision-Date: 2023-12-11 10:35+0000\n"
|
||||
"Last-Translator: Aleh <zucchini.enjoyer@protonmail.com>\n"
|
||||
"Language-Team: Belarusian <https://translate.blender.org/projects/blender-ui/ui/be/>\n"
|
||||
"Language: be\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2;\n"
|
||||
"X-Generator: Weblate 5.0.1"
|
||||
|
||||
|
||||
msgid "Shader AOV"
|
||||
msgstr "Шэйдар АВП"
|
||||
|
||||
|
||||
msgid "Valid"
|
||||
msgstr "Сапраўдны"
|
||||
|
||||
|
||||
msgid "Is the name of the AOV conflicting"
|
||||
msgstr "Ці канфліктуе назва АВП"
|
||||
|
||||
|
||||
msgid "Name"
|
||||
msgstr "Назва"
|
||||
|
||||
|
||||
msgid "Name of the AOV"
|
||||
msgstr "Назва АВП"
|
||||
|
||||
|
||||
msgid "Type"
|
||||
msgstr "Тып"
|
||||
|
||||
|
||||
msgid "Data type of the AOV"
|
||||
msgstr "Тып дадзеных АВП"
|
||||
|
||||
|
||||
msgid "Color"
|
||||
msgstr "Колер"
|
||||
|
||||
|
||||
msgid "Value"
|
||||
msgstr "Значэнне"
|
||||
|
||||
|
||||
msgid "List of AOVs"
|
||||
msgstr "Спіс АВП"
|
||||
|
||||
|
||||
msgid "Collection of AOVs"
|
||||
msgstr "Калекцыя АВП"
|
||||
|
||||
|
||||
msgid "Action F-Curves"
|
||||
msgstr "Ф-крывыя дзеянняў"
|
||||
|
||||
|
||||
msgid "Collection of action F-Curves"
|
||||
msgstr "Калекцыя Ф-крывых дзеянняў"
|
||||
|
||||
|
||||
msgid "Action Group"
|
||||
msgstr "Група дзеянняў"
|
||||
|
||||
|
||||
msgid "Groups of F-Curves"
|
||||
msgstr "Групы Ф-крывых"
|
||||
|
||||
|
||||
msgid "Channels"
|
||||
msgstr "Каналы"
|
||||
|
||||
|
||||
msgid "F-Curves in this group"
|
||||
msgstr "Ф-крывыя ў гэтай групе"
|
||||
|
||||
|
||||
msgid "Color Set"
|
||||
msgstr "Набор колераў"
|
||||
|
||||
|
||||
msgid "Custom color set to use"
|
||||
msgstr "Карыстальніцкі набор колераў для выкарыстання"
|
||||
|
||||
|
||||
msgid "Default Colors"
|
||||
msgstr "Колеры па змаўчанні"
|
||||
|
||||
|
||||
msgid "01 - Theme Color Set"
|
||||
msgstr "01 - Колеравая тэма"
|
||||
|
||||
|
||||
msgid "02 - Theme Color Set"
|
||||
msgstr "02 - Колеравая тэма"
|
||||
|
||||
|
||||
msgid "03 - Theme Color Set"
|
||||
msgstr "03 - Колеравая тэма"
|
||||
|
||||
|
||||
msgid "04 - Theme Color Set"
|
||||
msgstr "04 - Колеравая тэма"
|
||||
|
||||
|
||||
msgid "05 - Theme Color Set"
|
||||
msgstr "05 - Колеравая тэма"
|
||||
|
||||
|
||||
msgid "06 - Theme Color Set"
|
||||
msgstr "06 - Колеравая тэма"
|
||||
|
||||
|
||||
msgid "07 - Theme Color Set"
|
||||
msgstr "07 - Колеравая тэма"
|
||||
|
||||
|
||||
msgid "08 - Theme Color Set"
|
||||
msgstr "08 - Колеравая тэма"
|
||||
|
||||
|
||||
msgid "09 - Theme Color Set"
|
||||
msgstr "09 - Колеравая тэма"
|
||||
|
||||
|
||||
msgid "10 - Theme Color Set"
|
||||
msgstr "10 - Колеравая тэма"
|
||||
|
||||
|
||||
msgid "11 - Theme Color Set"
|
||||
msgstr "11 - Колеравая тэма"
|
||||
|
||||
|
||||
msgid "12 - Theme Color Set"
|
||||
msgstr "12 - Колеравая тэма"
|
||||
|
||||
|
||||
msgid "13 - Theme Color Set"
|
||||
msgstr "13 - Колеравая тэма"
|
||||
|
||||
|
||||
msgid "14 - Theme Color Set"
|
||||
msgstr "14 - Колеравая тэма"
|
||||
|
||||
|
||||
msgid "15 - Theme Color Set"
|
||||
msgstr "15 - Колеравая тэма"
|
||||
|
||||
|
||||
msgid "16 - Theme Color Set"
|
||||
msgstr "16 - Колеравая тэма"
|
||||
|
||||
|
||||
msgid "17 - Theme Color Set"
|
||||
msgstr "17 - Колеравая тэма"
|
||||
|
||||
|
||||
msgid "18 - Theme Color Set"
|
||||
msgstr "18 - Колеравая тэма"
|
||||
|
||||
|
||||
msgid "19 - Theme Color Set"
|
||||
msgstr "19 - Колеравая тэма"
|
||||
|
||||
|
||||
msgid "20 - Theme Color Set"
|
||||
msgstr "20 - Колеравая тэма"
|
||||
|
||||
|
||||
msgid "Custom Color Set"
|
||||
msgstr "Карыстальніцкі набор колераў"
|
||||
|
||||
|
||||
msgid "Colors"
|
||||
msgstr "Колеры"
|
||||
|
||||
|
||||
msgid "Copy of the colors associated with the group's color set"
|
||||
msgstr "Копія колераў, асацыяваных з наборам колераў групы"
|
||||
|
||||
|
||||
msgid "Color set is user-defined instead of a fixed theme color set"
|
||||
msgstr "Набор колераў, зададзены карыстальнікам, замест фіксаванай колеравай тэмы"
|
||||
|
||||
|
||||
msgid "Lock"
|
||||
msgstr "Заблакаваць"
|
||||
|
||||
|
||||
msgid "Action group is locked"
|
||||
msgstr "Група дзеянняў заблакавана"
|
||||
|
||||
|
||||
msgid "Mute"
|
||||
msgstr "Прыглушыць"
|
||||
|
||||
|
||||
msgid "Action group is muted"
|
||||
msgstr "Група дзеянняў прыглушана"
|
||||
|
||||
|
||||
msgid "Select"
|
||||
msgstr "Выбраць"
|
||||
|
||||
|
||||
msgid "Action group is selected"
|
||||
msgstr "Група дзеянняў выбрана"
|
||||
|
||||
|
||||
msgid "Expanded"
|
||||
msgstr "Разгорнуты"
|
||||
|
||||
|
||||
msgid "Action group is expanded except in graph editor"
|
||||
msgstr "Група дзеянняў разгорнута, акрамя рэдактара графаў"
|
||||
|
||||
|
||||
msgid "Expanded in Graph Editor"
|
||||
msgstr "Разгорнута ў рэдактары графаў"
|
||||
|
||||
|
||||
msgid "Action group is expanded in graph editor"
|
||||
msgstr "Група дзеянняў разгорнута ў рэдактары графаў"
|
||||
|
||||
|
||||
msgid "Pin in Graph Editor"
|
||||
msgstr "Прышпіліць у рэдактары графаў"
|
||||
|
||||
|
||||
msgid "Action Groups"
|
||||
msgstr "Групы дзеянняў"
|
||||
|
||||
|
||||
msgid "Collection of action groups"
|
||||
msgstr "Калекцыя груп дзеянняў"
|
||||
|
||||
|
||||
msgid "Action Pose Markers"
|
||||
msgstr "Маркеры поз дзеянняў"
|
||||
|
||||
|
||||
msgid "Collection of timeline markers"
|
||||
msgstr "Калекцыя маркераў шкалы часу"
|
||||
|
||||
|
||||
msgid "Active Pose Marker"
|
||||
msgstr "Актыўны маркер позы"
|
||||
|
||||
|
||||
msgid "Active pose marker for this action"
|
||||
msgstr "Актыўны маркер позы для гэтага дзеяння"
|
||||
|
||||
|
||||
msgid "Active Pose Marker Index"
|
||||
msgstr "Індэкс актыўнага маркера позы"
|
||||
|
||||
|
||||
msgid "Index of active pose marker"
|
||||
msgstr "Індэкс актыўнага маркера позы"
|
||||
|
||||
|
||||
msgid "Add-on"
|
||||
msgstr "Дадатак"
|
||||
|
||||
|
||||
msgid "Python add-ons to be loaded automatically"
|
||||
msgstr "Дадаткі Python, якія будуць загружацца аўтаматычна"
|
||||
|
||||
|
||||
msgid "Module"
|
||||
msgstr "Модуль"
|
||||
|
||||
|
||||
msgid "Module name"
|
||||
msgstr "Назва модуля"
|
||||
|
||||
|
||||
msgid "Add-on Preferences"
|
||||
msgstr "Налады дадатка"
|
||||
|
||||
|
||||
msgid "Password"
|
||||
msgstr "Пароль"
|
||||
|
||||
|
||||
msgid "E-mail address"
|
||||
msgstr "Адрасы электроннай пошты"
|
||||
|
||||
|
||||
msgid "Error Message"
|
||||
msgstr "Паведамленне аб памылцы"
|
||||
|
||||
|
||||
msgid "Message"
|
||||
msgstr "Паведамленне"
|
||||
|
||||
|
||||
msgid "Compute Device Type"
|
||||
msgstr "Тып вылічальнай прылады"
|
||||
|
||||
|
||||
msgid "Device to use for computation (rendering with Cycles)"
|
||||
msgstr "Прылада, якая выкарыстоўваецца для вылічэння (рэндэрынг з дапамогай Cycles)"
|
||||
|
||||
|
||||
msgid "Kernel Optimization"
|
||||
msgstr "Аптымізацыя ядра"
|
||||
|
||||
|
||||
msgid "Kernels can be optimized based on scene content. Optimized kernels are requested at the start of a render. If optimized kernels are not available, rendering will proceed using generic kernels until the optimized set is available in the cache. This can result in additional CPU usage for a brief time (tens of seconds)"
|
||||
msgstr "Ядры могуць быць аптымізаваныя на грунце змесціва сцэны. Аптымізаваныя ядры запытваюцца ў пачатку рэндэрынгу. Калі аптымізаваныя ядры недаступныя, рэндэрынг будзе адбывацца з выкарыстаннем агульных ядраў, пакуль аптымізаваны набор не будзе даступны ў кэшы. Гэта можа прывесці да дадатковага выкарыстання ЦП на кароткі час (дзясяткі секундаў)"
|
||||
|
||||
|
||||
msgid "Off"
|
||||
msgstr "Выключана"
|
||||
|
||||
|
||||
msgid "Disable kernel optimization. Slowest rendering, no extra background CPU usage"
|
||||
msgstr "Адключэнне аптымізацыі ядра. Самы павольны рэндэрынг, без дадатковай фонавай загрузкі ЦП"
|
||||
|
||||
|
||||
msgid "Intersection only"
|
||||
msgstr "Толькі перасячэнні"
|
||||
|
||||
|
||||
msgid "Optimize only intersection kernels. Faster rendering, negligible extra background CPU usage"
|
||||
msgstr "Аптымізацыя толькі ядраў перасячэння. Больш хуткі рэндэрынг, нязначнае дадатковае выкарыстанне ЦП ў фонавым рэжыме"
|
||||
|
||||
|
||||
msgid "Full"
|
||||
msgstr "Поўнае"
|
||||
|
||||
|
||||
msgid "Optimize all kernels. Fastest rendering, may result in extra background CPU usage"
|
||||
msgstr "Аптымізацыя ўсіх ядраў. Самы хуткі рэндэрынг, можа прывесці да дадатковай загрузцы ЦП ў фонавым рэжыме"
|
||||
|
||||
|
||||
msgid "MetalRT"
|
||||
msgstr "MetalRT"
|
||||
|
||||
|
||||
msgid "MetalRT for ray tracing uses less memory for scenes which use curves extensively, and can give better performance in specific cases"
|
||||
msgstr "MetalRT выкарыстоўвае менш памяці для трасіроўкі прамянёў у сцэнах, якія актыўна выкарыстоўваюць крывыя, і можа даць лепшую прадукцыйнасць у пэўных выпадках"
|
||||
|
||||
|
||||
msgid "On"
|
||||
msgstr "Уключана"
|
||||
|
||||
|
||||
msgid "Import Paths"
|
||||
msgstr "Шляхі імпарту"
|
||||
|
|
@ -1,9 +1,9 @@
|
|||
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Blender 4.1.0 Alpha (b'72b6c44e759b')\n"
|
||||
"Project-Id-Version: Blender 4.1.0 Alpha (b'274dc815eb35')\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-12-04 11:06:00\n"
|
||||
"POT-Creation-Date: 2023-12-11 11:18:04\n"
|
||||
"PO-Revision-Date: 2023-09-26 10:37+0000\n"
|
||||
"Last-Translator: Gilberto Rodrigues <gilbertorodrigues@outlook.com>\n"
|
||||
"Language-Team: Bulgarian <https://translate.blender.org/projects/blender-ui/ui/bg/>\n"
|
||||
|
|
969
locale/po/ca.po
969
locale/po/ca.po
File diff suppressed because it is too large
Load Diff
|
@ -1,9 +1,9 @@
|
|||
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Blender 4.1.0 Alpha (b'72b6c44e759b')\n"
|
||||
"Project-Id-Version: Blender 4.1.0 Alpha (b'274dc815eb35')\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-12-04 11:06:00\n"
|
||||
"POT-Creation-Date: 2023-12-11 11:18:04\n"
|
||||
"PO-Revision-Date: 2023-10-12 15:54+0000\n"
|
||||
"Last-Translator: Zdeněk Doležal <Griperis@outlook.cz>\n"
|
||||
"Language-Team: Czech <https://translate.blender.org/projects/blender-ui/ui/cs/>\n"
|
||||
|
@ -7131,6 +7131,18 @@ msgid "Save"
|
|||
msgstr "Uložit"
|
||||
|
||||
|
||||
msgid "File Extensions"
|
||||
msgstr "Přípony souborů"
|
||||
|
||||
|
||||
msgid "Operator"
|
||||
msgstr "Operátor"
|
||||
|
||||
|
||||
msgid "Label"
|
||||
msgstr "Úroveň"
|
||||
|
||||
|
||||
msgid "Icon ID"
|
||||
msgstr "ID Ikony"
|
||||
|
||||
|
@ -10713,10 +10725,6 @@ msgid "Proxy Custom Directory"
|
|||
msgstr "Adresář zvuků"
|
||||
|
||||
|
||||
msgid "Label"
|
||||
msgstr "Úroveň"
|
||||
|
||||
|
||||
msgid "Grease Pencil Data"
|
||||
msgstr "Kresba skicovací tužkou"
|
||||
|
||||
|
@ -23894,10 +23902,6 @@ msgid "Reverse Colors"
|
|||
msgstr "Nová vertexová barva"
|
||||
|
||||
|
||||
msgid "Flip direction of vertex colors inside faces"
|
||||
msgstr "Přepíná směr vybraných ploškových vrcholů a ploškových normál"
|
||||
|
||||
|
||||
msgctxt "Operator"
|
||||
msgid "Rotate Colors"
|
||||
msgstr "Vložit barvu"
|
||||
|
@ -29179,10 +29183,6 @@ msgid "Decrease Contrast"
|
|||
msgstr "Snížit Kontrast"
|
||||
|
||||
|
||||
msgid "Operator"
|
||||
msgstr "Operátor"
|
||||
|
||||
|
||||
msgctxt "Operator"
|
||||
msgid "Filter Mesh"
|
||||
msgstr "Filtrovat Síť"
|
||||
|
@ -32427,14 +32427,6 @@ msgid "Restrict"
|
|||
msgstr "Omezit"
|
||||
|
||||
|
||||
msgid "Refraction"
|
||||
msgstr "Lom"
|
||||
|
||||
|
||||
msgid "Denoising"
|
||||
msgstr "Odstranění šumu"
|
||||
|
||||
|
||||
msgid "Integrator Presets"
|
||||
msgstr "Generátory"
|
||||
|
||||
|
@ -33019,6 +33011,10 @@ msgid "Indirect Lighting"
|
|||
msgstr "Nepřímé osvětlení"
|
||||
|
||||
|
||||
msgid "Denoising"
|
||||
msgstr "Odstranění šumu"
|
||||
|
||||
|
||||
msgid "Shadows"
|
||||
msgstr "Stíny"
|
||||
|
||||
|
@ -35915,10 +35911,6 @@ msgid "Crop the rendered frame to the defined render region size"
|
|||
msgstr "Oříznout vykreslený snímek do definovaný velikosti vykreslovací oblasti"
|
||||
|
||||
|
||||
msgid "File Extensions"
|
||||
msgstr "Přípony souborů"
|
||||
|
||||
|
||||
msgid "Draw stylized strokes using Freestyle"
|
||||
msgstr "Kreslení stylizovaných tahů pomocí Freestyle"
|
||||
|
||||
|
@ -39715,6 +39707,10 @@ msgid "Show dashed lines indicating parent or constraint relationships"
|
|||
msgstr "Zobrazuje čárkované čáry naznačující vztahy s nadřazenými objekty, nebo vazby mezi objekty"
|
||||
|
||||
|
||||
msgid "Mesh Analysis"
|
||||
msgstr "Analýza sítě"
|
||||
|
||||
|
||||
msgid "Display vertex normals as lines"
|
||||
msgstr "Zobrazí normály vertexů pomocí čárek"
|
||||
|
||||
|
@ -41214,6 +41210,10 @@ msgid "Light Clamping"
|
|||
msgstr "Svorka Světla"
|
||||
|
||||
|
||||
msgid "Refraction"
|
||||
msgstr "Lom"
|
||||
|
||||
|
||||
msgid "Cascade Size"
|
||||
msgstr "Velikost kaskády"
|
||||
|
||||
|
@ -43108,16 +43108,6 @@ msgid "Face Set from Visible"
|
|||
msgstr "Sada Ploch z Viditelného"
|
||||
|
||||
|
||||
msgctxt "Operator"
|
||||
msgid "Invert Visible Face Sets"
|
||||
msgstr "Invertovat Viditelné Sady Ploch"
|
||||
|
||||
|
||||
msgctxt "Operator"
|
||||
msgid "Show All Face Sets"
|
||||
msgstr "Zobrazit Všechny Viditelné Sady Ploch"
|
||||
|
||||
|
||||
msgctxt "Operator"
|
||||
msgid "Randomize Colors"
|
||||
msgstr "Randomizovat barvy"
|
||||
|
@ -43350,10 +43340,6 @@ msgid "Seams"
|
|||
msgstr "Švy"
|
||||
|
||||
|
||||
msgid "Mesh Analysis"
|
||||
msgstr "Analýza sítě"
|
||||
|
||||
|
||||
msgid "Face Angle"
|
||||
msgstr "Úhel plochy"
|
||||
|
||||
|
@ -45875,6 +45861,10 @@ msgid "Mask not found"
|
|||
msgstr "Maska nebyla nalezena"
|
||||
|
||||
|
||||
msgid "Please select all related strips"
|
||||
msgstr "Odstranit označené značky"
|
||||
|
||||
|
||||
msgid "Cannot apply effects to audio sequence strips"
|
||||
msgstr "První frame animace"
|
||||
|
||||
|
@ -45887,10 +45877,6 @@ msgid "No valid inputs to swap"
|
|||
msgstr "Jméno skriptu"
|
||||
|
||||
|
||||
msgid "Please select all related strips"
|
||||
msgstr "Odstranit označené značky"
|
||||
|
||||
|
||||
msgid "Please select two strips"
|
||||
msgstr "Odstranit označené značky"
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Blender 4.1.0 Alpha (b'72b6c44e759b')\n"
|
||||
"Project-Id-Version: Blender 4.1.0 Alpha (b'274dc815eb35')\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-12-04 11:06:00\n"
|
||||
"POT-Creation-Date: 2023-12-11 11:18:04\n"
|
||||
"PO-Revision-Date: \n"
|
||||
"Last-Translator: Martin Reininger <martinreininger@gmx.net>\n"
|
||||
"Language-Team: German translation team\n"
|
||||
|
@ -9759,6 +9759,18 @@ msgid "Save"
|
|||
msgstr "Speichern"
|
||||
|
||||
|
||||
msgid "File Extensions"
|
||||
msgstr "Dateiendungen"
|
||||
|
||||
|
||||
msgid "Operator"
|
||||
msgstr "Operator"
|
||||
|
||||
|
||||
msgid "Label"
|
||||
msgstr "Beschriftung"
|
||||
|
||||
|
||||
msgid "File Select Entry"
|
||||
msgstr "Eintrag zur Dateiauswahl"
|
||||
|
||||
|
@ -15435,10 +15447,6 @@ msgid "Node tree consisting of linked nodes used for shading, textures and compo
|
|||
msgstr "Knotenbaum beinhaltet verknüpfte Knoten, die für Shading, Texturen und Kompositionen verwendet wurden"
|
||||
|
||||
|
||||
msgid "Label"
|
||||
msgstr "Beschriftung"
|
||||
|
||||
|
||||
msgid "Grease Pencil Data"
|
||||
msgstr "Wachsstift-Daten"
|
||||
|
||||
|
@ -32957,10 +32965,6 @@ msgid "Reverse Colors"
|
|||
msgstr "Farben umkehren"
|
||||
|
||||
|
||||
msgid "Flip direction of vertex colors inside faces"
|
||||
msgstr "Umkehrrichtung der Punktfarben innerhalb von Flächen"
|
||||
|
||||
|
||||
msgctxt "Operator"
|
||||
msgid "Rotate Colors"
|
||||
msgstr "Farben drehen"
|
||||
|
@ -38493,10 +38497,6 @@ msgid "Decrease Contrast"
|
|||
msgstr "Kontrast verringern"
|
||||
|
||||
|
||||
msgid "Operator"
|
||||
msgstr "Operator"
|
||||
|
||||
|
||||
msgctxt "Operator"
|
||||
msgid "Init Mask"
|
||||
msgstr "Maske initializieren"
|
||||
|
@ -42136,14 +42136,6 @@ msgid "Active Palette Color"
|
|||
msgstr "Aktive Farbpalette"
|
||||
|
||||
|
||||
msgid "Refraction"
|
||||
msgstr "Strahlenbrechnung"
|
||||
|
||||
|
||||
msgid "Denoising"
|
||||
msgstr "Rauschreduzierung"
|
||||
|
||||
|
||||
msgid "Integrator Presets"
|
||||
msgstr "Integrator-Voreinstellungen"
|
||||
|
||||
|
@ -42748,6 +42740,10 @@ msgid "Indirect Lighting"
|
|||
msgstr "Indirekte Beleuchtung"
|
||||
|
||||
|
||||
msgid "Denoising"
|
||||
msgstr "Rauschreduzierung"
|
||||
|
||||
|
||||
msgid "Shadows"
|
||||
msgstr "Schatten"
|
||||
|
||||
|
@ -46682,10 +46678,6 @@ msgid "Crop the rendered frame to the defined render region size"
|
|||
msgstr "Beschneidet den gerenderten Rahmen auf die definierte Größe des Renderbereichs"
|
||||
|
||||
|
||||
msgid "File Extensions"
|
||||
msgstr "Dateiendungen"
|
||||
|
||||
|
||||
msgid "Add the file format extensions to the rendered file name (eg: filename + .jpg)"
|
||||
msgstr "Dateiformaterweiterungen zu Dateinamen hinzufügen (z.B.: Dateiname + .jpg)"
|
||||
|
||||
|
@ -54936,6 +54928,10 @@ msgid "Auto-Step"
|
|||
msgstr "Auto-Schritt"
|
||||
|
||||
|
||||
msgid "Refraction"
|
||||
msgstr "Strahlenbrechnung"
|
||||
|
||||
|
||||
msgctxt "Operator"
|
||||
msgid "Bake Indirect Lighting"
|
||||
msgstr "Indirekte Beleuchtung backen"
|
||||
|
@ -58671,10 +58667,6 @@ msgid "Int"
|
|||
msgstr "Int"
|
||||
|
||||
|
||||
msgid "PreviewCol"
|
||||
msgstr "Vorschaufarbe"
|
||||
|
||||
|
||||
msgid "TexturedCol"
|
||||
msgstr "Texturierte Farbe"
|
||||
|
||||
|
@ -61689,14 +61681,6 @@ msgid "File '%s' could not be loaded"
|
|||
msgstr "Datei '%s' konnte nicht geladen werden"
|
||||
|
||||
|
||||
msgid "Cannot apply effects to audio sequence strips"
|
||||
msgstr "Effekt kann nicht auf Audio-Sequenzstreifen angewandt werden"
|
||||
|
||||
|
||||
msgid "Cannot apply effect to more than 3 sequence strips"
|
||||
msgstr "Effekt kann nicht auf mehr als 3 Sequenzstreifen angewandt werden"
|
||||
|
||||
|
||||
msgid "Please select all related strips"
|
||||
msgstr "Bitte alle beziehenden Streifen auswählen"
|
||||
|
||||
|
@ -61705,6 +61689,14 @@ msgid "No strips to paste"
|
|||
msgstr "Keine Streifen zum einfügen"
|
||||
|
||||
|
||||
msgid "Cannot apply effects to audio sequence strips"
|
||||
msgstr "Effekt kann nicht auf Audio-Sequenzstreifen angewandt werden"
|
||||
|
||||
|
||||
msgid "Cannot apply effect to more than 3 sequence strips"
|
||||
msgstr "Effekt kann nicht auf mehr als 3 Sequenzstreifen angewandt werden"
|
||||
|
||||
|
||||
msgid "Please select two strips"
|
||||
msgstr "Bitte zwei Steifen auswählen"
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Blender 4.1.0 Alpha (b'72b6c44e759b')\n"
|
||||
"Project-Id-Version: Blender 4.1.0 Alpha (b'274dc815eb35')\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-12-04 11:06:00\n"
|
||||
"POT-Creation-Date: 2023-12-11 11:18:04\n"
|
||||
"PO-Revision-Date: 2008-03-23 12:20+0200\n"
|
||||
"Last-Translator: Kostas Karvouniaris <neogen556@yahoo.gr>\n"
|
||||
"Language-Team: \n"
|
||||
|
|
275
locale/po/es.po
275
locale/po/es.po
|
@ -1,11 +1,11 @@
|
|||
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Blender 4.1.0 Alpha (b'72b6c44e759b')\n"
|
||||
"Project-Id-Version: Blender 4.1.0 Alpha (b'274dc815eb35')\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-12-04 11:06:00\n"
|
||||
"PO-Revision-Date: 2023-12-04 05:17+0000\n"
|
||||
"Last-Translator: Gabriel Gazzán <gabcorreo@gmail.com>\n"
|
||||
"POT-Creation-Date: 2023-12-11 11:18:04\n"
|
||||
"PO-Revision-Date: 2023-12-09 04:50+0000\n"
|
||||
"Last-Translator: Darwin Yip <yipdarwin+blender@gmail.com>\n"
|
||||
"Language-Team: Spanish <https://translate.blender.org/projects/blender-ui/ui/es/>\n"
|
||||
"Language: es\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
|
@ -1458,6 +1458,10 @@ msgid "Custom"
|
|||
msgstr "Personalizado"
|
||||
|
||||
|
||||
msgid "Show assets from the asset libraries configured in the Preferences"
|
||||
msgstr "Mostrar recursos de las bibliotecas de recursos configurados en las preferencias"
|
||||
|
||||
|
||||
msgid "ID Name"
|
||||
msgstr "Nombre"
|
||||
|
||||
|
@ -13118,6 +13122,18 @@ msgid "Whether this path is saved in bookmarks, or generated from OS"
|
|||
msgstr "Indica si esta ruta se encuentra guardada en los marcadores o proviene del sistema operativo"
|
||||
|
||||
|
||||
msgid "File Extensions"
|
||||
msgstr "Extensiones de archivo"
|
||||
|
||||
|
||||
msgid "Operator"
|
||||
msgstr "Operador"
|
||||
|
||||
|
||||
msgid "Label"
|
||||
msgstr "Etiqueta"
|
||||
|
||||
|
||||
msgid "File Select Entry"
|
||||
msgstr "Archivo seleccionado"
|
||||
|
||||
|
@ -25425,6 +25441,14 @@ msgid "True if this material has grease pencil data"
|
|||
msgstr "Verdadero si este material contiene datos de lápiz de cera"
|
||||
|
||||
|
||||
msgid "Light Probe Volume Single Sided"
|
||||
msgstr "Volumen de sonda de luz de un solo lado"
|
||||
|
||||
|
||||
msgid "Consider material single sided for light probe volume capture. Additionally helps rejecting probes inside the object to avoid light leaks"
|
||||
msgstr "Considere el material de un solo lado para la captura del volumen de la sonda de luz. Además ayuda a rechazar sondas dentro del objeto para evitar fugas de luz"
|
||||
|
||||
|
||||
msgid "Line Color"
|
||||
msgstr "Color de línea"
|
||||
|
||||
|
@ -25625,6 +25649,18 @@ msgid "How intense (bright) the specular reflection is"
|
|||
msgstr "Qué tan intensa es la reflectividad"
|
||||
|
||||
|
||||
msgid "Surface Render Method"
|
||||
msgstr "Método de procesar superficie"
|
||||
|
||||
|
||||
msgid "Controls the blending and the compatibility with certain features"
|
||||
msgstr "Controla la mezcla y la compatibilidad con ciertas características"
|
||||
|
||||
|
||||
msgid "Blended"
|
||||
msgstr "Mezclado"
|
||||
|
||||
|
||||
msgid "Texture Slot Images"
|
||||
msgstr "Imágenes del contenedor de texturas"
|
||||
|
||||
|
@ -26073,10 +26109,6 @@ msgid "Node tree consisting of linked nodes used for shading, textures and compo
|
|||
msgstr "Árbol de nodos compuesto por nodos vinculados entre sí; usados para sombreado, texturizado y composición"
|
||||
|
||||
|
||||
msgid "Label"
|
||||
msgstr "Etiqueta"
|
||||
|
||||
|
||||
msgid "The node tree label"
|
||||
msgstr "Etiqueta del árbol de nodos"
|
||||
|
||||
|
@ -51356,11 +51388,6 @@ msgid "Name of the bone collection to unassign this bone from; empty to unassign
|
|||
msgstr "Nombre de la colección de la cual quitar este hueso; dejar vacío para quitarlo de la colección activa"
|
||||
|
||||
|
||||
msgctxt "Operator"
|
||||
msgid "Remove Bone from Bone collections"
|
||||
msgstr "Eliminar hueso de colección de huesos"
|
||||
|
||||
|
||||
msgid "Unassign the bone from this bone collection"
|
||||
msgstr "Quita el hueso de esta colección de huesos"
|
||||
|
||||
|
@ -63015,19 +63042,11 @@ msgid "Reverse Colors"
|
|||
msgstr "Invertir colores"
|
||||
|
||||
|
||||
msgid "Flip direction of vertex colors inside faces"
|
||||
msgstr "Invierte la dirección de los colores de vértices dentro de las caras"
|
||||
|
||||
|
||||
msgctxt "Operator"
|
||||
msgid "Rotate Colors"
|
||||
msgstr "Rotar colores"
|
||||
|
||||
|
||||
msgid "Rotate color attributes inside faces"
|
||||
msgstr "Rota los atributos de color dentro de las caras"
|
||||
|
||||
|
||||
msgid "Counter Clockwise"
|
||||
msgstr "Antihorario"
|
||||
|
||||
|
@ -75207,19 +75226,6 @@ msgid "Modify Hidden"
|
|||
msgstr "Modificar ocultos"
|
||||
|
||||
|
||||
msgid "Apply the edit operation to hidden Face Sets"
|
||||
msgstr "Permite aplicar la operación de edición a los conjuntos de caras ocultos"
|
||||
|
||||
|
||||
msgctxt "Operator"
|
||||
msgid "Invert Face Set Visibility"
|
||||
msgstr "Invertir visibilidad de conjuntos de caras"
|
||||
|
||||
|
||||
msgid "Invert the visibility of the Face Sets of the sculpt"
|
||||
msgstr "Permite invertir la visibilidad de los conjuntos de caras de la escultura"
|
||||
|
||||
|
||||
msgctxt "Operator"
|
||||
msgid "Face Set Lasso Gesture"
|
||||
msgstr "Gesto de conjunto de caras con lazo"
|
||||
|
@ -75483,10 +75489,6 @@ msgid "Use settings from here"
|
|||
msgstr "Usar opciones de aquí"
|
||||
|
||||
|
||||
msgid "Operator"
|
||||
msgstr "Operador"
|
||||
|
||||
|
||||
msgid "Use settings from operator properties"
|
||||
msgstr "Usar opciones de propiedades del operador"
|
||||
|
||||
|
@ -84706,18 +84708,6 @@ msgid "Panel containing UI elements"
|
|||
msgstr "Panel que contiene elementos de la interfaz"
|
||||
|
||||
|
||||
msgid "Refraction"
|
||||
msgstr "Refracción"
|
||||
|
||||
|
||||
msgid "Screen Tracing"
|
||||
msgstr "Trazado en pantalla"
|
||||
|
||||
|
||||
msgid "Denoising"
|
||||
msgstr "Reducción de ruidos"
|
||||
|
||||
|
||||
msgid "Light Groups"
|
||||
msgstr "Grupos de luces"
|
||||
|
||||
|
@ -85596,10 +85586,18 @@ msgid "Indirect Lighting"
|
|||
msgstr "Iluminación indirecta"
|
||||
|
||||
|
||||
msgid "Denoising"
|
||||
msgstr "Reducción de ruidos"
|
||||
|
||||
|
||||
msgid "Raytracing"
|
||||
msgstr "Trazado de rayos"
|
||||
|
||||
|
||||
msgid "Screen Tracing"
|
||||
msgstr "Trazado en pantalla"
|
||||
|
||||
|
||||
msgid "Shadows"
|
||||
msgstr "Sombras"
|
||||
|
||||
|
@ -93603,10 +93601,6 @@ msgid "Crop the rendered frame to the defined render region size"
|
|||
msgstr "Recorta la imagen procesada al tamaño definido por la región"
|
||||
|
||||
|
||||
msgid "File Extensions"
|
||||
msgstr "Extensiones de archivo"
|
||||
|
||||
|
||||
msgid "Add the file format extensions to the rendered file name (eg: filename + .jpg)"
|
||||
msgstr "Agrega la extensión del formato de archivo al nombre del archivo procesado (p.ej: nombre + .jpg)"
|
||||
|
||||
|
@ -94775,14 +94769,6 @@ msgid "Brightness threshold for using sprite base depth of field"
|
|||
msgstr "Umbral de brillo para la profundidad de campo basada en sprites"
|
||||
|
||||
|
||||
msgid "Diffuse Trace Options"
|
||||
msgstr "Opciones de trazado de difusión"
|
||||
|
||||
|
||||
msgid "EEVEE settings for tracing diffuse reflections"
|
||||
msgstr "Opciones de EEVEE para el trazado de rayos de reflexión difusa"
|
||||
|
||||
|
||||
msgid "Auto Bake"
|
||||
msgstr "Captura automática"
|
||||
|
||||
|
@ -94995,26 +94981,6 @@ msgid "Percentage of render size to add as overscan to the internal render buffe
|
|||
msgstr "Porcentaje del tamaño de procesamiento a agregar como sobrebarrido a los buffers internos de procesamiento"
|
||||
|
||||
|
||||
msgid "Options Split"
|
||||
msgstr "División de opciones"
|
||||
|
||||
|
||||
msgid "Split settings per ray type"
|
||||
msgstr "Divide las opciones por tipo de rayo"
|
||||
|
||||
|
||||
msgid "Unified"
|
||||
msgstr "Unificado"
|
||||
|
||||
|
||||
msgid "All ray types use the same settings"
|
||||
msgstr "Todos los tipos de rayo usarán las mismas opciones"
|
||||
|
||||
|
||||
msgid "Settings are individual to each ray type"
|
||||
msgstr "Opciones individuales para cada tipo de rayo"
|
||||
|
||||
|
||||
msgid "Tracing Method"
|
||||
msgstr "Método de trazado"
|
||||
|
||||
|
@ -95043,14 +95009,6 @@ msgid "EEVEE settings for tracing reflections"
|
|||
msgstr "Opciones de EEVEE para el trazado de reflexiones"
|
||||
|
||||
|
||||
msgid "Refraction Trace Options"
|
||||
msgstr "Opciones de trazado de refracción"
|
||||
|
||||
|
||||
msgid "EEVEE settings for tracing refractions"
|
||||
msgstr "Opciones de EEVEE para el trazado de refracciones"
|
||||
|
||||
|
||||
msgid "Directional Shadows Resolution"
|
||||
msgstr "Resolución de sombras direccionales"
|
||||
|
||||
|
@ -104642,8 +104600,8 @@ msgid "Display scene statistics overlay text"
|
|||
msgstr "Mostrar sobreimpreso texto con estadísticas de la escena"
|
||||
|
||||
|
||||
msgid "Stat Vis"
|
||||
msgstr "Vis. estad."
|
||||
msgid "Mesh Analysis"
|
||||
msgstr "Análisis de mallas"
|
||||
|
||||
|
||||
msgid "Display statistical information about the mesh"
|
||||
|
@ -106110,10 +106068,6 @@ msgid "Vector2D"
|
|||
msgstr "Vector2D"
|
||||
|
||||
|
||||
msgid "2D float vector action, representing a thumbstick or trackpad"
|
||||
msgstr "Acción vectorial 2D decimal, representando un panel táctil"
|
||||
|
||||
|
||||
msgid "3D pose action, representing a controller's location and rotation"
|
||||
msgstr "Acción de pose 3D, representando la posición y rotación de un controlador"
|
||||
|
||||
|
@ -107589,11 +107543,6 @@ msgid "Stop Move Left"
|
|||
msgstr "Detener mov a izquierda"
|
||||
|
||||
|
||||
msgctxt "WindowManager"
|
||||
msgid "Stop Mode Right"
|
||||
msgstr "Detener mov a derecha"
|
||||
|
||||
|
||||
msgctxt "WindowManager"
|
||||
msgid "Teleport"
|
||||
msgstr "Teletransportación"
|
||||
|
@ -109151,6 +109100,10 @@ msgid "No glTF Animation"
|
|||
msgstr "No existe ninguna animación glTF"
|
||||
|
||||
|
||||
msgid "No Actions in .blend file"
|
||||
msgstr "No hay acciones en el archivo .blend"
|
||||
|
||||
|
||||
msgid "Variant"
|
||||
msgstr "Variante"
|
||||
|
||||
|
@ -112436,6 +112389,10 @@ msgid "Light Clamping"
|
|||
msgstr "Limitación de luz"
|
||||
|
||||
|
||||
msgid "Refraction"
|
||||
msgstr "Refracción"
|
||||
|
||||
|
||||
msgid "Cascade Size"
|
||||
msgstr "Tamaño cascada"
|
||||
|
||||
|
@ -113638,6 +113595,16 @@ msgid "Sound"
|
|||
msgstr "Sonido"
|
||||
|
||||
|
||||
msgctxt "Operator"
|
||||
msgid "Move Up"
|
||||
msgstr "Mover arriba"
|
||||
|
||||
|
||||
msgctxt "Operator"
|
||||
msgid "Move Down"
|
||||
msgstr "Mover abajo"
|
||||
|
||||
|
||||
msgctxt "Operator"
|
||||
msgid "Rename..."
|
||||
msgstr "Renombrar..."
|
||||
|
@ -116140,16 +116107,6 @@ msgid "Extract Face Set"
|
|||
msgstr "Extraer conjunto de caras"
|
||||
|
||||
|
||||
msgctxt "Operator"
|
||||
msgid "Invert Visible Face Sets"
|
||||
msgstr "Invertir conjuntos de caras visibles"
|
||||
|
||||
|
||||
msgctxt "Operator"
|
||||
msgid "Show All Face Sets"
|
||||
msgstr "Mostrar todos los conjuntos de caras"
|
||||
|
||||
|
||||
msgctxt "Operator"
|
||||
msgid "Randomize Colors"
|
||||
msgstr "Aleatorizar colores"
|
||||
|
@ -116574,10 +116531,6 @@ msgid "Vertex Group Weights"
|
|||
msgstr "Influencias de grupos de vértices"
|
||||
|
||||
|
||||
msgid "Mesh Analysis"
|
||||
msgstr "Análisis de mallas"
|
||||
|
||||
|
||||
msgid "Face Angle"
|
||||
msgstr "Ángulo de caras"
|
||||
|
||||
|
@ -117997,10 +117950,6 @@ msgid "Int"
|
|||
msgstr "Entero"
|
||||
|
||||
|
||||
msgid "PreviewCol"
|
||||
msgstr "ColPrevisualización"
|
||||
|
||||
|
||||
msgid "TexturedCol"
|
||||
msgstr "ColTexturizado"
|
||||
|
||||
|
@ -118025,10 +117974,6 @@ msgid "OS Loop"
|
|||
msgstr "Bucle del SO"
|
||||
|
||||
|
||||
msgid "PreviewLoopCol"
|
||||
msgstr "ColPrevisualizaciónBucle"
|
||||
|
||||
|
||||
msgid "Int8"
|
||||
msgstr "Entero8"
|
||||
|
||||
|
@ -118596,10 +118541,6 @@ msgid "No valid formats found"
|
|||
msgstr "No se encontraron formatos válidos"
|
||||
|
||||
|
||||
msgid "Can't allocate ffmpeg format context"
|
||||
msgstr "No es posible asignar el contexto del formato FFmpeg"
|
||||
|
||||
|
||||
msgid "Render width has to be 720 pixels for DV!"
|
||||
msgstr "¡El ancho de la imagen procesada debe ser de 720 píxeles para DV!"
|
||||
|
||||
|
@ -118612,10 +118553,6 @@ msgid "Render height has to be 576 pixels for DV-PAL!"
|
|||
msgstr "¡La altura de la imagen procesada debe ser de 576 píxeles para DV-PAL!"
|
||||
|
||||
|
||||
msgid "FFmpeg only supports 48khz / stereo audio for DV!"
|
||||
msgstr "¡FFmpeg sólo soporta audio estéreo de 48khz para DV!"
|
||||
|
||||
|
||||
msgid "Error initializing video stream"
|
||||
msgstr "Error inicializando flujo de video"
|
||||
|
||||
|
@ -125894,6 +125831,14 @@ msgid "File '%s' could not be loaded"
|
|||
msgstr "No fue posible cargar el archivo '%s'"
|
||||
|
||||
|
||||
msgid "Please select all related strips"
|
||||
msgstr "Por favor seleccionar todos los clips relacionados"
|
||||
|
||||
|
||||
msgid "No strips to paste"
|
||||
msgstr "No hay clips para pegar"
|
||||
|
||||
|
||||
msgid "Slip offset: %s"
|
||||
msgstr "Deslizamiento: %s"
|
||||
|
||||
|
@ -125934,14 +125879,6 @@ msgid "No valid inputs to swap"
|
|||
msgstr "No hay entradas válidas para intercambiar"
|
||||
|
||||
|
||||
msgid "Please select all related strips"
|
||||
msgstr "Por favor seleccionar todos los clips relacionados"
|
||||
|
||||
|
||||
msgid "No strips to paste"
|
||||
msgstr "No hay clips para pegar"
|
||||
|
||||
|
||||
msgid "Please select two strips"
|
||||
msgstr "Por favor seleccionar dos clips"
|
||||
|
||||
|
@ -132073,10 +132010,6 @@ msgid "Incident"
|
|||
msgstr "Incidente"
|
||||
|
||||
|
||||
msgid "Ior"
|
||||
msgstr "IR"
|
||||
|
||||
|
||||
msgid "No mesh in active object"
|
||||
msgstr "Ninguna malla en el objeto activo"
|
||||
|
||||
|
@ -133831,6 +133764,10 @@ msgid "Interpolates existing guide curves on a surface mesh"
|
|||
msgstr "Interpola las curvas guía existentes sobre la superficie de una malla"
|
||||
|
||||
|
||||
msgid "Follow Surface Normal"
|
||||
msgstr "Seguir la normal de la superficie"
|
||||
|
||||
|
||||
msgid "Redistribute Curve Points"
|
||||
msgstr "Redistribuir puntos de curva"
|
||||
|
||||
|
@ -133855,6 +133792,18 @@ msgid "Rolls up hair curves starting from their tips"
|
|||
msgstr "Enrolla las curvas de pelo, desde sus puntas"
|
||||
|
||||
|
||||
msgid "Variation Level"
|
||||
msgstr "Nivel de variación"
|
||||
|
||||
|
||||
msgid "Retain Overall Shape"
|
||||
msgstr "Conservar la forma general"
|
||||
|
||||
|
||||
msgid "Roll Direction"
|
||||
msgstr "Dirección de rollo"
|
||||
|
||||
|
||||
msgid "Rotate Hair Curves"
|
||||
msgstr "Rotar curvas de pelo"
|
||||
|
||||
|
@ -133867,6 +133816,14 @@ msgid "Sets the radius attribute of hair curves according to a profile shape"
|
|||
msgstr "Define el atributo de radio de las curvas de pelo mediante una forma de perfil"
|
||||
|
||||
|
||||
msgid "Replace Radius"
|
||||
msgstr "Reemplazar radio"
|
||||
|
||||
|
||||
msgid "Replace the original radius"
|
||||
msgstr "Reemplazar el radio original"
|
||||
|
||||
|
||||
msgid "Shrinkwrap Hair Curves"
|
||||
msgstr "Envolver curvas de pelo"
|
||||
|
||||
|
@ -133875,6 +133832,10 @@ msgid "Shrinkwraps hair curves to a mesh surface from below and optionally from
|
|||
msgstr "Envuelve las curvas de pelo alrededor de la superficie de una malla situada por debajo y opcionalmente por encima"
|
||||
|
||||
|
||||
msgid "Lock Roots"
|
||||
msgstr "Encerrar raíces"
|
||||
|
||||
|
||||
msgid "Smooth Hair Curves"
|
||||
msgstr "Suavizar curvas de pelo"
|
||||
|
||||
|
@ -133883,6 +133844,14 @@ msgid "Smoothes the shape of hair curves"
|
|||
msgstr "Suaviza la forma de las curvas de pelo"
|
||||
|
||||
|
||||
msgid "Lock Tips"
|
||||
msgstr "Encerrar puntas"
|
||||
|
||||
|
||||
msgid "Lock tip position when smoothing"
|
||||
msgstr "Encerrar posición de la punta al alisar"
|
||||
|
||||
|
||||
msgid "Straighten Hair Curves"
|
||||
msgstr "Enderezar curvas de pelo"
|
||||
|
||||
|
@ -133891,6 +133860,10 @@ msgid "Straightens hair curves between root and tip"
|
|||
msgstr "Endereza las curvas de pelo, de su raíz a su punta"
|
||||
|
||||
|
||||
msgid "Amount of straightening"
|
||||
msgstr "Cantidad de alisado"
|
||||
|
||||
|
||||
msgid "Trim Hair Curves"
|
||||
msgstr "Recortar curvas de pelo"
|
||||
|
||||
|
@ -133899,6 +133872,22 @@ msgid "Trims or scales hair curves to a certain length"
|
|||
msgstr "Recorta o escala las curvas de pelo a una cierta longitud"
|
||||
|
||||
|
||||
msgid "Multiply the original length by a factor"
|
||||
msgstr "Multiplicar el largo original por un factor"
|
||||
|
||||
|
||||
msgid "Mask to blend overall effect"
|
||||
msgstr "Máscara para mezclar el efecto general"
|
||||
|
||||
|
||||
msgid "Smooth by Angle"
|
||||
msgstr "Suavizar por ángulo"
|
||||
|
||||
|
||||
msgid "Maximum face angle for smooth edges"
|
||||
msgstr "Ángulo de cara máximo para bordes lisos"
|
||||
|
||||
|
||||
msgid "Ignore Sharpness"
|
||||
msgstr "Ignorar nitidez"
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: Blender 4.1.0 Alpha (b'72b6c44e759b')\n"
|
||||
"Project-Id-Version: Blender 4.1.0 Alpha (b'274dc815eb35')\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2023-12-04 11:06:00\n"
|
||||
"POT-Creation-Date: 2023-12-11 11:18:04\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: Ainhize & Miriam <agoenaga006@ikasle.ehu.eus>\n"
|
||||
"Language-Team: Euskara <agoenaga006@ikasle.ehu.eus>\n"
|
||||
|
@ -1706,10 +1706,6 @@ msgid "Save System Info"
|
|||
msgstr "Sistemaren Informazioa Gorde"
|
||||
|
||||
|
||||
msgid "Refraction"
|
||||
msgstr "Errefrakzioa"
|
||||
|
||||
|
||||
msgctxt "Operator"
|
||||
msgid "Scale"
|
||||
msgstr "Eskalatu"
|
||||
|
@ -1908,6 +1904,10 @@ msgid "Upper"
|
|||
msgstr "Altua"
|
||||
|
||||
|
||||
msgid "Refraction"
|
||||
msgstr "Errefrakzioa"
|
||||
|
||||
|
||||
msgctxt "Image"
|
||||
msgid "New"
|
||||
msgstr "Berria"
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue