diff options
-rw-r--r-- | sway/desktop/output.c | 142 |
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) { | |||
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 | |||
169 | static void render_surface_iterator(struct wlr_surface *surface, int sx, int sy, | 192 | static 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 | |||
244 | damage_finish: | ||
245 | pixman_region32_fini(&damage); | ||
204 | } | 246 | } |
205 | 247 | ||
206 | static void render_layer(struct sway_output *output, | 248 | static 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 | ||
213 | static void render_unmanaged(struct sway_output *output, | 259 | static 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 | ||
220 | static void render_view(struct sway_view *view, struct sway_output *output) { | 270 | static 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 | ||
383 | static void render_container(struct sway_output *output, | 438 | static 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 | */ |
392 | static void render_container_simple(struct sway_output *output, | 447 | static 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 | */ |
432 | static void render_container_tabbed(struct sway_output *output, | 487 | static 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 | */ |
440 | static void render_container_stacked(struct sway_output *output, | 495 | static 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 | ||
445 | static void render_container(struct sway_output *output, | 500 | static 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 | ||
531 | renderer_end: | 600 | renderer_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; |