Use single pixel buffer protocol for more efficient temp buffer creation

This commit is contained in:
Kovid Goyal 2024-04-04 09:00:33 +05:30
parent d3b5e86f30
commit b4bba99678
No known key found for this signature in database
GPG key ID: 06BC317B515ACE7C
4 changed files with 57 additions and 23 deletions

View file

@ -81,6 +81,7 @@
"unstable/tablet/tablet-unstable-v2.xml",
"staging/cursor-shape/cursor-shape-v1.xml",
"staging/fractional-scale/fractional-scale-v1.xml",
"staging/single-pixel-buffer/single-pixel-buffer-v1.xml",
"kwin-blur-v1.xml",
"wlr-layer-shell-unstable-v1.xml"

5
glfw/wl_init.c vendored
View file

@ -724,6 +724,9 @@ static void registryHandleGlobal(void* data UNUSED,
_glfwSetupWaylandPrimarySelectionDevice();
}
}
else if (is(wp_single_pixel_buffer_manager_v1)) {
_glfw.wl.wp_single_pixel_buffer_manager_v1 = wl_registry_bind(registry, name, &wp_single_pixel_buffer_manager_v1_interface, 1);
}
else if (is(xdg_activation_v1)) {
_glfw.wl.xdg_activation_v1 = wl_registry_bind(registry, name, &xdg_activation_v1_interface, 1);
}
@ -992,6 +995,8 @@ void _glfwPlatformTerminate(void)
zwp_primary_selection_device_manager_v1_destroy(_glfw.wl.primarySelectionDeviceManager);
if (_glfw.wl.xdg_activation_v1)
xdg_activation_v1_destroy(_glfw.wl.xdg_activation_v1);
if (_glfw.wl.wp_single_pixel_buffer_manager_v1)
wp_single_pixel_buffer_manager_v1_destroy(_glfw.wl.wp_single_pixel_buffer_manager_v1);
if (_glfw.wl.wp_cursor_shape_manager_v1)
wp_cursor_shape_manager_v1_destroy(_glfw.wl.wp_cursor_shape_manager_v1);
if (_glfw.wl.wp_viewporter)

2
glfw/wl_platform.h vendored
View file

