mirror of
https://gitlab.freedesktop.org/wlroots/wlroots.git
synced 2026-03-02 01:40:54 -05:00
render: add support for clearing render passes
introduces a new `wlr_render_pass_clear` function, allowing render passes to be cleared with a solid color.
This commit is contained in:
parent
7cb4e30bfd
commit
eeecb382cc
8 changed files with 120 additions and 8 deletions
|
|
@ -62,6 +62,8 @@ struct wlr_render_pass_impl {
|
||||||
/* Implementers are also guaranteed that options->box is nonempty */
|
/* Implementers are also guaranteed that options->box is nonempty */
|
||||||
void (*add_rect)(struct wlr_render_pass *pass,
|
void (*add_rect)(struct wlr_render_pass *pass,
|
||||||
const struct wlr_render_rect_options *options);
|
const struct wlr_render_rect_options *options);
|
||||||
|
void (*clear)(struct wlr_render_pass *pass,
|
||||||
|
const struct wlr_render_clear_options *options);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wlr_render_timer {
|
struct wlr_render_timer {
|
||||||
|
|
|
||||||
|
|
@ -157,4 +157,20 @@ struct wlr_render_rect_options {
|
||||||
void wlr_render_pass_add_rect(struct wlr_render_pass *render_pass,
|
void wlr_render_pass_add_rect(struct wlr_render_pass *render_pass,
|
||||||
const struct wlr_render_rect_options *options);
|
const struct wlr_render_rect_options *options);
|
||||||
|
|
||||||
|
struct wlr_render_clear_options {
|
||||||
|
/* Clear color */
|
||||||
|
struct wlr_render_color color;
|
||||||
|
/* Clip region, leave NULL to disable clipping */
|
||||||
|
const pixman_region32_t *clip;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear the render target with a solid color.
|
||||||
|
*
|
||||||
|
* This is optimized for GPU hardware (e.g., glClear + glScissor) and is more
|
||||||
|
* efficient than drawing a rectangle.
|
||||||
|
*/
|
||||||
|
void wlr_render_pass_clear(struct wlr_render_pass *render_pass,
|
||||||
|
const struct wlr_render_clear_options *options);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -275,10 +275,41 @@ static void render_pass_add_rect(struct wlr_render_pass *wlr_pass,
|
||||||
pop_gles2_debug(renderer);
|
pop_gles2_debug(renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void render_pass_clear(struct wlr_render_pass *wlr_pass,
|
||||||
|
const struct wlr_render_clear_options *options) {
|
||||||
|
struct wlr_gles2_render_pass *pass = get_render_pass(wlr_pass);
|
||||||
|
struct wlr_gles2_renderer *renderer = pass->buffer->renderer;
|
||||||
|
|
||||||
|
push_gles2_debug(renderer);
|
||||||
|
|
||||||
|
const struct wlr_render_color *color = &options->color;
|
||||||
|
glClearColor(color->r, color->g, color->b, color->a);
|
||||||
|
|
||||||
|
if (options->clip) {
|
||||||
|
int rects_len;
|
||||||
|
const pixman_box32_t *rects = pixman_region32_rectangles(options->clip, &rects_len);
|
||||||
|
|
||||||
|
glEnable(GL_SCISSOR_TEST);
|
||||||
|
for (int i = 0; i < rects_len; i++) {
|
||||||
|
const pixman_box32_t *rect = &rects[i];
|
||||||
|
int height = pass->buffer->buffer->height;
|
||||||
|
glScissor(rect->x1, height - rect->y2,
|
||||||
|
rect->x2 - rect->x1, rect->y2 - rect->y1);
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
}
|
||||||
|
glDisable(GL_SCISSOR_TEST);
|
||||||
|
} else {
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
pop_gles2_debug(renderer);
|
||||||
|
}
|
||||||
|
|
||||||
static const struct wlr_render_pass_impl render_pass_impl = {
|
static const struct wlr_render_pass_impl render_pass_impl = {
|
||||||
.submit = render_pass_submit,
|
.submit = render_pass_submit,
|
||||||
.add_texture = render_pass_add_texture,
|
.add_texture = render_pass_add_texture,
|
||||||
.add_rect = render_pass_add_rect,
|
.add_rect = render_pass_add_rect,
|
||||||
|
.clear = render_pass_clear,
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *reset_status_str(GLenum status) {
|
static const char *reset_status_str(GLenum status) {
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
|
|
||||||
void wlr_render_pass_init(struct wlr_render_pass *render_pass,
|
void wlr_render_pass_init(struct wlr_render_pass *render_pass,
|
||||||
const struct wlr_render_pass_impl *impl) {
|
const struct wlr_render_pass_impl *impl) {
|
||||||
assert(impl->submit && impl->add_texture && impl->add_rect);
|
assert(impl->submit && impl->add_texture && impl->add_rect && impl->clear);
|
||||||
*render_pass = (struct wlr_render_pass){
|
*render_pass = (struct wlr_render_pass){
|
||||||
.impl = impl,
|
.impl = impl,
|
||||||
};
|
};
|
||||||
|
|
@ -34,6 +34,11 @@ void wlr_render_pass_add_rect(struct wlr_render_pass *render_pass,
|
||||||
render_pass->impl->add_rect(render_pass, options);
|
render_pass->impl->add_rect(render_pass, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void wlr_render_pass_clear(struct wlr_render_pass *render_pass,
|
||||||
|
const struct wlr_render_clear_options *options) {
|
||||||
|
render_pass->impl->clear(render_pass, options);
|
||||||
|
}
|
||||||
|
|
||||||
void wlr_render_texture_options_get_src_box(const struct wlr_render_texture_options *options,
|
void wlr_render_texture_options_get_src_box(const struct wlr_render_texture_options *options,
|
||||||
struct wlr_fbox *box) {
|
struct wlr_fbox *box) {
|
||||||
*box = options->src_box;
|
*box = options->src_box;
|
||||||
|
|
|
||||||
|
|
@ -225,10 +225,23 @@ static void render_pass_add_rect(struct wlr_render_pass *wlr_pass,
|
||||||
pixman_image_unref(fill);
|
pixman_image_unref(fill);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void render_pass_clear(struct wlr_render_pass *wlr_pass,
|
||||||
|
const struct wlr_render_clear_options *options) {
|
||||||
|
struct wlr_pixman_render_pass *pass = get_render_pass(wlr_pass);
|
||||||
|
|
||||||
|
render_pass_add_rect(wlr_pass, &(struct wlr_render_rect_options){
|
||||||
|
.box = { .width = pass->buffer->buffer->width, .height = pass->buffer->buffer->height },
|
||||||
|
.color = options->color,
|
||||||
|
.clip = options->clip,
|
||||||
|
.blend_mode = WLR_RENDER_BLEND_MODE_NONE,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
static const struct wlr_render_pass_impl render_pass_impl = {
|
static const struct wlr_render_pass_impl render_pass_impl = {
|
||||||
.submit = render_pass_submit,
|
.submit = render_pass_submit,
|
||||||
.add_texture = render_pass_add_texture,
|
.add_texture = render_pass_add_texture,
|
||||||
.add_rect = render_pass_add_rect,
|
.add_rect = render_pass_add_rect,
|
||||||
|
.clear = render_pass_clear,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct wlr_pixman_render_pass *begin_pixman_render_pass(
|
struct wlr_pixman_render_pass *begin_pixman_render_pass(
|
||||||
|
|
|
||||||
|
|
@ -943,13 +943,60 @@ static void render_pass_add_texture(struct wlr_render_pass *wlr_pass,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void render_pass_clear(struct wlr_render_pass *wlr_pass,
|
||||||
|
const struct wlr_render_clear_options *options) {
|
||||||
|
struct wlr_vk_render_pass *pass = get_render_pass(wlr_pass);
|
||||||
|
VkCommandBuffer cb = pass->command_buffer->vk;
|
||||||
|
|
||||||
|
float linear_color[] = {
|
||||||
|
color_to_linear_premult(options->color.r, options->color.a),
|
||||||
|
color_to_linear_premult(options->color.g, options->color.a),
|
||||||
|
color_to_linear_premult(options->color.b, options->color.a),
|
||||||
|
options->color.a,
|
||||||
|
};
|
||||||
|
|
||||||
|
VkClearAttachment clear_att = {
|
||||||
|
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
||||||
|
.colorAttachment = 0,
|
||||||
|
.clearValue.color.float32 = {
|
||||||
|
linear_color[0],
|
||||||
|
linear_color[1],
|
||||||
|
linear_color[2],
|
||||||
|
linear_color[3],
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
pixman_region32_t clip;
|
||||||
|
get_clip_region(pass, options->clip, &clip);
|
||||||
|
|
||||||
|
int clip_rects_len;
|
||||||
|
const pixman_box32_t *clip_rects = pixman_region32_rectangles(&clip, &clip_rects_len);
|
||||||
|
|
||||||
|
VkClearRect clear_rect = {
|
||||||
|
.layerCount = 1,
|
||||||
|
};
|
||||||
|
for (int i = 0; i < clip_rects_len; i++) {
|
||||||
|
convert_pixman_box_to_vk_rect(&clip_rects[i], &clear_rect.rect);
|
||||||
|
vkCmdClearAttachments(cb, 1, &clear_att, 1, &clear_rect);
|
||||||
|
struct wlr_box box = {
|
||||||
|
.x = clip_rects[i].x1,
|
||||||
|
.y = clip_rects[i].y1,
|
||||||
|
.width = clip_rects[i].x2 - clip_rects[i].x1,
|
||||||
|
.height = clip_rects[i].y2 - clip_rects[i].y1,
|
||||||
|
};
|
||||||
|
render_pass_mark_box_updated(pass, &box);
|
||||||
|
}
|
||||||
|
|
||||||
|
pixman_region32_fini(&clip);
|
||||||
|
}
|
||||||
|
|
||||||
static const struct wlr_render_pass_impl render_pass_impl = {
|
static const struct wlr_render_pass_impl render_pass_impl = {
|
||||||
.submit = render_pass_submit,
|
.submit = render_pass_submit,
|
||||||
.add_rect = render_pass_add_rect,
|
.add_rect = render_pass_add_rect,
|
||||||
.add_texture = render_pass_add_texture,
|
.add_texture = render_pass_add_texture,
|
||||||
|
.clear = render_pass_clear,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
void vk_color_transform_destroy(struct wlr_addon *addon) {
|
void vk_color_transform_destroy(struct wlr_addon *addon) {
|
||||||
struct wlr_vk_renderer *renderer = (struct wlr_vk_renderer *)addon->owner;
|
struct wlr_vk_renderer *renderer = (struct wlr_vk_renderer *)addon->owner;
|
||||||
struct wlr_vk_color_transform *transform = wl_container_of(addon, transform, addon);
|
struct wlr_vk_color_transform *transform = wl_container_of(addon, transform, addon);
|
||||||
|
|
|
||||||
|
|
@ -268,9 +268,8 @@ static struct wlr_buffer *render_cursor_buffer(struct wlr_output_cursor *cursor)
|
||||||
enum wl_output_transform transform = wlr_output_transform_invert(cursor->transform);
|
enum wl_output_transform transform = wlr_output_transform_invert(cursor->transform);
|
||||||
transform = wlr_output_transform_compose(transform, output->transform);
|
transform = wlr_output_transform_compose(transform, output->transform);
|
||||||
|
|
||||||
wlr_render_pass_add_rect(pass, &(struct wlr_render_rect_options){
|
wlr_render_pass_clear(pass, &(struct wlr_render_clear_options){
|
||||||
.box = { .width = buffer->width, .height = buffer->height },
|
.color = { 0, 0, 0, 0 },
|
||||||
.blend_mode = WLR_RENDER_BLEND_MODE_NONE,
|
|
||||||
});
|
});
|
||||||
wlr_render_pass_add_texture(pass, &(struct wlr_render_texture_options){
|
wlr_render_pass_add_texture(pass, &(struct wlr_render_texture_options){
|
||||||
.texture = texture,
|
.texture = texture,
|
||||||
|
|
@ -535,4 +534,4 @@ bool output_cursor_refresh_color_transform(struct wlr_output_cursor *output_curs
|
||||||
wlr_color_transform_unref(transforms[0]);
|
wlr_color_transform_unref(transforms[0]);
|
||||||
wlr_color_transform_unref(transforms[1]);
|
wlr_color_transform_unref(transforms[1]);
|
||||||
return output_cursor->color_transform != NULL;
|
return output_cursor->color_transform != NULL;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -63,9 +63,8 @@ static struct wlr_buffer *output_acquire_empty_buffer(struct wlr_output *output,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
wlr_render_pass_add_rect(pass, &(struct wlr_render_rect_options){
|
wlr_render_pass_clear(pass, &(struct wlr_render_clear_options){
|
||||||
.color = { 0, 0, 0, 0 },
|
.color = { 0, 0, 0, 0 },
|
||||||
.blend_mode = WLR_RENDER_BLEND_MODE_NONE,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!wlr_render_pass_submit(pass)) {
|
if (!wlr_render_pass_submit(pass)) {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue