aboutsummaryrefslogtreecommitdiff
path: root/render/pass.c
diff options
context:
space:
mode:
authorSimon Ser <contact@emersion.fr>2022-12-07 11:33:45 +0100
committerSimon Ser <contact@emersion.fr>2023-04-25 17:25:10 +0200
commit471249ae4f84f3f34877a1dbf20b94ba0cb0a9f0 (patch)
treea7b3f4f0ffb9ef9a0fe66c41850ac7666a8f67c1 /render/pass.c
parent4a1ad32534e1a5f53a066d0b546f5f979a9c5b5e (diff)
render/pass: add legacy render pass implementation
Add a render pass implementation which leverages the legacy rendering API. This is helpful during the migration.
Diffstat (limited to 'render/pass.c')
-rw-r--r--render/pass.c132
1 files changed, 132 insertions, 0 deletions
diff --git a/render/pass.c b/render/pass.c
index f3309668..17c5d247 100644
--- a/render/pass.c
+++ b/render/pass.c
@@ -1,7 +1,16 @@
#include <assert.h>
+#include <stdlib.h>
#include <string.h>
#include <wlr/render/interface.h>
#include <wlr/render/wlr_renderer.h>
+#include <wlr/types/wlr_matrix.h>
+#include "render/pass.h"
+
+struct wlr_render_pass_legacy {
+ struct wlr_render_pass base;
+ struct wlr_renderer *renderer;
+ int width, height;
+};
void wlr_render_pass_init(struct wlr_render_pass *render_pass,
const struct wlr_render_pass_impl *impl) {
@@ -50,3 +59,126 @@ float wlr_render_texture_options_get_alpha(const struct wlr_render_texture_optio
}
return *options->alpha;
}
+
+static const struct wlr_render_pass_impl legacy_impl;
+
+static struct wlr_render_pass_legacy *legacy_pass_from_pass(struct wlr_render_pass *pass) {
+ assert(pass->impl == &legacy_impl);
+ struct wlr_render_pass_legacy *legacy = wl_container_of(pass, legacy, base);
+ return legacy;
+}
+
+static bool legacy_submit(struct wlr_render_pass *wlr_pass) {
+ struct wlr_render_pass_legacy *pass = legacy_pass_from_pass(wlr_pass);
+ wlr_renderer_end(pass->renderer);
+ free(pass);
+ return true;
+}
+
+static void get_clip_region(struct wlr_render_pass_legacy *pass,
+ const pixman_region32_t *in, pixman_region32_t *out) {
+ if (in != NULL) {
+ pixman_region32_init(out);
+ pixman_region32_copy(out, in);
+ } else {
+ pixman_region32_init_rect(out, 0, 0, pass->width, pass->height);
+ }
+}
+
+static void scissor(struct wlr_renderer *renderer, const pixman_box32_t *rect) {
+ struct wlr_box box = {
+ .x = rect->x1,
+ .y = rect->y1,
+ .width = rect->x2 - rect->x1,
+ .height = rect->y2 - rect->y1,
+ };
+ wlr_renderer_scissor(renderer, &box);
+}
+
+static void legacy_add_texture(struct wlr_render_pass *wlr_pass,
+ const struct wlr_render_texture_options *options) {
+ struct wlr_render_pass_legacy *pass = legacy_pass_from_pass(wlr_pass);
+ struct wlr_texture *texture = options->texture;
+
+ struct wlr_fbox src_box;
+ wlr_render_texture_options_get_src_box(options, &src_box);
+ struct wlr_box dst_box;
+ wlr_render_texture_options_get_dst_box(options, &dst_box);
+ float alpha = wlr_render_texture_options_get_alpha(options);
+
+ float proj[9], matrix[9];
+ wlr_matrix_identity(proj);
+ wlr_matrix_project_box(matrix, &dst_box, options->transform, 0.0, proj);
+
+ pixman_region32_t clip;
+ get_clip_region(pass, options->clip, &clip);
+
+ int rects_len = 0;
+ const pixman_box32_t *rects = pixman_region32_rectangles(&clip, &rects_len);
+ for (int i = 0; i < rects_len; i++) {
+ scissor(pass->renderer, &rects[i]);
+ wlr_render_subtexture_with_matrix(pass->renderer, texture, &src_box, matrix, alpha);
+ }
+
+ wlr_renderer_scissor(pass->renderer, NULL);
+ pixman_region32_fini(&clip);
+}
+
+static void legacy_add_rect(struct wlr_render_pass *wlr_pass,
+ const struct wlr_render_rect_options *options) {
+ struct wlr_render_pass_legacy *pass = legacy_pass_from_pass(wlr_pass);
+
+ float proj[9], matrix[9];
+ wlr_matrix_identity(proj);
+ wlr_matrix_project_box(matrix, &options->box, WL_OUTPUT_TRANSFORM_NORMAL, 0.0, proj);
+
+ pixman_region32_t clip;
+ get_clip_region(pass, options->clip, &clip);
+
+ float color[4] = {
+ options->color.r,
+ options->color.g,
+ options->color.b,
+ options->color.a,
+ };
+
+ int rects_len = 0;
+ const pixman_box32_t *rects = pixman_region32_rectangles(&clip, &rects_len);
+ for (int i = 0; i < rects_len; i++) {
+ scissor(pass->renderer, &rects[i]);
+ wlr_render_quad_with_matrix(pass->renderer, color, matrix);
+ }
+
+ wlr_renderer_scissor(pass->renderer, NULL);
+ pixman_region32_fini(&clip);
+}
+
+static const struct wlr_render_pass_impl legacy_impl = {
+ .submit = legacy_submit,
+ .add_texture = legacy_add_texture,
+ .add_rect = legacy_add_rect,
+};
+
+struct wlr_render_pass *begin_legacy_buffer_render_pass(struct wlr_renderer *renderer,
+ struct wlr_buffer *buffer) {
+ if (renderer->rendering) {
+ return NULL;
+ }
+
+ struct wlr_render_pass_legacy *pass = calloc(1, sizeof(*pass));
+ if (pass == NULL) {
+ return NULL;
+ }
+
+ wlr_render_pass_init(&pass->base, &legacy_impl);
+ pass->renderer = renderer;
+ pass->width = buffer->width;
+ pass->height = buffer->height;
+
+ if (!wlr_renderer_begin_with_buffer(renderer, buffer)) {
+ free(pass);
+ return NULL;
+ }
+
+ return &pass->base;
+}