aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Alexander Orzechowski <alex@ozal.ski>2023-05-02 11:43:44 -0400
committerLibravatar Simon Ser <contact@emersion.fr>2023-05-02 18:31:55 +0200
commit029b99b4829148ef3e899f21bba4fe2a1d4d0db9 (patch)
treec1211ce46f432ebe3fe84e95608d62a35e51dcbc
parentrender: Don't pass matrix into render_texture (diff)
downloadsway-029b99b4829148ef3e899f21bba4fe2a1d4d0db9.tar.gz
sway-029b99b4829148ef3e899f21bba4fe2a1d4d0db9.tar.zst
sway-029b99b4829148ef3e899f21bba4fe2a1d4d0db9.zip
render: Use wlr_render_pass
-rw-r--r--include/sway/output.h2
-rw-r--r--sway/desktop/output.c26
-rw-r--r--sway/desktop/render.c171
3 files changed, 109 insertions, 90 deletions
diff --git a/include/sway/output.h b/include/sway/output.h
index b397c8e2..f6dc6af2 100644
--- a/include/sway/output.h
+++ b/include/sway/output.h
@@ -69,6 +69,8 @@ struct render_context {
69 struct sway_output *output; 69 struct sway_output *output;
70 struct wlr_renderer *renderer; 70 struct wlr_renderer *renderer;
71 const pixman_region32_t *output_damage; 71 const pixman_region32_t *output_damage;
72
73 struct wlr_render_pass *pass;
72}; 74};
73 75
74struct sway_output *output_create(struct wlr_output *wlr_output); 76struct sway_output *output_create(struct wlr_output *wlr_output);
diff --git a/sway/desktop/output.c b/sway/desktop/output.c
index 02e08bd2..01bc87bb 100644
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -6,6 +6,7 @@
6#include <wayland-server-core.h> 6#include <wayland-server-core.h>
7#include <wlr/config.h> 7#include <wlr/config.h>
8#include <wlr/backend/headless.h> 8#include <wlr/backend/headless.h>
9#include <wlr/render/swapchain.h>
9#include <wlr/render/wlr_renderer.h> 10#include <wlr/render/wlr_renderer.h>
10#include <wlr/types/wlr_buffer.h> 11#include <wlr/types/wlr_buffer.h>
11#include <wlr/types/wlr_matrix.h> 12#include <wlr/types/wlr_matrix.h>
@@ -604,9 +605,21 @@ static int output_repaint_timer_handler(void *data) {
604 } 605 }
605 } 606 }
606 607
608 if (!wlr_output_configure_primary_swapchain(wlr_output, NULL, &wlr_output->swapchain)) {
609 return false;
610 }
611
607 int buffer_age; 612 int buffer_age;
608 if (!wlr_output_attach_render(output->wlr_output, &buffer_age)) { 613 struct wlr_buffer *buffer = wlr_swapchain_acquire(wlr_output->swapchain, &buffer_age);
609 return 0; 614 if (buffer == NULL) {
615 return false;
616 }
617
618 struct wlr_render_pass *render_pass = wlr_renderer_begin_buffer_pass(
619 wlr_output->renderer, buffer);
620 if (render_pass == NULL) {
621 wlr_buffer_unlock(buffer);
622 return false;
610 } 623 }
611 624
612 pixman_region32_t damage; 625 pixman_region32_t damage;
@@ -623,6 +636,7 @@ static int output_repaint_timer_handler(void *data) {
623 .output_damage = &damage, 636 .output_damage = &damage,
624 .renderer = wlr_output->renderer, 637 .renderer = wlr_output->renderer,
625 .output = output, 638 .output = output,
639 .pass = render_pass,
626 }; 640 };
627 641
628 struct timespec now; 642 struct timespec now;
@@ -632,6 +646,14 @@ static int output_repaint_timer_handler(void *data) {
632 646
633 pixman_region32_fini(&damage); 647 pixman_region32_fini(&damage);
634 648
649 if (!wlr_render_pass_submit(render_pass)) {
650 wlr_buffer_unlock(buffer);
651 return false;
652 }
653
654 wlr_output_attach_buffer(wlr_output, buffer);
655 wlr_buffer_unlock(buffer);
656
635 if (!wlr_output_commit(wlr_output)) { 657 if (!wlr_output_commit(wlr_output)) {
636 return 0; 658 return 0;
637 } 659 }
diff --git a/sway/desktop/render.c b/sway/desktop/render.c
index a3ae5efc..37e84647 100644
--- a/sway/desktop/render.c
+++ b/sway/desktop/render.c
@@ -38,6 +38,23 @@ struct render_data {
38 struct wlr_box *clip_box; 38 struct wlr_box *clip_box;
39}; 39};
40 40
41static void transform_output_damage(pixman_region32_t *damage, struct wlr_output *output) {
42 int ow, oh;
43 wlr_output_transformed_resolution(output, &ow, &oh);
44 enum wl_output_transform transform =
45 wlr_output_transform_invert(output->transform);
46 wlr_region_transform(damage, damage, transform, ow, oh);
47}
48
49static void transform_output_box(struct wlr_box *box, struct wlr_output *output) {
50 int ow, oh;
51 wlr_output_transformed_resolution(output, &ow, &oh);
52 enum wl_output_transform transform =
53 wlr_output_transform_invert(output->transform);
54 wlr_box_transform(box, box, transform, ow, oh);
55}
56
57
41/** 58/**
42 * Apply scale to a width or height. 59 * Apply scale to a width or height.
43 * 60 *
@@ -54,28 +71,6 @@ static int scale_length(int length, int offset, float scale) {
54 return roundf((offset + length) * scale) - roundf(offset * scale); 71 return roundf((offset + length) * scale) - roundf(offset * scale);
55} 72}
56 73
57static void scissor_output(struct wlr_output *wlr_output,
58 pixman_box32_t *rect) {
59 struct wlr_renderer *renderer = wlr_output->renderer;
60 assert(renderer);
61
62 struct wlr_box box = {
63 .x = rect->x1,
64 .y = rect->y1,
65 .width = rect->x2 - rect->x1,
66 .height = rect->y2 - rect->y1,
67 };
68
69 int ow, oh;
70 wlr_output_transformed_resolution(wlr_output, &ow, &oh);
71
72 enum wl_output_transform transform =
73 wlr_output_transform_invert(wlr_output->transform);
74 wlr_box_transform(&box, &box, transform, ow, oh);
75
76 wlr_renderer_scissor(renderer, &box);
77}
78
79static void set_scale_filter(struct wlr_output *wlr_output, 74static void set_scale_filter(struct wlr_output *wlr_output,
80 struct wlr_texture *texture, enum scale_filter_mode scale_filter) { 75 struct wlr_texture *texture, enum scale_filter_mode scale_filter) {
81#if WLR_HAS_GLES2_RENDERER 76#if WLR_HAS_GLES2_RENDERER
@@ -103,40 +98,39 @@ static void set_scale_filter(struct wlr_output *wlr_output,
103} 98}
104 99
105static void render_texture(struct render_context *ctx, struct wlr_texture *texture, 100static void render_texture(struct render_context *ctx, struct wlr_texture *texture,
106 const struct wlr_fbox *src_box, const struct wlr_box *dst_box, 101 const struct wlr_fbox *_src_box, const struct wlr_box *dst_box,
107 enum wl_output_transform transform, float alpha) { 102 enum wl_output_transform transform, float alpha) {
108 struct wlr_renderer *renderer = ctx->renderer;
109 struct sway_output *output = ctx->output; 103 struct sway_output *output = ctx->output;
110 104
111 struct wlr_box proj_box = *dst_box; 105 struct wlr_box proj_box = *dst_box;
112 scale_box(&proj_box, output->wlr_output->scale);
113 106
114 float matrix[9]; 107 struct wlr_fbox src_box = {0};
115 enum wl_output_transform inv_transform = wlr_output_transform_invert(transform); 108 if (_src_box) {
116 wlr_matrix_project_box(matrix, &proj_box, inv_transform, 0, 109 src_box = *_src_box;
117 output->wlr_output->transform_matrix); 110 }
118 111
119 pixman_region32_t damage; 112 pixman_region32_t damage;
120 pixman_region32_init(&damage); 113 pixman_region32_init_rect(&damage, proj_box.x, proj_box.y,
121 pixman_region32_union_rect(&damage, &damage, dst_box->x, dst_box->y, 114 proj_box.width, proj_box.height);
122 dst_box->width, dst_box->height);
123 pixman_region32_intersect(&damage, &damage, ctx->output_damage); 115 pixman_region32_intersect(&damage, &damage, ctx->output_damage);
124 bool damaged = pixman_region32_not_empty(&damage); 116 bool damaged = pixman_region32_not_empty(&damage);
125 if (!damaged) { 117 if (!damaged) {
126 goto damage_finish; 118 goto damage_finish;
127 } 119 }
128 120
129 int nrects; 121 transform_output_box(&proj_box, output->wlr_output);
130 pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects); 122 transform_output_damage(&damage, output->wlr_output);
131 for (int i = 0; i < nrects; ++i) { 123 transform = wlr_output_transform_compose(transform, output->wlr_output->transform);
132 scissor_output(output->wlr_output, &rects[i]); 124
133 set_scale_filter(output->wlr_output, texture, output->scale_filter); 125 set_scale_filter(output->wlr_output, texture, output->scale_filter);
134 if (src_box != NULL) { 126 wlr_render_pass_add_texture(ctx->pass, &(struct wlr_render_texture_options) {
135 wlr_render_subtexture_with_matrix(renderer, texture, src_box, matrix, alpha); 127 .texture = texture,
136 } else { 128 .src_box = src_box,
137 wlr_render_texture_with_matrix(renderer, texture, matrix, alpha); 129 .dst_box = proj_box,
138 } 130 .transform = transform,
139 } 131 .alpha = &alpha,
132 .clip = &damage,
133 });
140 134
141damage_finish: 135damage_finish:
142 pixman_region32_fini(&damage); 136 pixman_region32_fini(&damage);
@@ -218,16 +212,13 @@ static void render_drag_icons(struct render_context *ctx, struct wl_list *drag_i
218void render_rect(struct render_context *ctx, const struct wlr_box *_box, 212void render_rect(struct render_context *ctx, const struct wlr_box *_box,
219 float color[static 4]) { 213 float color[static 4]) {
220 struct wlr_output *wlr_output = ctx->output->wlr_output; 214 struct wlr_output *wlr_output = ctx->output->wlr_output;
221 struct wlr_renderer *renderer = ctx->renderer;
222 215
223 struct wlr_box box; 216 struct wlr_box box = *_box;
224 memcpy(&box, _box, sizeof(struct wlr_box));
225 box.x -= ctx->output->lx * wlr_output->scale; 217 box.x -= ctx->output->lx * wlr_output->scale;
226 box.y -= ctx->output->ly * wlr_output->scale; 218 box.y -= ctx->output->ly * wlr_output->scale;
227 219
228 pixman_region32_t damage; 220 pixman_region32_t damage;
229 pixman_region32_init(&damage); 221 pixman_region32_init_rect(&damage, box.x, box.y,
230 pixman_region32_union_rect(&damage, &damage, box.x, box.y,
231 box.width, box.height); 222 box.width, box.height);
232 pixman_region32_intersect(&damage, &damage, ctx->output_damage); 223 pixman_region32_intersect(&damage, &damage, ctx->output_damage);
233 bool damaged = pixman_region32_not_empty(&damage); 224 bool damaged = pixman_region32_not_empty(&damage);
@@ -235,13 +226,19 @@ void render_rect(struct render_context *ctx, const struct wlr_box *_box,
235 goto damage_finish; 226 goto damage_finish;
236 } 227 }
237 228
238 int nrects; 229 transform_output_damage(&damage, wlr_output);
239 pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects); 230 transform_output_box(&box, wlr_output);
240 for (int i = 0; i < nrects; ++i) { 231
241 scissor_output(wlr_output, &rects[i]); 232 wlr_render_pass_add_rect(ctx->pass, &(struct wlr_render_rect_options){
242 wlr_render_rect(renderer, &box, color, 233 .box = box,
243 wlr_output->transform_matrix); 234 .color = {
244 } 235 .r = color[0],
236 .g = color[1],
237 .b = color[2],
238 .a = color[3],
239 },
240 .clip = &damage,
241 });
245 242
246damage_finish: 243damage_finish:
247 pixman_region32_fini(&damage); 244 pixman_region32_fini(&damage);
@@ -1006,7 +1003,6 @@ static void render_seatops(struct render_context *ctx) {
1006 1003
1007void output_render(struct render_context *ctx) { 1004void output_render(struct render_context *ctx) {
1008 struct wlr_output *wlr_output = ctx->output->wlr_output; 1005 struct wlr_output *wlr_output = ctx->output->wlr_output;
1009 struct wlr_renderer *renderer = ctx->renderer;
1010 struct sway_output *output = ctx->output; 1006 struct sway_output *output = ctx->output;
1011 const pixman_region32_t *damage = ctx->output_damage; 1007 const pixman_region32_t *damage = ctx->output_damage;
1012 1008
@@ -1020,32 +1016,38 @@ void output_render(struct render_context *ctx) {
1020 fullscreen_con = workspace->current.fullscreen; 1016 fullscreen_con = workspace->current.fullscreen;
1021 } 1017 }
1022 1018
1023 if (!wlr_renderer_begin(renderer, wlr_output->width, wlr_output->height)) {
1024 return;
1025 }
1026
1027 if (!pixman_region32_not_empty(damage)) { 1019 if (!pixman_region32_not_empty(damage)) {
1028 // Output isn't damaged but needs buffer swap 1020 // Output isn't damaged but needs buffer swap
1029 goto renderer_end; 1021 goto renderer_end;
1030 } 1022 }
1031 1023
1032 if (debug.damage == DAMAGE_HIGHLIGHT) { 1024 if (debug.damage == DAMAGE_HIGHLIGHT) {
1033 wlr_renderer_clear(renderer, (float[]){1, 1, 0, 1}); 1025 wlr_render_pass_add_rect(ctx->pass, &(struct wlr_render_rect_options){
1026 .box = { .width = output->width, .height = output->height },
1027 .color = { .r = 1, .g = 1, .b = 0, .a = 1 },
1028 });
1034 } 1029 }
1035 1030
1031 pixman_region32_t transformed_damage;
1032 pixman_region32_init(&transformed_damage);
1033 pixman_region32_copy(&transformed_damage, damage);
1034 transform_output_damage(&transformed_damage, wlr_output);
1035
1036 if (server.session_lock.locked) { 1036 if (server.session_lock.locked) {
1037 float clear_color[] = {0.0f, 0.0f, 0.0f, 1.0f}; 1037 struct wlr_render_color clear_color = {
1038 .a = 1.0f
1039 };
1038 if (server.session_lock.lock == NULL) { 1040 if (server.session_lock.lock == NULL) {
1039 // abandoned lock -> red BG 1041 // abandoned lock -> red BG
1040 clear_color[0] = 1.f; 1042 clear_color.r = 1.f;
1041 }
1042 int nrects;
1043 pixman_box32_t *rects = pixman_region32_rectangles(damage, &nrects);
1044 for (int i = 0; i < nrects; ++i) {
1045 scissor_output(wlr_output, &rects[i]);
1046 wlr_renderer_clear(renderer, clear_color);
1047 } 1043 }
1048 1044
1045 wlr_render_pass_add_rect(ctx->pass, &(struct wlr_render_rect_options){
1046 .box = { .width = output->width, .height = output->height },
1047 .color = clear_color,
1048 .clip = &transformed_damage,
1049 });
1050
1049 if (server.session_lock.lock != NULL) { 1051 if (server.session_lock.lock != NULL) {
1050 struct render_data data = { 1052 struct render_data data = {
1051 .alpha = 1.0f, 1053 .alpha = 1.0f,
@@ -1073,14 +1075,11 @@ void output_render(struct render_context *ctx) {
1073 } 1075 }
1074 1076
1075 if (fullscreen_con) { 1077 if (fullscreen_con) {
1076 float clear_color[] = {0.0f, 0.0f, 0.0f, 1.0f}; 1078 wlr_render_pass_add_rect(ctx->pass, &(struct wlr_render_rect_options){
1077 1079 .box = { .width = output->width, .height = output->height },
1078 int nrects; 1080 .color = { .r = 0, .g = 0, .b = 0, .a = 1 },
1079 pixman_box32_t *rects = pixman_region32_rectangles(damage, &nrects); 1081 .clip = &transformed_damage,
1080 for (int i = 0; i < nrects; ++i) { 1082 });
1081 scissor_output(wlr_output, &rects[i]);
1082 wlr_renderer_clear(renderer, clear_color);
1083 }
1084 1083
1085 if (fullscreen_con->view) { 1084 if (fullscreen_con->view) {
1086 if (!wl_list_empty(&fullscreen_con->view->saved_buffers)) { 1085 if (!wl_list_empty(&fullscreen_con->view->saved_buffers)) {
@@ -1104,14 +1103,11 @@ void output_render(struct render_context *ctx) {
1104 render_unmanaged(ctx, &root->xwayland_unmanaged); 1103 render_unmanaged(ctx, &root->xwayland_unmanaged);
1105#endif 1104#endif
1106 } else { 1105 } else {
1107 float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f}; 1106 wlr_render_pass_add_rect(ctx->pass, &(struct wlr_render_rect_options){
1108 1107 .box = { .width = output->width, .height = output->height },
1109 int nrects; 1108 .color = { .r = 0.25f, .g = 0.25f, .b = 0.25f, .a = 1 },
1110 pixman_box32_t *rects = pixman_region32_rectangles(damage, &nrects); 1109 .clip = &transformed_damage,
1111 for (int i = 0; i < nrects; ++i) { 1110 });
1112 scissor_output(wlr_output, &rects[i]);
1113 wlr_renderer_clear(renderer, clear_color);
1114 }
1115 1111
1116 render_layer_toplevel(ctx, 1112 render_layer_toplevel(ctx,
1117 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]); 1113 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]);
@@ -1150,7 +1146,6 @@ render_overlay:
1150 render_drag_icons(ctx, &root->drag_icons); 1146 render_drag_icons(ctx, &root->drag_icons);
1151 1147
1152renderer_end: 1148renderer_end:
1153 wlr_renderer_scissor(renderer, NULL); 1149 pixman_region32_fini(&transformed_damage);
1154 wlr_output_render_software_cursors(wlr_output, damage); 1150 wlr_output_add_software_cursors_to_render_pass(wlr_output, ctx->pass, damage);
1155 wlr_renderer_end(renderer);
1156} 1151}