Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use single pixel buffer and viewporter for solid backgrounds #255

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion include/swaylock.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include "pool-buffer.h"
#include "seat.h"
#include "wlr-layer-shell-unstable-v1-client-protocol.h"
#include "viewporter-client-protocol.h"
#include "single-pixel-buffer-v1-client-protocol.h"

enum auth_state {
AUTH_STATE_IDLE,
Expand Down Expand Up @@ -78,6 +80,9 @@ struct swaylock_state {
struct wl_display *display;
struct wl_compositor *compositor;
struct wl_subcompositor *subcompositor;
struct wp_viewporter *viewporter;
struct wl_buffer *background_buffer;
struct wp_single_pixel_buffer_manager_v1 *single_pixel_buffer_manager;
struct zwlr_layer_shell_v1 *layer_shell;
struct zwlr_input_inhibit_manager_v1 *input_inhibit_manager;
struct wl_shm *shm;
Expand All @@ -100,12 +105,13 @@ struct swaylock_surface {
uint32_t output_global_name;
struct wl_surface *surface;
struct wl_surface *child; // surface made into subsurface
struct wp_viewport *viewport;
struct wl_subsurface *subsurface;
struct zwlr_layer_surface_v1 *layer_surface;
struct ext_session_lock_surface_v1 *ext_session_lock_surface_v1;
struct pool_buffer buffers[2];
struct pool_buffer indicator_buffers[2];
struct pool_buffer *current_buffer;
struct wl_buffer *backgound_buffer;
bool frame_pending, dirty;
uint32_t width, height;
uint32_t indicator_width, indicator_height;
Expand Down
42 changes: 40 additions & 2 deletions main.c
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ static void destroy_surface(struct swaylock_surface *surface) {
destroy_buffer(&surface->buffers[1]);
destroy_buffer(&surface->indicator_buffers[0]);
destroy_buffer(&surface->indicator_buffers[1]);
wp_viewport_destroy(surface->viewport);
wl_output_destroy(surface->output);
free(surface);
}
Expand Down Expand Up @@ -173,6 +174,11 @@ static void create_surface(struct swaylock_surface *surface) {
wl_region_destroy(region);
}

if (state->viewporter) {
surface->viewport = wp_viewporter_get_viewport(
state->viewporter, surface->surface);
}

if (!state->ext_session_lock_v1) {
wl_surface_commit(surface->surface);
}
Expand Down Expand Up @@ -373,6 +379,13 @@ static void handle_global(void *data, struct wl_registry *registry,
} else if (strcmp(interface, ext_session_lock_manager_v1_interface.name) == 0) {
state->ext_session_lock_manager_v1 = wl_registry_bind(registry, name,
&ext_session_lock_manager_v1_interface, 1);
} else if (strcmp(interface, wp_viewporter_interface.name) == 0) {
state->viewporter = wl_registry_bind(registry, name,
&wp_viewporter_interface, 1);
} else if (strcmp(interface,
wp_single_pixel_buffer_manager_v1_interface.name) == 0) {
state->single_pixel_buffer_manager = wl_registry_bind(registry, name,
&wp_single_pixel_buffer_manager_v1_interface, 1);
}
}

Expand Down Expand Up @@ -1226,8 +1239,18 @@ int main(int argc, char **argv) {
wl_registry_add_listener(registry, &registry_listener, &state);
wl_display_roundtrip(state.display);

if (!state.compositor || !state.shm) {
swaylock_log(LOG_ERROR, "Missing wl_compositor or wl_shm");
if (!state.compositor) {
swaylock_log(LOG_ERROR, "Missing wl_compositor");
return 1;
}

if (!state.subcompositor) {
swaylock_log(LOG_ERROR, "Missing wl_subcompositor");
return 1;
}

if (!state.shm) {
swaylock_log(LOG_ERROR, "Missing wl_shm");
return 1;
}

Expand Down Expand Up @@ -1255,6 +1278,20 @@ int main(int argc, char **argv) {
return 1;
}

if (state.single_pixel_buffer_manager && state.viewporter) {
uint8_t r8 = (state.args.colors.background >> 24) & 0xFF;
uint8_t g8 = (state.args.colors.background >> 16) & 0xFF;
uint8_t b8 = (state.args.colors.background >> 8) & 0xFF;
uint8_t a8 = (state.args.colors.background >> 0) & 0xFF;
uint32_t f = 0xFFFFFFFF / 0xFF; // division result is an integer
uint32_t r32 = r8 * f;
uint32_t g32 = g8 * f;
uint32_t b32 = b8 * f;
uint32_t a32 = a8 * f;
state.background_buffer = wp_single_pixel_buffer_manager_v1_create_u32_rgba_buffer(
state.single_pixel_buffer_manager, r32, g32, b32, a32);
}

struct swaylock_surface *surface;
wl_list_for_each(surface, &state.surfaces, link) {
create_surface(surface);
Expand Down Expand Up @@ -1288,6 +1325,7 @@ int main(int argc, char **argv) {
wl_display_flush(state.display);
}

wl_buffer_destroy(state.background_buffer);
free(state.args.font);
return 0;
}
4 changes: 3 additions & 1 deletion meson.build
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ if is_freebsd
endif

wayland_client = dependency('wayland-client', version: '>=1.20.0')
wayland_protos = dependency('wayland-protocols', version: '>=1.25', fallback: 'wayland-protocols')
wayland_protos = dependency('wayland-protocols', version: '>=1.26', fallback: 'wayland-protocols')
# use native version of wayland-scanner when cross-compiling
# meson does this too: https://github.com/mesonbuild/meson/blob/c649a2b8c59c9f49affca9bd89c126bfa0f54449/mesonbuild/modules/unstable_wayland.py#L48-L53
wayland_scanner = dependency('wayland-scanner', version: '>=1.15.0', native: true)
Expand Down Expand Up @@ -84,6 +84,8 @@ client_protos_headers = []
client_protocols = [
wl_protocol_dir / 'stable/xdg-shell/xdg-shell.xml',
wl_protocol_dir / 'staging/ext-session-lock/ext-session-lock-v1.xml',
wl_protocol_dir / 'stable/viewporter/viewporter.xml',
wl_protocol_dir / 'staging/single-pixel-buffer/single-pixel-buffer-v1.xml',
'wlr-layer-shell-unstable-v1.xml',
'wlr-input-inhibitor-unstable-v1.xml',
]
Expand Down
38 changes: 29 additions & 9 deletions render.c
Original file line number Diff line number Diff line change
Expand Up @@ -41,13 +41,33 @@ void render_frame_background(struct swaylock_surface *surface) {
return; // not yet configured
}

surface->current_buffer = get_next_buffer(state->shm,
if (surface->viewport && state->background_buffer &&
(!surface->image || state->args.mode == BACKGROUND_MODE_SOLID_COLOR)) {
// no need to carry around shm buffers if we are going to use the single
// pixel buffer
destroy_buffer(&surface->buffers[0]);
destroy_buffer(&surface->buffers[1]);

wl_surface_set_buffer_scale(surface->surface, 1);
wl_surface_attach(surface->surface, state->background_buffer, 0, 0);
wl_surface_damage_buffer(surface->surface, 0, 0, INT32_MAX, INT32_MAX);
wp_viewport_set_destination(surface->viewport, surface->width, surface->height);

wl_surface_commit(surface->surface);
return;
}

if (surface->viewport) {
wp_viewport_set_destination(surface->viewport, -1, -1);
}

struct pool_buffer *buffer = get_next_buffer(state->shm,
surface->buffers, buffer_width, buffer_height);
if (surface->current_buffer == NULL) {
if (buffer == NULL) {
return;
}

cairo_t *cairo = surface->current_buffer->cairo;
cairo_t *cairo = buffer->cairo;
cairo_set_antialias(cairo, CAIRO_ANTIALIAS_BEST);

cairo_save(cairo);
Expand All @@ -63,7 +83,7 @@ void render_frame_background(struct swaylock_surface *surface) {
cairo_identity_matrix(cairo);

wl_surface_set_buffer_scale(surface->surface, surface->scale);
wl_surface_attach(surface->surface, surface->current_buffer->buffer, 0, 0);
wl_surface_attach(surface->surface, buffer->buffer, 0, 0);
wl_surface_damage_buffer(surface->surface, 0, 0, INT32_MAX, INT32_MAX);
wl_surface_commit(surface->surface);
}
Expand Down Expand Up @@ -102,17 +122,17 @@ void render_frame(struct swaylock_surface *surface) {

wl_subsurface_set_position(surface->subsurface, subsurf_xpos, subsurf_ypos);

surface->current_buffer = get_next_buffer(state->shm,
struct pool_buffer *buffer = get_next_buffer(state->shm,
surface->indicator_buffers, buffer_width, buffer_height);
if (surface->current_buffer == NULL) {
if (buffer == NULL) {
return;
}

// Hide subsurface until we want it visible
wl_surface_attach(surface->child, NULL, 0, 0);
wl_surface_commit(surface->child);

cairo_t *cairo = surface->current_buffer->cairo;
cairo_t *cairo = buffer->cairo;
cairo_set_antialias(cairo, CAIRO_ANTIALIAS_BEST);
cairo_font_options_t *fo = cairo_font_options_create();
cairo_font_options_set_hint_style(fo, CAIRO_HINT_STYLE_FULL);
Expand Down Expand Up @@ -317,15 +337,15 @@ void render_frame(struct swaylock_surface *surface) {
new_width += surface->scale - (new_width % surface->scale);

if (buffer_width != new_width || buffer_height != new_height) {
destroy_buffer(surface->current_buffer);
destroy_buffer(buffer);
surface->indicator_width = new_width;
surface->indicator_height = new_height;
render_frame(surface);
return;
}

wl_surface_set_buffer_scale(surface->child, surface->scale);
wl_surface_attach(surface->child, surface->current_buffer->buffer, 0, 0);
wl_surface_attach(surface->child, buffer->buffer, 0, 0);
wl_surface_damage_buffer(surface->child, 0, 0, INT32_MAX, INT32_MAX);
wl_surface_commit(surface->child);

Expand Down