Merge pull request #2396 from RyanDwyer/fix-resize-wiggle

Correctly track saved surfaces during multiple transactions
This commit is contained in:
emersion 2018-08-02 08:20:39 +01:00 committed by GitHub
commit fe39129b96
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 46 additions and 61 deletions

View file

@ -42,17 +42,4 @@ void transaction_notify_view_ready(struct sway_view *view, uint32_t serial);
void transaction_notify_view_ready_by_size(struct sway_view *view, void transaction_notify_view_ready_by_size(struct sway_view *view,
int width, int height); int width, int height);
/**
* Get the saved texture that should be rendered for a view.
*
* The addresses pointed at by the width and height pointers will be populated
* with the surface's dimensions, which may be different to the texture's
* dimensions if output scaling is used.
*
* This function should only be called if it is known that the view has
* instructions.
*/
struct wlr_texture *transaction_get_saved_texture(struct sway_view *view,
int *width, int *height);
#endif #endif

View file

@ -85,6 +85,9 @@ struct sway_view {
bool allow_request_urgent; bool allow_request_urgent;
struct wl_event_source *urgent_timer; struct wl_event_source *urgent_timer;
struct wlr_buffer *saved_buffer;
int saved_buffer_width, saved_buffer_height;
bool destroying; bool destroying;
list_t *executed_criteria; // struct criteria * list_t *executed_criteria; // struct criteria *
@ -339,4 +342,8 @@ void view_set_urgent(struct sway_view *view, bool enable);
bool view_is_urgent(struct sway_view *view); bool view_is_urgent(struct sway_view *view);
void view_remove_saved_buffer(struct sway_view *view);
void view_save_buffer(struct sway_view *view);
#endif #endif

View file

@ -222,17 +222,14 @@ static void render_saved_view(struct sway_view *view,
struct sway_output *output, pixman_region32_t *damage, float alpha) { struct sway_output *output, pixman_region32_t *damage, float alpha) {
struct wlr_output *wlr_output = output->wlr_output; struct wlr_output *wlr_output = output->wlr_output;
int width, height; if (!view->saved_buffer || !view->saved_buffer->texture) {
struct wlr_texture *texture =
transaction_get_saved_texture(view, &width, &height);
if (!texture) {
return; return;
} }
struct wlr_box box = { struct wlr_box box = {
.x = view->swayc->current.view_x - output->swayc->current.swayc_x, .x = view->swayc->current.view_x - output->swayc->current.swayc_x,
.y = view->swayc->current.view_y - output->swayc->current.swayc_y, .y = view->swayc->current.view_y - output->swayc->current.swayc_y,
.width = width, .width = view->saved_buffer_width,
.height = height, .height = view->saved_buffer_height,
}; };
struct wlr_box output_box = { struct wlr_box output_box = {
@ -252,7 +249,8 @@ static void render_saved_view(struct sway_view *view,
wlr_matrix_project_box(matrix, &box, WL_OUTPUT_TRANSFORM_NORMAL, 0, wlr_matrix_project_box(matrix, &box, WL_OUTPUT_TRANSFORM_NORMAL, 0,
wlr_output->transform_matrix); wlr_output->transform_matrix);
render_texture(wlr_output, damage, texture, &box, matrix, alpha); render_texture(wlr_output, damage, view->saved_buffer->texture,
&box, matrix, alpha);
} }
/** /**
@ -261,7 +259,7 @@ static void render_saved_view(struct sway_view *view,
static void render_view(struct sway_output *output, pixman_region32_t *damage, static void render_view(struct sway_output *output, pixman_region32_t *damage,
struct sway_container *con, struct border_colors *colors) { struct sway_container *con, struct border_colors *colors) {
struct sway_view *view = con->sway_view; struct sway_view *view = con->sway_view;
if (view->swayc->instructions->length) { if (view->saved_buffer) {
render_saved_view(view, output, damage, view->swayc->alpha); render_saved_view(view, output, damage, view->swayc->alpha);
} else { } else {
render_view_toplevels(view, output, damage, view->swayc->alpha); render_view_toplevels(view, output, damage, view->swayc->alpha);
@ -864,7 +862,7 @@ void output_render(struct sway_output *output, struct timespec *when,
// TODO: handle views smaller than the output // TODO: handle views smaller than the output
if (fullscreen_con->type == C_VIEW) { if (fullscreen_con->type == C_VIEW) {
if (fullscreen_con->instructions->length) { if (fullscreen_con->sway_view->saved_buffer) {
render_saved_view(fullscreen_con->sway_view, render_saved_view(fullscreen_con->sway_view,
output, damage, 1.0f); output, damage, 1.0f);
} else { } else {

View file

@ -41,8 +41,6 @@ struct sway_transaction_instruction {
struct sway_transaction *transaction; struct sway_transaction *transaction;
struct sway_container *container; struct sway_container *container;
struct sway_container_state state; struct sway_container_state state;
struct wlr_buffer *saved_buffer;
int saved_buffer_width, saved_buffer_height;
uint32_t serial; uint32_t serial;
bool ready; bool ready;
}; };
@ -57,27 +55,6 @@ static struct sway_transaction *transaction_create() {
return transaction; return transaction;
} }
static void remove_saved_view_buffer(
struct sway_transaction_instruction *instruction) {
if (instruction->saved_buffer) {
wlr_buffer_unref(instruction->saved_buffer);
instruction->saved_buffer = NULL;
}
}
static void save_view_buffer(struct sway_view *view,
struct sway_transaction_instruction *instruction) {
if (!sway_assert(instruction->saved_buffer == NULL,
"Didn't expect instruction to have a saved buffer already")) {
remove_saved_view_buffer(instruction);
}
if (view->surface && wlr_surface_has_buffer(view->surface)) {
instruction->saved_buffer = wlr_buffer_ref(view->surface->buffer);
instruction->saved_buffer_width = view->surface->current.width;
instruction->saved_buffer_height = view->surface->current.height;
}
}
static void transaction_destroy(struct sway_transaction *transaction) { static void transaction_destroy(struct sway_transaction *transaction) {
// Free instructions // Free instructions
for (int i = 0; i < transaction->instructions->length; ++i) { for (int i = 0; i < transaction->instructions->length; ++i) {
@ -93,7 +70,6 @@ static void transaction_destroy(struct sway_transaction *transaction) {
if (con->destroying && !con->instructions->length) { if (con->destroying && !con->instructions->length) {
container_free(con); container_free(con);
} }
remove_saved_view_buffer(instruction);
free(instruction); free(instruction);
} }
list_free(transaction->instructions); list_free(transaction->instructions);
@ -158,9 +134,6 @@ static void transaction_add_container(struct sway_transaction *transaction,
copy_pending_state(container, &instruction->state); copy_pending_state(container, &instruction->state);
if (container->type == C_VIEW) {
save_view_buffer(container->sway_view, instruction);
}
list_add(transaction->instructions, instruction); list_add(transaction->instructions, instruction);
} }
@ -220,6 +193,15 @@ static void transaction_apply(struct sway_transaction *transaction) {
memcpy(&container->current, &instruction->state, memcpy(&container->current, &instruction->state,
sizeof(struct sway_container_state)); sizeof(struct sway_container_state));
if (container->type == C_VIEW) {
if (container->sway_view->saved_buffer) {
view_remove_saved_buffer(container->sway_view);
}
if (container->instructions->length > 1) {
view_save_buffer(container->sway_view);
}
}
} }
} }
@ -294,6 +276,9 @@ static void transaction_commit(struct sway_transaction *transaction) {
// mapping and its default geometry doesn't intersect an output. // mapping and its default geometry doesn't intersect an output.
struct timespec when; struct timespec when;
wlr_surface_send_frame_done(con->sway_view->surface, &when); wlr_surface_send_frame_done(con->sway_view->surface, &when);
if (!con->sway_view->saved_buffer) {
view_save_buffer(con->sway_view);
}
} }
list_add(con->instructions, instruction); list_add(con->instructions, instruction);
} }
@ -400,18 +385,6 @@ void transaction_notify_view_ready_by_size(struct sway_view *view,
} }
} }
struct wlr_texture *transaction_get_saved_texture(struct sway_view *view,
int *width, int *height) {
struct sway_transaction_instruction *instruction =
view->swayc->instructions->items[0];
if (!instruction->saved_buffer) {
return NULL;
}
*width = instruction->saved_buffer_width;
*height = instruction->saved_buffer_height;
return instruction->saved_buffer->texture;
}
void transaction_commit_dirty(void) { void transaction_commit_dirty(void) {
if (!server.dirty_containers->length) { if (!server.dirty_containers->length) {
return; return;

View file

@ -2,6 +2,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <wayland-server.h> #include <wayland-server.h>
#include <wlr/render/wlr_renderer.h> #include <wlr/render/wlr_renderer.h>
#include <wlr/types/wlr_buffer.h>
#include <wlr/types/wlr_output_layout.h> #include <wlr/types/wlr_output_layout.h>
#include "config.h" #include "config.h"
#ifdef HAVE_XWAYLAND #ifdef HAVE_XWAYLAND
@ -1093,3 +1094,22 @@ void view_set_urgent(struct sway_view *view, bool enable) {
bool view_is_urgent(struct sway_view *view) { bool view_is_urgent(struct sway_view *view) {
return view->urgent.tv_sec || view->urgent.tv_nsec; return view->urgent.tv_sec || view->urgent.tv_nsec;
} }
void view_remove_saved_buffer(struct sway_view *view) {
if (!sway_assert(view->saved_buffer, "Expected a saved buffer")) {
return;
}
wlr_buffer_unref(view->saved_buffer);
view->saved_buffer = NULL;
}
void view_save_buffer(struct sway_view *view) {
if (!sway_assert(!view->saved_buffer, "Didn't expect saved buffer")) {
view_remove_saved_buffer(view);
}
if (view->surface && wlr_surface_has_buffer(view->surface)) {
view->saved_buffer = wlr_buffer_ref(view->surface->buffer);
view->saved_buffer_width = view->surface->current.width;
view->saved_buffer_height = view->surface->current.height;
}
}