BLI: refactor IndexMask for better performance and memory usage #104629

Merged
Jacques Lucke merged 254 commits from JacquesLucke/blender:index-mask-refactor into main 2023-05-24 18:11:47 +02:00
1729 changed files with 7432 additions and 10398 deletions
Showing only changes of commit 1c68b3d588 - Show all commits

View File

@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright 2006 Blender Foundation. All rights reserved.
# Copyright 2006 Blender Foundation
# -----------------------------------------------------------------------------
# Early Initialization

View File

@ -528,10 +528,10 @@ set(XR_OPENXR_SDK_HASH a2623ebab3d0b340bc16311b14f02075)
set(XR_OPENXR_SDK_HASH_TYPE MD5)
set(XR_OPENXR_SDK_FILE OpenXR-SDK-${XR_OPENXR_SDK_VERSION}.tar.gz)
set(WL_PROTOCOLS_VERSION 1.21)
set(WL_PROTOCOLS_VERSION 1.31)
set(WL_PROTOCOLS_FILE wayland-protocols-${WL_PROTOCOLS_VERSION}.tar.gz)
set(WL_PROTOCOLS_URI https://gitlab.freedesktop.org/wayland/wayland-protocols/-/archive/${WL_PROTOCOLS_VERSION}/${WL_PROTOCOLS_FILE})
set(WL_PROTOCOLS_HASH af5ca07e13517cdbab33504492cef54a)
set(WL_PROTOCOLS_HASH a28ff59a56e2ebb746048b6ef8d931d6)
set(WL_PROTOCOLS_HASH_TYPE MD5)
set(WAYLAND_VERSION 1.21.0)

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright 2022 Blender Foundation. All rights reserved.
# Copyright 2022 Blender Foundation
# This file is used to test the system for headers & symbols.
# Variables should use the `HAVE_` prefix.

View File

@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright 2006 Blender Foundation. All rights reserved.
# Copyright 2006 Blender Foundation
macro(list_insert_after
list_id item_check item_add

View File

@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright 2016 Blender Foundation. All rights reserved.
# Copyright 2016 Blender Foundation
# Libraries configuration for Apple.
@ -245,6 +245,7 @@ if(WITH_BOOST)
if(WITH_USD AND USD_PYTHON_SUPPORT)
list(APPEND _boost_FIND_COMPONENTS python${PYTHON_VERSION_NO_DOTS})
endif()
set(Boost_NO_WARN_NEW_VERSIONS ON)
find_package(Boost COMPONENTS ${_boost_FIND_COMPONENTS})
# Boost Python is separate to avoid linking Python into tests that don't need it.

View File

@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright 2016 Blender Foundation. All rights reserved.
# Copyright 2016 Blender Foundation
# Xcode and system configuration for Apple.

View File

@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright 2022 Blender Foundation. All rights reserved.
# Copyright 2022 Blender Foundation
# Auto update existing CMake caches for new libraries.

View File

@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright 2016 Blender Foundation. All rights reserved.
# Copyright 2016 Blender Foundation
# Libraries configuration for any *nix system including Linux and Unix (excluding APPLE).
@ -394,6 +394,7 @@ if(WITH_BOOST)
list(APPEND __boost_packages python${PYTHON_VERSION_NO_DOTS})
endif()
list(APPEND __boost_packages system)
set(Boost_NO_WARN_NEW_VERSIONS ON)
find_package(Boost 1.48 COMPONENTS ${__boost_packages})
if(NOT Boost_FOUND)
# try to find non-multithreaded if -mt not found, this flag
@ -645,7 +646,7 @@ if(WITH_GHOST_WAYLAND)
else()
# Rocky8 packages have too old a version, a newer version exist in the pre-compiled libraries.
find_path(WAYLAND_PROTOCOLS_DIR
NAMES unstable/xdg-decoration/xdg-decoration-unstable-v1.xml
NAMES staging/xdg-activation/xdg-activation-v1.xml
PATH_SUFFIXES share/wayland-protocols
PATHS ${LIBDIR}/wayland-protocols
)

View File

@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright 2016 Blender Foundation. All rights reserved.
# Copyright 2016 Blender Foundation
# Libraries configuration for Windows.

View File

@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright 2006 Blender Foundation. All rights reserved.
# Copyright 2006 Blender Foundation
# Libs that adhere to strict flags
add_subdirectory(curve_fit_nd)

View File

@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright 2008 Blender Foundation. All rights reserved.
# Copyright 2008 Blender Foundation
set(INC
include

View File

@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright 2006 Blender Foundation. All rights reserved.
# Copyright 2006 Blender Foundation
# avoid noisy warnings
if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang")

View File

@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright 2012 Blender Foundation. All rights reserved.
# Copyright 2012 Blender Foundation
set(INC
.

View File

@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright 2006 Blender Foundation. All rights reserved.
# Copyright 2006 Blender Foundation
set(INC
.

View File

@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright 2006 Blender Foundation. All rights reserved.
# Copyright 2006 Blender Foundation
set(INC
.

View File

@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright 2019 Blender Foundation. All rights reserved.
# Copyright 2019 Blender Foundation
# Build Draco library.
add_subdirectory(draco)

View File

@ -1,7 +1,7 @@
Project: fast_float
URL: https://github.com/fastfloat/fast_float
License: MIT
Upstream version: 3.4.0 (b7f9d6c)
Upstream version: 4.0.0 (fbd5bd7, 2023 Mar 31)
Local modifications:
- Took only the fast_float.h header and the license/readme files

View File

@ -1,12 +1,5 @@
## fast_float number parsing library: 4x faster than strtod
![Ubuntu 20.04 CI (GCC 9)](https://github.com/lemire/fast_float/workflows/Ubuntu%2020.04%20CI%20(GCC%209)/badge.svg)
![Ubuntu 18.04 CI (GCC 7)](https://github.com/lemire/fast_float/workflows/Ubuntu%2018.04%20CI%20(GCC%207)/badge.svg)
![Alpine Linux](https://github.com/lemire/fast_float/workflows/Alpine%20Linux/badge.svg)
![MSYS2-CI](https://github.com/lemire/fast_float/workflows/MSYS2-CI/badge.svg)
![VS16-CLANG-CI](https://github.com/lemire/fast_float/workflows/VS16-CLANG-CI/badge.svg)
[![VS16-CI](https://github.com/fastfloat/fast_float/actions/workflows/vs16-ci.yml/badge.svg)](https://github.com/fastfloat/fast_float/actions/workflows/vs16-ci.yml)
The fast_float library provides fast header-only implementations for the C++ from_chars
functions for `float` and `double` types. These functions convert ASCII strings representing
decimal values (e.g., `1.3e10`) into binary types. We provide exact rounding (including
@ -28,8 +21,8 @@ struct from_chars_result {
```
It parses the character sequence [first,last) for a number. It parses floating-point numbers expecting
a locale-independent format equivalent to the C++17 from_chars function.
The resulting floating-point value is the closest floating-point values (using either float or double),
a locale-independent format equivalent to the C++17 from_chars function.
The resulting floating-point value is the closest floating-point values (using either float or double),
using the "round to even" convention for values that would otherwise fall right in-between two values.
That is, we provide exact parsing according to the IEEE standard.
@ -47,7 +40,7 @@ Example:
``` C++
#include "fast_float/fast_float.h"
#include <iostream>
int main() {
const std::string input = "3.1416 xyz ";
double result;
@ -60,39 +53,60 @@ int main() {
Like the C++17 standard, the `fast_float::from_chars` functions take an optional last argument of
the type `fast_float::chars_format`. It is a bitset value: we check whether
the type `fast_float::chars_format`. It is a bitset value: we check whether
`fmt & fast_float::chars_format::fixed` and `fmt & fast_float::chars_format::scientific` are set
to determine whether we allow the fixed point and scientific notation respectively.
The default is `fast_float::chars_format::general` which allows both `fixed` and `scientific`.
The library seeks to follow the C++17 (see [20.19.3](http://eel.is/c++draft/charconv.from.chars).(7.1)) specification.
The library seeks to follow the C++17 (see [20.19.3](http://eel.is/c++draft/charconv.from.chars).(7.1)) specification.
* The `from_chars` function does not skip leading white-space characters.
* [A leading `+` sign](https://en.cppreference.com/w/cpp/utility/from_chars) is forbidden.
* It is generally impossible to represent a decimal value exactly as binary floating-point number (`float` and `double` types). We seek the nearest value. We round to an even mantissa when we are in-between two binary floating-point numbers.
* It is generally impossible to represent a decimal value exactly as binary floating-point number (`float` and `double` types). We seek the nearest value. We round to an even mantissa when we are in-between two binary floating-point numbers.
Furthermore, we have the following restrictions:
* We only support `float` and `double` types at this time.
* We only support the decimal format: we do not support hexadecimal strings.
* For values that are either very large or very small (e.g., `1e9999`), we represent it using the infinity or negative infinity value.
* For values that are either very large or very small (e.g., `1e9999`), we represent it using the infinity or negative infinity value and the returned `ec` is set to `std::errc::result_out_of_range`.
We support Visual Studio, macOS, Linux, freeBSD. We support big and little endian. We support 32-bit and 64-bit systems.
We assume that the rounding mode is set to nearest (`std::fegetround() == FE_TONEAREST`).
## C++20: compile-time evaluation (constexpr)
In C++20, you may use `fast_float::from_chars` to parse strings
at compile-time, as in the following example:
```C++
// consteval forces compile-time evaluation of the function in C++20.
consteval double parse(std::string_view input) {
double result;
auto answer = fast_float::from_chars(input.data(), input.data()+input.size(), result);
if(answer.ec != std::errc()) { return -1.0; }
return result;
}
// This function should compile to a function which
// merely returns 3.1415.
constexpr double constexptest() {
return parse("3.1415 input");
}
```
## Using commas as decimal separator
The C++ standard stipulate that `from_chars` has to be locale-independent. In
particular, the decimal separator has to be the period (`.`). However,
some users still want to use the `fast_float` library with in a locale-dependent
particular, the decimal separator has to be the period (`.`). However,
some users still want to use the `fast_float` library with in a locale-dependent
manner. Using a separate function called `from_chars_advanced`, we allow the users
to pass a `parse_options` instance which contains a custom decimal separator (e.g.,
to pass a `parse_options` instance which contains a custom decimal separator (e.g.,
the comma). You may use it as follows.
```C++
#include "fast_float/fast_float.h"
#include <iostream>
int main() {
const std::string input = "3,1416 xyz ";
double result;
@ -104,25 +118,62 @@ int main() {
}
```
You can parse delimited numbers:
```C++
const std::string input = "234532.3426362,7869234.9823,324562.645";
double result;
auto answer = fast_float::from_chars(input.data(), input.data()+input.size(), result);
if(answer.ec != std::errc()) {
// check error
}
// we have result == 234532.3426362.
if(answer.ptr[0] != ',') {
// unexpected delimiter
}
answer = fast_float::from_chars(answer.ptr + 1, input.data()+input.size(), result);
if(answer.ec != std::errc()) {
// check error
}
// we have result == 7869234.9823.
if(answer.ptr[0] != ',') {
// unexpected delimiter
}
answer = fast_float::from_chars(answer.ptr + 1, input.data()+input.size(), result);
if(answer.ec != std::errc()) {
// check error
}
// we have result == 324562.645.
```
## Reference
- Daniel Lemire, [Number Parsing at a Gigabyte per Second](https://arxiv.org/abs/2101.11408), Software: Pratice and Experience 51 (8), 2021.
## Relation With Other Work
The fast_float library is part of:
- GCC (as of version 12): the `from_chars` function in GCC relies on fast_float.
- [WebKit](https://github.com/WebKit/WebKit), the engine behind Safari (Apple's web browser)
The fastfloat algorithm is part of the [LLVM standard libraries](https://github.com/llvm/llvm-project/commit/87c016078ad72c46505461e4ff8bfa04819fe7ba).
There is a [derived implementation part of AdaCore](https://github.com/AdaCore/VSS).
The fast_float library provides a performance similar to that of the [fast_double_parser](https://github.com/lemire/fast_double_parser) library but using an updated algorithm reworked from the ground up, and while offering an API more in line with the expectations of C++ programmers. The fast_double_parser library is part of the [Microsoft LightGBM machine-learning framework](https://github.com/microsoft/LightGBM).
## References
- Daniel Lemire, [Number Parsing at a Gigabyte per Second](https://arxiv.org/abs/2101.11408), Software: Practice and Experience 51 (8), 2021.
- Noble Mushtak, Daniel Lemire, [Fast Number Parsing Without Fallback](https://arxiv.org/abs/2212.06644), Software: Practice and Experience (to appear)
## Other programming languages
- [There is an R binding](https://github.com/eddelbuettel/rcppfastfloat) called `rcppfastfloat`.
- [There is a Rust port of the fast_float library](https://github.com/aldanor/fast-float-rust/) called `fast-float-rust`.
- [There is a Java port of the fast_float library](https://github.com/wrandelshofer/FastDoubleParser) called `FastDoubleParser`.
- [There is a Java port of the fast_float library](https://github.com/wrandelshofer/FastDoubleParser) called `FastDoubleParser`. It used for important systems such as [Jackson](https://github.com/FasterXML/jackson-core).
- [There is a C# port of the fast_float library](https://github.com/CarlVerret/csFastFloat) called `csFastFloat`.
## Relation With Other Work
The fastfloat algorithm is part of the [LLVM standard libraries](https://github.com/llvm/llvm-project/commit/87c016078ad72c46505461e4ff8bfa04819fe7ba).
The fast_float library provides a performance similar to that of the [fast_double_parser](https://github.com/lemire/fast_double_parser) library but using an updated algorithm reworked from the ground up, and while offering an API more in line with the expectations of C++ programmers. The fast_double_parser library is part of the [Microsoft LightGBM machine-learning framework](https://github.com/microsoft/LightGBM).
## Users
The fast_float library is used by [Apache Arrow](https://github.com/apache/arrow/pull/8494) where it multiplied the number parsing speed by two or three times. It is also used by [Yandex ClickHouse](https://github.com/ClickHouse/ClickHouse) and by [Google Jsonnet](https://github.com/google/jsonnet).
@ -135,14 +186,14 @@ It can parse random floating-point numbers at a speed of 1 GB/s on some systems.
<img src="http://lemire.me/blog/wp-content/uploads/2020/11/fastfloat_speed.png" width="400">
```
$ ./build/benchmarks/benchmark
$ ./build/benchmarks/benchmark
# parsing random integers in the range [0,1)
volume = 2.09808 MB
netlib : 271.18 MB/s (+/- 1.2 %) 12.93 Mfloat/s
doubleconversion : 225.35 MB/s (+/- 1.2 %) 10.74 Mfloat/s
strtod : 190.94 MB/s (+/- 1.6 %) 9.10 Mfloat/s
abseil : 430.45 MB/s (+/- 2.2 %) 20.52 Mfloat/s
fastfloat : 1042.38 MB/s (+/- 9.9 %) 49.68 Mfloat/s
volume = 2.09808 MB
netlib : 271.18 MB/s (+/- 1.2 %) 12.93 Mfloat/s
doubleconversion : 225.35 MB/s (+/- 1.2 %) 10.74 Mfloat/s
strtod : 190.94 MB/s (+/- 1.6 %) 9.10 Mfloat/s
abseil : 430.45 MB/s (+/- 2.2 %) 20.52 Mfloat/s
fastfloat : 1042.38 MB/s (+/- 9.9 %) 49.68 Mfloat/s
```
See https://github.com/lemire/simple_fastfloat_benchmark for our benchmarking code.
@ -183,23 +234,23 @@ You should change the `GIT_TAG` line so that you recover the version you wish to
## Using as single header
The script `script/amalgamate.py` may be used to generate a single header
The script `script/amalgamate.py` may be used to generate a single header
version of the library if so desired.
Just run the script from the root directory of this repository.
Just run the script from the root directory of this repository.
You can customize the license type and output file if desired as described in
the command line help.
You may directly download automatically generated single-header files:
https://github.com/fastfloat/fast_float/releases/download/v1.1.2/fast_float.h
https://github.com/fastfloat/fast_float/releases/download/v3.4.0/fast_float.h
## Credit
Though this work is inspired by many different people, this work benefited especially from exchanges with
Michael Eisel, who motivated the original research with his key insights, and with Nigel Tao who provided
Though this work is inspired by many different people, this work benefited especially from exchanges with
Michael Eisel, who motivated the original research with his key insights, and with Nigel Tao who provided
invaluable feedback. Rémy Oudompheng first implemented a fast path we use in the case of long digits.
The library includes code adapted from Google Wuffs (written by Nigel Tao) which was originally published
The library includes code adapted from Google Wuffs (written by Nigel Tao) which was originally published
under the Apache 2.0 license.
## License

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright 2016 Blender Foundation. All rights reserved.
# Copyright 2016 Blender Foundation
# Too noisy for code we don't maintain.
if(CMAKE_COMPILER_IS_GNUCC)

View File

@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright 2016 Blender Foundation. All rights reserved.
# Copyright 2016 Blender Foundation
set(INC
src

View File

@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright 2014 Blender Foundation. All rights reserved.
# Copyright 2014 Blender Foundation
set(INC
.

View File

@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright 2014 Blender Foundation. All rights reserved.
# Copyright 2014 Blender Foundation
# avoid noisy warnings
if(CMAKE_COMPILER_IS_GNUCC)

View File

@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright 2021 Blender Foundation. All rights reserved.
# Copyright 2021 Blender Foundation
set(INC
.

View File

@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright 2006 Blender Foundation. All rights reserved.
# Copyright 2006 Blender Foundation
# avoid noisy warnings
if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang")

View File

@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright 2006 Blender Foundation. All rights reserved.
# Copyright 2006 Blender Foundation
remove_strict_flags()

View File

@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright 2016 Blender Foundation. All rights reserved.
# Copyright 2016 Blender Foundation
# The Original Code is: all of this file.
# Contributor(s): Sebastian Barschkis (sebbas).

View File

@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright 2019 Blender Foundation. All rights reserved.
# Copyright 2019 Blender Foundation
# avoid noisy warnings
if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_C_COMPILER_ID MATCHES "Clang")

View File

@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright 2006 Blender Foundation. All rights reserved.
# Copyright 2006 Blender Foundation
set(INC
.

View File

@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright 2017 Blender Foundation. All rights reserved.
# Copyright 2017 Blender Foundation
# The Original Code is: all of this file.
# Contributor(s): IRIE Shinsuke.

View File

@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright 2022 Blender Foundation. All rights reserved.
# Copyright 2022 Blender Foundation
set(INC
.

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2022 Blender Foundation. All rights reserved. */
* Copyright 2022 Blender Foundation */
#ifdef __APPLE__
# include <MoltenVK/vk_mvk_moltenvk.h>

View File

@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright 2013 Blender Foundation. All rights reserved.
# Copyright 2013 Blender Foundation
set(INC
.

View File

@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright 2012 Blender Foundation. All rights reserved.
# Copyright 2012 Blender Foundation
set(INC
.

View File

@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright 2006 Blender Foundation. All rights reserved.
# Copyright 2006 Blender Foundation
# add_subdirectory(atomic) # header only
add_subdirectory(atomic)

View File

@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright 2020 Blender Foundation. All rights reserved.
# Copyright 2020 Blender Foundation
set(INC
.

View File

@ -38,10 +38,8 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2016 Blender Foundation.
* All rights reserved.
*
* The Original Code is: adapted from jemalloc.
* The Original Code is adapted from jemalloc.
* Modifications Copyright (C) 2016 Blender Foundation.
*/
/** \file

View File

@ -38,10 +38,8 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2016 Blender Foundation.
* All rights reserved.
*
* The Original Code is: adapted from jemalloc.
* The Original Code is adapted from jemalloc.
* Modifications Copyright (C) 2016 Blender Foundation.
*/
/** \file

View File

@ -38,10 +38,8 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2016 Blender Foundation.
* All rights reserved.
*
* The Original Code is: adapted from jemalloc.
* The Original Code is adapted from jemalloc.
* Modifications Copyright (C) 2016 Blender Foundation.
*/
/** \file

View File

@ -38,10 +38,8 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2016 Blender Foundation.
* All rights reserved.
*
* The Original Code is: adapted from jemalloc.
* The Original Code is adapted from jemalloc.
* Modifications Copyright (C) 2016 Blender Foundation.
*/
/** \file

View File

@ -590,11 +590,10 @@ bool MetalDeviceQueue::enqueue(DeviceKernel kernel,
[mtlComputeCommandEncoder setThreadgroupMemoryLength:shared_mem_bytes atIndex:0];
}
MTLSize size_threadgroups_per_dispatch = MTLSizeMake(
divide_up(work_size, num_threads_per_block), 1, 1);
MTLSize size_threads_per_dispatch = MTLSizeMake(work_size, 1, 1);
MTLSize size_threads_per_threadgroup = MTLSizeMake(num_threads_per_block, 1, 1);
[mtlComputeCommandEncoder dispatchThreadgroups:size_threadgroups_per_dispatch
threadsPerThreadgroup:size_threads_per_threadgroup];
[mtlComputeCommandEncoder dispatchThreads:size_threads_per_dispatch
threadsPerThreadgroup:size_threads_per_threadgroup];
[mtlCommandBuffer_ addCompletedHandler:^(id<MTLCommandBuffer> command_buffer) {
NSString *kernel_name = metal_kernel_pso->function.label;

View File

@ -91,6 +91,7 @@
#define ccl_gpu_kernel_postfix
#define ccl_gpu_kernel_call(x) x
#define ccl_gpu_kernel_within_bounds(i, n) ((i) < (n))
/* Define a function object where "func" is the lambda body, and additional parameters are used to
* specify captured state */

View File

@ -136,7 +136,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
{
const int global_index = ccl_gpu_global_id_x();
if (global_index < work_size) {
if (ccl_gpu_kernel_within_bounds(global_index, work_size)) {
const int state = (path_index_array) ? path_index_array[global_index] : global_index;
ccl_gpu_kernel_call(integrator_intersect_closest(NULL, state, render_buffer));
}
@ -150,7 +150,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
{
const int global_index = ccl_gpu_global_id_x();
if (global_index < work_size) {
if (ccl_gpu_kernel_within_bounds(global_index, work_size)) {
const int state = (path_index_array) ? path_index_array[global_index] : global_index;
ccl_gpu_kernel_call(integrator_intersect_shadow(NULL, state));
}
@ -164,7 +164,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
{
const int global_index = ccl_gpu_global_id_x();
if (global_index < work_size) {
if (ccl_gpu_kernel_within_bounds(global_index, work_size)) {
const int state = (path_index_array) ? path_index_array[global_index] : global_index;
ccl_gpu_kernel_call(integrator_intersect_subsurface(NULL, state));
}
@ -178,7 +178,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
{
const int global_index = ccl_gpu_global_id_x();
if (global_index < work_size) {
if (ccl_gpu_kernel_within_bounds(global_index, work_size)) {
const int state = (path_index_array) ? path_index_array[global_index] : global_index;
ccl_gpu_kernel_call(integrator_intersect_volume_stack(NULL, state));
}
@ -193,7 +193,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
{
const int global_index = ccl_gpu_global_id_x();
if (global_index < work_size) {
if (ccl_gpu_kernel_within_bounds(global_index, work_size)) {
const int state = (path_index_array) ? path_index_array[global_index] : global_index;
ccl_gpu_kernel_call(integrator_shade_background(NULL, state, render_buffer));
}
@ -208,7 +208,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
{
const int global_index = ccl_gpu_global_id_x();
if (global_index < work_size) {
if (ccl_gpu_kernel_within_bounds(global_index, work_size)) {
const int state = (path_index_array) ? path_index_array[global_index] : global_index;
ccl_gpu_kernel_call(integrator_shade_light(NULL, state, render_buffer));
}
@ -223,7 +223,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
{
const int global_index = ccl_gpu_global_id_x();
if (global_index < work_size) {
if (ccl_gpu_kernel_within_bounds(global_index, work_size)) {
const int state = (path_index_array) ? path_index_array[global_index] : global_index;
ccl_gpu_kernel_call(integrator_shade_shadow(NULL, state, render_buffer));
}
@ -238,7 +238,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
{
const int global_index = ccl_gpu_global_id_x();
if (global_index < work_size) {
if (ccl_gpu_kernel_within_bounds(global_index, work_size)) {
const int state = (path_index_array) ? path_index_array[global_index] : global_index;
ccl_gpu_kernel_call(integrator_shade_surface(NULL, state, render_buffer));
}
@ -257,7 +257,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
{
const int global_index = ccl_gpu_global_id_x();
if (global_index < work_size) {
if (ccl_gpu_kernel_within_bounds(global_index, work_size)) {
const int state = (path_index_array) ? path_index_array[global_index] : global_index;
#if defined(__KERNEL_METAL_APPLE__) && defined(__METALRT__)
@ -281,7 +281,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
{
const int global_index = ccl_gpu_global_id_x();
if (global_index < work_size) {
if (ccl_gpu_kernel_within_bounds(global_index, work_size)) {
const int state = (path_index_array) ? path_index_array[global_index] : global_index;
ccl_gpu_kernel_call(integrator_shade_surface_mnee(NULL, state, render_buffer));
}
@ -296,7 +296,7 @@ ccl_gpu_kernel(GPU_KERNEL_BLOCK_NUM_THREADS, GPU_KERNEL_MAX_REGISTERS)
{
const int global_index = ccl_gpu_global_id_x();
if (global_index < work_size) {
if (ccl_gpu_kernel_within_bounds(global_index, work_size)) {
const int state = (path_index_array) ? path_index_array[global_index] : global_index;
ccl_gpu_kernel_call(integrator_shade_volume(NULL, state, render_buffer));
}
@ -492,7 +492,7 @@ ccl_gpu_kernel_threads(GPU_PARALLEL_SORTED_INDEX_DEFAULT_BLOCK_SIZE)
{
const int global_index = ccl_gpu_global_id_x();
if (global_index < work_size) {
if (ccl_gpu_kernel_within_bounds(global_index, work_size)) {
const int from_state = active_terminated_states[active_states_offset + global_index];
const int to_state = active_terminated_states[terminated_states_offset + global_index];
@ -526,7 +526,7 @@ ccl_gpu_kernel_threads(GPU_PARALLEL_SORTED_INDEX_DEFAULT_BLOCK_SIZE)
{
const int global_index = ccl_gpu_global_id_x();
if (global_index < work_size) {
if (ccl_gpu_kernel_within_bounds(global_index, work_size)) {
const int from_state = active_terminated_states[active_states_offset + global_index];
const int to_state = active_terminated_states[terminated_states_offset + global_index];

View File

@ -34,6 +34,7 @@
#define ccl_gpu_kernel_postfix
#define ccl_gpu_kernel_call(x) x
#define ccl_gpu_kernel_within_bounds(i, n) ((i) < (n))
/* Define a function object where "func" is the lambda body, and additional parameters are used to
* specify captured state */

View File

@ -143,6 +143,7 @@ void kernel_gpu_##name::run(thread MetalKernelContext& context, \
#define ccl_gpu_kernel_postfix
#define ccl_gpu_kernel_call(x) context.x
#define ccl_gpu_kernel_within_bounds(i,n) true
/* define a function object where "func" is the lambda body, and additional parameters are used to specify captured state */
#define ccl_gpu_kernel_lambda(func, ...) \

View File

@ -289,9 +289,8 @@ bool metalrt_shadow_all_hit(constant KernelParamsMetal &launch_params_metal,
}
if (ray_tmax >= max_recorded_t) {
/* Accept hit, so that we don't consider any more hits beyond the distance of the
* current hit anymore. */
payload.result = true;
/* Ray hits are not guaranteed to be ordered by distance so don't exit early here.
* Continue search. */
return true;
}

View File

@ -101,6 +101,7 @@ void oneapi_kernel_##name(KernelGlobalsGPU *ccl_restrict kg, \
#endif
#define ccl_gpu_kernel_call(x) ((ONEAPIKernelContext*)kg)->x
#define ccl_gpu_kernel_within_bounds(i, n) ((i) < (n))
#define ccl_gpu_kernel_lambda(func, ...) \
struct KernelLambda \

View File

@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright 2015 Blender Foundation. All rights reserved.
# Copyright 2015 Blender Foundation
set(INC
.

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2015 Blender Foundation. All rights reserved. */
* Copyright 2015 Blender Foundation */
/** \file
* \ingroup intern_eigen

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2015 Blender Foundation. All rights reserved. */
* Copyright 2015 Blender Foundation */
#ifndef __EIGEN3_EIGENVALUES_C_API_CC__
#define __EIGEN3_EIGENVALUES_C_API_CC__

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2015 Blender Foundation. All rights reserved. */
* Copyright 2015 Blender Foundation */
/** \file
* \ingroup intern_eigen

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2018 Blender Foundation. All rights reserved. */
* Copyright 2018 Blender Foundation */
/** \file
* \ingroup intern_eigen

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2015 Blender Foundation. All rights reserved. */
* Copyright 2015 Blender Foundation */
/** \file
* \ingroup intern_eigen

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2015 Blender Foundation. All rights reserved. */
* Copyright 2015 Blender Foundation */
/** \file
* \ingroup intern_eigen

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2015 Blender Foundation. All rights reserved. */
* Copyright 2015 Blender Foundation */
/** \file
* \ingroup intern_eigen

View File

@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright 2020 Blender Foundation. All rights reserved.
# Copyright 2020 Blender Foundation
if(WITH_GTESTS)
set(TEST_SRC

View File

@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright 2006 Blender Foundation. All rights reserved.
# Copyright 2006 Blender Foundation
set(INC
.
@ -378,6 +378,14 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND)
unset(_name)
endmacro()
macro(generate_protocol_bindings_when_found PROT_DEF FOUND_VAR)
if(EXISTS ${PROT_DEF})
generate_protocol_bindings(${PROT_DEF})
set(${FOUND_VAR} TRUE)
else()
set(${FOUND_VAR} FALSE)
endif()
endmacro()
list(APPEND INC_SYS
${INC_DST}
@ -402,6 +410,17 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND)
generate_protocol_bindings(
"${WAYLAND_PROTOCOLS_DIR}/staging/xdg-activation/xdg-activation-v1.xml"
)
# Fractional scale.
generate_protocol_bindings_when_found(
"${WAYLAND_PROTOCOLS_DIR}/staging/fractional-scale/fractional-scale-v1.xml"
_has_fractional_scale
)
if(_has_fractional_scale)
# Viewport (only required when fractional scale is in use).
generate_protocol_bindings(
"${WAYLAND_PROTOCOLS_DIR}/stable/viewporter/viewporter.xml"
)
endif()
# Pointer-constraints.
generate_protocol_bindings(
"${WAYLAND_PROTOCOLS_DIR}/unstable/pointer-constraints/pointer-constraints-unstable-v1.xml"
@ -427,6 +446,11 @@ elseif(WITH_GHOST_X11 OR WITH_GHOST_WAYLAND)
add_definitions(-DWITH_GHOST_WAYLAND)
if(_has_fractional_scale)
add_definitions(-DWITH_GHOST_WAYLAND_FRACTIONAL_SCALE)
endif()
unset(_has_fractional_scale)
if(NOT WITH_GHOST_WAYLAND_APP_ID STREQUAL "")
add_definitions(-DWITH_GHOST_WAYLAND_APP_ID=${WITH_GHOST_WAYLAND_APP_ID})
endif()

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2009 Blender Foundation. All rights reserved. */
* Copyright 2009 Blender Foundation */
/** \file
* \ingroup GHOST

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2010 Blender Foundation. All rights reserved. */
* Copyright 2010 Blender Foundation */
/** \file
* \ingroup GHOST

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2013 Blender Foundation. All rights reserved. */
* Copyright 2013 Blender Foundation */
/** \file
* \ingroup GHOST

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2013 Blender Foundation. All rights reserved. */
* Copyright 2013 Blender Foundation */
/** \file
* \ingroup GHOST

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2014 Blender Foundation. All rights reserved. */
* Copyright 2014 Blender Foundation */
/** \file
* \ingroup GHOST

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2013 Blender Foundation. All rights reserved. */
* Copyright 2013 Blender Foundation */
/** \file
* \ingroup GHOST

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2013 Blender Foundation. All rights reserved. */
* Copyright 2013 Blender Foundation */
/** \file
* \ingroup GHOST

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2013 Blender Foundation. All rights reserved. */
* Copyright 2013 Blender Foundation */
/** \file
* \ingroup GHOST

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2014 Blender Foundation. All rights reserved. */
* Copyright 2014 Blender Foundation */
/** \file
* \ingroup GHOST

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2014 Blender Foundation. All rights reserved. */
* Copyright 2014 Blender Foundation */
/** \file
* \ingroup GHOST

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2013 Blender Foundation. All rights reserved. */
* Copyright 2013 Blender Foundation */
/** \file
* \ingroup GHOST

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2013 Blender Foundation. All rights reserved. */
* Copyright 2013 Blender Foundation */
/** \file
* \ingroup GHOST

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2014 Blender Foundation. All rights reserved. */
* Copyright 2014 Blender Foundation */
/** \file
* \ingroup GHOST

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2014 Blender Foundation. All rights reserved. */
* Copyright 2014 Blender Foundation */
/** \file
* \ingroup GHOST

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2013 Blender Foundation. All rights reserved. */
* Copyright 2013 Blender Foundation */
/** \file
* \ingroup GHOST

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2013 Blender Foundation. All rights reserved. */
* Copyright 2013 Blender Foundation */
/** \file
* \ingroup GHOST

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2012 Blender Foundation. All rights reserved. */
* Copyright 2012 Blender Foundation */
/** \file
* \ingroup GHOST

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2012 Blender Foundation. All rights reserved. */
* Copyright 2012 Blender Foundation */
/** \file
* \ingroup GHOST

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2010 Blender Foundation. All rights reserved. */
* Copyright 2010 Blender Foundation */
/** \file
* \ingroup GHOST

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2010 Blender Foundation. All rights reserved. */
* Copyright 2010 Blender Foundation */
/** \file
* \ingroup GHOST

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2010 Blender Foundation. All rights reserved. */
* Copyright 2010 Blender Foundation */
/** \file
* \ingroup GHOST

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2009 Blender Foundation. All rights reserved. */
* Copyright 2009 Blender Foundation */
/** \file
* \ingroup GHOST

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2010 Blender Foundation. All rights reserved. */
* Copyright 2010 Blender Foundation */
/** \file
* \ingroup GHOST

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2010 Blender Foundation. All rights reserved. */
* Copyright 2010 Blender Foundation */
#import <Foundation/Foundation.h>

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2010 Blender Foundation. All rights reserved. */
* Copyright 2010 Blender Foundation */
/** \file
* \ingroup GHOST

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2010 Blender Foundation. All rights reserved. */
* Copyright 2010 Blender Foundation */
/** \file
* \ingroup GHOST

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2011 Blender Foundation. All rights reserved. */
* Copyright 2011 Blender Foundation */
/** \file
* \ingroup GHOST

View File

@ -61,6 +61,10 @@
#include <tablet-unstable-v2-client-protocol.h>
#include <xdg-activation-v1-client-protocol.h>
#include <xdg-output-unstable-v1-client-protocol.h>
#ifdef WITH_GHOST_WAYLAND_FRACTIONAL_SCALE
# include <fractional-scale-v1-client-protocol.h>
# include <viewporter-client-protocol.h>
#endif
/* Decorations `xdg_decor`. */
#include <xdg-decoration-unstable-v1-client-protocol.h>
@ -205,6 +209,14 @@ static bool use_gnome_confine_hack = false;
#define WL_NAME_UNSET uint32_t(-1)
/**
* Initializer for GHOST integer coordinates from `wl_fixed_t`,
* taking window scale into account.
*/
#define WL_FIXED_TO_INT_FOR_WINDOW_V2(win, xy) \
wl_fixed_to_int((win)->wl_fixed_to_window((xy)[0])), \
wl_fixed_to_int((win)->wl_fixed_to_window((xy)[1])),
/** \} */
/* -------------------------------------------------------------------- */
@ -936,6 +948,10 @@ struct GWL_Display {
struct zwp_relative_pointer_manager_v1 *wp_relative_pointer_manager = nullptr;
struct zwp_primary_selection_device_manager_v1 *wp_primary_selection_device_manager = nullptr;
struct xdg_activation_v1 *xdg_activation_manager = nullptr;
#ifdef WITH_GHOST_WAYLAND_FRACTIONAL_SCALE
struct wp_fractional_scale_manager_v1 *wp_fractional_scale_manager = nullptr;
struct wp_viewporter *wp_viewporter = nullptr;
#endif
struct zwp_pointer_constraints_v1 *wp_pointer_constraints = nullptr;
struct zwp_pointer_gestures_v1 *wp_pointer_gestures = nullptr;
@ -1925,8 +1941,6 @@ static void relative_pointer_handle_relative_motion_impl(GWL_Seat *seat,
GHOST_WindowWayland *win,
const wl_fixed_t xy[2])
{
const wl_fixed_t scale = win->scale();
seat->pointer.xy[0] = xy[0];
seat->pointer.xy[1] = xy[1];
@ -1937,21 +1951,19 @@ static void relative_pointer_handle_relative_motion_impl(GWL_Seat *seat,
/* Needed or the cursor is considered outside the window and doesn't restore the location. */
bounds.m_r -= 1;
bounds.m_b -= 1;
bounds.m_l = wl_fixed_from_int(bounds.m_l) / scale;
bounds.m_t = wl_fixed_from_int(bounds.m_t) / scale;
bounds.m_r = wl_fixed_from_int(bounds.m_r) / scale;
bounds.m_b = wl_fixed_from_int(bounds.m_b) / scale;
bounds.m_l = win->wl_fixed_from_window(wl_fixed_from_int(bounds.m_l));
bounds.m_t = win->wl_fixed_from_window(wl_fixed_from_int(bounds.m_t));
bounds.m_r = win->wl_fixed_from_window(wl_fixed_from_int(bounds.m_r));
bounds.m_b = win->wl_fixed_from_window(wl_fixed_from_int(bounds.m_b));
bounds.clampPoint(UNPACK2(seat->pointer.xy));
}
#endif
seat->system->pushEvent_maybe_pending(
new GHOST_EventCursor(seat->system->getMilliSeconds(),
GHOST_kEventCursorMove,
win,
wl_fixed_to_int(scale * seat->pointer.xy[0]),
wl_fixed_to_int(scale * seat->pointer.xy[1]),
GHOST_TABLET_DATA_NONE));
const int event_xy[2] = {WL_FIXED_TO_INT_FOR_WINDOW_V2(win, seat->pointer.xy)};
seat->system->pushEvent_maybe_pending(new GHOST_EventCursor(seat->system->getMilliSeconds(),
GHOST_kEventCursorMove,
win,
UNPACK2(event_xy),
GHOST_TABLET_DATA_NONE));
}
static void relative_pointer_handle_relative_motion(
@ -1968,10 +1980,9 @@ static void relative_pointer_handle_relative_motion(
if (wl_surface *wl_surface_focus = seat->pointer.wl_surface_window) {
CLOG_INFO(LOG, 2, "relative_motion");
GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus);
const wl_fixed_t scale = win->scale();
const wl_fixed_t xy_next[2] = {
seat->pointer.xy[0] + (dx / scale),
seat->pointer.xy[1] + (dy / scale),
seat->pointer.xy[0] + win->wl_fixed_from_window(dx),
seat->pointer.xy[1] + win->wl_fixed_from_window(dy),
};
relative_pointer_handle_relative_motion_impl(seat, win, xy_next);
}
@ -2000,12 +2011,7 @@ static void dnd_events(const GWL_Seat *const seat, const GHOST_TEventType event)
/* NOTE: `seat->data_offer_dnd_mutex` must already be locked. */
if (wl_surface *wl_surface_focus = seat->wl_surface_window_focus_dnd) {
GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus);
const wl_fixed_t scale = win->scale();
const int event_xy[2] = {
wl_fixed_to_int(scale * seat->data_offer_dnd->dnd.xy[0]),
wl_fixed_to_int(scale * seat->data_offer_dnd->dnd.xy[1]),
};
const int event_xy[2] = {WL_FIXED_TO_INT_FOR_WINDOW_V2(win, seat->data_offer_dnd->dnd.xy)};
const uint64_t time = seat->system->getMilliSeconds();
for (size_t i = 0; i < ARRAY_SIZE(ghost_wl_mime_preference_order_type); i++) {
const GHOST_TDragnDropTypes type = ghost_wl_mime_preference_order_type[i];
@ -2477,13 +2483,12 @@ static void data_device_handle_drop(void *data, struct wl_data_device * /*wl_dat
}
CLOG_INFO(LOG, 2, "drop_read_uris_fn file_count=%d", flist->count);
const wl_fixed_t scale = win->scale();
const int event_xy[2] = {WL_FIXED_TO_INT_FOR_WINDOW_V2(win, xy)};
system->pushEvent_maybe_pending(new GHOST_EventDragnDrop(system->getMilliSeconds(),
GHOST_kEventDraggingDropDone,
GHOST_kDragnDropTypeFilenames,
win,
wl_fixed_to_int(scale * xy[0]),
wl_fixed_to_int(scale * xy[1]),
UNPACK2(event_xy),
flist));
}
else if (ELEM(mime_receive, ghost_wl_mime_text_plain, ghost_wl_mime_text_utf8)) {
@ -2685,14 +2690,12 @@ static void pointer_handle_enter(void *data,
seat->system->cursor_shape_set(win->getCursorShape());
const wl_fixed_t scale = win->scale();
seat->system->pushEvent_maybe_pending(
new GHOST_EventCursor(seat->system->getMilliSeconds(),
GHOST_kEventCursorMove,
win,
wl_fixed_to_int(scale * seat->pointer.xy[0]),
wl_fixed_to_int(scale * seat->pointer.xy[1]),
GHOST_TABLET_DATA_NONE));
const int event_xy[2] = {WL_FIXED_TO_INT_FOR_WINDOW_V2(win, seat->pointer.xy)};
seat->system->pushEvent_maybe_pending(new GHOST_EventCursor(seat->system->getMilliSeconds(),
GHOST_kEventCursorMove,
win,
UNPACK2(event_xy),
GHOST_TABLET_DATA_NONE));
}
static void pointer_handle_leave(void *data,
@ -2723,14 +2726,12 @@ static void pointer_handle_motion(void *data,
if (wl_surface *wl_surface_focus = seat->pointer.wl_surface_window) {
CLOG_INFO(LOG, 2, "motion");
GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus);
const wl_fixed_t scale = win->scale();
seat->system->pushEvent_maybe_pending(
new GHOST_EventCursor(seat->system->getMilliSeconds(),
GHOST_kEventCursorMove,
win,
wl_fixed_to_int(scale * seat->pointer.xy[0]),
wl_fixed_to_int(scale * seat->pointer.xy[1]),
GHOST_TABLET_DATA_NONE));
const int event_xy[2] = {WL_FIXED_TO_INT_FOR_WINDOW_V2(win, seat->pointer.xy)};
seat->system->pushEvent_maybe_pending(new GHOST_EventCursor(seat->system->getMilliSeconds(),
GHOST_kEventCursorMove,
win,
UNPACK2(event_xy),
GHOST_TABLET_DATA_NONE));
}
else {
CLOG_INFO(LOG, 2, "motion (skipped)");
@ -2849,13 +2850,12 @@ static void pointer_handle_frame(void *data, struct wl_pointer * /*wl_pointer*/)
if (seat->pointer_scroll.smooth_xy[0] || seat->pointer_scroll.smooth_xy[1]) {
if (wl_surface *wl_surface_focus = seat->pointer.wl_surface_window) {
GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus);
const wl_fixed_t scale = win->scale();
const int event_xy[2] = {WL_FIXED_TO_INT_FOR_WINDOW_V2(win, seat->pointer.xy)};
seat->system->pushEvent_maybe_pending(new GHOST_EventTrackpad(
seat->system->getMilliSeconds(),
win,
GHOST_kTrackpadEventScroll,
wl_fixed_to_int(scale * seat->pointer.xy[0]),
wl_fixed_to_int(scale * seat->pointer.xy[1]),
UNPACK2(event_xy),
/* NOTE: scaling the delta doesn't seem necessary.
* NOTE: inverting delta gives correct results, see: QTBUG-85767.
* NOTE: the preference to invert scrolling (in GNOME at least)
@ -3014,19 +3014,6 @@ static void gesture_pinch_handle_begin(void *data,
if (wl_surface *wl_surface_focus = seat->pointer.wl_surface_window) {
win = ghost_wl_surface_user_data(wl_surface_focus);
}
/* NOTE(@ideasman42): Blender's use of track-pad 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 this window scale is not correct because it doesn't account for:
* 1) Fractional window scale.
* 2) Blender's UI scale preference (which GHOST doesn't know about).
*
* If support for this were all that was needed it could be handled in GHOST,
* however as the operators are not even using coordinates compatible with each other,
* it would be better to resolve this by passing rotation & zoom levels directly,
* instead of attempting to handle them as cursor coordinates.
*/
const wl_fixed_t win_scale = win ? win->scale() : 1;
/* NOTE(@ideasman42): Scale factors match Blender's operators & default preferences.
* For these values to work correctly, operator logic will need to be changed not to scale input
@ -3041,10 +3028,30 @@ static void gesture_pinch_handle_begin(void *data,
seat->pointer_gesture_pinch.scale.value = wl_fixed_from_int(1);
/* The value 300 matches a value used in clip & image zoom operators.
* It seems OK for the 3D view too. */
seat->pointer_gesture_pinch.scale.factor = 300 * win_scale;
seat->pointer_gesture_pinch.scale.factor = 300;
/* The value 5 is used on macOS and roughly maps 1:1 with turntable rotation,
* although preferences can scale the sensitivity (which would be skipped ideally). */
seat->pointer_gesture_pinch.rotation.factor = 5 * win_scale;
seat->pointer_gesture_pinch.rotation.factor = 5;
if (win) {
/* NOTE(@ideasman42): Blender's use of track-pad 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 this window scale is not correct because it doesn't account for:
* 1) Fractional window scale.
* 2) Blender's UI scale preference (which GHOST doesn't know about).
*
* If support for this were all that was needed it could be handled in GHOST,
* however as the operators are not even using coordinates compatible with each other,
* it would be better to resolve this by passing rotation & zoom levels directly,
* instead of attempting to handle them as cursor coordinates.
*/
const struct GWL_WindowScaleParams &scale_params = win->scale_params();
seat->pointer_gesture_pinch.scale.factor = gwl_window_scale_int_to(
scale_params, seat->pointer_gesture_pinch.scale.factor);
seat->pointer_gesture_pinch.rotation.factor = gwl_window_scale_int_to(
scale_params, seat->pointer_gesture_pinch.rotation.factor);
}
}
static void gesture_pinch_handle_update(void *data,
@ -3082,11 +3089,7 @@ static void gesture_pinch_handle_update(void *data,
&seat->pointer_gesture_pinch.rotation, rotation);
if (win) {
const wl_fixed_t win_scale = win->scale();
const int32_t event_xy[2] = {
wl_fixed_to_int(win_scale * seat->pointer.xy[0]),
wl_fixed_to_int(win_scale * seat->pointer.xy[1]),
};
const int event_xy[2] = {WL_FIXED_TO_INT_FOR_WINDOW_V2(win, seat->pointer.xy)};
if (scale_as_delta_px) {
seat->system->pushEvent_maybe_pending(
new GHOST_EventTrackpad(seat->system->getMilliSeconds(),
@ -3566,14 +3569,12 @@ static void tablet_tool_handle_frame(void *data,
/* No need to check the surfaces origin, it's already known to be owned by GHOST. */
if (wl_surface *wl_surface_focus = seat->tablet.wl_surface_window) {
GHOST_WindowWayland *win = ghost_wl_surface_user_data(wl_surface_focus);
const wl_fixed_t scale = win->scale();
seat->system->pushEvent_maybe_pending(
new GHOST_EventCursor(seat->system->getMilliSeconds(),
GHOST_kEventCursorMove,
win,
wl_fixed_to_int(scale * seat->tablet.xy[0]),
wl_fixed_to_int(scale * seat->tablet.xy[1]),
tablet_tool->data));
const int event_xy[2] = {WL_FIXED_TO_INT_FOR_WINDOW_V2(win, seat->tablet.xy)};
seat->system->pushEvent_maybe_pending(new GHOST_EventCursor(seat->system->getMilliSeconds(),
GHOST_kEventCursorMove,
win,
UNPACK2(event_xy),
tablet_tool->data));
if (tablet_tool->proximity == false) {
seat->system->cursor_shape_set(win->getCursorShape());
}
@ -5181,6 +5182,47 @@ static void gwl_registry_xdg_activation_remove(GWL_Display *display,
*value_p = nullptr;
}
/* #GWL_Display.wp_fractional_scale_manger */
#ifdef WITH_GHOST_WAYLAND_FRACTIONAL_SCALE
static void gwl_registry_wp_fractional_scale_manager_add(GWL_Display *display,
const GWL_RegisteryAdd_Params *params)
{
display->wp_fractional_scale_manager = static_cast<wp_fractional_scale_manager_v1 *>(
wl_registry_bind(
display->wl_registry, params->name, &wp_fractional_scale_manager_v1_interface, 1));
gwl_registry_entry_add(display, params, nullptr);
}
static void gwl_registry_wp_fractional_scale_manager_remove(GWL_Display *display,
void * /*user_data*/,
const bool /*on_exit*/)
{
struct wp_fractional_scale_manager_v1 **value_p = &display->wp_fractional_scale_manager;
wp_fractional_scale_manager_v1_destroy(*value_p);
*value_p = nullptr;
}
/* #GWL_Display.wl_viewport */
static void gwl_registry_wp_viewporter_add(GWL_Display *display,
const GWL_RegisteryAdd_Params *params)
{
display->wp_viewporter = static_cast<wp_viewporter *>(
wl_registry_bind(display->wl_registry, params->name, &wp_viewporter_interface, 1));
gwl_registry_entry_add(display, params, nullptr);
}
static void gwl_registry_wp_viewporter_remove(GWL_Display *display,
void * /*user_data*/,
const bool /*on_exit*/)
{
struct wp_viewporter **value_p = &display->wp_viewporter;
wp_viewporter_destroy(*value_p);
*value_p = nullptr;
}
#endif /* WITH_GHOST_WAYLAND_FRACTIONAL_SCALE */
/* #GWL_Display.wp_primary_selection_device_manager */
static void gwl_registry_wp_primary_selection_device_manager_add(
@ -5290,6 +5332,20 @@ static const GWL_RegistryHandler gwl_registry_handlers[] = {
/*update_fn*/ nullptr,
/*remove_fn*/ gwl_registry_xdg_activation_remove,
},
#ifdef WITH_GHOST_WAYLAND_FRACTIONAL_SCALE
{
/*interface_p*/ &wp_fractional_scale_manager_v1_interface.name,
/*add_fn*/ gwl_registry_wp_fractional_scale_manager_add,
/*update_fn*/ nullptr,
/*remove_fn*/ gwl_registry_wp_fractional_scale_manager_remove,
},
{
/*interface_p*/ &wp_viewporter_interface.name,
/*add_fn*/ gwl_registry_wp_viewporter_add,
/*update_fn*/ nullptr,
/*remove_fn*/ gwl_registry_wp_viewporter_remove,
},
#endif /* WITH_GHOST_WAYLAND_FRACTIONAL_SCALE */
/* Display outputs. */
{
/*interface_p*/ &wl_output_interface.name,
@ -6020,7 +6076,6 @@ static GHOST_TSuccess getCursorPositionClientRelative_impl(
int32_t &x,
int32_t &y)
{
const wl_fixed_t scale = win->scale();
if (win->getCursorGrabModeIsWarp()) {
/* As the cursor is restored at the warped location,
@ -6037,18 +6092,19 @@ static GHOST_TSuccess getCursorPositionClientRelative_impl(
};
GHOST_Rect wrap_bounds_scale;
wrap_bounds_scale.m_l = wl_fixed_from_int(wrap_bounds.m_l) / scale;
wrap_bounds_scale.m_t = wl_fixed_from_int(wrap_bounds.m_t) / scale;
wrap_bounds_scale.m_r = wl_fixed_from_int(wrap_bounds.m_r) / scale;
wrap_bounds_scale.m_b = wl_fixed_from_int(wrap_bounds.m_b) / scale;
wrap_bounds_scale.m_l = win->wl_fixed_from_window(wl_fixed_from_int(wrap_bounds.m_l));
wrap_bounds_scale.m_t = win->wl_fixed_from_window(wl_fixed_from_int(wrap_bounds.m_t));
wrap_bounds_scale.m_r = win->wl_fixed_from_window(wl_fixed_from_int(wrap_bounds.m_r));
wrap_bounds_scale.m_b = win->wl_fixed_from_window(wl_fixed_from_int(wrap_bounds.m_b));
wrap_bounds_scale.wrapPoint(UNPACK2(xy_wrap), 0, win->getCursorGrabAxis());
x = wl_fixed_to_int(scale * xy_wrap[0]);
y = wl_fixed_to_int(scale * xy_wrap[1]);
x = wl_fixed_to_int(win->wl_fixed_to_window(xy_wrap[0]));
y = wl_fixed_to_int(win->wl_fixed_to_window(xy_wrap[1]));
}
else {
x = wl_fixed_to_int(scale * seat_state_pointer->xy[0]);
y = wl_fixed_to_int(scale * seat_state_pointer->xy[1]);
x = win->wl_fixed_to_window(seat_state_pointer->xy[0]);
y = win->wl_fixed_to_window(seat_state_pointer->xy[1]);
}
return GHOST_kSuccess;
@ -6065,10 +6121,9 @@ static GHOST_TSuccess setCursorPositionClientRelative_impl(GWL_Seat *seat,
if (!seat->wp_relative_pointer) {
return GHOST_kFailure;
}
const wl_fixed_t scale = win->scale();
const wl_fixed_t xy_next[2] = {
wl_fixed_from_int(x) / scale,
wl_fixed_from_int(y) / scale,
const wl_fixed_t xy_next[2]{
win->wl_fixed_from_window(wl_fixed_from_int(x)),
win->wl_fixed_from_window(wl_fixed_from_int(y)),
};
/* As the cursor was "warped" generate an event at the new location. */
@ -6855,6 +6910,17 @@ struct xdg_activation_v1 *GHOST_SystemWayland::xdg_activation_manager()
return display_->xdg_activation_manager;
}
#ifdef WITH_GHOST_WAYLAND_FRACTIONAL_SCALE
struct wp_fractional_scale_manager_v1 *GHOST_SystemWayland::wp_fractional_scale_manager()
{
return display_->wp_fractional_scale_manager;
}
struct wp_viewporter *GHOST_SystemWayland::wp_viewporter()
{
return display_->wp_viewporter;
}
#endif /* WITH_GHOST_WAYLAND_FRACTIONAL_SCALE */
struct zwp_pointer_gestures_v1 *GHOST_SystemWayland::wp_pointer_gestures()
{
return display_->wp_pointer_gestures;
@ -7070,7 +7136,7 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod
const GHOST_Rect *wrap_bounds,
const GHOST_TAxisFlag wrap_axis,
wl_surface *wl_surface,
const int scale)
const struct GWL_WindowScaleParams &scale_params)
{
/* Caller must lock `server_mutex`. */
@ -7130,10 +7196,14 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod
GHOST_Rect bounds_scale;
bounds_scale.m_l = wl_fixed_from_int(wrap_bounds->m_l) / scale;
bounds_scale.m_t = wl_fixed_from_int(wrap_bounds->m_t) / scale;
bounds_scale.m_r = wl_fixed_from_int(wrap_bounds->m_r) / scale;
bounds_scale.m_b = wl_fixed_from_int(wrap_bounds->m_b) / scale;
bounds_scale.m_l = gwl_window_scale_wl_fixed_from(scale_params,
wl_fixed_from_int(wrap_bounds->m_l));
bounds_scale.m_t = gwl_window_scale_wl_fixed_from(scale_params,
wl_fixed_from_int(wrap_bounds->m_t));
bounds_scale.m_r = gwl_window_scale_wl_fixed_from(scale_params,
wl_fixed_from_int(wrap_bounds->m_r));
bounds_scale.m_b = gwl_window_scale_wl_fixed_from(scale_params,
wl_fixed_from_int(wrap_bounds->m_b));
bounds_scale.wrapPoint(UNPACK2(xy_next), 0, wrap_axis);
@ -7153,8 +7223,8 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod
if ((init_grab_xy[0] != seat->grab_lock_xy[0]) ||
(init_grab_xy[1] != seat->grab_lock_xy[1])) {
const wl_fixed_t xy_next[2] = {
wl_fixed_from_int(init_grab_xy[0]) / scale,
wl_fixed_from_int(init_grab_xy[1]) / scale,
gwl_window_scale_wl_fixed_from(scale_params, wl_fixed_from_int(init_grab_xy[0])),
gwl_window_scale_wl_fixed_from(scale_params, wl_fixed_from_int(init_grab_xy[1])),
};
zwp_locked_pointer_v1_set_cursor_position_hint(seat->wp_locked_pointer,
UNPACK2(xy_next));
@ -7179,13 +7249,13 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod
#endif
if (xy_motion_create_event) {
seat->system->pushEvent_maybe_pending(
new GHOST_EventCursor(seat->system->getMilliSeconds(),
GHOST_kEventCursorMove,
ghost_wl_surface_user_data(wl_surface),
wl_fixed_to_int(scale * xy_motion[0]),
wl_fixed_to_int(scale * xy_motion[1]),
GHOST_TABLET_DATA_NONE));
seat->system->pushEvent_maybe_pending(new GHOST_EventCursor(
seat->system->getMilliSeconds(),
GHOST_kEventCursorMove,
ghost_wl_surface_user_data(wl_surface),
wl_fixed_to_int(gwl_window_scale_wl_fixed_to(scale_params, xy_motion[0])),
wl_fixed_to_int(gwl_window_scale_wl_fixed_to(scale_params, xy_motion[1])),
GHOST_TABLET_DATA_NONE));
}
zwp_locked_pointer_v1_destroy(seat->wp_locked_pointer);
@ -7221,8 +7291,10 @@ bool GHOST_SystemWayland::window_cursor_grab_set(const GHOST_TGrabCursorMode mod
if (mode == GHOST_kGrabHide) {
/* Set the initial position to detect any changes when un-grabbing,
* otherwise the unlocked cursor defaults to un-locking in-place. */
init_grab_xy[0] = wl_fixed_to_int(scale * seat->pointer.xy[0]);
init_grab_xy[1] = wl_fixed_to_int(scale * seat->pointer.xy[1]);
init_grab_xy[0] = wl_fixed_to_int(
gwl_window_scale_wl_fixed_to(scale_params, seat->pointer.xy[0]));
init_grab_xy[1] = wl_fixed_to_int(
gwl_window_scale_wl_fixed_to(scale_params, seat->pointer.xy[1]));
seat->grab_lock_xy[0] = init_grab_xy[0];
seat->grab_lock_xy[1] = init_grab_xy[1];
}

View File

@ -47,6 +47,26 @@ void ghost_wl_surface_tag_cursor_pointer(struct wl_surface *surface);
bool ghost_wl_surface_own_cursor_tablet(const struct wl_surface *surface);
void ghost_wl_surface_tag_cursor_tablet(struct wl_surface *surface);
/* Scaling to: translates from WAYLAND into GHOST (viewport local) coordinates.
* Scaling from: performs the reverse translation.
*
* Scaling "to" is used to map WAYLAND location cursor coordinates to GHOST coordinates.
* Scaling "from" is used to clamp cursor coordinates in WAYLAND local coordinates. */
struct GWL_WindowScaleParams;
wl_fixed_t gwl_window_scale_wl_fixed_to(const GWL_WindowScaleParams &scale_params,
wl_fixed_t value);
wl_fixed_t gwl_window_scale_wl_fixed_from(const GWL_WindowScaleParams &scale_params,
wl_fixed_t value);
/* Avoid this where possible as scaling integers often incurs rounding errors.
* Scale #wl_fixed_t where possible.
*
* In general scale by large values where this is less likely to be a problem. */
int gwl_window_scale_int_to(const GWL_WindowScaleParams &scale_params, int value);
int gwl_window_scale_int_from(const GWL_WindowScaleParams &scale_params, int value);
#ifdef WITH_GHOST_WAYLAND_DYNLOAD
/**
* Return true when all required WAYLAND libraries are present,
@ -181,6 +201,10 @@ class GHOST_SystemWayland : public GHOST_System {
struct zwp_primary_selection_device_manager_v1 *wp_primary_selection_manager();
struct xdg_activation_v1 *xdg_activation_manager();
struct zwp_pointer_gestures_v1 *wp_pointer_gestures();
#ifdef WITH_GHOST_WAYLAND_FRACTIONAL_SCALE
struct wp_fractional_scale_manager_v1 *wp_fractional_scale_manager();
struct wp_viewporter *wp_viewporter();
#endif
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
libdecor *libdecor_context();
@ -234,7 +258,7 @@ class GHOST_SystemWayland : public GHOST_System {
const GHOST_Rect *wrap_bounds,
GHOST_TAxisFlag wrap_axis,
wl_surface *wl_surface,
int scale);
const struct GWL_WindowScaleParams &scale_params);
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
static bool use_libdecor_runtime();

View File

@ -38,6 +38,11 @@
#include <xdg-activation-v1-client-protocol.h>
#include <xdg-decoration-unstable-v1-client-protocol.h>
#include <xdg-shell-client-protocol.h>
#ifdef WITH_GHOST_WAYLAND_FRACTIONAL_SCALE
# include <fractional-scale-v1-client-protocol.h>
# include <viewporter-client-protocol.h>
# define FRACTIONAL_DENOMINATOR 120
#endif
#include <atomic>
@ -83,15 +88,92 @@ static void gwl_xdg_decor_window_destroy(WGL_XDG_Decor_Window *decor)
delete decor;
}
/* -------------------------------------------------------------------- */
/** \name Window-Viewport/Wayland to/from Scale Conversion
* \{ */
struct GWL_WindowScaleParams {
bool is_fractional = false;
/**
* When fractional:
* Scale is multiplied by #FRACTIONAL_DENOMINATOR.
* Otherwise scale is an integer.
*/
wl_fixed_t scale = 0;
};
wl_fixed_t gwl_window_scale_wl_fixed_to(const GWL_WindowScaleParams &scale_params,
wl_fixed_t value)
{
#ifdef WITH_GHOST_WAYLAND_FRACTIONAL_SCALE
if (scale_params.is_fractional) {
return (value * scale_params.scale) / FRACTIONAL_DENOMINATOR;
}
#endif
return value * scale_params.scale;
}
wl_fixed_t gwl_window_scale_wl_fixed_from(const GWL_WindowScaleParams &scale_params,
wl_fixed_t value)
{
#ifdef WITH_GHOST_WAYLAND_FRACTIONAL_SCALE
if (scale_params.is_fractional) {
return (value * FRACTIONAL_DENOMINATOR) / scale_params.scale;
}
#endif
return value / scale_params.scale;
}
int gwl_window_scale_int_to(const GWL_WindowScaleParams &scale_params, int value)
{
return wl_fixed_to_int(gwl_window_scale_wl_fixed_to(scale_params, wl_fixed_from_int(value)));
}
int gwl_window_scale_int_from(const GWL_WindowScaleParams &scale_params, int value)
{
return wl_fixed_to_int(gwl_window_scale_wl_fixed_from(scale_params, wl_fixed_from_int(value)));
}
/** \} */
/* -------------------------------------------------------------------- */
/** \name Internal #GWL_Window
* \{ */
#ifdef USE_EVENT_BACKGROUND_THREAD
enum eGWL_PendingWindowActions {
/**
* The state of the window frame has changed, apply the state from #GWL_Window::frame_pending.
*/
PENDING_WINDOW_FRAME_CONFIGURE = 0,
/** The EGL buffer must be resized to match #GWL_WindowFrame::size. */
PENDING_EGL_WINDOW_RESIZE,
# ifdef GHOST_OPENGL_ALPHA
/** Draw an opaque region behind the window. */
PENDING_OPAQUE_SET,
# endif
/**
* The DPI for a monitor has changed or the monitors (outputs)
* this window is visible on may have changed. Recalculate the windows scale.
*/
PENDING_OUTPUT_SCALE_UPDATE,
};
# define PENDING_NUM (PENDING_OUTPUT_SCALE_UPDATE + 1)
#endif /* USE_EVENT_BACKGROUND_THREAD */
struct GWL_WindowFrame {
/**
* The frame size (in GHOST window coordinates).
*
* These must be converted to WAYLADN relative coordinates when the window is scaled
* by Hi-DPI/fractional scaling.
*/
int32_t size[2] = {0, 0};
bool is_maximised = false;
bool is_fullscreen = false;
bool is_active = false;
/** Disable when the fractional scale is a whole number. */
int fractional_scale = 0;
};
struct GWL_Window {
@ -109,14 +191,20 @@ struct GWL_Window {
/** The scale value written to #wl_surface_set_buffer_scale. */
int scale = 0;
/**
* The fractional scale used to calculate the DPI.
* (always set, even when scaling is rounded to whole units).
* The scale value to be used in the case fractional scale is disable.
* In general this should only be used when changing states
* (when disabling fractional scale).
*/
wl_fixed_t scale_fractional = 0;
int scale_on_output = 0;
/** A temporary token used for the window to be notified of it's activation. */
struct xdg_activation_token_v1 *xdg_activation_token = nullptr;
#ifdef WITH_GHOST_WAYLAND_FRACTIONAL_SCALE
struct wp_viewport *viewport = nullptr;
struct wp_fractional_scale_v1 *fractional_scale_handle = nullptr;
#endif
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
WGL_LibDecor_Window *libdecor = nullptr;
#endif
@ -143,12 +231,15 @@ struct GWL_Window {
bool is_dialog = false;
/** Currently only initialized on access (avoids allocations & allows to keep private). */
GWL_WindowScaleParams scale_params;
#ifdef USE_EVENT_BACKGROUND_THREAD
/**
* These pending actions can't be performed when WAYLAND handlers are running from a thread.
* Postpone their execution until the main thread can handle them.
*/
std::atomic<bool> pending_actions[3];
std::atomic<bool> pending_actions[PENDING_NUM];
#endif /* USE_EVENT_BACKGROUND_THREAD */
};
@ -287,6 +378,124 @@ static bool gwl_window_state_set(GWL_Window *win, const GHOST_TWindowState state
/** \} */
/* -------------------------------------------------------------------- */
/** \name Internal #GWL_Window Viewport Setup/Teardown
*
* A viewport is needed to implement fractional scale,
* as the outputs scale may change at runtime, support creating & clearing the viewport as needed.
* \{ */
#ifdef WITH_GHOST_WAYLAND_FRACTIONAL_SCALE
/**
* Scale a value from a viewport value to Wayland windowing.
* Scale down or not at all.
*/
static int gwl_window_fractional_to_viewport(const GWL_WindowFrame &frame, int value)
{
GHOST_ASSERT(frame.fractional_scale != 0, "Not fractional or called before initiazlized!");
return (value * frame.fractional_scale) / FRACTIONAL_DENOMINATOR;
}
/**
* Scale a value from a Wayland windowing value to the viewport.
* Scales up or not at all.
*/
static int gwl_window_fractional_from_viewport(const GWL_WindowFrame &frame, int value)
{
GHOST_ASSERT(frame.fractional_scale != 0, "Not fractional or called before initiazlized!");
return (value * FRACTIONAL_DENOMINATOR) / frame.fractional_scale;
}
/* NOTE: rounded versions are needed for window-frame dimensions conversions.
* (rounding is part of the WAYLAND spec). All other conversions such as cursor coordinates
* can used simple integer division as rounding is not defined in this case. */
static int gwl_window_fractional_to_viewport_round(const GWL_WindowFrame &frame, int value)
{
GHOST_ASSERT(frame.fractional_scale != 0, "Not fractional or called before initiazlized!");
return lroundf(double(value * frame.fractional_scale) / double(FRACTIONAL_DENOMINATOR));
}
static int gwl_window_fractional_from_viewport_round(const GWL_WindowFrame &frame, int value)
{
GHOST_ASSERT(frame.fractional_scale != 0, "Not fractional or called before initiazlized!");
return lroundf(double(value * FRACTIONAL_DENOMINATOR) / double(frame.fractional_scale));
}
static bool gwl_window_viewport_set(GWL_Window *win, bool *r_surface_needs_commit)
{
if (win->viewport != nullptr) {
return false;
}
struct wp_viewporter *viewporter = win->ghost_system->wp_viewporter();
if (viewporter == nullptr) {
return false;
}
win->viewport = wp_viewporter_get_viewport(viewporter, win->wl_surface);
if (win->viewport == nullptr) {
return false;
}
/* Set the buffer scale to 1 since a viewport will be used. */
if (win->scale != 1) {
win->scale = 1;
wl_surface_set_buffer_scale(win->wl_surface, win->scale);
if (r_surface_needs_commit) {
*r_surface_needs_commit = true;
}
else {
wl_surface_commit(win->wl_surface);
}
}
return true;
}
static bool gwl_window_viewport_unset(GWL_Window *win, bool *r_surface_needs_commit)
{
if (win->viewport == nullptr) {
return false;
}
wp_viewport_destroy(win->viewport);
win->viewport = nullptr;
GHOST_ASSERT(win->scale == 1, "Unexpected scale!");
if (win->scale != win->scale_on_output) {
win->scale = win->scale_on_output;
wl_surface_set_buffer_scale(win->wl_surface, win->scale);
if (r_surface_needs_commit) {
*r_surface_needs_commit = true;
}
else {
wl_surface_commit(win->wl_surface);
}
}
return true;
}
static bool gwl_window_viewport_size_update(GWL_Window *win)
{
if (win->viewport == nullptr) {
return false;
}
wp_viewport_set_source(win->viewport,
wl_fixed_from_int(0),
wl_fixed_from_int(0),
wl_fixed_from_int(win->frame.size[0]),
wl_fixed_from_int(win->frame.size[1]));
wp_viewport_set_destination(
win->viewport,
gwl_window_fractional_from_viewport_round(win->frame, win->frame.size[0]),
gwl_window_fractional_from_viewport_round(win->frame, win->frame.size[1]));
return true;
}
#endif /* WITH_GHOST_WAYLAND_FRACTIONAL_SCALE */
/** \} */
/* -------------------------------------------------------------------- */
/** \name Internal #GWL_Window Activation
* \{ */
@ -346,7 +555,26 @@ static void gwl_window_activate(GWL_Window *win)
/** \name Internal #GWL_Window Pending Actions
* \{ */
static void gwl_window_frame_pending_size_set(GWL_Window *win)
#ifdef WITH_GHOST_WAYLAND_FRACTIONAL_SCALE
static void gwl_window_frame_pending_fractional_scale_set(GWL_Window *win,
bool *r_surface_needs_commit)
{
if (win->frame_pending.fractional_scale == win->frame.fractional_scale) {
return;
}
win->frame.fractional_scale = win->frame_pending.fractional_scale;
if (win->frame_pending.fractional_scale) {
gwl_window_viewport_set(win, r_surface_needs_commit);
gwl_window_viewport_size_update(win);
}
else {
gwl_window_viewport_unset(win, r_surface_needs_commit);
}
}
#endif /* WITH_GHOST_WAYLAND_FRACTIONAL_SCALE */
static void gwl_window_frame_pending_size_set(GWL_Window *win, bool *r_surface_needs_commit)
{
if (win->frame_pending.size[0] == 0 || win->frame_pending.size[1] == 0) {
return;
@ -355,7 +583,19 @@ static void gwl_window_frame_pending_size_set(GWL_Window *win)
win->frame.size[0] = win->frame_pending.size[0];
win->frame.size[1] = win->frame_pending.size[1];
#ifdef WITH_GHOST_WAYLAND_FRACTIONAL_SCALE
if (win->frame_pending.fractional_scale != win->frame.fractional_scale) {
gwl_window_frame_pending_fractional_scale_set(win, r_surface_needs_commit);
}
else {
gwl_window_viewport_size_update(win);
}
#else
(void)r_surface_needs_commit;
#endif
wl_egl_window_resize(win->egl_window, UNPACK2(win->frame.size), 0, 0);
win->ghost_window->notify_size();
win->frame_pending.size[0] = 0;
@ -366,25 +606,6 @@ static void gwl_window_frame_update_from_pending(GWL_Window *win);
#ifdef USE_EVENT_BACKGROUND_THREAD
enum eGWL_PendingWindowActions {
/**
* The state of the window frame has changed, apply the state from #GWL_Window::frame_pending.
*/
PENDING_WINDOW_FRAME_CONFIGURE = 0,
/** The EGL buffer must be resized to match #GWL_WindowFrame::size. */
PENDING_EGL_WINDOW_RESIZE,
# ifdef GHOST_OPENGL_ALPHA
/** Draw an opaque region behind the window. */
PENDING_OPAQUE_SET,
# endif
/**
* The DPI for a monitor has changed or the monitors (outputs)
* this window is visible on may have changed. Recalculate the windows scale.
*/
PENDING_OUTPUT_SCALE_UPDATE,
};
# define PENDING_NUM (PENDING_OUTPUT_SCALE_UPDATE + 1)
static void gwl_window_pending_actions_tag(GWL_Window *win, enum eGWL_PendingWindowActions type)
{
win->pending_actions[int(type)].store(true);
@ -397,6 +618,9 @@ static void gwl_window_pending_actions_handle(GWL_Window *win)
gwl_window_frame_update_from_pending(win);
}
if (win->pending_actions[PENDING_EGL_WINDOW_RESIZE].exchange(false)) {
# ifdef WITH_GHOST_WAYLAND_FRACTIONAL_SCALE
gwl_window_viewport_size_update(win);
# endif
wl_egl_window_resize(win->egl_window, UNPACK2(win->frame.size), 0, 0);
}
# ifdef GHOST_OPENGL_ALPHA
@ -423,13 +647,32 @@ static void gwl_window_frame_update_from_pending_no_lock(GWL_Window *win)
#endif
const bool dpi_changed = win->frame_pending.fractional_scale != win->frame.fractional_scale;
bool surface_needs_commit = false;
if (win->frame_pending.size[0] != 0 && win->frame_pending.size[1] != 0) {
if ((win->frame.size[0] != win->frame_pending.size[0]) ||
(win->frame.size[1] != win->frame_pending.size[1])) {
gwl_window_frame_pending_size_set(win);
gwl_window_frame_pending_size_set(win, &surface_needs_commit);
}
}
#ifdef WITH_GHOST_WAYLAND_FRACTIONAL_SCALE
if (win->frame_pending.fractional_scale != win->frame.fractional_scale) {
gwl_window_frame_pending_fractional_scale_set(win, &surface_needs_commit);
}
#endif
if (surface_needs_commit) {
wl_surface_commit(win->wl_surface);
}
if (dpi_changed) {
GHOST_SystemWayland *system = win->ghost_system;
system->pushEvent(new GHOST_Event(
system->getMilliSeconds(), GHOST_kEventWindowDPIHintChanged, win->ghost_window));
}
if (win->frame_pending.is_active) {
win->ghost_window->activate();
}
@ -472,26 +715,11 @@ static int output_scale_cmp(const GWL_Output *output_a, const GWL_Output *output
if (output_a->scale > output_b->scale) {
return 1;
}
if (output_a->has_scale_fractional || output_b->has_scale_fractional) {
const wl_fixed_t scale_fractional_a = output_a->has_scale_fractional ?
output_a->scale_fractional :
wl_fixed_from_int(output_a->scale);
const wl_fixed_t scale_fractional_b = output_b->has_scale_fractional ?
output_b->scale_fractional :
wl_fixed_from_int(output_b->scale);
if (scale_fractional_a < scale_fractional_b) {
return -1;
}
if (scale_fractional_a > scale_fractional_b) {
return 1;
}
}
return 0;
}
static int outputs_max_scale_or_default(const std::vector<GWL_Output *> &outputs,
const int32_t scale_default,
wl_fixed_t *r_scale_fractional)
const int32_t scale_default)
{
const GWL_Output *output_max = nullptr;
for (const GWL_Output *reg_output : outputs) {
@ -501,17 +729,9 @@ static int outputs_max_scale_or_default(const std::vector<GWL_Output *> &outputs
}
if (output_max) {
if (r_scale_fractional) {
*r_scale_fractional = output_max->has_scale_fractional ?
output_max->scale_fractional :
wl_fixed_from_int(output_max->scale);
}
return output_max->scale;
}
if (r_scale_fractional) {
*r_scale_fractional = wl_fixed_from_int(scale_default);
}
return scale_default;
}
@ -539,8 +759,17 @@ static void xdg_toplevel_handle_configure(void *data,
std::lock_guard lock_frame_guard{win->frame_pending_mutex};
#endif
win->frame_pending.size[0] = win->scale * width;
win->frame_pending.size[1] = win->scale * height;
#ifdef WITH_GHOST_WAYLAND_FRACTIONAL_SCALE
if (win->frame.fractional_scale) {
win->frame_pending.size[0] = gwl_window_fractional_to_viewport_round(win->frame, width);
win->frame_pending.size[1] = gwl_window_fractional_to_viewport_round(win->frame, height);
}
else
#endif /* WITH_GHOST_WAYLAND_FRACTIONAL_SCALE */
{
win->frame_pending.size[0] = width * win->scale;
win->frame_pending.size[1] = height * win->scale;
}
win->frame_pending.is_maximised = false;
win->frame_pending.is_fullscreen = false;
@ -615,6 +844,63 @@ static const struct xdg_activation_token_v1_listener *xdg_activation_listener_ge
/** \} */
/* -------------------------------------------------------------------- */
/** \name Listener (Fractional Scale), #wp_fractional_scale_manager_v1_interface
*
* Used by #gwl_window_activate.
* \{ */
#ifdef WITH_GHOST_WAYLAND_FRACTIONAL_SCALE
static CLG_LogRef LOG_WL_FRACTIONAL_SCALE = {"ghost.wl.handle.fractional_scale"};
# define LOG (&LOG_WL_FRACTIONAL_SCALE)
static void wp_fractional_scale_handle_preferred_scale(
void *data, struct wp_fractional_scale_v1 * /*wp_fractional_scale_v1*/, uint preferred_scale)
{
CLOG_INFO(LOG,
2,
"preferred_scale (preferred_scale=%.6f)",
double(preferred_scale) / FRACTIONAL_DENOMINATOR);
GWL_Window *win = static_cast<GWL_Window *>(data);
const bool is_fractional = (preferred_scale % FRACTIONAL_DENOMINATOR) != 0;
/* When non-fractional, never use fractional scaling! */
win->frame_pending.fractional_scale = is_fractional ? preferred_scale : 0;
if (win->frame.fractional_scale != win->frame_pending.fractional_scale) {
/* Resize the window failing to do so results in severe flickering with a
* multi-monitor setup when multiple monitors have different scales.
*
* NOTE: some flickering is still possible even when resizing this
* happens when dragging the right hand side of the title-bar in KDE
* as expanding changed the size on the RHS, this may be up to the compositor to fix. */
const int scale_prev = win->frame.fractional_scale ?
win->frame.fractional_scale :
win->scale_on_output * FRACTIONAL_DENOMINATOR;
const int scale_next = win->frame_pending.fractional_scale ?
win->frame_pending.fractional_scale :
win->scale_on_output * FRACTIONAL_DENOMINATOR;
for (size_t i = 0; i < ARRAY_SIZE(win->frame_pending.size); i++) {
const int value = win->frame_pending.size[i] ? win->frame_pending.size[i] :
win->frame.size[i];
win->frame_pending.size[i] = lroundf(value * (double(scale_next) / double(scale_prev)));
}
gwl_window_pending_actions_tag(win, PENDING_WINDOW_FRAME_CONFIGURE);
}
}
static const struct wp_fractional_scale_v1_listener wp_fractional_scale_listener = {
/*preferred_scale*/ wp_fractional_scale_handle_preferred_scale,
};
# undef LOG
#endif /* WITH_GHOST_WAYLAND_FRACTIONAL_SCALE */
/** \} */
/* -------------------------------------------------------------------- */
/** \name Listener (LibDecor Frame), #libdecor_frame_interface
* \{ */
@ -639,16 +925,27 @@ static void frame_handle_configure(struct libdecor_frame *frame,
/* Set the size. */
int size_next[2];
{
const int scale = static_cast<GWL_Window *>(data)->scale;
GWL_Window *win = static_cast<GWL_Window *>(data);
const int scale = win->scale;
if (!libdecor_configuration_get_content_size(
configuration, frame, &size_next[0], &size_next[1])) {
GWL_Window *win = static_cast<GWL_Window *>(data);
size_next[0] = win->frame.size[0] / scale;
size_next[1] = win->frame.size[1] / scale;
}
frame_pending->size[0] = scale * size_next[0];
frame_pending->size[1] = scale * size_next[1];
# ifdef WITH_GHOST_WAYLAND_FRACTIONAL_SCALE
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]);
}
else
# endif /* WITH_GHOST_WAYLAND_FRACTIONAL_SCALE */
{
frame_pending->size[0] = size_next[0] * scale;
frame_pending->size[1] = size_next[1] * scale;
}
}
/* Set the state. */
@ -888,7 +1185,8 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
*
* Using the maximum scale is best as it results in the window first being smaller,
* avoiding a large window flashing before it's made smaller. */
window_->scale = outputs_max_scale_or_default(system_->outputs(), 1, &window_->scale_fractional);
window_->scale = outputs_max_scale_or_default(system_->outputs(), 1);
window_->scale_on_output = window_->scale;
window_->frame.size[0] = int32_t(width);
window_->frame.size[1] = int32_t(height);
@ -911,6 +1209,17 @@ GHOST_WindowWayland::GHOST_WindowWayland(GHOST_SystemWayland *system,
window_->egl_window = wl_egl_window_create(
window_->wl_surface, int(window_->frame.size[0]), int(window_->frame.size[1]));
#ifdef WITH_GHOST_WAYLAND_FRACTIONAL_SCALE
struct wp_fractional_scale_manager_v1 *fractional_scale_manager =
system->wp_fractional_scale_manager();
if (fractional_scale_manager) {
window_->fractional_scale_handle = wp_fractional_scale_manager_v1_get_fractional_scale(
fractional_scale_manager, window_->wl_surface);
wp_fractional_scale_v1_add_listener(
window_->fractional_scale_handle, &wp_fractional_scale_listener, window_);
}
#endif /* WITH_GHOST_WAYLAND_FRACTIONAL_SCALE */
/* NOTE: The limit is in points (not pixels) so Hi-DPI will limit to larger number of pixels.
* This has the advantage that the size limit is the same when moving the window between monitors
* with different scales set. If it was important to limit in pixels it could be re-calculated
@ -1029,13 +1338,14 @@ GHOST_TSuccess GHOST_WindowWayland::setWindowCursorGrab(GHOST_TGrabCursorMode mo
}
bounds = &bounds_buf;
}
if (system_->window_cursor_grab_set(mode,
m_cursorGrab,
m_cursorGrabInitPos,
bounds,
m_cursorGrabAxis,
window_->wl_surface,
window_->scale)) {
this->scale_params())) {
return GHOST_kSuccess;
}
return GHOST_kFailure;
@ -1121,7 +1431,7 @@ GHOST_TSuccess GHOST_WindowWayland::setClientSize(const uint32_t width, const ui
window_->frame_pending.size[0] = width;
window_->frame_pending.size[1] = height;
gwl_window_frame_pending_size_set(window_);
gwl_window_frame_pending_size_set(window_, nullptr);
return GHOST_kSuccess;
}
@ -1159,6 +1469,18 @@ GHOST_WindowWayland::~GHOST_WindowWayland()
window_->xdg_activation_token = nullptr;
}
#ifdef WITH_GHOST_WAYLAND_FRACTIONAL_SCALE
if (window_->fractional_scale_handle) {
wp_fractional_scale_v1_destroy(window_->fractional_scale_handle);
window_->fractional_scale_handle = nullptr;
}
if (window_->viewport) {
wp_viewport_destroy(window_->viewport);
window_->viewport = nullptr;
}
#endif /* WITH_GHOST_WAYLAND_FRACTIONAL_SCALE */
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
if (use_libdecor) {
gwl_libdecor_window_destroy(window_->libdecor);
@ -1188,25 +1510,13 @@ uint16_t GHOST_WindowWayland::getDPIHint()
/* No need to lock `server_mutex`
* (`outputs_changed_update_scale` never changes values in a non-main thread). */
const wl_fixed_t scale_fractional = window_->scale_fractional;
GHOST_ASSERT(wl_fixed_from_int(window_->scale) >= scale_fractional,
"Fractional scale should always be less than the fixed scale.");
/* Using the physical DPI will cause wrong scaling of the UI
* use a multiplier for the default DPI as a workaround. */
if (wl_fixed_from_int(window_->scale) == scale_fractional || window_->scale <= 1) {
/* No fractional scaling. */
return window_->scale * base_dpi;
#ifdef WITH_GHOST_WAYLAND_FRACTIONAL_SCALE
if (window_->frame.fractional_scale) {
return gwl_window_fractional_to_viewport(window_->frame, base_dpi);
}
const int scale_ceil = window_->scale;
const int scale_floor = scale_ceil - 1;
const wl_fixed_t scale_fractional_final = wl_fixed_to_int(
scale_fractional *
/* Compensate for the buffer being rendered at `window_->scale`,
* then scaled down fractionally. */
(wl_fixed_from_int(1) + ((wl_fixed_from_int(scale_ceil) - scale_fractional) / scale_floor)));
#endif /* WITH_GHOST_WAYLAND_FRACTIONAL_SCALE */
return wl_fixed_to_int(scale_fractional_final * base_dpi);
return window_->scale * base_dpi;
}
GHOST_TSuccess GHOST_WindowWayland::setWindowCursorVisibility(bool visible)
@ -1379,9 +1689,35 @@ int GHOST_WindowWayland::scale() const
return window_->scale;
}
wl_fixed_t GHOST_WindowWayland::scale_fractional() const
const struct GWL_WindowScaleParams &GHOST_WindowWayland::scale_params() const
{
return window_->scale_fractional;
/* NOTE(@ideasman42): This could be kept initialized,
* since it's such a small struct it's not so important. */
GWL_WindowScaleParams *scale_params = &window_->scale_params;
scale_params->is_fractional = (window_->frame.fractional_scale != 0);
scale_params->scale = scale_params->is_fractional ? window_->frame.fractional_scale :
window_->scale;
return *scale_params;
}
wl_fixed_t GHOST_WindowWayland::wl_fixed_from_window(wl_fixed_t value) const
{
#ifdef WITH_GHOST_WAYLAND_FRACTIONAL_SCALE
if (window_->frame.fractional_scale) {
return gwl_window_fractional_from_viewport(window_->frame, value);
}
#endif
return value / window_->scale;
}
wl_fixed_t GHOST_WindowWayland::wl_fixed_to_window(wl_fixed_t value) const
{
#ifdef WITH_GHOST_WAYLAND_FRACTIONAL_SCALE
if (window_->frame.fractional_scale) {
return gwl_window_fractional_to_viewport(window_->frame, value);
}
#endif
return value * window_->scale;
}
wl_surface *GHOST_WindowWayland::wl_surface() const
@ -1499,13 +1835,19 @@ bool GHOST_WindowWayland::outputs_changed_update_scale()
}
#endif
wl_fixed_t scale_fractional_next = 0;
const int scale_next = outputs_max_scale_or_default(outputs(), 0, &scale_fractional_next);
const int scale_next = outputs_max_scale_or_default(outputs(), 0);
if (UNLIKELY(scale_next == 0)) {
return false;
}
const wl_fixed_t scale_fractional_curr = window_->scale_fractional;
#ifdef WITH_GHOST_WAYLAND_FRACTIONAL_SCALE
if (window_->frame.fractional_scale) {
GHOST_ASSERT(window_->scale == 1, "Scale is expected to be 1 for fractional scaling!");
window_->scale_on_output = scale_next;
return false;
}
#endif /* WITH_GHOST_WAYLAND_FRACTIONAL_SCALE */
const int scale_curr = window_->scale;
bool changed = false;
@ -1530,22 +1872,18 @@ bool GHOST_WindowWayland::outputs_changed_update_scale()
window_->frame_pending.size[0] = (window_->frame.size[0] / scale_curr) * scale_next;
window_->frame_pending.size[1] = (window_->frame.size[1] / scale_curr) * scale_next;
gwl_window_frame_pending_size_set(window_);
gwl_window_frame_pending_size_set(window_, nullptr);
changed = true;
}
if (scale_fractional_next != scale_fractional_curr) {
window_->scale_fractional = scale_fractional_next;
changed = true;
/* As this is a low-level function, we might want adding this event to be optional,
* always add the event unless it causes issues. */
GHOST_SystemWayland *system = window_->ghost_system;
system->pushEvent(
new GHOST_Event(system->getMilliSeconds(), GHOST_kEventWindowDPIHintChanged, this));
changed = true;
}
/* Ensure both are always set. */
window_->scale_on_output = window_->scale;
return changed;
}

View File

@ -140,10 +140,14 @@ class GHOST_WindowWayland : public GHOST_Window {
/* WAYLAND direct-data access. */
int scale() const;
wl_fixed_t scale_fractional() const;
const struct GWL_WindowScaleParams &scale_params() const;
struct wl_surface *wl_surface() const;
const std::vector<GWL_Output *> &outputs();
wl_fixed_t wl_fixed_from_window(wl_fixed_t value) const;
wl_fixed_t wl_fixed_to_window(wl_fixed_t value) const;
/* WAYLAND window-level functions. */
GHOST_TSuccess close();

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2013 Blender Foundation. All rights reserved. */
* Copyright 2013 Blender Foundation */
#include <stdlib.h>

View File

@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright 2006 Blender Foundation. All rights reserved.
# Copyright 2006 Blender Foundation
if(HAVE_MALLOC_STATS_H)
add_definitions(-DHAVE_MALLOC_STATS_H)

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2013 Blender Foundation. All rights reserved. */
* Copyright 2013 Blender Foundation */
/** \file
* \ingroup intern_mem

View File

@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright 2006 Blender Foundation. All rights reserved.
# Copyright 2006 Blender Foundation
set(INC
intern

View File

@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright 2006 Blender Foundation. All rights reserved.
# Copyright 2006 Blender Foundation
remove_strict_flags()
set(INC

View File

@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright 2015 Blender Foundation. All rights reserved.
# Copyright 2015 Blender Foundation
set(INC
.

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2020 Blender Foundation. All rights reserved. */
* Copyright 2020 Blender Foundation */
/* On Linux, precompiled libraries may be made with an glibc version that is
* incompatible with the system libraries that Blender is built on. To solve

View File

@ -1,5 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-or-later
# Copyright 2011 Blender Foundation. All rights reserved.
# Copyright 2011 Blender Foundation
# NOTE: This file is automatically generated by bundle.sh script
# If you're doing changes in this file, please update template

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2014 Blender Foundation. All rights reserved. */
* Copyright 2014 Blender Foundation */
#include "intern/autotrack.h"
#include "intern/tracksN.h"

View File

@ -1,5 +1,5 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2014 Blender Foundation. All rights reserved. */
* Copyright 2014 Blender Foundation */
#ifndef LIBMV_C_API_AUTOTRACK_H_
#define LIBMV_C_API_AUTOTRACK_H_

Some files were not shown because too many files have changed in this diff Show More