mirror of
https://github.com/labwc/labwc.git
synced 2025-10-29 05:40:24 -04:00
backend/drm: Implement support for renderer loss recovery
This implementation is nearly identical to Sway's, except that
it also reloads the configuration, to spur on reloading the
server-side decorations.
v2: Fix style.
v3: Add a reset to the magnifier.
v4: Oops, restructure reset handler a bit.
v5: Commit the magnifier reset immediately, before freeing the
lost allocator and renderer.
v6: Also check for failed render pass, which may return NULL.
v7: Add a second NULL test, just in case.
This commit is contained in:
parent
e934c7a417
commit
3879f1f080
4 changed files with 76 additions and 4 deletions
|
|
@ -318,6 +318,8 @@ struct server {
|
||||||
*/
|
*/
|
||||||
int pending_output_layout_change;
|
int pending_output_layout_change;
|
||||||
|
|
||||||
|
struct wl_listener renderer_lost;
|
||||||
|
|
||||||
struct wlr_gamma_control_manager_v1 *gamma_control_manager_v1;
|
struct wlr_gamma_control_manager_v1 *gamma_control_manager_v1;
|
||||||
struct wl_listener gamma_control_set_gamma;
|
struct wl_listener gamma_control_set_gamma;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20,5 +20,6 @@ bool output_wants_magnification(struct output *output);
|
||||||
void magnify(struct output *output, struct wlr_buffer *output_buffer,
|
void magnify(struct output *output, struct wlr_buffer *output_buffer,
|
||||||
struct wlr_box *damage);
|
struct wlr_box *damage);
|
||||||
bool is_magnify_on(void);
|
bool is_magnify_on(void);
|
||||||
|
void magnify_reset(void);
|
||||||
|
|
||||||
#endif /* LABWC_MAGNIFIER_H */
|
#endif /* LABWC_MAGNIFIER_H */
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,10 @@
|
||||||
static bool magnify_on;
|
static bool magnify_on;
|
||||||
static double mag_scale = 0.0;
|
static double mag_scale = 0.0;
|
||||||
|
|
||||||
|
/* Reuse a single scratch buffer */
|
||||||
|
static struct wlr_buffer *tmp_buffer = NULL;
|
||||||
|
static struct wlr_texture *tmp_texture = NULL;
|
||||||
|
|
||||||
#define CLAMP(in, lower, upper) MAX(MIN((in), (upper)), (lower))
|
#define CLAMP(in, lower, upper) MAX(MIN((in), (upper)), (lower))
|
||||||
|
|
||||||
void
|
void
|
||||||
|
|
@ -21,10 +25,6 @@ magnify(struct output *output, struct wlr_buffer *output_buffer, struct wlr_box
|
||||||
struct wlr_fbox src_box;
|
struct wlr_fbox src_box;
|
||||||
bool fullscreen = false;
|
bool fullscreen = false;
|
||||||
|
|
||||||
/* Reuse a single scratch buffer */
|
|
||||||
static struct wlr_buffer *tmp_buffer = NULL;
|
|
||||||
static struct wlr_texture *tmp_texture = NULL;
|
|
||||||
|
|
||||||
/* TODO: This looks way too complicated to just get the used format */
|
/* TODO: This looks way too complicated to just get the used format */
|
||||||
struct wlr_drm_format wlr_drm_format = {0};
|
struct wlr_drm_format wlr_drm_format = {0};
|
||||||
struct wlr_shm_attributes shm_attribs = {0};
|
struct wlr_shm_attributes shm_attribs = {0};
|
||||||
|
|
@ -125,6 +125,10 @@ magnify(struct output *output, struct wlr_buffer *output_buffer, struct wlr_box
|
||||||
/* Extract source region into temporary buffer */
|
/* Extract source region into temporary buffer */
|
||||||
struct wlr_render_pass *tmp_render_pass = wlr_renderer_begin_buffer_pass(
|
struct wlr_render_pass *tmp_render_pass = wlr_renderer_begin_buffer_pass(
|
||||||
server->renderer, tmp_buffer, NULL);
|
server->renderer, tmp_buffer, NULL);
|
||||||
|
if (!tmp_render_pass) {
|
||||||
|
wlr_log(WLR_ERROR, "Failed to begin magnifier render pass");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
wlr_buffer_lock(output_buffer);
|
wlr_buffer_lock(output_buffer);
|
||||||
struct wlr_texture *output_texture = wlr_texture_from_buffer(
|
struct wlr_texture *output_texture = wlr_texture_from_buffer(
|
||||||
|
|
@ -152,6 +156,10 @@ magnify(struct output *output, struct wlr_buffer *output_buffer, struct wlr_box
|
||||||
/* Render to the output buffer itself */
|
/* Render to the output buffer itself */
|
||||||
tmp_render_pass = wlr_renderer_begin_buffer_pass(
|
tmp_render_pass = wlr_renderer_begin_buffer_pass(
|
||||||
server->renderer, output_buffer, NULL);
|
server->renderer, output_buffer, NULL);
|
||||||
|
if (!tmp_render_pass) {
|
||||||
|
wlr_log(WLR_ERROR, "Failed to begin second magnifier render pass");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
/* Borders */
|
/* Borders */
|
||||||
if (fullscreen) {
|
if (fullscreen) {
|
||||||
|
|
@ -286,6 +294,18 @@ magnify_set_scale(struct server *server, enum magnify_dir dir)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Reset any buffers held by the magnifier */
|
||||||
|
void
|
||||||
|
magnify_reset(void)
|
||||||
|
{
|
||||||
|
if (tmp_texture && tmp_buffer) {
|
||||||
|
wlr_texture_destroy(tmp_texture);
|
||||||
|
wlr_buffer_drop(tmp_buffer);
|
||||||
|
tmp_buffer = NULL;
|
||||||
|
tmp_texture = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Report whether magnification is enabled */
|
/* Report whether magnification is enabled */
|
||||||
bool
|
bool
|
||||||
is_magnify_on(void)
|
is_magnify_on(void)
|
||||||
|
|
|
||||||
49
src/server.c
49
src/server.c
|
|
@ -28,6 +28,7 @@
|
||||||
#include "idle.h"
|
#include "idle.h"
|
||||||
#include "labwc.h"
|
#include "labwc.h"
|
||||||
#include "layers.h"
|
#include "layers.h"
|
||||||
|
#include "magnifier.h"
|
||||||
#include "menu/menu.h"
|
#include "menu/menu.h"
|
||||||
#include "output-state.h"
|
#include "output-state.h"
|
||||||
#include "output-virtual.h"
|
#include "output-virtual.h"
|
||||||
|
|
@ -249,6 +250,51 @@ get_headless_backend(struct wlr_backend *backend, void *data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
handle_renderer_lost(struct wl_listener *listener, void *data)
|
||||||
|
{
|
||||||
|
struct server *server = wl_container_of(listener, server, renderer_lost);
|
||||||
|
|
||||||
|
wlr_log(WLR_INFO, "Re-creating renderer after GPU reset");
|
||||||
|
|
||||||
|
struct wlr_renderer *renderer = wlr_renderer_autocreate(server->backend);
|
||||||
|
if (!renderer) {
|
||||||
|
wlr_log(WLR_ERROR, "Unable to create renderer");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_allocator *allocator =
|
||||||
|
wlr_allocator_autocreate(server->backend, renderer);
|
||||||
|
if (!allocator) {
|
||||||
|
wlr_log(WLR_ERROR, "Unable to create allocator");
|
||||||
|
wlr_renderer_destroy(renderer);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct wlr_renderer *old_renderer = server->renderer;
|
||||||
|
struct wlr_allocator *old_allocator = server->allocator;
|
||||||
|
server->renderer = renderer;
|
||||||
|
server->allocator = allocator;
|
||||||
|
|
||||||
|
wl_list_remove(&server->renderer_lost.link);
|
||||||
|
wl_signal_add(&server->renderer->events.lost, &server->renderer_lost);
|
||||||
|
|
||||||
|
wlr_compositor_set_renderer(compositor, renderer);
|
||||||
|
|
||||||
|
struct output *output;
|
||||||
|
wl_list_for_each(output, &server->outputs, link) {
|
||||||
|
wlr_output_init_render(output->wlr_output,
|
||||||
|
server->allocator, server->renderer);
|
||||||
|
}
|
||||||
|
|
||||||
|
reload_config_and_theme(server);
|
||||||
|
|
||||||
|
magnify_reset();
|
||||||
|
|
||||||
|
wlr_allocator_destroy(old_allocator);
|
||||||
|
wlr_renderer_destroy(old_renderer);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
server_init(struct server *server)
|
server_init(struct server *server)
|
||||||
{
|
{
|
||||||
|
|
@ -336,6 +382,9 @@ server_init(struct server *server)
|
||||||
exit(EXIT_FAILURE);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
server->renderer_lost.notify = handle_renderer_lost;
|
||||||
|
wl_signal_add(&server->renderer->events.lost, &server->renderer_lost);
|
||||||
|
|
||||||
wlr_renderer_init_wl_display(server->renderer, server->wl_display);
|
wlr_renderer_init_wl_display(server->renderer, server->wl_display);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue