aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-08-01 16:23:11 +1000
committerLibravatar Ryan Dwyer <ryandwyer1@gmail.com>2018-08-01 16:24:15 +1000
commitd10ccc1eb144e4de2477398f6b11753f6b7df70b (patch)
treea4792f1ca754ed427a5b472d1bcf3e75fcf1f2ef
parentMerge pull request #2395 from RedSoxFan/create-mouse-binding-list (diff)
downloadsway-d10ccc1eb144e4de2477398f6b11753f6b7df70b.tar.gz
sway-d10ccc1eb144e4de2477398f6b11753f6b7df70b.tar.zst
sway-d10ccc1eb144e4de2477398f6b11753f6b7df70b.zip
Correctly track saved surfaces during multiple transactions
Fixes #2364. Suppose a view is 600px wide, and we tell it to resize to 601px during a resize operation. We create a transaction, save the 600px buffer and send the configure. This buffer is saved into the associated instruction, and is rendered while we wait for the view to commit a 601px buffer. Before the view commits the 601px buffer, suppose we tell it to resize to 602px. The new transaction will also save the buffer, but it's still the 600px buffer because we haven't received a new one yet. Then suppose the view commits its original 601px buffer. This completes the first transaction, so we apply the 601px width to the container. There's still the second (now only) transaction remaining, so we render the saved buffer from that. But this is still the 600px buffer, and we believe it's 601px. Whoops. The problem here is we can't stack buffers like this. So this commit removes the saved buffer from the instructions, places it in the view instead, and re-saves the latest buffer every time the view completes a transaction and still has further pending transactions. As saved buffers are now specific to views rather than instructions, the functions for saving and removing the saved buffer have been moved to view.c. The calls to save and restore the buffer have been relocated to more appropriate functions too, favouring transaction_commit and transaction_apply rather than transaction_add_container and transaction_destroy.
-rw-r--r--include/sway/desktop/transaction.h13
-rw-r--r--include/sway/tree/view.h7
-rw-r--r--sway/desktop/render.c16
-rw-r--r--sway/desktop/transaction.c51
-rw-r--r--sway/tree/view.c20
5 files changed, 46 insertions, 61 deletions
diff --git a/include/sway/desktop/transaction.h b/include/sway/desktop/transaction.h
index cee4afed..56361d94 100644
--- a/include/sway/desktop/transaction.h
+++ b/include/sway/desktop/transaction.h
@@ -42,17 +42,4 @@ void transaction_notify_view_ready(struct sway_view *view, uint32_t serial);
42void transaction_notify_view_ready_by_size(struct sway_view *view, 42void transaction_notify_view_ready_by_size(struct sway_view *view,
43 int width, int height); 43 int width, int height);
44 44
45/**
46 * Get the saved texture that should be rendered for a view.
47 *
48 * The addresses pointed at by the width and height pointers will be populated
49 * with the surface's dimensions, which may be different to the texture's
50 * dimensions if output scaling is used.
51 *
52 * This function should only be called if it is known that the view has
53 * instructions.
54 */
55struct wlr_texture *transaction_get_saved_texture(struct sway_view *view,
56 int *width, int *height);
57
58#endif 45#endif
diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h
index 0152ed55..0f9b0bb2 100644
--- a/include/sway/tree/view.h
+++ b/include/sway/tree/view.h
@@ -82,6 +82,9 @@ struct sway_view {
82 bool allow_request_urgent; 82 bool allow_request_urgent;
83 struct wl_event_source *urgent_timer; 83 struct wl_event_source *urgent_timer;
84 84
85 struct wlr_buffer *saved_buffer;
86 int saved_buffer_width, saved_buffer_height;
87
85 bool destroying; 88 bool destroying;
86 89
87 list_t *executed_criteria; // struct criteria * 90 list_t *executed_criteria; // struct criteria *
@@ -323,4 +326,8 @@ void view_set_urgent(struct sway_view *view, bool enable);
323 326
324bool view_is_urgent(struct sway_view *view); 327bool view_is_urgent(struct sway_view *view);
325 328
329void view_remove_saved_buffer(struct sway_view *view);
330
331void view_save_buffer(struct sway_view *view);
332
326#endif 333#endif
diff --git a/sway/desktop/render.c b/sway/desktop/render.c
index f25055b8..f0e47c95 100644
--- a/sway/desktop/render.c
+++ b/sway/desktop/render.c
@@ -199,17 +199,14 @@ static void render_saved_view(struct sway_view *view,
199 struct sway_output *output, pixman_region32_t *damage, float alpha) { 199 struct sway_output *output, pixman_region32_t *damage, float alpha) {
200 struct wlr_output *wlr_output = output->wlr_output; 200 struct wlr_output *wlr_output = output->wlr_output;
201 201
202 int width, height; 202 if (!view->saved_buffer || !view->saved_buffer->texture) {
203 struct wlr_texture *texture =
204 transaction_get_saved_texture(view, &width, &height);
205 if (!texture) {
206 return; 203 return;
207 } 204 }
208 struct wlr_box box = { 205 struct wlr_box box = {
209 .x = view->swayc->current.view_x - output->swayc->current.swayc_x, 206 .x = view->swayc->current.view_x - output->swayc->current.swayc_x,
210 .y = view->swayc->current.view_y - output->swayc->current.swayc_y, 207 .y = view->swayc->current.view_y - output->swayc->current.swayc_y,
211 .width = width, 208 .width = view->saved_buffer_width,
212 .height = height, 209 .height = view->saved_buffer_height,
213 }; 210 };
214 211
215 struct wlr_box output_box = { 212 struct wlr_box output_box = {
@@ -229,7 +226,8 @@ static void render_saved_view(struct sway_view *view,
229 wlr_matrix_project_box(matrix, &box, WL_OUTPUT_TRANSFORM_NORMAL, 0, 226 wlr_matrix_project_box(matrix, &box, WL_OUTPUT_TRANSFORM_NORMAL, 0,
230 wlr_output->transform_matrix); 227 wlr_output->transform_matrix);
231 228
232 render_texture(wlr_output, damage, texture, &box, matrix, alpha); 229 render_texture(wlr_output, damage, view->saved_buffer->texture,
230 &box, matrix, alpha);
233} 231}
234 232
235/** 233/**
@@ -238,7 +236,7 @@ static void render_saved_view(struct sway_view *view,
238static void render_view(struct sway_output *output, pixman_region32_t *damage, 236static void render_view(struct sway_output *output, pixman_region32_t *damage,
239 struct sway_container *con, struct border_colors *colors) { 237 struct sway_container *con, struct border_colors *colors) {
240 struct sway_view *view = con->sway_view; 238 struct sway_view *view = con->sway_view;
241 if (view->swayc->instructions->length) { 239 if (view->saved_buffer) {
242 render_saved_view(view, output, damage, view->swayc->alpha); 240 render_saved_view(view, output, damage, view->swayc->alpha);
243 } else { 241 } else {
244 render_view_surfaces(view, output, damage, view->swayc->alpha); 242 render_view_surfaces(view, output, damage, view->swayc->alpha);
@@ -841,7 +839,7 @@ void output_render(struct sway_output *output, struct timespec *when,
841 839
842 // TODO: handle views smaller than the output 840 // TODO: handle views smaller than the output
843 if (fullscreen_con->type == C_VIEW) { 841 if (fullscreen_con->type == C_VIEW) {
844 if (fullscreen_con->instructions->length) { 842 if (fullscreen_con->sway_view->saved_buffer) {
845 render_saved_view(fullscreen_con->sway_view, 843 render_saved_view(fullscreen_con->sway_view,
846 output, damage, 1.0f); 844 output, damage, 1.0f);
847 } else { 845 } else {
diff --git a/sway/desktop/transaction.c b/sway/desktop/transaction.c
index 7975366e..94070363 100644
--- a/sway/desktop/transaction.c
+++ b/sway/desktop/transaction.c
@@ -41,8 +41,6 @@ struct sway_transaction_instruction {
41 struct sway_transaction *transaction; 41 struct sway_transaction *transaction;
42 struct sway_container *container; 42 struct sway_container *container;
43 struct sway_container_state state; 43 struct sway_container_state state;
44 struct wlr_buffer *saved_buffer;
45 int saved_buffer_width, saved_buffer_height;
46 uint32_t serial; 44 uint32_t serial;
47 bool ready; 45 bool ready;
48}; 46};
@@ -57,27 +55,6 @@ static struct sway_transaction *transaction_create() {
57 return transaction; 55 return transaction;
58} 56}
59 57
60static void remove_saved_view_buffer(
61 struct sway_transaction_instruction *instruction) {
62 if (instruction->saved_buffer) {
63 wlr_buffer_unref(instruction->saved_buffer);
64 instruction->saved_buffer = NULL;
65 }
66}
67
68static void save_view_buffer(struct sway_view *view,
69 struct sway_transaction_instruction *instruction) {
70 if (!sway_assert(instruction->saved_buffer == NULL,
71 "Didn't expect instruction to have a saved buffer already")) {
72 remove_saved_view_buffer(instruction);
73 }
74 if (view->surface && wlr_surface_has_buffer(view->surface)) {
75 instruction->saved_buffer = wlr_buffer_ref(view->surface->buffer);
76 instruction->saved_buffer_width = view->surface->current.width;
77 instruction->saved_buffer_height = view->surface->current.height;
78 }
79}
80
81static void transaction_destroy(struct sway_transaction *transaction) { 58static void transaction_destroy(struct sway_transaction *transaction) {
82 // Free instructions 59 // Free instructions
83 for (int i = 0; i < transaction->instructions->length; ++i) { 60 for (int i = 0; i < transaction->instructions->length; ++i) {
@@ -93,7 +70,6 @@ static void transaction_destroy(struct sway_transaction *transaction) {
93 if (con->destroying && !con->instructions->length) { 70 if (con->destroying && !con->instructions->length) {
94 container_free(con); 71 container_free(con);
95 } 72 }
96 remove_saved_view_buffer(instruction);
97 free(instruction); 73 free(instruction);
98 } 74 }
99 list_free(transaction->instructions); 75 list_free(transaction->instructions);
@@ -158,9 +134,6 @@ static void transaction_add_container(struct sway_transaction *transaction,
158 134
159 copy_pending_state(container, &instruction->state); 135 copy_pending_state(container, &instruction->state);
160 136
161 if (container->type == C_VIEW) {
162 save_view_buffer(container->sway_view, instruction);
163 }
164 list_add(transaction->instructions, instruction); 137 list_add(transaction->instructions, instruction);
165} 138}
166 139
@@ -220,6 +193,15 @@ static void transaction_apply(struct sway_transaction *transaction) {
220 193
221 memcpy(&container->current, &instruction->state, 194 memcpy(&container->current, &instruction->state,
222 sizeof(struct sway_container_state)); 195 sizeof(struct sway_container_state));
196
197 if (container->type == C_VIEW) {
198 if (container->sway_view->saved_buffer) {
199 view_remove_saved_buffer(container->sway_view);
200 }
201 if (container->instructions->length > 1) {
202 view_save_buffer(container->sway_view);
203 }
204 }
223 } 205 }
224} 206}
225 207
@@ -294,6 +276,9 @@ static void transaction_commit(struct sway_transaction *transaction) {
294 // mapping and its default geometry doesn't intersect an output. 276 // mapping and its default geometry doesn't intersect an output.
295 struct timespec when; 277 struct timespec when;
296 wlr_surface_send_frame_done(con->sway_view->surface, &when); 278 wlr_surface_send_frame_done(con->sway_view->surface, &when);
279 if (!con->sway_view->saved_buffer) {
280 view_save_buffer(con->sway_view);
281 }
297 } 282 }
298 list_add(con->instructions, instruction); 283 list_add(con->instructions, instruction);
299 } 284 }
@@ -400,18 +385,6 @@ void transaction_notify_view_ready_by_size(struct sway_view *view,
400 } 385 }
401} 386}
402 387
403struct wlr_texture *transaction_get_saved_texture(struct sway_view *view,
404 int *width, int *height) {
405 struct sway_transaction_instruction *instruction =
406 view->swayc->instructions->items[0];
407 if (!instruction->saved_buffer) {
408 return NULL;
409 }
410 *width = instruction->saved_buffer_width;
411 *height = instruction->saved_buffer_height;
412 return instruction->saved_buffer->texture;
413}
414
415void transaction_commit_dirty(void) { 388void transaction_commit_dirty(void) {
416 if (!server.dirty_containers->length) { 389 if (!server.dirty_containers->length) {
417 return; 390 return;
diff --git a/sway/tree/view.c b/sway/tree/view.c
index 8f54cc11..0dbd3812 100644
--- a/sway/tree/view.c
+++ b/sway/tree/view.c
@@ -2,6 +2,7 @@
2#include <stdlib.h> 2#include <stdlib.h>
3#include <wayland-server.h> 3#include <wayland-server.h>
4#include <wlr/render/wlr_renderer.h> 4#include <wlr/render/wlr_renderer.h>
5#include <wlr/types/wlr_buffer.h>
5#include <wlr/types/wlr_output_layout.h> 6#include <wlr/types/wlr_output_layout.h>
6#include "config.h" 7#include "config.h"
7#ifdef HAVE_XWAYLAND 8#ifdef HAVE_XWAYLAND
@@ -1070,3 +1071,22 @@ void view_set_urgent(struct sway_view *view, bool enable) {
1070bool view_is_urgent(struct sway_view *view) { 1071bool view_is_urgent(struct sway_view *view) {
1071 return view->urgent.tv_sec || view->urgent.tv_nsec; 1072 return view->urgent.tv_sec || view->urgent.tv_nsec;
1072} 1073}
1074
1075void view_remove_saved_buffer(struct sway_view *view) {
1076 if (!sway_assert(view->saved_buffer, "Expected a saved buffer")) {
1077 return;
1078 }
1079 wlr_buffer_unref(view->saved_buffer);
1080 view->saved_buffer = NULL;
1081}
1082
1083void view_save_buffer(struct sway_view *view) {
1084 if (!sway_assert(!view->saved_buffer, "Didn't expect saved buffer")) {
1085 view_remove_saved_buffer(view);
1086 }
1087 if (view->surface && wlr_surface_has_buffer(view->surface)) {
1088 view->saved_buffer = wlr_buffer_ref(view->surface->buffer);
1089 view->saved_buffer_width = view->surface->current.width;
1090 view->saved_buffer_height = view->surface->current.height;
1091 }
1092}