diff options
author | Drew DeVault <sir@cmpwn.com> | 2018-05-10 18:46:14 -0400 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-05-10 18:46:14 -0400 |
commit | fbddd34b47fd774631d2a5495e4b0b69acb34688 (patch) | |
tree | 7b74a17124cb1d8a0adf777b9cb337574bea52a7 | |
parent | Merge pull request #1932 from emersion/fix-layer-shell-exclusive (diff) | |
parent | Fix damage tracking on HiDPI (diff) | |
download | sway-fbddd34b47fd774631d2a5495e4b0b69acb34688.tar.gz sway-fbddd34b47fd774631d2a5495e4b0b69acb34688.tar.zst sway-fbddd34b47fd774631d2a5495e4b0b69acb34688.zip |
Merge pull request #1923 from emersion/full-damage-tracking
Implement full damage tracking
-rw-r--r-- | include/sway/output.h | 4 | ||||
-rw-r--r-- | include/sway/tree/view.h | 2 | ||||
-rw-r--r-- | sway/desktop/output.c | 317 | ||||
-rw-r--r-- | sway/desktop/wl_shell.c | 2 | ||||
-rw-r--r-- | sway/desktop/xdg_shell_v6.c | 2 | ||||
-rw-r--r-- | sway/desktop/xwayland.c | 2 | ||||
-rw-r--r-- | sway/input/seat.c | 5 | ||||
-rw-r--r-- | sway/tree/container.c | 12 | ||||
-rw-r--r-- | sway/tree/view.c | 26 |
9 files changed, 240 insertions, 132 deletions
diff --git a/include/sway/output.h b/include/sway/output.h index 56571548..be19d7b2 100644 --- a/include/sway/output.h +++ b/include/sway/output.h | |||
@@ -37,8 +37,8 @@ void output_damage_whole(struct sway_output *output); | |||
37 | void output_damage_surface(struct sway_output *output, double ox, double oy, | 37 | void output_damage_surface(struct sway_output *output, double ox, double oy, |
38 | struct wlr_surface *surface, bool whole); | 38 | struct wlr_surface *surface, bool whole); |
39 | 39 | ||
40 | void output_damage_view(struct sway_output *output, struct sway_view *view, | 40 | void output_damage_from_view(struct sway_output *output, |
41 | bool whole); | 41 | struct sway_view *view); |
42 | 42 | ||
43 | void output_damage_whole_container(struct sway_output *output, | 43 | void output_damage_whole_container(struct sway_output *output, |
44 | struct sway_container *con); | 44 | struct sway_container *con); |
diff --git a/include/sway/tree/view.h b/include/sway/tree/view.h index 9d4256f7..4ecd8c44 100644 --- a/include/sway/tree/view.h +++ b/include/sway/tree/view.h | |||
@@ -184,7 +184,7 @@ void view_set_fullscreen(struct sway_view *view, bool fullscreen); | |||
184 | 184 | ||
185 | void view_close(struct sway_view *view); | 185 | void view_close(struct sway_view *view); |
186 | 186 | ||
187 | void view_damage(struct sway_view *view, bool whole); | 187 | void view_damage_from(struct sway_view *view); |
188 | 188 | ||
189 | void view_for_each_surface(struct sway_view *view, | 189 | void view_for_each_surface(struct sway_view *view, |
190 | wlr_surface_iterator_func_t iterator, void *user_data); | 190 | wlr_surface_iterator_func_t iterator, void *user_data); |
diff --git a/sway/desktop/output.c b/sway/desktop/output.c index 9b0f1ae3..c150270e 100644 --- a/sway/desktop/output.c +++ b/sway/desktop/output.c | |||
@@ -163,14 +163,65 @@ static void scale_box(struct wlr_box *box, float scale) { | |||
163 | struct render_data { | 163 | struct render_data { |
164 | struct root_geometry root_geo; | 164 | struct root_geometry root_geo; |
165 | struct sway_output *output; | 165 | struct sway_output *output; |
166 | pixman_region32_t *damage; | ||
166 | float alpha; | 167 | float alpha; |
167 | }; | 168 | }; |
168 | 169 | ||
170 | static void scissor_output(struct wlr_output *wlr_output, | ||
171 | pixman_box32_t *rect) { | ||
172 | struct wlr_renderer *renderer = wlr_backend_get_renderer(wlr_output->backend); | ||
173 | assert(renderer); | ||
174 | |||
175 | struct wlr_box box = { | ||
176 | .x = rect->x1, | ||
177 | .y = rect->y1, | ||
178 | .width = rect->x2 - rect->x1, | ||
179 | .height = rect->y2 - rect->y1, | ||
180 | }; | ||
181 | |||
182 | int ow, oh; | ||
183 | wlr_output_transformed_resolution(wlr_output, &ow, &oh); | ||
184 | |||
185 | enum wl_output_transform transform = | ||
186 | wlr_output_transform_invert(wlr_output->transform); | ||
187 | wlr_box_transform(&box, transform, ow, oh, &box); | ||
188 | |||
189 | wlr_renderer_scissor(renderer, &box); | ||
190 | } | ||
191 | |||
192 | static void render_texture(struct wlr_output *wlr_output, | ||
193 | pixman_region32_t *output_damage, struct wlr_texture *texture, | ||
194 | const struct wlr_box *box, const float matrix[static 9], float alpha) { | ||
195 | struct wlr_renderer *renderer = | ||
196 | wlr_backend_get_renderer(wlr_output->backend); | ||
197 | |||
198 | pixman_region32_t damage; | ||
199 | pixman_region32_init(&damage); | ||
200 | pixman_region32_union_rect(&damage, &damage, box->x, box->y, | ||
201 | box->width, box->height); | ||
202 | pixman_region32_intersect(&damage, &damage, output_damage); | ||
203 | bool damaged = pixman_region32_not_empty(&damage); | ||
204 | if (!damaged) { | ||
205 | goto damage_finish; | ||
206 | } | ||
207 | |||
208 | int nrects; | ||
209 | pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects); | ||
210 | for (int i = 0; i < nrects; ++i) { | ||
211 | scissor_output(wlr_output, &rects[i]); | ||
212 | wlr_render_texture_with_matrix(renderer, texture, matrix, alpha); | ||
213 | } | ||
214 | |||
215 | damage_finish: | ||
216 | pixman_region32_fini(&damage); | ||
217 | } | ||
218 | |||
169 | static void render_surface_iterator(struct wlr_surface *surface, int sx, int sy, | 219 | static void render_surface_iterator(struct wlr_surface *surface, int sx, int sy, |
170 | void *_data) { | 220 | void *_data) { |
171 | struct render_data *data = _data; | 221 | struct render_data *data = _data; |
172 | struct wlr_output *wlr_output = data->output->wlr_output; | 222 | struct wlr_output *wlr_output = data->output->wlr_output; |
173 | float rotation = data->root_geo.rotation; | 223 | float rotation = data->root_geo.rotation; |
224 | pixman_region32_t *output_damage = data->damage; | ||
174 | float alpha = data->alpha; | 225 | float alpha = data->alpha; |
175 | 226 | ||
176 | if (!wlr_surface_has_buffer(surface)) { | 227 | if (!wlr_surface_has_buffer(surface)) { |
@@ -184,13 +235,6 @@ static void render_surface_iterator(struct wlr_surface *surface, int sx, int sy, | |||
184 | return; | 235 | return; |
185 | } | 236 | } |
186 | 237 | ||
187 | struct wlr_renderer *renderer = | ||
188 | wlr_backend_get_renderer(wlr_output->backend); | ||
189 | if (!sway_assert(renderer != NULL, | ||
190 | "expected the output backend to have a renderer")) { | ||
191 | return; | ||
192 | } | ||
193 | |||
194 | scale_box(&box, wlr_output->scale); | 238 | scale_box(&box, wlr_output->scale); |
195 | 239 | ||
196 | float matrix[9]; | 240 | float matrix[9]; |
@@ -199,38 +243,81 @@ static void render_surface_iterator(struct wlr_surface *surface, int sx, int sy, | |||
199 | wlr_matrix_project_box(matrix, &box, transform, rotation, | 243 | wlr_matrix_project_box(matrix, &box, transform, rotation, |
200 | wlr_output->transform_matrix); | 244 | wlr_output->transform_matrix); |
201 | 245 | ||
202 | wlr_render_texture_with_matrix(renderer, surface->texture, | 246 | render_texture(wlr_output, output_damage, surface->texture, &box, matrix, |
203 | matrix, alpha); | 247 | alpha); |
204 | } | 248 | } |
205 | 249 | ||
206 | static void render_layer(struct sway_output *output, | 250 | static void render_layer(struct sway_output *output, |
207 | struct wl_list *layer_surfaces) { | 251 | pixman_region32_t *damage, struct wl_list *layer_surfaces) { |
208 | struct render_data data = { .output = output, .alpha = 1.0f }; | 252 | struct render_data data = { |
253 | .output = output, | ||
254 | .damage = damage, | ||
255 | .alpha = 1.0f, | ||
256 | }; | ||
209 | layer_for_each_surface(layer_surfaces, &data.root_geo, | 257 | layer_for_each_surface(layer_surfaces, &data.root_geo, |
210 | render_surface_iterator, &data); | 258 | render_surface_iterator, &data); |
211 | } | 259 | } |
212 | 260 | ||
213 | static void render_unmanaged(struct sway_output *output, | 261 | static void render_unmanaged(struct sway_output *output, |
214 | struct wl_list *unmanaged) { | 262 | pixman_region32_t *damage, struct wl_list *unmanaged) { |
215 | struct render_data data = { .output = output, .alpha = 1.0f }; | 263 | struct render_data data = { |
264 | .output = output, | ||
265 | .damage = damage, | ||
266 | .alpha = 1.0f, | ||
267 | }; | ||
216 | unmanaged_for_each_surface(unmanaged, output, &data.root_geo, | 268 | unmanaged_for_each_surface(unmanaged, output, &data.root_geo, |
217 | render_surface_iterator, &data); | 269 | render_surface_iterator, &data); |
218 | } | 270 | } |
219 | 271 | ||
220 | static void render_view(struct sway_view *view, struct sway_output *output) { | 272 | static void render_view(struct sway_view *view, struct sway_output *output, |
221 | struct render_data data = { .output = output, .alpha = view->swayc->alpha }; | 273 | pixman_region32_t *damage) { |
274 | struct render_data data = { | ||
275 | .output = output, | ||
276 | .damage = damage, | ||
277 | .alpha = view->swayc->alpha, | ||
278 | }; | ||
222 | output_view_for_each_surface( | 279 | output_view_for_each_surface( |
223 | view, &data.root_geo, render_surface_iterator, &data); | 280 | view, &data.root_geo, render_surface_iterator, &data); |
224 | } | 281 | } |
225 | 282 | ||
283 | static void render_rect(struct wlr_output *wlr_output, | ||
284 | pixman_region32_t *output_damage, const struct wlr_box *_box, | ||
285 | float color[static 4]) { | ||
286 | struct wlr_renderer *renderer = | ||
287 | wlr_backend_get_renderer(wlr_output->backend); | ||
288 | |||
289 | struct wlr_box box = *_box; | ||
290 | scale_box(&box, wlr_output->scale); | ||
291 | |||
292 | pixman_region32_t damage; | ||
293 | pixman_region32_init(&damage); | ||
294 | pixman_region32_union_rect(&damage, &damage, box.x, box.y, | ||
295 | box.width, box.height); | ||
296 | pixman_region32_intersect(&damage, &damage, output_damage); | ||
297 | bool damaged = pixman_region32_not_empty(&damage); | ||
298 | if (!damaged) { | ||
299 | goto damage_finish; | ||
300 | } | ||
301 | |||
302 | int nrects; | ||
303 | pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects); | ||
304 | for (int i = 0; i < nrects; ++i) { | ||
305 | scissor_output(wlr_output, &rects[i]); | ||
306 | wlr_render_rect(renderer, &box, color, | ||
307 | wlr_output->transform_matrix); | ||
308 | } | ||
309 | |||
310 | damage_finish: | ||
311 | pixman_region32_fini(&damage); | ||
312 | } | ||
313 | |||
226 | /** | 314 | /** |
227 | * Render decorations for a view with "border normal". | 315 | * Render decorations for a view with "border normal". |
228 | */ | 316 | */ |
229 | static void render_container_simple_border_normal(struct sway_output *output, | 317 | static void render_container_simple_border_normal(struct sway_output *output, |
318 | pixman_region32_t *output_damage, | ||
230 | struct sway_container *con, struct border_colors *colors, | 319 | struct sway_container *con, struct border_colors *colors, |
231 | struct wlr_texture *title_texture) { | 320 | struct wlr_texture *title_texture) { |
232 | struct wlr_renderer *renderer = | ||
233 | wlr_backend_get_renderer(output->wlr_output->backend); | ||
234 | struct wlr_box box; | 321 | struct wlr_box box; |
235 | float color[4]; | 322 | float color[4]; |
236 | 323 | ||
@@ -241,9 +328,7 @@ static void render_container_simple_border_normal(struct sway_output *output, | |||
241 | box.y = con->y + 1; | 328 | box.y = con->y + 1; |
242 | box.width = con->sway_view->border_thickness; | 329 | box.width = con->sway_view->border_thickness; |
243 | box.height = con->height - 1; | 330 | box.height = con->height - 1; |
244 | scale_box(&box, output->wlr_output->scale); | 331 | render_rect(output->wlr_output, output_damage, &box, color); |
245 | wlr_render_rect(renderer, &box, color, | ||
246 | output->wlr_output->transform_matrix); | ||
247 | 332 | ||
248 | // Child border - right edge | 333 | // Child border - right edge |
249 | if (con->parent->children->length == 1 && con->parent->layout == L_HORIZ) { | 334 | if (con->parent->children->length == 1 && con->parent->layout == L_HORIZ) { |
@@ -256,9 +341,7 @@ static void render_container_simple_border_normal(struct sway_output *output, | |||
256 | box.y = con->y + 1; | 341 | box.y = con->y + 1; |
257 | box.width = con->sway_view->border_thickness; | 342 | box.width = con->sway_view->border_thickness; |
258 | box.height = con->height - 1; | 343 | box.height = con->height - 1; |
259 | scale_box(&box, output->wlr_output->scale); | 344 | render_rect(output->wlr_output, output_damage, &box, color); |
260 | wlr_render_rect(renderer, &box, color, | ||
261 | output->wlr_output->transform_matrix); | ||
262 | 345 | ||
263 | // Child border - bottom edge | 346 | // Child border - bottom edge |
264 | if (con->parent->children->length == 1 && con->parent->layout == L_VERT) { | 347 | if (con->parent->children->length == 1 && con->parent->layout == L_VERT) { |
@@ -271,9 +354,7 @@ static void render_container_simple_border_normal(struct sway_output *output, | |||
271 | box.y = con->y + con->height - con->sway_view->border_thickness; | 354 | box.y = con->y + con->height - con->sway_view->border_thickness; |
272 | box.width = con->width; | 355 | box.width = con->width; |
273 | box.height = con->sway_view->border_thickness; | 356 | box.height = con->sway_view->border_thickness; |
274 | scale_box(&box, output->wlr_output->scale); | 357 | render_rect(output->wlr_output, output_damage, &box, color); |
275 | wlr_render_rect(renderer, &box, color, | ||
276 | output->wlr_output->transform_matrix); | ||
277 | 358 | ||
278 | // Single pixel bar above title | 359 | // Single pixel bar above title |
279 | memcpy(&color, colors->border, sizeof(float) * 4); | 360 | memcpy(&color, colors->border, sizeof(float) * 4); |
@@ -282,18 +363,14 @@ static void render_container_simple_border_normal(struct sway_output *output, | |||
282 | box.y = con->y; | 363 | box.y = con->y; |
283 | box.width = con->width; | 364 | box.width = con->width; |
284 | box.height = 1; | 365 | box.height = 1; |
285 | scale_box(&box, output->wlr_output->scale); | 366 | render_rect(output->wlr_output, output_damage, &box, color); |
286 | wlr_render_rect(renderer, &box, color, | ||
287 | output->wlr_output->transform_matrix); | ||
288 | 367 | ||
289 | // Single pixel bar below title | 368 | // Single pixel bar below title |
290 | box.x = con->x + con->sway_view->border_thickness; | 369 | box.x = con->x + con->sway_view->border_thickness; |
291 | box.y = con->sway_view->y - 1; | 370 | box.y = con->sway_view->y - 1; |
292 | box.width = con->width - con->sway_view->border_thickness * 2; | 371 | box.width = con->width - con->sway_view->border_thickness * 2; |
293 | box.height = 1; | 372 | box.height = 1; |
294 | scale_box(&box, output->wlr_output->scale); | 373 | render_rect(output->wlr_output, output_damage, &box, color); |
295 | wlr_render_rect(renderer, &box, color, | ||
296 | output->wlr_output->transform_matrix); | ||
297 | 374 | ||
298 | // Title background | 375 | // Title background |
299 | memcpy(&color, colors->background, sizeof(float) * 4); | 376 | memcpy(&color, colors->background, sizeof(float) * 4); |
@@ -302,20 +379,24 @@ static void render_container_simple_border_normal(struct sway_output *output, | |||
302 | box.y = con->y + 1; | 379 | box.y = con->y + 1; |
303 | box.width = con->width - con->sway_view->border_thickness * 2; | 380 | box.width = con->width - con->sway_view->border_thickness * 2; |
304 | box.height = con->sway_view->y - con->y - 2; | 381 | box.height = con->sway_view->y - con->y - 2; |
305 | scale_box(&box, output->wlr_output->scale); | 382 | render_rect(output->wlr_output, output_damage, &box, color); |
306 | wlr_render_rect(renderer, &box, color, | ||
307 | output->wlr_output->transform_matrix); | ||
308 | 383 | ||
309 | // Title text | 384 | // Title text |
310 | if (title_texture) { | 385 | if (title_texture) { |
311 | struct wlr_box scissor_box; | 386 | float output_scale = output->wlr_output->scale; |
312 | wlr_box_transform(&box, | 387 | struct wlr_box texture_box = { |
313 | wlr_output_transform_invert(output->wlr_output->transform), | 388 | .x = box.x * output_scale, |
314 | output->swayc->width, output->swayc->height, &scissor_box); | 389 | .y = box.y * output_scale, |
315 | wlr_renderer_scissor(renderer, &scissor_box); | 390 | }; |
316 | wlr_render_texture(renderer, title_texture, | 391 | wlr_texture_get_size(title_texture, |
317 | output->wlr_output->transform_matrix, box.x, box.y, 1); | 392 | &texture_box.width, &texture_box.height); |
318 | wlr_renderer_scissor(renderer, NULL); | 393 | |
394 | float matrix[9]; | ||
395 | wlr_matrix_project_box(matrix, &texture_box, WL_OUTPUT_TRANSFORM_NORMAL, | ||
396 | 0.0, output->wlr_output->transform_matrix); | ||
397 | |||
398 | render_texture(output->wlr_output, output_damage, title_texture, | ||
399 | &texture_box, matrix, 1.0); | ||
319 | } | 400 | } |
320 | } | 401 | } |
321 | 402 | ||
@@ -323,9 +404,8 @@ static void render_container_simple_border_normal(struct sway_output *output, | |||
323 | * Render decorations for a view with "border pixel". | 404 | * Render decorations for a view with "border pixel". |
324 | */ | 405 | */ |
325 | static void render_container_simple_border_pixel(struct sway_output *output, | 406 | static void render_container_simple_border_pixel(struct sway_output *output, |
326 | struct sway_container *con, struct border_colors *colors) { | 407 | pixman_region32_t *output_damage, struct sway_container *con, |
327 | struct wlr_renderer *renderer = | 408 | struct border_colors *colors) { |
328 | wlr_backend_get_renderer(output->wlr_output->backend); | ||
329 | struct wlr_box box; | 409 | struct wlr_box box; |
330 | float color[4]; | 410 | float color[4]; |
331 | 411 | ||
@@ -336,9 +416,7 @@ static void render_container_simple_border_pixel(struct sway_output *output, | |||
336 | box.y = con->y; | 416 | box.y = con->y; |
337 | box.width = con->sway_view->border_thickness; | 417 | box.width = con->sway_view->border_thickness; |
338 | box.height = con->height; | 418 | box.height = con->height; |
339 | scale_box(&box, output->wlr_output->scale); | 419 | render_rect(output->wlr_output, output_damage, &box, color); |
340 | wlr_render_rect(renderer, &box, color, | ||
341 | output->wlr_output->transform_matrix); | ||
342 | 420 | ||
343 | // Child border - right edge | 421 | // Child border - right edge |
344 | if (con->parent->children->length == 1 && con->parent->layout == L_HORIZ) { | 422 | if (con->parent->children->length == 1 && con->parent->layout == L_HORIZ) { |
@@ -351,18 +429,14 @@ static void render_container_simple_border_pixel(struct sway_output *output, | |||
351 | box.y = con->y; | 429 | box.y = con->y; |
352 | box.width = con->sway_view->border_thickness; | 430 | box.width = con->sway_view->border_thickness; |
353 | box.height = con->height; | 431 | box.height = con->height; |
354 | scale_box(&box, output->wlr_output->scale); | 432 | render_rect(output->wlr_output, output_damage, &box, color); |
355 | wlr_render_rect(renderer, &box, color, | ||
356 | output->wlr_output->transform_matrix); | ||
357 | 433 | ||
358 | // Child border - top edge | 434 | // Child border - top edge |
359 | box.x = con->x; | 435 | box.x = con->x; |
360 | box.y = con->y; | 436 | box.y = con->y; |
361 | box.width = con->width; | 437 | box.width = con->width; |
362 | box.height = con->sway_view->border_thickness; | 438 | box.height = con->sway_view->border_thickness; |
363 | scale_box(&box, output->wlr_output->scale); | 439 | render_rect(output->wlr_output, output_damage, &box, color); |
364 | wlr_render_rect(renderer, &box, color, | ||
365 | output->wlr_output->transform_matrix); | ||
366 | 440 | ||
367 | // Child border - bottom edge | 441 | // Child border - bottom edge |
368 | if (con->parent->children->length == 1 && con->parent->layout == L_VERT) { | 442 | if (con->parent->children->length == 1 && con->parent->layout == L_VERT) { |
@@ -375,13 +449,11 @@ static void render_container_simple_border_pixel(struct sway_output *output, | |||
375 | box.y = con->y + con->height - con->sway_view->border_thickness; | 449 | box.y = con->y + con->height - con->sway_view->border_thickness; |
376 | box.width = con->width; | 450 | box.width = con->width; |
377 | box.height = con->sway_view->border_thickness; | 451 | box.height = con->sway_view->border_thickness; |
378 | scale_box(&box, output->wlr_output->scale); | 452 | render_rect(output->wlr_output, output_damage, &box, color); |
379 | wlr_render_rect(renderer, &box, color, | ||
380 | output->wlr_output->transform_matrix); | ||
381 | } | 453 | } |
382 | 454 | ||
383 | static void render_container(struct sway_output *output, | 455 | static void render_container(struct sway_output *output, |
384 | struct sway_container *con); | 456 | pixman_region32_t *damage, struct sway_container *con); |
385 | 457 | ||
386 | /** | 458 | /** |
387 | * Render a container's children using a L_HORIZ or L_VERT layout. | 459 | * Render a container's children using a L_HORIZ or L_VERT layout. |
@@ -390,7 +462,7 @@ static void render_container(struct sway_output *output, | |||
390 | * they'll apply their own borders to their children. | 462 | * they'll apply their own borders to their children. |
391 | */ | 463 | */ |
392 | static void render_container_simple(struct sway_output *output, | 464 | static void render_container_simple(struct sway_output *output, |
393 | struct sway_container *con) { | 465 | pixman_region32_t *damage, struct sway_container *con) { |
394 | struct sway_seat *seat = input_manager_current_seat(input_manager); | 466 | struct sway_seat *seat = input_manager_current_seat(input_manager); |
395 | struct sway_container *focus = seat_get_focus(seat); | 467 | struct sway_container *focus = seat_get_focus(seat); |
396 | 468 | ||
@@ -413,15 +485,16 @@ static void render_container_simple(struct sway_output *output, | |||
413 | } | 485 | } |
414 | 486 | ||
415 | if (child->sway_view->border == B_NORMAL) { | 487 | if (child->sway_view->border == B_NORMAL) { |
416 | render_container_simple_border_normal(output, child, | 488 | render_container_simple_border_normal(output, damage, |
417 | colors, title_texture); | 489 | child, colors, title_texture); |
418 | } else { | 490 | } else { |
419 | render_container_simple_border_pixel(output, child, colors); | 491 | render_container_simple_border_pixel(output, damage, child, |
492 | colors); | ||
420 | } | 493 | } |
421 | } | 494 | } |
422 | render_view(child->sway_view, output); | 495 | render_view(child->sway_view, output, damage); |
423 | } else { | 496 | } else { |
424 | render_container(output, child); | 497 | render_container(output, damage, child); |
425 | } | 498 | } |
426 | } | 499 | } |
427 | } | 500 | } |
@@ -430,7 +503,7 @@ static void render_container_simple(struct sway_output *output, | |||
430 | * Render a container's children using the L_TABBED layout. | 503 | * Render a container's children using the L_TABBED layout. |
431 | */ | 504 | */ |
432 | static void render_container_tabbed(struct sway_output *output, | 505 | static void render_container_tabbed(struct sway_output *output, |
433 | struct sway_container *con) { | 506 | pixman_region32_t *damage, struct sway_container *con) { |
434 | // TODO | 507 | // TODO |
435 | } | 508 | } |
436 | 509 | ||
@@ -438,23 +511,23 @@ static void render_container_tabbed(struct sway_output *output, | |||
438 | * Render a container's children using the L_STACKED layout. | 511 | * Render a container's children using the L_STACKED layout. |
439 | */ | 512 | */ |
440 | static void render_container_stacked(struct sway_output *output, | 513 | static void render_container_stacked(struct sway_output *output, |
441 | struct sway_container *con) { | 514 | pixman_region32_t *damage, struct sway_container *con) { |
442 | // TODO | 515 | // TODO |
443 | } | 516 | } |
444 | 517 | ||
445 | static void render_container(struct sway_output *output, | 518 | static void render_container(struct sway_output *output, |
446 | struct sway_container *con) { | 519 | pixman_region32_t *damage, struct sway_container *con) { |
447 | switch (con->layout) { | 520 | switch (con->layout) { |
448 | case L_NONE: | 521 | case L_NONE: |
449 | case L_HORIZ: | 522 | case L_HORIZ: |
450 | case L_VERT: | 523 | case L_VERT: |
451 | render_container_simple(output, con); | 524 | render_container_simple(output, damage, con); |
452 | break; | 525 | break; |
453 | case L_STACKED: | 526 | case L_STACKED: |
454 | render_container_stacked(output, con); | 527 | render_container_stacked(output, damage, con); |
455 | break; | 528 | break; |
456 | case L_TABBED: | 529 | case L_TABBED: |
457 | render_container_tabbed(output, con); | 530 | render_container_tabbed(output, damage, con); |
458 | break; | 531 | break; |
459 | case L_FLOATING: | 532 | case L_FLOATING: |
460 | // TODO | 533 | // TODO |
@@ -496,37 +569,51 @@ static void render_output(struct sway_output *output, struct timespec *when, | |||
496 | goto renderer_end; | 569 | goto renderer_end; |
497 | } | 570 | } |
498 | 571 | ||
499 | // TODO: don't damage the whole output | 572 | //wlr_renderer_clear(renderer, (float[]){1, 1, 0, 1}); |
500 | int width, height; | ||
501 | wlr_output_transformed_resolution(wlr_output, &width, &height); | ||
502 | pixman_region32_union_rect(damage, damage, 0, 0, width, height); | ||
503 | 573 | ||
504 | struct sway_container *workspace = output_get_active_workspace(output); | 574 | struct sway_container *workspace = output_get_active_workspace(output); |
505 | 575 | ||
506 | if (workspace->sway_workspace->fullscreen) { | 576 | if (workspace->sway_workspace->fullscreen) { |
507 | float clear_color[] = {0.0f, 0.0f, 0.0f, 1.0f}; | 577 | float clear_color[] = {0.0f, 0.0f, 0.0f, 1.0f}; |
508 | wlr_renderer_clear(renderer, clear_color); | 578 | |
579 | int nrects; | ||
580 | pixman_box32_t *rects = pixman_region32_rectangles(damage, &nrects); | ||
581 | for (int i = 0; i < nrects; ++i) { | ||
582 | scissor_output(wlr_output, &rects[i]); | ||
583 | wlr_renderer_clear(renderer, clear_color); | ||
584 | } | ||
585 | |||
509 | // TODO: handle views smaller than the output | 586 | // TODO: handle views smaller than the output |
510 | render_view(workspace->sway_workspace->fullscreen, output); | 587 | render_view(workspace->sway_workspace->fullscreen, output, damage); |
511 | 588 | ||
512 | if (workspace->sway_workspace->fullscreen->type == SWAY_VIEW_XWAYLAND) { | 589 | if (workspace->sway_workspace->fullscreen->type == SWAY_VIEW_XWAYLAND) { |
513 | render_unmanaged(output, | 590 | render_unmanaged(output, damage, |
514 | &root_container.sway_root->xwayland_unmanaged); | 591 | &root_container.sway_root->xwayland_unmanaged); |
515 | } | 592 | } |
516 | } else { | 593 | } else { |
517 | float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f}; | 594 | float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f}; |
518 | wlr_renderer_clear(renderer, clear_color); | ||
519 | 595 | ||
520 | render_layer(output, | 596 | int nrects; |
521 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]); | 597 | pixman_box32_t *rects = pixman_region32_rectangles(damage, &nrects); |
522 | render_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]); | 598 | for (int i = 0; i < nrects; ++i) { |
599 | scissor_output(wlr_output, &rects[i]); | ||
600 | wlr_renderer_clear(renderer, clear_color); | ||
601 | } | ||
602 | |||
603 | render_layer(output, damage, | ||
604 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]); | ||
605 | render_layer(output, damage, | ||
606 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]); | ||
523 | 607 | ||
524 | render_container(output, workspace); | 608 | render_container(output, damage, workspace); |
525 | 609 | ||
526 | render_unmanaged(output, &root_container.sway_root->xwayland_unmanaged); | 610 | render_unmanaged(output, damage, |
527 | render_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); | 611 | &root_container.sway_root->xwayland_unmanaged); |
612 | render_layer(output, damage, | ||
613 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); | ||
528 | } | 614 | } |
529 | render_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); | 615 | render_layer(output, damage, |
616 | &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); | ||
530 | 617 | ||
531 | renderer_end: | 618 | renderer_end: |
532 | if (root_container.sway_root->debug_tree) { | 619 | if (root_container.sway_root->debug_tree) { |
@@ -534,6 +621,7 @@ renderer_end: | |||
534 | wlr_output->transform_matrix, 0, 0, 1); | 621 | wlr_output->transform_matrix, 0, 0, 1); |
535 | } | 622 | } |
536 | 623 | ||
624 | wlr_renderer_scissor(renderer, NULL); | ||
537 | wlr_renderer_end(renderer); | 625 | wlr_renderer_end(renderer); |
538 | if (!wlr_output_damage_swap_buffers(output->damage, when, damage)) { | 626 | if (!wlr_output_damage_swap_buffers(output->damage, when, damage)) { |
539 | return; | 627 | return; |
@@ -663,28 +751,28 @@ static void damage_surface_iterator(struct wlr_surface *surface, int sx, int sy, | |||
663 | 751 | ||
664 | scale_box(&box, output->wlr_output->scale); | 752 | scale_box(&box, output->wlr_output->scale); |
665 | 753 | ||
754 | int center_x = box.x + box.width/2; | ||
755 | int center_y = box.y + box.height/2; | ||
756 | |||
757 | pixman_region32_t damage; | ||
758 | pixman_region32_init(&damage); | ||
759 | pixman_region32_copy(&damage, &surface->current->surface_damage); | ||
760 | wlr_region_scale(&damage, &damage, output->wlr_output->scale); | ||
761 | if (ceil(output->wlr_output->scale) > surface->current->scale) { | ||
762 | // When scaling up a surface, it'll become blurry so we need to | ||
763 | // expand the damage region | ||
764 | wlr_region_expand(&damage, &damage, | ||
765 | ceil(output->wlr_output->scale) - surface->current->scale); | ||
766 | } | ||
767 | pixman_region32_translate(&damage, box.x, box.y); | ||
768 | wlr_region_rotated_bounds(&damage, &damage, rotation, | ||
769 | center_x, center_y); | ||
770 | wlr_output_damage_add(output->damage, &damage); | ||
771 | pixman_region32_fini(&damage); | ||
772 | |||
666 | if (whole) { | 773 | if (whole) { |
667 | wlr_box_rotated_bounds(&box, rotation, &box); | 774 | wlr_box_rotated_bounds(&box, rotation, &box); |
668 | wlr_output_damage_add_box(output->damage, &box); | 775 | wlr_output_damage_add_box(output->damage, &box); |
669 | } else { | ||
670 | int center_x = box.x + box.width/2; | ||
671 | int center_y = box.y + box.height/2; | ||
672 | |||
673 | pixman_region32_t damage; | ||
674 | pixman_region32_init(&damage); | ||
675 | pixman_region32_copy(&damage, &surface->current->surface_damage); | ||
676 | wlr_region_scale(&damage, &damage, output->wlr_output->scale); | ||
677 | if (ceil(output->wlr_output->scale) > surface->current->scale) { | ||
678 | // When scaling up a surface, it'll become blurry so we need to | ||
679 | // expand the damage region | ||
680 | wlr_region_expand(&damage, &damage, | ||
681 | ceil(output->wlr_output->scale) - surface->current->scale); | ||
682 | } | ||
683 | pixman_region32_translate(&damage, box.x, box.y); | ||
684 | wlr_region_rotated_bounds(&damage, &damage, rotation, | ||
685 | center_x, center_y); | ||
686 | wlr_output_damage_add(output->damage, &damage); | ||
687 | pixman_region32_fini(&damage); | ||
688 | } | 776 | } |
689 | } | 777 | } |
690 | 778 | ||
@@ -699,8 +787,8 @@ void output_damage_surface(struct sway_output *output, double ox, double oy, | |||
699 | damage_surface_iterator, &data); | 787 | damage_surface_iterator, &data); |
700 | } | 788 | } |
701 | 789 | ||
702 | void output_damage_view(struct sway_output *output, struct sway_view *view, | 790 | static void output_damage_view(struct sway_output *output, |
703 | bool whole) { | 791 | struct sway_view *view, bool whole) { |
704 | if (!sway_assert(view->swayc != NULL, "expected a view in the tree")) { | 792 | if (!sway_assert(view->swayc != NULL, "expected a view in the tree")) { |
705 | return; | 793 | return; |
706 | } | 794 | } |
@@ -720,6 +808,11 @@ void output_damage_view(struct sway_output *output, struct sway_view *view, | |||
720 | damage_surface_iterator, &data); | 808 | damage_surface_iterator, &data); |
721 | } | 809 | } |
722 | 810 | ||
811 | void output_damage_from_view(struct sway_output *output, | ||
812 | struct sway_view *view) { | ||
813 | output_damage_view(output, view, false); | ||
814 | } | ||
815 | |||
723 | static void output_damage_whole_container_iterator(struct sway_container *con, | 816 | static void output_damage_whole_container_iterator(struct sway_container *con, |
724 | void *data) { | 817 | void *data) { |
725 | struct sway_output *output = data; | 818 | struct sway_output *output = data; |
@@ -742,8 +835,12 @@ void output_damage_whole_container(struct sway_output *output, | |||
742 | }; | 835 | }; |
743 | wlr_output_damage_add_box(output->damage, &box); | 836 | wlr_output_damage_add_box(output->damage, &box); |
744 | 837 | ||
745 | container_descendants(con, C_VIEW, output_damage_whole_container_iterator, | 838 | if (con->type == C_VIEW) { |
746 | output); | 839 | output_damage_whole_container_iterator(con, output); |
840 | } else { | ||
841 | container_descendants(con, C_VIEW, | ||
842 | output_damage_whole_container_iterator, output); | ||
843 | } | ||
747 | } | 844 | } |
748 | 845 | ||
749 | static void damage_handle_destroy(struct wl_listener *listener, void *data) { | 846 | static void damage_handle_destroy(struct wl_listener *listener, void *data) { |
diff --git a/sway/desktop/wl_shell.c b/sway/desktop/wl_shell.c index e97a898e..99e8947b 100644 --- a/sway/desktop/wl_shell.c +++ b/sway/desktop/wl_shell.c | |||
@@ -85,7 +85,7 @@ static void handle_commit(struct wl_listener *listener, void *data) { | |||
85 | // TODO: Let floating views do whatever | 85 | // TODO: Let floating views do whatever |
86 | view_update_size(view, wl_shell_view->pending_width, | 86 | view_update_size(view, wl_shell_view->pending_width, |
87 | wl_shell_view->pending_height); | 87 | wl_shell_view->pending_height); |
88 | view_damage(view, false); | 88 | view_damage_from(view); |
89 | } | 89 | } |
90 | 90 | ||
91 | static void handle_destroy(struct wl_listener *listener, void *data) { | 91 | static void handle_destroy(struct wl_listener *listener, void *data) { |
diff --git a/sway/desktop/xdg_shell_v6.c b/sway/desktop/xdg_shell_v6.c index fcee8ce9..8ecb330d 100644 --- a/sway/desktop/xdg_shell_v6.c +++ b/sway/desktop/xdg_shell_v6.c | |||
@@ -177,7 +177,7 @@ static void handle_commit(struct wl_listener *listener, void *data) { | |||
177 | view_update_size(view, xdg_shell_v6_view->pending_width, | 177 | view_update_size(view, xdg_shell_v6_view->pending_width, |
178 | xdg_shell_v6_view->pending_height); | 178 | xdg_shell_v6_view->pending_height); |
179 | view_update_title(view, false); | 179 | view_update_title(view, false); |
180 | view_damage(view, false); | 180 | view_damage_from(view); |
181 | } | 181 | } |
182 | 182 | ||
183 | static void handle_new_popup(struct wl_listener *listener, void *data) { | 183 | static void handle_new_popup(struct wl_listener *listener, void *data) { |
diff --git a/sway/desktop/xwayland.c b/sway/desktop/xwayland.c index b4eda71f..8f935760 100644 --- a/sway/desktop/xwayland.c +++ b/sway/desktop/xwayland.c | |||
@@ -222,7 +222,7 @@ static void handle_commit(struct wl_listener *listener, void *data) { | |||
222 | // TODO: Let floating views do whatever | 222 | // TODO: Let floating views do whatever |
223 | view_update_size(view, xwayland_view->pending_width, | 223 | view_update_size(view, xwayland_view->pending_width, |
224 | xwayland_view->pending_height); | 224 | xwayland_view->pending_height); |
225 | view_damage(view, false); | 225 | view_damage_from(view); |
226 | view_update_title(view, false); | 226 | view_update_title(view, false); |
227 | } | 227 | } |
228 | 228 | ||
diff --git a/sway/input/seat.c b/sway/input/seat.c index 443fe367..2c279ff2 100644 --- a/sway/input/seat.c +++ b/sway/input/seat.c | |||
@@ -530,6 +530,7 @@ void seat_set_focus_warp(struct sway_seat *seat, | |||
530 | if (container->type == C_VIEW) { | 530 | if (container->type == C_VIEW) { |
531 | seat_send_focus(seat, container); | 531 | seat_send_focus(seat, container); |
532 | } | 532 | } |
533 | container_damage_whole(container); | ||
533 | } | 534 | } |
534 | 535 | ||
535 | // clean up unfocused empty workspace on new output | 536 | // clean up unfocused empty workspace on new output |
@@ -575,6 +576,10 @@ void seat_set_focus_warp(struct sway_seat *seat, | |||
575 | } | 576 | } |
576 | } | 577 | } |
577 | 578 | ||
579 | if (last_focus) { | ||
580 | container_damage_whole(last_focus); | ||
581 | } | ||
582 | |||
578 | if (last_focus && last_focus->type == C_VIEW && | 583 | if (last_focus && last_focus->type == C_VIEW && |
579 | !input_manager_has_focus(seat->input, last_focus)) { | 584 | !input_manager_has_focus(seat->input, last_focus)) { |
580 | struct sway_view *view = last_focus->sway_view; | 585 | struct sway_view *view = last_focus->sway_view; |
diff --git a/sway/tree/container.c b/sway/tree/container.c index 38db29c2..db02c69c 100644 --- a/sway/tree/container.c +++ b/sway/tree/container.c | |||
@@ -547,12 +547,13 @@ bool container_has_child(struct sway_container *con, | |||
547 | return container_find(con, find_child_func, child); | 547 | return container_find(con, find_child_func, child); |
548 | } | 548 | } |
549 | 549 | ||
550 | void container_damage_whole(struct sway_container *con) { | 550 | void container_damage_whole(struct sway_container *container) { |
551 | struct sway_container *output = con; | 551 | for (int i = 0; i < root_container.children->length; ++i) { |
552 | if (output->type != C_OUTPUT) { | 552 | struct sway_container *cont = root_container.children->items[i]; |
553 | output = container_parent(output, C_OUTPUT); | 553 | if (cont->type == C_OUTPUT) { |
554 | output_damage_whole_container(cont->sway_output, container); | ||
555 | } | ||
554 | } | 556 | } |
555 | output_damage_whole_container(output->sway_output, con); | ||
556 | } | 557 | } |
557 | 558 | ||
558 | static void update_title_texture(struct sway_container *con, | 559 | static void update_title_texture(struct sway_container *con, |
@@ -620,6 +621,7 @@ void container_update_title_textures(struct sway_container *container) { | |||
620 | &config->border_colors.unfocused); | 621 | &config->border_colors.unfocused); |
621 | update_title_texture(container, &container->title_urgent, | 622 | update_title_texture(container, &container->title_urgent, |
622 | &config->border_colors.urgent); | 623 | &config->border_colors.urgent); |
624 | container_damage_whole(container); | ||
623 | } | 625 | } |
624 | 626 | ||
625 | void container_calculate_title_height(struct sway_container *container) { | 627 | void container_calculate_title_height(struct sway_container *container) { |
diff --git a/sway/tree/view.c b/sway/tree/view.c index fe944466..afd7eade 100644 --- a/sway/tree/view.c +++ b/sway/tree/view.c | |||
@@ -199,11 +199,11 @@ void view_close(struct sway_view *view) { | |||
199 | } | 199 | } |
200 | } | 200 | } |
201 | 201 | ||
202 | void view_damage(struct sway_view *view, bool whole) { | 202 | void view_damage_from(struct sway_view *view) { |
203 | for (int i = 0; i < root_container.children->length; ++i) { | 203 | for (int i = 0; i < root_container.children->length; ++i) { |
204 | struct sway_container *cont = root_container.children->items[i]; | 204 | struct sway_container *cont = root_container.children->items[i]; |
205 | if (cont->type == C_OUTPUT) { | 205 | if (cont->type == C_OUTPUT) { |
206 | output_damage_view(cont->sway_output, view, whole); | 206 | output_damage_from_view(cont->sway_output, view); |
207 | } | 207 | } |
208 | } | 208 | } |
209 | } | 209 | } |
@@ -333,7 +333,7 @@ void view_map(struct sway_view *view, struct wlr_surface *wlr_surface) { | |||
333 | arrange_children_of(cont->parent); | 333 | arrange_children_of(cont->parent); |
334 | input_manager_set_focus(input_manager, cont); | 334 | input_manager_set_focus(input_manager, cont); |
335 | 335 | ||
336 | view_damage(view, true); | 336 | container_damage_whole(cont); |
337 | view_handle_container_reparent(&view->container_reparent, NULL); | 337 | view_handle_container_reparent(&view->container_reparent, NULL); |
338 | 338 | ||
339 | view_execute_criteria(view); | 339 | view_execute_criteria(view); |
@@ -351,7 +351,7 @@ void view_unmap(struct sway_view *view) { | |||
351 | ws->sway_workspace->fullscreen = NULL; | 351 | ws->sway_workspace->fullscreen = NULL; |
352 | } | 352 | } |
353 | 353 | ||
354 | view_damage(view, true); | 354 | container_damage_whole(view->swayc); |
355 | 355 | ||
356 | wl_list_remove(&view->surface_new_subsurface.link); | 356 | wl_list_remove(&view->surface_new_subsurface.link); |
357 | wl_list_remove(&view->container_reparent.link); | 357 | wl_list_remove(&view->container_reparent.link); |
@@ -380,10 +380,10 @@ void view_update_position(struct sway_view *view, double ox, double oy) { | |||
380 | 380 | ||
381 | // TODO: Only allow this if the view is floating (this function will only be | 381 | // TODO: Only allow this if the view is floating (this function will only be |
382 | // called in response to wayland clients wanting to reposition themselves). | 382 | // called in response to wayland clients wanting to reposition themselves). |
383 | view_damage(view, true); | 383 | container_damage_whole(view->swayc); |
384 | view->swayc->x = ox; | 384 | view->swayc->x = ox; |
385 | view->swayc->y = oy; | 385 | view->swayc->y = oy; |
386 | view_damage(view, true); | 386 | container_damage_whole(view->swayc); |
387 | } | 387 | } |
388 | 388 | ||
389 | void view_update_size(struct sway_view *view, int width, int height) { | 389 | void view_update_size(struct sway_view *view, int width, int height) { |
@@ -391,11 +391,11 @@ void view_update_size(struct sway_view *view, int width, int height) { | |||
391 | return; | 391 | return; |
392 | } | 392 | } |
393 | 393 | ||
394 | view_damage(view, true); | 394 | container_damage_whole(view->swayc); |
395 | // Should we update the swayc width/height here too? | 395 | // Should we update the swayc width/height here too? |
396 | view->width = width; | 396 | view->width = width; |
397 | view->height = height; | 397 | view->height = height; |
398 | view_damage(view, true); | 398 | container_damage_whole(view->swayc); |
399 | } | 399 | } |
400 | 400 | ||
401 | 401 | ||
@@ -414,7 +414,7 @@ static void view_child_handle_surface_commit(struct wl_listener *listener, | |||
414 | struct sway_view_child *child = | 414 | struct sway_view_child *child = |
415 | wl_container_of(listener, child, surface_commit); | 415 | wl_container_of(listener, child, surface_commit); |
416 | // TODO: only accumulate damage from the child | 416 | // TODO: only accumulate damage from the child |
417 | view_damage(child->view, false); | 417 | view_damage_from(child->view); |
418 | } | 418 | } |
419 | 419 | ||
420 | static void view_child_handle_surface_new_subsurface( | 420 | static void view_child_handle_surface_new_subsurface( |
@@ -476,12 +476,16 @@ void view_child_init(struct sway_view_child *child, | |||
476 | view_init_subsurfaces(child->view, surface); | 476 | view_init_subsurfaces(child->view, surface); |
477 | 477 | ||
478 | // TODO: only damage the whole child | 478 | // TODO: only damage the whole child |
479 | view_damage(child->view, true); | 479 | if (child->view->swayc) { |
480 | container_damage_whole(child->view->swayc); | ||
481 | } | ||
480 | } | 482 | } |
481 | 483 | ||
482 | void view_child_destroy(struct sway_view_child *child) { | 484 | void view_child_destroy(struct sway_view_child *child) { |
483 | // TODO: only damage the whole child | 485 | // TODO: only damage the whole child |
484 | view_damage(child->view, true); | 486 | if (child->view->swayc) { |
487 | container_damage_whole(child->view->swayc); | ||
488 | } | ||
485 | 489 | ||
486 | wl_list_remove(&child->surface_commit.link); | 490 | wl_list_remove(&child->surface_commit.link); |
487 | wl_list_remove(&child->surface_destroy.link); | 491 | wl_list_remove(&child->surface_destroy.link); |