aboutsummaryrefslogtreecommitdiffstats
path: root/sway/desktop/output.c
diff options
context:
space:
mode:
authorLibravatar emersion <contact@emersion.fr>2018-05-05 18:51:13 +0100
committerLibravatar emersion <contact@emersion.fr>2018-05-10 23:02:37 +0100
commitc8a9ea3903fbb5f81dad87a1d6ccb50e38d66e3f (patch)
treeeb17315e69c91765bdd72a5922b41553ca04e512 /sway/desktop/output.c
parentMerge pull request #1932 from emersion/fix-layer-shell-exclusive (diff)
downloadsway-c8a9ea3903fbb5f81dad87a1d6ccb50e38d66e3f.tar.gz
sway-c8a9ea3903fbb5f81dad87a1d6ccb50e38d66e3f.tar.zst
sway-c8a9ea3903fbb5f81dad87a1d6ccb50e38d66e3f.zip
Implement full damage tracking
Diffstat (limited to 'sway/desktop/output.c')
-rw-r--r--sway/desktop/output.c142
1 files changed, 106 insertions, 36 deletions
diff --git a/sway/desktop/output.c b/sway/desktop/output.c
index 9b0f1ae3..9eeed9b9 100644
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -163,14 +163,38 @@ static void scale_box(struct wlr_box *box, float scale) {
163struct render_data { 163struct 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
170static 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
169static void render_surface_iterator(struct wlr_surface *surface, int sx, int sy, 192static void render_surface_iterator(struct wlr_surface *surface, int sx, int sy,
170 void *_data) { 193 void *_data) {
171 struct render_data *data = _data; 194 struct render_data *data = _data;
172 struct wlr_output *wlr_output = data->output->wlr_output; 195 struct wlr_output *wlr_output = data->output->wlr_output;
173 float rotation = data->root_geo.rotation; 196 float rotation = data->root_geo.rotation;
197 pixman_region32_t *output_damage = data->damage;
174 float alpha = data->alpha; 198 float alpha = data->alpha;
175 199
176 if (!wlr_surface_has_buffer(surface)) { 200 if (!wlr_surface_has_buffer(surface)) {
@@ -184,6 +208,18 @@ static void render_surface_iterator(struct wlr_surface *surface, int sx, int sy,
184 return; 208 return;
185 } 209 }
186 210
211 scale_box(&box, wlr_output->scale);
212
213 pixman_region32_t damage;
214 pixman_region32_init(&damage);
215 pixman_region32_union_rect(&damage, &damage, box.x, box.y,
216 box.width, box.height);
217 pixman_region32_intersect(&damage, &damage, output_damage);
218 bool damaged = pixman_region32_not_empty(&damage);
219 if (!damaged) {
220 goto damage_finish;
221 }
222
187 struct wlr_renderer *renderer = 223 struct wlr_renderer *renderer =
188 wlr_backend_get_renderer(wlr_output->backend); 224 wlr_backend_get_renderer(wlr_output->backend);
189 if (!sway_assert(renderer != NULL, 225 if (!sway_assert(renderer != NULL,
@@ -191,34 +227,53 @@ static void render_surface_iterator(struct wlr_surface *surface, int sx, int sy,
191 return; 227 return;
192 } 228 }
193 229
194 scale_box(&box, wlr_output->scale);
195
196 float matrix[9]; 230 float matrix[9];
197 enum wl_output_transform transform = 231 enum wl_output_transform transform =
198 wlr_output_transform_invert(surface->current->transform); 232 wlr_output_transform_invert(surface->current->transform);
199 wlr_matrix_project_box(matrix, &box, transform, rotation, 233 wlr_matrix_project_box(matrix, &box, transform, rotation,
200 wlr_output->transform_matrix); 234 wlr_output->transform_matrix);
201 235
202 wlr_render_texture_with_matrix(renderer, surface->texture, 236 int nrects;
203 matrix, alpha); 237 pixman_box32_t *rects = pixman_region32_rectangles(&damage, &nrects);
238 for (int i = 0; i < nrects; ++i) {
239 scissor_output(wlr_output, &rects[i]);
240 wlr_render_texture_with_matrix(renderer, surface->texture, matrix,
241 alpha);
242 }
243
244damage_finish:
245 pixman_region32_fini(&damage);
204} 246}
205 247
206static void render_layer(struct sway_output *output, 248static void render_layer(struct sway_output *output,
207 struct wl_list *layer_surfaces) { 249 pixman_region32_t *damage, struct wl_list *layer_surfaces) {
208 struct render_data data = { .output = output, .alpha = 1.0f }; 250 struct render_data data = {
251 .output = output,
252 .damage = damage,
253 .alpha = 1.0f,
254 };
209 layer_for_each_surface(layer_surfaces, &data.root_geo, 255 layer_for_each_surface(layer_surfaces, &data.root_geo,
210 render_surface_iterator, &data); 256 render_surface_iterator, &data);
211} 257}
212 258
213static void render_unmanaged(struct sway_output *output, 259static void render_unmanaged(struct sway_output *output,
214 struct wl_list *unmanaged) { 260 pixman_region32_t *damage, struct wl_list *unmanaged) {
215 struct render_data data = { .output = output, .alpha = 1.0f }; 261 struct render_data data = {
262 .output = output,
263 .damage = damage,
264 .alpha = 1.0f,
265 };
216 unmanaged_for_each_surface(unmanaged, output, &data.root_geo, 266 unmanaged_for_each_surface(unmanaged, output, &data.root_geo,
217 render_surface_iterator, &data); 267 render_surface_iterator, &data);
218} 268}
219 269
220static void render_view(struct sway_view *view, struct sway_output *output) { 270static void render_view(struct sway_view *view, struct sway_output *output,
221 struct render_data data = { .output = output, .alpha = view->swayc->alpha }; 271 pixman_region32_t *damage) {
272 struct render_data data = {
273 .output = output,
274 .damage = damage,
275 .alpha = view->swayc->alpha,
276 };
222 output_view_for_each_surface( 277 output_view_for_each_surface(
223 view, &data.root_geo, render_surface_iterator, &data); 278 view, &data.root_geo, render_surface_iterator, &data);
224} 279}
@@ -381,7 +436,7 @@ static void render_container_simple_border_pixel(struct sway_output *output,
381} 436}
382 437
383static void render_container(struct sway_output *output, 438static void render_container(struct sway_output *output,
384 struct sway_container *con); 439 pixman_region32_t *damage, struct sway_container *con);
385 440
386/** 441/**
387 * Render a container's children using a L_HORIZ or L_VERT layout. 442 * Render a container's children using a L_HORIZ or L_VERT layout.
@@ -390,7 +445,7 @@ static void render_container(struct sway_output *output,
390 * they'll apply their own borders to their children. 445 * they'll apply their own borders to their children.
391 */ 446 */
392static void render_container_simple(struct sway_output *output, 447static void render_container_simple(struct sway_output *output,
393 struct sway_container *con) { 448 pixman_region32_t *damage, struct sway_container *con) {
394 struct sway_seat *seat = input_manager_current_seat(input_manager); 449 struct sway_seat *seat = input_manager_current_seat(input_manager);
395 struct sway_container *focus = seat_get_focus(seat); 450 struct sway_container *focus = seat_get_focus(seat);
396 451
@@ -419,9 +474,9 @@ static void render_container_simple(struct sway_output *output,
419 render_container_simple_border_pixel(output, child, colors); 474 render_container_simple_border_pixel(output, child, colors);
420 } 475 }
421 } 476 }
422 render_view(child->sway_view, output); 477 render_view(child->sway_view, output, damage);
423 } else { 478 } else {
424 render_container(output, child); 479 render_container(output, damage, child);
425 } 480 }
426 } 481 }
427} 482}
@@ -430,7 +485,7 @@ static void render_container_simple(struct sway_output *output,
430 * Render a container's children using the L_TABBED layout. 485 * Render a container's children using the L_TABBED layout.
431 */ 486 */
432static void render_container_tabbed(struct sway_output *output, 487static void render_container_tabbed(struct sway_output *output,
433 struct sway_container *con) { 488 pixman_region32_t *damage, struct sway_container *con) {
434 // TODO 489 // TODO
435} 490}
436 491
@@ -438,23 +493,23 @@ static void render_container_tabbed(struct sway_output *output,
438 * Render a container's children using the L_STACKED layout. 493 * Render a container's children using the L_STACKED layout.
439 */ 494 */
440static void render_container_stacked(struct sway_output *output, 495static void render_container_stacked(struct sway_output *output,
441 struct sway_container *con) { 496 pixman_region32_t *damage, struct sway_container *con) {
442 // TODO 497 // TODO
443} 498}
444 499
445static void render_container(struct sway_output *output, 500static void render_container(struct sway_output *output,
446 struct sway_container *con) { 501 pixman_region32_t *damage, struct sway_container *con) {
447 switch (con->layout) { 502 switch (con->layout) {
448 case L_NONE: 503 case L_NONE:
449 case L_HORIZ: 504 case L_HORIZ:
450 case L_VERT: 505 case L_VERT:
451 render_container_simple(output, con); 506 render_container_simple(output, damage, con);
452 break; 507 break;
453 case L_STACKED: 508 case L_STACKED:
454 render_container_stacked(output, con); 509 render_container_stacked(output, damage, con);
455 break; 510 break;
456 case L_TABBED: 511 case L_TABBED:
457 render_container_tabbed(output, con); 512 render_container_tabbed(output, damage, con);
458 break; 513 break;
459 case L_FLOATING: 514 case L_FLOATING:
460 // TODO 515 // TODO
@@ -496,37 +551,51 @@ static void render_output(struct sway_output *output, struct timespec *when,
496 goto renderer_end; 551 goto renderer_end;
497 } 552 }
498 553
499 // TODO: don't damage the whole output 554 wlr_renderer_clear(renderer, (float[]){1, 1, 0, 0});
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 555
504 struct sway_container *workspace = output_get_active_workspace(output); 556 struct sway_container *workspace = output_get_active_workspace(output);
505 557
506 if (workspace->sway_workspace->fullscreen) { 558 if (workspace->sway_workspace->fullscreen) {
507 float clear_color[] = {0.0f, 0.0f, 0.0f, 1.0f}; 559 float clear_color[] = {0.0f, 0.0f, 0.0f, 1.0f};
508 wlr_renderer_clear(renderer, clear_color); 560
561 int nrects;
562 pixman_box32_t *rects = pixman_region32_rectangles(damage, &nrects);
563 for (int i = 0; i < nrects; ++i) {
564 scissor_output(wlr_output, &rects[i]);
565 wlr_renderer_clear(renderer, clear_color);
566 }
567
509 // TODO: handle views smaller than the output 568 // TODO: handle views smaller than the output
510 render_view(workspace->sway_workspace->fullscreen, output); 569 render_view(workspace->sway_workspace->fullscreen, output, damage);
511 570
512 if (workspace->sway_workspace->fullscreen->type == SWAY_VIEW_XWAYLAND) { 571 if (workspace->sway_workspace->fullscreen->type == SWAY_VIEW_XWAYLAND) {
513 render_unmanaged(output, 572 render_unmanaged(output, damage,
514 &root_container.sway_root->xwayland_unmanaged); 573 &root_container.sway_root->xwayland_unmanaged);
515 } 574 }
516 } else { 575 } else {
517 float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f}; 576 float clear_color[] = {0.25f, 0.25f, 0.25f, 1.0f};
518 wlr_renderer_clear(renderer, clear_color);
519 577
520 render_layer(output, 578 int nrects;
521 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]); 579 pixman_box32_t *rects = pixman_region32_rectangles(damage, &nrects);
522 render_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]); 580 for (int i = 0; i < nrects; ++i) {
581 scissor_output(wlr_output, &rects[i]);
582 wlr_renderer_clear(renderer, clear_color);
583 }
523 584
524 render_container(output, workspace); 585 render_layer(output, damage,
586 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND]);
587 render_layer(output, damage,
588 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM]);
525 589
526 render_unmanaged(output, &root_container.sway_root->xwayland_unmanaged); 590 render_container(output, damage, workspace);
527 render_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]); 591
592 render_unmanaged(output, damage,
593 &root_container.sway_root->xwayland_unmanaged);
594 render_layer(output, damage,
595 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP]);
528 } 596 }
529 render_layer(output, &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]); 597 render_layer(output, damage,
598 &output->layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY]);
530 599
531renderer_end: 600renderer_end:
532 if (root_container.sway_root->debug_tree) { 601 if (root_container.sway_root->debug_tree) {
@@ -534,6 +603,7 @@ renderer_end:
534 wlr_output->transform_matrix, 0, 0, 1); 603 wlr_output->transform_matrix, 0, 0, 1);
535 } 604 }
536 605
606 wlr_renderer_scissor(renderer, NULL);
537 wlr_renderer_end(renderer); 607 wlr_renderer_end(renderer);
538 if (!wlr_output_damage_swap_buffers(output->damage, when, damage)) { 608 if (!wlr_output_damage_swap_buffers(output->damage, when, damage)) {
539 return; 609 return;