mirror of
https://github.com/yshui/picom.git
synced 2025-04-07 17:44:04 -04:00
backend: embed backend_operations table in backend_base
The idea is to allow backend plugins to override backend functions by modifying this table. Right now, when they do this they are actually changing a global variable and their change will persist after backend resets (!). Store the table inside backend_base solves this problem. Signed-off-by: Yuxuan Shui <yshuiv7@gmail.com>
This commit is contained in:
parent
9c4f62cd24
commit
bd26302f07
13 changed files with 124 additions and 130 deletions
|
@ -36,15 +36,7 @@ struct managed_win;
|
|||
struct ev_loop;
|
||||
struct backend_operations;
|
||||
|
||||
typedef struct backend_base {
|
||||
struct backend_operations *ops;
|
||||
struct x_connection *c;
|
||||
struct ev_loop *loop;
|
||||
|
||||
/// Whether the backend can accept new render request at the moment
|
||||
bool busy;
|
||||
// ...
|
||||
} backend_t;
|
||||
typedef struct backend_base backend_t;
|
||||
|
||||
// This mimics OpenGL's ARB_robustness extension, which enables detection of GPU context
|
||||
// resets.
|
||||
|
@ -475,6 +467,16 @@ struct backend_operations {
|
|||
enum device_status (*device_status)(backend_t *backend_data);
|
||||
};
|
||||
|
||||
struct backend_base {
|
||||
struct backend_operations ops;
|
||||
struct x_connection *c;
|
||||
struct ev_loop *loop;
|
||||
|
||||
/// Whether the backend can accept new render request at the moment
|
||||
bool busy;
|
||||
// ...
|
||||
};
|
||||
|
||||
/// Register a new backend, `major` and `minor` should be the version of the picom backend
|
||||
/// interface. You should just pass `PICOM_BACKEND_MAJOR` and `PICOM_BACKEND_MINOR` here.
|
||||
/// `name` is the name of the backend, `init` is the function to initialize the backend,
|
||||
|
|
|
@ -118,22 +118,22 @@ bool backend_execute(struct backend_base *backend, image_handle target, unsigned
|
|||
continue;
|
||||
}
|
||||
succeeded =
|
||||
backend->ops->blit(backend, cmd->origin, target, &cmd->blit);
|
||||
backend->ops.blit(backend, cmd->origin, target, &cmd->blit);
|
||||
break;
|
||||
case BACKEND_COMMAND_COPY_AREA:
|
||||
if (!pixman_region32_not_empty(cmd->copy_area.region)) {
|
||||
continue;
|
||||
}
|
||||
succeeded = backend->ops->copy_area(backend, cmd->origin, target,
|
||||
cmd->copy_area.source_image,
|
||||
cmd->copy_area.region);
|
||||
succeeded = backend->ops.copy_area(backend, cmd->origin, target,
|
||||
cmd->copy_area.source_image,
|
||||
cmd->copy_area.region);
|
||||
break;
|
||||
case BACKEND_COMMAND_BLUR:
|
||||
if (!pixman_region32_not_empty(cmd->blur.target_mask)) {
|
||||
continue;
|
||||
}
|
||||
succeeded =
|
||||
backend->ops->blur(backend, cmd->origin, target, &cmd->blur);
|
||||
backend->ops.blur(backend, cmd->origin, target, &cmd->blur);
|
||||
break;
|
||||
case BACKEND_COMMAND_INVALID:
|
||||
default: assert(false);
|
||||
|
|
|
@ -6,7 +6,6 @@
|
|||
#include <xcb/xcb_image.h>
|
||||
#include <xcb/xcb_renderutil.h>
|
||||
|
||||
#include "backend/backend.h"
|
||||
#include "backend/backend_common.h"
|
||||
#include "common.h"
|
||||
#include "config.h"
|
||||
|
@ -413,7 +412,7 @@ void init_backend_base(struct backend_base *base, session_t *ps) {
|
|||
base->c = &ps->c;
|
||||
base->loop = ps->loop;
|
||||
base->busy = false;
|
||||
base->ops = NULL;
|
||||
base->ops = (struct backend_operations){};
|
||||
}
|
||||
|
||||
uint32_t backend_no_quirks(struct backend_base *base attr_unused) {
|
||||
|
|
|
@ -7,15 +7,14 @@
|
|||
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "backend.h"
|
||||
#include "config.h"
|
||||
#include "region.h"
|
||||
|
||||
struct session;
|
||||
struct win;
|
||||
struct conv;
|
||||
struct backend_base;
|
||||
struct backend_operations;
|
||||
struct x_connection;
|
||||
|
||||
struct dual_kawase_params {
|
||||
/// Number of downsample passes
|
||||
|
|
|
@ -83,8 +83,8 @@ enum driver detect_driver(xcb_connection_t *c, backend_t *backend_data, xcb_wind
|
|||
free(randr_version);
|
||||
|
||||
// If the backend supports driver detection, use that as well
|
||||
if (backend_data && backend_data->ops->detect_driver) {
|
||||
ret |= backend_data->ops->detect_driver(backend_data);
|
||||
if (backend_data && backend_data->ops.detect_driver) {
|
||||
ret |= backend_data->ops.detect_driver(backend_data);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -29,12 +29,12 @@ struct dummy_data {
|
|||
struct dummy_image back_buffer;
|
||||
};
|
||||
|
||||
struct backend_operations dummy_ops;
|
||||
const struct backend_operations dummy_ops;
|
||||
|
||||
struct backend_base *dummy_init(session_t *ps attr_unused, xcb_window_t target attr_unused) {
|
||||
auto ret = ccalloc(1, struct dummy_data);
|
||||
init_backend_base(&ret->base, ps);
|
||||
ret->base.ops = &dummy_ops;
|
||||
ret->base.ops = dummy_ops;
|
||||
list_init_head(&ret->non_pixmap_images);
|
||||
return &ret->base;
|
||||
}
|
||||
|
@ -216,7 +216,7 @@ static void dummy_version(struct backend_base * /*base*/, uint64_t *major, uint6
|
|||
*minor = PICOM_BACKEND_DUMMY_MINOR;
|
||||
}
|
||||
|
||||
struct backend_operations dummy_ops = {
|
||||
const struct backend_operations dummy_ops = {
|
||||
.apply_alpha = dummy_apply_alpha,
|
||||
.back_buffer = dummy_back_buffer,
|
||||
.blit = dummy_blit,
|
||||
|
|
|
@ -4,8 +4,6 @@
|
|||
*/
|
||||
|
||||
#include <X11/Xlib-xcb.h>
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -105,7 +103,7 @@ static bool egl_set_swap_interval(int interval, EGLDisplay dpy) {
|
|||
return eglSwapInterval(dpy, interval);
|
||||
}
|
||||
|
||||
struct backend_operations egl_ops;
|
||||
const struct backend_operations egl_ops;
|
||||
/**
|
||||
* Initialize OpenGL.
|
||||
*/
|
||||
|
@ -154,7 +152,7 @@ static backend_t *egl_init(session_t *ps, xcb_window_t target) {
|
|||
|
||||
eglext_init(gd->display);
|
||||
init_backend_base(&gd->gl.base, ps);
|
||||
gd->gl.base.ops = &egl_ops;
|
||||
gd->gl.base.ops = egl_ops;
|
||||
if (!eglext.has_EGL_KHR_image_pixmap) {
|
||||
log_error("EGL_KHR_image_pixmap not available.");
|
||||
goto end;
|
||||
|
@ -355,7 +353,7 @@ static void egl_version(struct backend_base * /*base*/, uint64_t *major, uint64_
|
|||
*minor = PICOM_BACKEND_EGL_MINOR;
|
||||
}
|
||||
|
||||
struct backend_operations egl_ops = {
|
||||
const struct backend_operations egl_ops = {
|
||||
.apply_alpha = gl_apply_alpha,
|
||||
.back_buffer = gl_back_buffer,
|
||||
.blit = gl_blit,
|
||||
|
|
|
@ -11,7 +11,6 @@
|
|||
*/
|
||||
|
||||
#include <X11/Xlib-xcb.h>
|
||||
#include <assert.h>
|
||||
#include <limits.h>
|
||||
#include <pixman.h>
|
||||
#include <stdbool.h>
|
||||
|
@ -31,7 +30,6 @@
|
|||
#include "config.h"
|
||||
#include "log.h"
|
||||
#include "picom.h"
|
||||
#include "region.h"
|
||||
#include "utils.h"
|
||||
#include "win.h"
|
||||
#include "x.h"
|
||||
|
@ -225,7 +223,7 @@ static bool glx_set_swap_interval(int interval, Display *dpy, GLXDrawable drawab
|
|||
return vsync_enabled;
|
||||
}
|
||||
|
||||
struct backend_operations glx_ops;
|
||||
const struct backend_operations glx_ops;
|
||||
/**
|
||||
* Initialize OpenGL.
|
||||
*/
|
||||
|
@ -234,7 +232,7 @@ static backend_t *glx_init(session_t *ps, xcb_window_t target) {
|
|||
glxext_init(ps->c.dpy, ps->c.screen);
|
||||
auto gd = ccalloc(1, struct _glx_data);
|
||||
init_backend_base(&gd->gl.base, ps);
|
||||
gd->gl.base.ops = &glx_ops;
|
||||
gd->gl.base.ops = glx_ops;
|
||||
|
||||
gd->target_win = target;
|
||||
|
||||
|
@ -529,7 +527,7 @@ static void glx_version(struct backend_base * /*base*/, uint64_t *major, uint64_
|
|||
*minor = PICOM_BACKEND_GLX_MINOR;
|
||||
}
|
||||
|
||||
struct backend_operations glx_ops = {
|
||||
const struct backend_operations glx_ops = {
|
||||
.apply_alpha = gl_apply_alpha,
|
||||
.back_buffer = gl_back_buffer,
|
||||
.bind_pixmap = glx_bind_pixmap,
|
||||
|
|
|
@ -865,7 +865,7 @@ static void xrender_get_blur_size(void *blur_context, int *width, int *height) {
|
|||
*width = ctx->resize_width;
|
||||
*height = ctx->resize_height;
|
||||
}
|
||||
struct backend_operations xrender_ops;
|
||||
const struct backend_operations xrender_ops;
|
||||
static backend_t *xrender_init(session_t *ps, xcb_window_t target) {
|
||||
if (ps->o.dithered_present) {
|
||||
log_warn("\"dithered-present\" is not supported by the xrender backend, "
|
||||
|
@ -878,7 +878,7 @@ static backend_t *xrender_init(session_t *ps, xcb_window_t target) {
|
|||
|
||||
auto xd = ccalloc(1, struct xrender_data);
|
||||
init_backend_base(&xd->base, ps);
|
||||
xd->base.ops = &xrender_ops;
|
||||
xd->base.ops = xrender_ops;
|
||||
|
||||
for (int i = 0; i <= MAX_ALPHA; ++i) {
|
||||
double o = (double)i / (double)MAX_ALPHA;
|
||||
|
@ -1032,7 +1032,7 @@ static void xrender_version(struct backend_base * /*base*/, uint64_t *major, uin
|
|||
*minor = PICOM_BACKEND_XRENDER_MINOR;
|
||||
}
|
||||
|
||||
struct backend_operations xrender_ops = {
|
||||
const struct backend_operations xrender_ops = {
|
||||
.apply_alpha = xrender_apply_alpha,
|
||||
.back_buffer = xrender_back_buffer,
|
||||
.bind_pixmap = xrender_bind_pixmap,
|
||||
|
|
|
@ -51,11 +51,11 @@ void print_diagnostics(session_t *ps, const char *config_file, bool compositor_r
|
|||
printf(" Cannot initialize backend %s\n", backend_name(i));
|
||||
continue;
|
||||
}
|
||||
if (backend_data->ops->diagnostics) {
|
||||
if (backend_data->ops.diagnostics) {
|
||||
printf("\n### Backend: %s\n\n", backend_name(i));
|
||||
backend_data->ops->diagnostics(backend_data);
|
||||
backend_data->ops.diagnostics(backend_data);
|
||||
}
|
||||
backend_data->ops->deinit(backend_data);
|
||||
backend_data->ops.deinit(backend_data);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
36
src/picom.c
36
src/picom.c
|
@ -152,7 +152,7 @@ enum vblank_callback_action check_render_finish(struct vblank_event *e attr_unus
|
|||
|
||||
struct timespec render_time;
|
||||
bool completed =
|
||||
ps->backend_data->ops->last_render_time(ps->backend_data, &render_time);
|
||||
ps->backend_data->ops.last_render_time(ps->backend_data, &render_time);
|
||||
if (!completed) {
|
||||
// Render hasn't completed yet, we can't start another render.
|
||||
// Check again at the next vblank.
|
||||
|
@ -575,14 +575,14 @@ static void destroy_backend(session_t *ps) {
|
|||
|
||||
HASH_ITER2(ps->shaders, shader) {
|
||||
if (shader->backend_shader != NULL) {
|
||||
ps->backend_data->ops->destroy_shader(ps->backend_data,
|
||||
shader->backend_shader);
|
||||
ps->backend_data->ops.destroy_shader(ps->backend_data,
|
||||
shader->backend_shader);
|
||||
shader->backend_shader = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (ps->backend_data && ps->root_image) {
|
||||
ps->backend_data->ops->release_image(ps->backend_data, ps->root_image);
|
||||
ps->backend_data->ops.release_image(ps->backend_data, ps->root_image);
|
||||
ps->root_image = NULL;
|
||||
}
|
||||
|
||||
|
@ -593,11 +593,11 @@ static void destroy_backend(session_t *ps) {
|
|||
}
|
||||
// deinit backend
|
||||
if (ps->backend_blur_context) {
|
||||
ps->backend_data->ops->destroy_blur_context(
|
||||
ps->backend_data->ops.destroy_blur_context(
|
||||
ps->backend_data, ps->backend_blur_context);
|
||||
ps->backend_blur_context = NULL;
|
||||
}
|
||||
ps->backend_data->ops->deinit(ps->backend_data);
|
||||
ps->backend_data->ops.deinit(ps->backend_data);
|
||||
ps->backend_data = NULL;
|
||||
}
|
||||
}
|
||||
|
@ -635,7 +635,7 @@ static bool initialize_blur(session_t *ps) {
|
|||
enum backend_image_format format = ps->o.dithered_present
|
||||
? BACKEND_IMAGE_FORMAT_PIXMAP_HIGH
|
||||
: BACKEND_IMAGE_FORMAT_PIXMAP;
|
||||
ps->backend_blur_context = ps->backend_data->ops->create_blur_context(
|
||||
ps->backend_blur_context = ps->backend_data->ops.create_blur_context(
|
||||
ps->backend_data, ps->o.blur_method, format, args);
|
||||
return ps->backend_blur_context != NULL;
|
||||
}
|
||||
|
@ -674,14 +674,14 @@ static bool initialize_backend(session_t *ps) {
|
|||
}
|
||||
|
||||
// Create shaders
|
||||
if (!ps->backend_data->ops->create_shader && ps->shaders) {
|
||||
if (!ps->backend_data->ops.create_shader && ps->shaders) {
|
||||
log_warn("Shaders are not supported by selected backend %s, "
|
||||
"they will be ignored",
|
||||
backend_name(ps->o.backend));
|
||||
} else {
|
||||
HASH_ITER2(ps->shaders, shader) {
|
||||
assert(shader->backend_shader == NULL);
|
||||
shader->backend_shader = ps->backend_data->ops->create_shader(
|
||||
shader->backend_shader = ps->backend_data->ops.create_shader(
|
||||
ps->backend_data, shader->source);
|
||||
if (shader->backend_shader == NULL) {
|
||||
log_warn("Failed to create shader for shader "
|
||||
|
@ -689,9 +689,9 @@ static bool initialize_backend(session_t *ps) {
|
|||
shader->key);
|
||||
} else {
|
||||
shader->attributes = 0;
|
||||
if (ps->backend_data->ops->get_shader_attributes) {
|
||||
if (ps->backend_data->ops.get_shader_attributes) {
|
||||
shader->attributes =
|
||||
ps->backend_data->ops->get_shader_attributes(
|
||||
ps->backend_data->ops.get_shader_attributes(
|
||||
ps->backend_data,
|
||||
shader->backend_shader);
|
||||
}
|
||||
|
@ -719,7 +719,7 @@ static bool initialize_backend(session_t *ps) {
|
|||
// The old backends binds pixmap lazily, nothing to do here
|
||||
return true;
|
||||
err:
|
||||
ps->backend_data->ops->deinit(ps->backend_data);
|
||||
ps->backend_data->ops.deinit(ps->backend_data);
|
||||
ps->backend_data = NULL;
|
||||
quit(ps);
|
||||
return false;
|
||||
|
@ -741,7 +741,7 @@ static void configure_root(session_t *ps) {
|
|||
// On root window changes
|
||||
if (!ps->o.use_legacy_backends) {
|
||||
assert(ps->backend_data);
|
||||
has_root_change = ps->backend_data->ops->root_change != NULL;
|
||||
has_root_change = ps->backend_data->ops.root_change != NULL;
|
||||
} else {
|
||||
// Old backend can handle root change
|
||||
has_root_change = true;
|
||||
|
@ -788,7 +788,7 @@ static void configure_root(session_t *ps) {
|
|||
#endif
|
||||
if (has_root_change) {
|
||||
if (ps->backend_data != NULL) {
|
||||
ps->backend_data->ops->root_change(ps->backend_data, ps);
|
||||
ps->backend_data->ops.root_change(ps->backend_data, ps);
|
||||
}
|
||||
// Old backend's root_change is not a specific function
|
||||
} else {
|
||||
|
@ -1082,7 +1082,7 @@ void root_damaged(session_t *ps) {
|
|||
|
||||
if (ps->backend_data) {
|
||||
if (ps->root_image) {
|
||||
ps->backend_data->ops->release_image(ps->backend_data, ps->root_image);
|
||||
ps->backend_data->ops.release_image(ps->backend_data, ps->root_image);
|
||||
ps->root_image = NULL;
|
||||
}
|
||||
auto pixmap = x_get_root_back_pixmap(&ps->c, ps->atoms);
|
||||
|
@ -1116,7 +1116,7 @@ void root_damaged(session_t *ps) {
|
|||
: x_get_visual_for_depth(ps->c.screen_info, r->depth);
|
||||
free(r);
|
||||
|
||||
ps->root_image = ps->backend_data->ops->bind_pixmap(
|
||||
ps->root_image = ps->backend_data->ops.bind_pixmap(
|
||||
ps->backend_data, pixmap, x_get_visual_info(&ps->c, visual));
|
||||
ps->root_image_generation += 1;
|
||||
if (!ps->root_image) {
|
||||
|
@ -1421,7 +1421,7 @@ static bool redirect_start(session_t *ps) {
|
|||
if (!ps->o.use_legacy_backends) {
|
||||
assert(ps->backend_data);
|
||||
ps->damage_ring.count =
|
||||
ps->backend_data->ops->max_buffer_age(ps->backend_data);
|
||||
ps->backend_data->ops.max_buffer_age(ps->backend_data);
|
||||
ps->layout_manager = layout_manager_new((unsigned)ps->damage_ring.count);
|
||||
} else {
|
||||
ps->damage_ring.count = maximum_buffer_age(ps);
|
||||
|
@ -1435,7 +1435,7 @@ static bool redirect_start(session_t *ps) {
|
|||
|
||||
ps->frame_pacing = ps->o.frame_pacing && ps->o.vsync;
|
||||
if ((ps->o.use_legacy_backends || ps->o.benchmark ||
|
||||
!ps->backend_data->ops->last_render_time) &&
|
||||
!ps->backend_data->ops.last_render_time) &&
|
||||
ps->frame_pacing) {
|
||||
// Disable frame pacing if we are using a legacy backend or if we are in
|
||||
// benchmark mode, or if the backend doesn't report render time
|
||||
|
|
|
@ -69,19 +69,19 @@ static void renderer_reallocate_culled_masks(struct renderer *r, size_t capacity
|
|||
|
||||
void renderer_free(struct backend_base *backend, struct renderer *r) {
|
||||
if (r->white_image) {
|
||||
backend->ops->release_image(backend, r->white_image);
|
||||
backend->ops.release_image(backend, r->white_image);
|
||||
}
|
||||
if (r->black_image) {
|
||||
backend->ops->release_image(backend, r->black_image);
|
||||
backend->ops.release_image(backend, r->black_image);
|
||||
}
|
||||
if (r->back_image) {
|
||||
backend->ops->release_image(backend, r->back_image);
|
||||
backend->ops.release_image(backend, r->back_image);
|
||||
}
|
||||
if (r->monitor_repaint_pixel) {
|
||||
backend->ops->release_image(backend, r->monitor_repaint_pixel);
|
||||
backend->ops.release_image(backend, r->monitor_repaint_pixel);
|
||||
}
|
||||
if (r->shadow_blur_context) {
|
||||
backend->ops->destroy_blur_context(backend, r->shadow_blur_context);
|
||||
backend->ops.destroy_blur_context(backend, r->shadow_blur_context);
|
||||
}
|
||||
if (r->shadow_kernel) {
|
||||
free_conv(r->shadow_kernel);
|
||||
|
@ -97,7 +97,7 @@ void renderer_free(struct backend_base *backend, struct renderer *r) {
|
|||
}
|
||||
if (r->monitor_repaint_copy) {
|
||||
for (int i = 0; i < r->max_buffer_age; i++) {
|
||||
backend->ops->release_image(backend, r->monitor_repaint_copy[i]);
|
||||
backend->ops.release_image(backend, r->monitor_repaint_copy[i]);
|
||||
}
|
||||
free(r->monitor_repaint_copy);
|
||||
}
|
||||
|
@ -109,21 +109,21 @@ static bool
|
|||
renderer_init(struct renderer *renderer, struct backend_base *backend,
|
||||
double shadow_radius, struct color shadow_color, bool dithered_present) {
|
||||
auto has_high_precision =
|
||||
backend->ops->is_format_supported(backend, BACKEND_IMAGE_FORMAT_PIXMAP_HIGH);
|
||||
backend->ops.is_format_supported(backend, BACKEND_IMAGE_FORMAT_PIXMAP_HIGH);
|
||||
renderer->format = has_high_precision && dithered_present
|
||||
? BACKEND_IMAGE_FORMAT_PIXMAP_HIGH
|
||||
: BACKEND_IMAGE_FORMAT_PIXMAP;
|
||||
renderer->back_image = NULL;
|
||||
renderer->white_image =
|
||||
backend->ops->new_image(backend, renderer->format, (ivec2){1, 1});
|
||||
if (!renderer->white_image || !backend->ops->clear(backend, renderer->white_image,
|
||||
(struct color){1, 1, 1, 1})) {
|
||||
backend->ops.new_image(backend, renderer->format, (ivec2){1, 1});
|
||||
if (!renderer->white_image || !backend->ops.clear(backend, renderer->white_image,
|
||||
(struct color){1, 1, 1, 1})) {
|
||||
return false;
|
||||
}
|
||||
renderer->black_image =
|
||||
backend->ops->new_image(backend, renderer->format, (ivec2){1, 1});
|
||||
if (!renderer->black_image || !backend->ops->clear(backend, renderer->black_image,
|
||||
(struct color){0, 0, 0, 1})) {
|
||||
backend->ops.new_image(backend, renderer->format, (ivec2){1, 1});
|
||||
if (!renderer->black_image || !backend->ops.clear(backend, renderer->black_image,
|
||||
(struct color){0, 0, 0, 1})) {
|
||||
return false;
|
||||
}
|
||||
renderer->canvas_size = (ivec2){0, 0};
|
||||
|
@ -132,7 +132,7 @@ renderer_init(struct renderer *renderer, struct backend_base *backend,
|
|||
.size = (int)shadow_radius,
|
||||
.deviation = gaussian_kernel_std_for_size(shadow_radius, 0.5 / 256.0),
|
||||
};
|
||||
renderer->shadow_blur_context = backend->ops->create_blur_context(
|
||||
renderer->shadow_blur_context = backend->ops.create_blur_context(
|
||||
backend, BLUR_METHOD_GAUSSIAN, BACKEND_IMAGE_FORMAT_MASK, &args);
|
||||
if (!renderer->shadow_blur_context) {
|
||||
log_error("Failed to create shadow blur context");
|
||||
|
@ -154,7 +154,7 @@ renderer_init(struct renderer *renderer, struct backend_base *backend,
|
|||
}
|
||||
sum_kernel_preprocess(renderer->shadow_kernel);
|
||||
}
|
||||
renderer->max_buffer_age = backend->ops->max_buffer_age(backend) + 1;
|
||||
renderer->max_buffer_age = backend->ops.max_buffer_age(backend) + 1;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -176,23 +176,23 @@ renderer_set_root_size(struct renderer *r, struct backend_base *backend, ivec2 r
|
|||
return true;
|
||||
}
|
||||
if (r->back_image) {
|
||||
backend->ops->release_image(backend, r->back_image);
|
||||
backend->ops.release_image(backend, r->back_image);
|
||||
}
|
||||
if (r->back_buffer_copy) {
|
||||
for (int i = 0; i < r->max_buffer_age; i++) {
|
||||
backend->ops->release_image(backend, r->back_buffer_copy[i]);
|
||||
backend->ops.release_image(backend, r->back_buffer_copy[i]);
|
||||
}
|
||||
free(r->back_buffer_copy);
|
||||
r->back_buffer_copy = NULL;
|
||||
}
|
||||
if (r->monitor_repaint_copy) {
|
||||
for (int i = 0; i < r->max_buffer_age; i++) {
|
||||
backend->ops->release_image(backend, r->monitor_repaint_copy[i]);
|
||||
backend->ops.release_image(backend, r->monitor_repaint_copy[i]);
|
||||
}
|
||||
free(r->monitor_repaint_copy);
|
||||
r->monitor_repaint_copy = NULL;
|
||||
}
|
||||
r->back_image = backend->ops->new_image(backend, r->format, root_size);
|
||||
r->back_image = backend->ops.new_image(backend, r->format, root_size);
|
||||
if (r->back_image != NULL) {
|
||||
r->canvas_size = root_size;
|
||||
return true;
|
||||
|
@ -205,16 +205,16 @@ static bool
|
|||
renderer_bind_mask(struct renderer *r, struct backend_base *backend, struct managed_win *w) {
|
||||
ivec2 size = {.width = w->widthb, .height = w->heightb};
|
||||
bool succeeded = false;
|
||||
auto image = backend->ops->new_image(backend, BACKEND_IMAGE_FORMAT_MASK, size);
|
||||
if (!image || !backend->ops->clear(backend, image, (struct color){0, 0, 0, 0})) {
|
||||
auto image = backend->ops.new_image(backend, BACKEND_IMAGE_FORMAT_MASK, size);
|
||||
if (!image || !backend->ops.clear(backend, image, (struct color){0, 0, 0, 0})) {
|
||||
log_error("Failed to create mask image");
|
||||
goto err;
|
||||
}
|
||||
|
||||
auto bound_region_local = win_get_bounding_shape_global_by_val(w);
|
||||
pixman_region32_translate(&bound_region_local, -w->g.x, -w->g.y);
|
||||
succeeded = backend->ops->copy_area(backend, (ivec2){0, 0}, (image_handle)image,
|
||||
r->white_image, &bound_region_local);
|
||||
succeeded = backend->ops.copy_area(backend, (ivec2){0, 0}, (image_handle)image,
|
||||
r->white_image, &bound_region_local);
|
||||
pixman_region32_fini(&bound_region_local);
|
||||
if (!succeeded) {
|
||||
log_error("Failed to fill the mask");
|
||||
|
@ -225,7 +225,7 @@ renderer_bind_mask(struct renderer *r, struct backend_base *backend, struct mana
|
|||
|
||||
err:
|
||||
if (image != NULL) {
|
||||
backend->ops->release_image(backend, image);
|
||||
backend->ops.release_image(backend, image);
|
||||
}
|
||||
return succeeded;
|
||||
}
|
||||
|
@ -243,11 +243,11 @@ image_handle renderer_shadow_from_mask(struct renderer *r, struct backend_base *
|
|||
|
||||
// Apply the properties on the mask image and blit the result into a larger
|
||||
// image, each side larger by `2 * radius` so there is space for blurring.
|
||||
normalized_mask_image = backend->ops->new_image(
|
||||
normalized_mask_image = backend->ops.new_image(
|
||||
backend, BACKEND_IMAGE_FORMAT_MASK,
|
||||
(ivec2){mask_size.width + 2 * radius, mask_size.height + 2 * radius});
|
||||
if (!normalized_mask_image || !backend->ops->clear(backend, normalized_mask_image,
|
||||
(struct color){0, 0, 0, 0})) {
|
||||
if (!normalized_mask_image || !backend->ops.clear(backend, normalized_mask_image,
|
||||
(struct color){0, 0, 0, 0})) {
|
||||
log_error("Failed to create mask image");
|
||||
goto out;
|
||||
}
|
||||
|
@ -276,8 +276,8 @@ image_handle renderer_shadow_from_mask(struct renderer *r, struct backend_base *
|
|||
pixman_region32_init_rect(&target_mask, radius, radius,
|
||||
(unsigned)mask_size.width,
|
||||
(unsigned)mask_size.height);
|
||||
succeeded = backend->ops->blit(backend, (ivec2){radius, radius},
|
||||
normalized_mask_image, &args);
|
||||
succeeded = backend->ops.blit(backend, (ivec2){radius, radius},
|
||||
normalized_mask_image, &args);
|
||||
pixman_region32_fini(&target_mask);
|
||||
if (!succeeded) {
|
||||
log_error("Failed to blit for shadow generation");
|
||||
|
@ -297,7 +297,7 @@ image_handle renderer_shadow_from_mask(struct renderer *r, struct backend_base *
|
|||
(unsigned)(mask_size.width + 2 * radius),
|
||||
(unsigned)(mask_size.height + 2 * radius));
|
||||
succeeded =
|
||||
backend->ops->blur(backend, (ivec2){0, 0}, normalized_mask_image, &args);
|
||||
backend->ops.blur(backend, (ivec2){0, 0}, normalized_mask_image, &args);
|
||||
pixman_region32_fini(&target_mask);
|
||||
if (!succeeded) {
|
||||
log_error("Failed to blur for shadow generation");
|
||||
|
@ -306,19 +306,19 @@ image_handle renderer_shadow_from_mask(struct renderer *r, struct backend_base *
|
|||
}
|
||||
// Finally, we blit with this mask to colorize the shadow
|
||||
succeeded = false;
|
||||
shadow_image = backend->ops->new_image(
|
||||
shadow_image = backend->ops.new_image(
|
||||
backend, BACKEND_IMAGE_FORMAT_PIXMAP,
|
||||
(ivec2){mask_size.width + 2 * radius, mask_size.height + 2 * radius});
|
||||
if (!shadow_image ||
|
||||
!backend->ops->clear(backend, shadow_image, (struct color){0, 0, 0, 0})) {
|
||||
!backend->ops.clear(backend, shadow_image, (struct color){0, 0, 0, 0})) {
|
||||
log_error("Failed to allocate shadow image");
|
||||
goto out;
|
||||
}
|
||||
|
||||
shadow_color_pixel =
|
||||
backend->ops->new_image(backend, BACKEND_IMAGE_FORMAT_PIXMAP, (ivec2){1, 1});
|
||||
backend->ops.new_image(backend, BACKEND_IMAGE_FORMAT_PIXMAP, (ivec2){1, 1});
|
||||
if (!shadow_color_pixel ||
|
||||
!backend->ops->clear(backend, shadow_color_pixel, r->shadow_color)) {
|
||||
!backend->ops.clear(backend, shadow_color_pixel, r->shadow_color)) {
|
||||
log_error("Failed to create shadow color image");
|
||||
goto out;
|
||||
}
|
||||
|
@ -348,19 +348,19 @@ image_handle renderer_shadow_from_mask(struct renderer *r, struct backend_base *
|
|||
};
|
||||
pixman_region32_init_rect(&target_mask, 0, 0, (unsigned)shadow_size.width,
|
||||
(unsigned)shadow_size.height);
|
||||
succeeded = backend->ops->blit(backend, (ivec2){0, 0}, shadow_image, &args);
|
||||
succeeded = backend->ops.blit(backend, (ivec2){0, 0}, shadow_image, &args);
|
||||
pixman_region32_fini(&target_mask);
|
||||
|
||||
out:
|
||||
if (normalized_mask_image) {
|
||||
backend->ops->release_image(backend, normalized_mask_image);
|
||||
backend->ops.release_image(backend, normalized_mask_image);
|
||||
}
|
||||
if (shadow_color_pixel) {
|
||||
backend->ops->release_image(backend, shadow_color_pixel);
|
||||
backend->ops.release_image(backend, shadow_color_pixel);
|
||||
}
|
||||
if (!succeeded && shadow_image) {
|
||||
log_error("Failed to draw shadow image");
|
||||
backend->ops->release_image(backend, shadow_image);
|
||||
backend->ops.release_image(backend, shadow_image);
|
||||
shadow_image = NULL;
|
||||
}
|
||||
return shadow_image;
|
||||
|
@ -368,7 +368,7 @@ out:
|
|||
|
||||
static bool renderer_bind_shadow(struct renderer *r, struct backend_base *backend,
|
||||
struct managed_win *w) {
|
||||
if (backend->ops->quirks(backend) & BACKEND_QUIRK_SLOW_BLUR) {
|
||||
if (backend->ops.quirks(backend) & BACKEND_QUIRK_SLOW_BLUR) {
|
||||
xcb_pixmap_t shadow = XCB_NONE;
|
||||
xcb_render_picture_t pict = XCB_NONE;
|
||||
|
||||
|
@ -379,7 +379,7 @@ static bool renderer_bind_shadow(struct renderer *r, struct backend_base *backen
|
|||
|
||||
auto visual =
|
||||
x_get_visual_for_standard(backend->c, XCB_PICT_STANDARD_ARGB_32);
|
||||
w->shadow_image = backend->ops->bind_pixmap(
|
||||
w->shadow_image = backend->ops.bind_pixmap(
|
||||
backend, shadow, x_get_visual_info(backend->c, visual));
|
||||
} else {
|
||||
if (!w->mask_image && !renderer_bind_mask(r, backend, w)) {
|
||||
|
@ -467,16 +467,16 @@ void renderer_ensure_images_ready(struct renderer *r, struct backend_base *backe
|
|||
bool monitor_repaint) {
|
||||
if (monitor_repaint) {
|
||||
if (!r->monitor_repaint_pixel) {
|
||||
r->monitor_repaint_pixel = backend->ops->new_image(
|
||||
r->monitor_repaint_pixel = backend->ops.new_image(
|
||||
backend, BACKEND_IMAGE_FORMAT_PIXMAP, (ivec2){1, 1});
|
||||
BUG_ON(!r->monitor_repaint_pixel);
|
||||
backend->ops->clear(backend, r->monitor_repaint_pixel,
|
||||
(struct color){.alpha = 0.5, .red = 0.5});
|
||||
backend->ops.clear(backend, r->monitor_repaint_pixel,
|
||||
(struct color){.alpha = 0.5, .red = 0.5});
|
||||
}
|
||||
if (!r->monitor_repaint_copy) {
|
||||
r->monitor_repaint_copy = ccalloc(r->max_buffer_age, image_handle);
|
||||
for (int i = 0; i < r->max_buffer_age; i++) {
|
||||
r->monitor_repaint_copy[i] = backend->ops->new_image(
|
||||
r->monitor_repaint_copy[i] = backend->ops.new_image(
|
||||
backend, BACKEND_IMAGE_FORMAT_PIXMAP,
|
||||
(ivec2){.width = r->canvas_size.width,
|
||||
.height = r->canvas_size.height});
|
||||
|
@ -493,10 +493,10 @@ void renderer_ensure_images_ready(struct renderer *r, struct backend_base *backe
|
|||
if (global_debug_options.consistent_buffer_age && !r->back_buffer_copy) {
|
||||
r->back_buffer_copy = ccalloc(r->max_buffer_age, image_handle);
|
||||
for (int i = 0; i < r->max_buffer_age; i++) {
|
||||
r->back_buffer_copy[i] = backend->ops->new_image(
|
||||
backend, BACKEND_IMAGE_FORMAT_PIXMAP,
|
||||
(ivec2){.width = r->canvas_size.width,
|
||||
.height = r->canvas_size.height});
|
||||
r->back_buffer_copy[i] =
|
||||
backend->ops.new_image(backend, BACKEND_IMAGE_FORMAT_PIXMAP,
|
||||
(ivec2){.width = r->canvas_size.width,
|
||||
.height = r->canvas_size.height});
|
||||
BUG_ON(!r->back_buffer_copy[i]);
|
||||
}
|
||||
}
|
||||
|
@ -554,19 +554,19 @@ bool renderer_render(struct renderer *r, struct backend_base *backend,
|
|||
pixman_region32_init(&damage_region);
|
||||
pixman_region32_copy(&damage_region, &screen_region);
|
||||
ivec2 blur_size = {};
|
||||
if (backend->ops->get_blur_size && blur_context) {
|
||||
backend->ops->get_blur_size(blur_context, &blur_size.width, &blur_size.height);
|
||||
if (backend->ops.get_blur_size && blur_context) {
|
||||
backend->ops.get_blur_size(blur_context, &blur_size.width, &blur_size.height);
|
||||
}
|
||||
auto buffer_age =
|
||||
(use_damage || monitor_repaint) ? backend->ops->buffer_age(backend) : 0;
|
||||
(use_damage || monitor_repaint) ? backend->ops.buffer_age(backend) : 0;
|
||||
if (buffer_age > 0 && global_debug_options.consistent_buffer_age) {
|
||||
int past_frame =
|
||||
(r->frame_index + r->max_buffer_age - buffer_age) % r->max_buffer_age;
|
||||
region_t region;
|
||||
pixman_region32_init_rect(®ion, 0, 0, (unsigned)r->canvas_size.width,
|
||||
(unsigned)r->canvas_size.height);
|
||||
backend->ops->copy_area(backend, (ivec2){}, backend->ops->back_buffer(backend),
|
||||
r->back_buffer_copy[past_frame], ®ion);
|
||||
backend->ops.copy_area(backend, (ivec2){}, backend->ops.back_buffer(backend),
|
||||
r->back_buffer_copy[past_frame], ®ion);
|
||||
pixman_region32_fini(®ion);
|
||||
}
|
||||
if (buffer_age > 0 && (unsigned)buffer_age <= layout_manager_max_buffer_age(lm)) {
|
||||
|
@ -595,17 +595,17 @@ bool renderer_render(struct renderer *r, struct backend_base *backend,
|
|||
xcb_sync_reset_fence(backend->c->c, xsync_fence));
|
||||
}
|
||||
|
||||
if (backend->ops->prepare) {
|
||||
backend->ops->prepare(backend, &layout->commands[0].target_mask);
|
||||
if (backend->ops.prepare) {
|
||||
backend->ops.prepare(backend, &layout->commands[0].target_mask);
|
||||
}
|
||||
|
||||
if (monitor_repaint && buffer_age <= r->max_buffer_age) {
|
||||
// Restore the area of back buffer that was tainted by monitor repaint
|
||||
int past_frame =
|
||||
(r->frame_index + r->max_buffer_age - buffer_age) % r->max_buffer_age;
|
||||
backend->ops->copy_area(backend, (ivec2){}, backend->ops->back_buffer(backend),
|
||||
r->monitor_repaint_copy[past_frame],
|
||||
&r->monitor_repaint_region[past_frame]);
|
||||
backend->ops.copy_area(backend, (ivec2){}, backend->ops.back_buffer(backend),
|
||||
r->monitor_repaint_copy[past_frame],
|
||||
&r->monitor_repaint_region[past_frame]);
|
||||
}
|
||||
|
||||
if (!backend_execute(backend, r->back_image, layout->number_of_commands,
|
||||
|
@ -616,9 +616,9 @@ bool renderer_render(struct renderer *r, struct backend_base *backend,
|
|||
|
||||
if (monitor_repaint) {
|
||||
// Keep a copy of un-tainted back image
|
||||
backend->ops->copy_area(backend, (ivec2){},
|
||||
r->monitor_repaint_copy[r->frame_index],
|
||||
r->back_image, &damage_region);
|
||||
backend->ops.copy_area(backend, (ivec2){},
|
||||
r->monitor_repaint_copy[r->frame_index],
|
||||
r->back_image, &damage_region);
|
||||
pixman_region32_copy(&r->monitor_repaint_region[r->frame_index], &damage_region);
|
||||
|
||||
struct backend_blit_args blit = {
|
||||
|
@ -631,24 +631,22 @@ bool renderer_render(struct renderer *r, struct backend_base *backend,
|
|||
.scale = SCALE_IDENTITY,
|
||||
};
|
||||
log_trace("Blit for monitor repaint");
|
||||
backend->ops->blit(backend, (ivec2){}, r->back_image, &blit);
|
||||
backend->ops.blit(backend, (ivec2){}, r->back_image, &blit);
|
||||
}
|
||||
|
||||
backend->ops->copy_area_quantize(backend, (ivec2){},
|
||||
backend->ops->back_buffer(backend),
|
||||
r->back_image, &damage_region);
|
||||
backend->ops.copy_area_quantize(backend, (ivec2){}, backend->ops.back_buffer(backend),
|
||||
r->back_image, &damage_region);
|
||||
|
||||
if (global_debug_options.consistent_buffer_age) {
|
||||
region_t region;
|
||||
pixman_region32_init_rect(®ion, 0, 0, (unsigned)r->canvas_size.width,
|
||||
(unsigned)r->canvas_size.height);
|
||||
backend->ops->copy_area(backend, (ivec2){},
|
||||
r->back_buffer_copy[r->frame_index],
|
||||
backend->ops->back_buffer(backend), ®ion);
|
||||
backend->ops.copy_area(backend, (ivec2){}, r->back_buffer_copy[r->frame_index],
|
||||
backend->ops.back_buffer(backend), ®ion);
|
||||
pixman_region32_fini(®ion);
|
||||
}
|
||||
|
||||
if (backend->ops->present && !backend->ops->present(backend)) {
|
||||
if (backend->ops.present && !backend->ops.present(backend)) {
|
||||
log_warn("Failed to present the frame");
|
||||
}
|
||||
|
||||
|
|
|
@ -331,7 +331,7 @@ static inline void win_release_pixmap(backend_t *base, struct managed_win *w) {
|
|||
assert(w->win_image);
|
||||
if (w->win_image) {
|
||||
xcb_pixmap_t pixmap = XCB_NONE;
|
||||
pixmap = base->ops->release_image(base, w->win_image);
|
||||
pixmap = base->ops.release_image(base, w->win_image);
|
||||
w->win_image = NULL;
|
||||
// Bypassing win_set_flags, because `w` might have been destroyed
|
||||
w->flags |= WIN_FLAGS_PIXMAP_NONE;
|
||||
|
@ -345,7 +345,7 @@ static inline void win_release_shadow(backend_t *base, struct managed_win *w) {
|
|||
if (w->shadow_image) {
|
||||
assert(w->shadow);
|
||||
xcb_pixmap_t pixmap = XCB_NONE;
|
||||
pixmap = base->ops->release_image(base, w->shadow_image);
|
||||
pixmap = base->ops.release_image(base, w->shadow_image);
|
||||
w->shadow_image = NULL;
|
||||
if (pixmap != XCB_NONE) {
|
||||
xcb_free_pixmap(base->c->c, pixmap);
|
||||
|
@ -356,7 +356,7 @@ static inline void win_release_shadow(backend_t *base, struct managed_win *w) {
|
|||
static inline void win_release_mask(backend_t *base, struct managed_win *w) {
|
||||
if (w->mask_image) {
|
||||
xcb_pixmap_t pixmap = XCB_NONE;
|
||||
pixmap = base->ops->release_image(base, w->mask_image);
|
||||
pixmap = base->ops.release_image(base, w->mask_image);
|
||||
w->mask_image = NULL;
|
||||
if (pixmap != XCB_NONE) {
|
||||
xcb_free_pixmap(base->c->c, pixmap);
|
||||
|
@ -376,7 +376,7 @@ static inline bool win_bind_pixmap(struct backend_base *b, struct managed_win *w
|
|||
return false;
|
||||
}
|
||||
log_debug("New named pixmap for %#010x (%s) : %#010x", w->base.id, w->name, pixmap);
|
||||
w->win_image = b->ops->bind_pixmap(b, pixmap, x_get_visual_info(b->c, w->a.visual));
|
||||
w->win_image = b->ops.bind_pixmap(b, pixmap, x_get_visual_info(b->c, w->a.visual));
|
||||
if (!w->win_image) {
|
||||
log_error("Failed to bind pixmap");
|
||||
xcb_free_pixmap(b->c->c, pixmap);
|
||||
|
|
Loading…
Add table
Reference in a new issue