From 756dedae20eead72af6cfc7f724d0b2af6597eeb Mon Sep 17 00:00:00 2001 From: Simon Ser Date: Tue, 21 Jun 2022 22:39:29 +0200 Subject: [PATCH] Add a new renderer API Goals: - Extensibility: we need to be able to add new params to the calls to render a texture/rect. For instance we'll need to add fences to the render texture operation for explicit sync purposes. - No implicit state: no more bind_buffer, begin, end. - No matrices: these hurt Pixman and we don't need them. - Clip regions for optimized damage repainting. Closes: https://gitlab.freedesktop.org/wlroots/wlroots/-/issues/3188 --- include/wlr/render/interface.h | 17 ++++++++ include/wlr/render/wlr_renderer.h | 68 +++++++++++++++++++++++++++++++ render/meson.build | 1 + render/pass.c | 25 ++++++++++++ render/wlr_renderer.c | 20 ++++++--- 5 files changed, 126 insertions(+), 5 deletions(-) create mode 100644 render/pass.c diff --git a/include/wlr/render/interface.h b/include/wlr/render/interface.h index 07b26fbc..85a98202 100644 --- a/include/wlr/render/interface.h +++ b/include/wlr/render/interface.h @@ -48,6 +48,8 @@ struct wlr_renderer_impl { uint32_t (*get_render_buffer_caps)(struct wlr_renderer *renderer); struct wlr_texture *(*texture_from_buffer)(struct wlr_renderer *renderer, struct wlr_buffer *buffer); + struct wlr_render_pass *(*begin_buffer_pass)(struct wlr_renderer *renderer, + struct wlr_buffer *buffer); }; void wlr_renderer_init(struct wlr_renderer *renderer, @@ -62,4 +64,19 @@ struct wlr_texture_impl { void wlr_texture_init(struct wlr_texture *texture, struct wlr_renderer *rendener, const struct wlr_texture_impl *impl, uint32_t width, uint32_t height); +struct wlr_render_pass { + const struct wlr_render_pass_impl *impl; +}; + +void wlr_render_pass_init(struct wlr_render_pass *pass, + const struct wlr_render_pass_impl *impl); + +struct wlr_render_pass_impl { + bool (*submit)(struct wlr_render_pass *pass); + void (*add_texture)(struct wlr_render_pass *pass, + const struct wlr_render_texture_options *options); + void (*add_rect)(struct wlr_render_pass *pass, + const struct wlr_render_rect_options *options); +}; + #endif diff --git a/include/wlr/render/wlr_renderer.h b/include/wlr/render/wlr_renderer.h index 0e08fe24..f6b58df5 100644 --- a/include/wlr/render/wlr_renderer.h +++ b/include/wlr/render/wlr_renderer.h @@ -12,6 +12,7 @@ #include #include #include +#include struct wlr_backend; struct wlr_renderer_impl; @@ -155,4 +156,71 @@ int wlr_renderer_get_drm_fd(struct wlr_renderer *r); */ void wlr_renderer_destroy(struct wlr_renderer *renderer); +/** + * A render pass accumulates drawing operations until submitted to the GPU. + */ +struct wlr_render_pass; + +/** + * Begin a new render pass with the supplied destination buffer. + * + * Callers must call wlr_render_pass_submit() once they are done with the + * render pass. + */ +struct wlr_render_pass *wlr_renderer_begin_buffer_pass( + struct wlr_renderer *renderer, struct wlr_buffer *buffer); + +/** + * Submit the render pass. + * + * The render pass cannot be used after this function is called. + */ +bool wlr_render_pass_submit(struct wlr_render_pass *render_pass); + +struct wlr_render_texture_options { + /* Source texture */ + struct wlr_texture *texture; + /* Source coordinates, leave empty to render the whole texture */ + struct wlr_fbox src_box; + /* Destination coordinates, width/height default to the texture size */ + struct wlr_box dst_box; + /* Opacity between 0 (transparent) and 1 (opaque), leave NULL for opaque */ + const float *alpha; + /* Clip region, leave NULL to disable clipping */ + const pixman_region32_t *clip; + /* Transform applied to the source texture */ + enum wl_output_transform transform; +}; + +/** + * Render a texture. + */ +void wlr_render_pass_add_texture(struct wlr_render_pass *render_pass, + const struct wlr_render_texture_options *options); + +/** + * A color value. + * + * Each channel has values between 0 and 1 inclusive. The R, G, B + * channels need to be pre-multiplied by A. + */ +struct wlr_render_color { + float r, g, b, a; +}; + +struct wlr_render_rect_options { + /* Rectangle coordinates */ + struct wlr_box box; + /* Source color */ + struct wlr_render_color color; + /* Clip region, leave NULL to disable clipping */ + const pixman_region32_t *clip; +}; + +/** + * Render a rectangle. + */ +void wlr_render_pass_add_rect(struct wlr_render_pass *render_pass, + const struct wlr_render_rect_options *options); + #endif diff --git a/render/meson.build b/render/meson.build index 4c3d4522..f09905c7 100644 --- a/render/meson.build +++ b/render/meson.build @@ -8,6 +8,7 @@ endif wlr_files += files( 'dmabuf.c', 'drm_format_set.c', + 'pass.c', 'pixel_format.c', 'swapchain.c', 'wlr_renderer.c', diff --git a/render/pass.c b/render/pass.c new file mode 100644 index 00000000..c1b88b8d --- /dev/null +++ b/render/pass.c @@ -0,0 +1,25 @@ +#include +#include +#include +#include + +void wlr_render_pass_init(struct wlr_render_pass *render_pass, + const struct wlr_render_pass_impl *impl) { + assert(impl->submit && impl->add_texture && impl->add_rect); + memset(render_pass, 0, sizeof(*render_pass)); + render_pass->impl = impl; +} + +bool wlr_render_pass_submit(struct wlr_render_pass *render_pass) { + return render_pass->impl->submit(render_pass); +} + +void wlr_render_pass_add_texture(struct wlr_render_pass *render_pass, + const struct wlr_render_texture_options *options) { + render_pass->impl->add_texture(render_pass, options); +} + +void wlr_render_pass_add_rect(struct wlr_render_pass *render_pass, + const struct wlr_render_rect_options *options) { + render_pass->impl->add_rect(render_pass, options); +} diff --git a/render/wlr_renderer.c b/render/wlr_renderer.c index 3b1e87e2..459016b6 100644 --- a/render/wlr_renderer.c +++ b/render/wlr_renderer.c @@ -33,11 +33,13 @@ void wlr_renderer_init(struct wlr_renderer *renderer, const struct wlr_renderer_impl *impl) { - assert(impl->begin); - assert(impl->clear); - assert(impl->scissor); - assert(impl->render_subtexture_with_matrix); - assert(impl->render_quad_with_matrix); + if (!impl->begin_buffer_pass) { + assert(impl->begin); + assert(impl->clear); + assert(impl->scissor); + assert(impl->render_subtexture_with_matrix); + assert(impl->render_quad_with_matrix); + } assert(impl->get_shm_texture_formats); assert(impl->get_render_buffer_caps); @@ -409,3 +411,11 @@ int wlr_renderer_get_drm_fd(struct wlr_renderer *r) { } return r->impl->get_drm_fd(r); } + +struct wlr_render_pass *wlr_renderer_begin_buffer_pass( + struct wlr_renderer *renderer, struct wlr_buffer *buffer) { + if (!renderer->impl->begin_buffer_pass) { + return NULL; + } + return renderer->impl->begin_buffer_pass(renderer, buffer); +}