@ -64,6 +64,7 @@ typedef VkBool32 (APIENTRY *PFN_vkGetPhysicalDeviceWaylandPresentationSupportKHR
#include "wayland-viewporter-client-protocol.h"
#include "wayland-kwin-blur-v1-client-protocol.h"
#include "wayland-wlr-layer-shell-unstable-v1-client-protocol.h"
#include "wayland-single-pixel-buffer-v1-client-protocol.h"
#define _glfw_dlopen(name) dlopen(name, RTLD_LAZY | RTLD_LOCAL)
#define _glfw_dlclose(handle) dlclose(handle)
@ -308,6 +309,7 @@ typedef struct _GLFWlibraryWayland
struct wp_viewporter *wp_viewporter;
struct org_kde_kwin_blur_manager *org_kde_kwin_blur_manager;
struct zwlr_layer_shell_v1* zwlr_layer_shell_v1; uint32_t zwlr_layer_shell_v1_version;
struct wp_single_pixel_buffer_manager_v1 *wp_single_pixel_buffer_manager_v1;
int compositorVersion;
int seatVersion;

72
glfw/wl_window.c vendored
View file

@ -752,28 +752,23 @@ apply_xdg_configure_changes(_GLFWwindow *window) {
commit_window_surface_if_safe(window);
window->wl.pending_state = 0;
}
typedef union pixel {
struct {
uint8_t blue, green, red, alpha;
};
uint32_t value;
} pixel;
static bool
attach_temp_buffer_during_window_creation(_GLFWwindow *window) {
int width, height;
_glfwPlatformGetFramebufferSize(window, &width, &height);
static struct wl_buffer*
create_single_color_buffer(int width, int height, pixel color) {
int shm_format = color.alpha == 0xff ? WL_SHM_FORMAT_XRGB8888 : WL_SHM_FORMAT_ARGB8888;
const size_t size = 4 * width * height;
int fd = createAnonymousFile(size);
if (fd < 0) {
_glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: failed to create anonymous file");
return false;
return NULL;
}
uint32_t *shm_data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
union {
struct {
uint8_t blue, green, red, alpha;
};
uint32_t value;
} color;
color.value = _glfw.hints.window.wl.bgcolor;
int shm_format = WL_SHM_FORMAT_ARGB8888;
if (!window->wl.transparent) { color.alpha = 0xff; shm_format = WL_SHM_FORMAT_XRGB8888; }
else if (color.alpha == 0) color.value = 0; // fully transparent blends best with black and we can use memset
// convert to pre-multiplied alpha
float alpha = color.alpha / 255.f; color.red = (uint8_t)(alpha * color.red); color.green = (uint8_t)(alpha * color.green); color.blue = (uint8_t)(alpha * color.blue);
if (color.value) for (size_t i = 0; i < size/4; i++) shm_data[i] = color.value;
@ -781,25 +776,56 @@ attach_temp_buffer_during_window_creation(_GLFWwindow *window) {
if (!shm_data) {
close(fd);
_glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: failed to mmap anonymous file");
return false;
return NULL;
}
struct wl_shm_pool *pool = wl_shm_create_pool(_glfw.wl.shm, fd, size);
if (!pool) {
close(fd); munmap(shm_data, size);
_glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: failed to create wl_shm_pool of size: %zu", size);
return false;
return NULL;
}
struct wl_buffer *buffer = wl_shm_pool_create_buffer(pool, 0, width, height, width * 4, shm_format);
wl_shm_pool_destroy(pool); munmap(shm_data, size); close(fd);
if (!buffer) {
_glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: failed to create wl_buffer of size: %zu", size);
return false;
return NULL;
}
if (window->wl.temp_buffer_used_during_window_creation) wl_buffer_destroy(window->wl.temp_buffer_used_during_window_creation);
window->wl.temp_buffer_used_during_window_creation = buffer;
wl_surface_set_buffer_scale(window->wl.surface, window->wl.fractional_scale ? 1: _glfwWaylandIntegerWindowScale(window));
wl_surface_attach(window->wl.surface, buffer, 0, 0);
if (window->wl.wp_viewport) wp_viewport_set_destination(window->wl.wp_viewport, window->wl.width, window->wl.height);
return buffer;
}
static bool
attach_temp_buffer_during_window_creation(_GLFWwindow *window) {
pixel color;
color.value = _glfw.hints.window.wl.bgcolor;
if (!window->wl.transparent) color.alpha = 0xff;
else if (color.alpha == 0) color.value = 0; // fully transparent blends best with black and we can use memset
if (window->wl.temp_buffer_used_during_window_creation) {
wl_buffer_destroy(window->wl.temp_buffer_used_during_window_creation);
window->wl.temp_buffer_used_during_window_creation = NULL;
}
int width, height;
_glfwPlatformGetFramebufferSize(window, &width, &height);
if (window->wl.wp_viewport) {
if (_glfw.wl.wp_single_pixel_buffer_manager_v1) {
window->wl.temp_buffer_used_during_window_creation = wp_single_pixel_buffer_manager_v1_create_u32_rgba_buffer(_glfw.wl.wp_single_pixel_buffer_manager_v1, color.red, color.green, color.blue, color.alpha);
if (!window->wl.temp_buffer_used_during_window_creation) {
_glfwInputError(GLFW_PLATFORM_ERROR, "Wayland: failed to create single pixel buffer");
return false;
}
} else {
window->wl.temp_buffer_used_during_window_creation = create_single_color_buffer(1, 1, color);
if (!window->wl.temp_buffer_used_during_window_creation) return false;
}
wl_surface_set_buffer_scale(window->wl.surface, 1);
wp_viewport_set_destination(window->wl.wp_viewport, window->wl.width, window->wl.height);
} else {
window->wl.temp_buffer_used_during_window_creation = create_single_color_buffer(1, 1, color);
if (!window->wl.temp_buffer_used_during_window_creation) return false;
wl_surface_set_buffer_scale(window->wl.surface, window->wl.fractional_scale ? 1: _glfwWaylandIntegerWindowScale(window));
}
wl_surface_attach(window->wl.surface, window->wl.temp_buffer_used_during_window_creation, 0, 0);
wl_surface_commit(window->wl.surface);
debug("Attached temp buffer during window creation of size: %dx%d\n", width, height);
return true;