aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Alexander Orzechowski <alex@ozal.ski>2023-12-04 06:33:57 -0500
committerLibravatar Kirill Primak <vyivel@eclair.cafe>2024-01-18 18:36:54 +0300
commit9c17cba0b29979ae23c4521b884f7419fd558770 (patch)
treedb563b9ebcc9eda7afed3e5cd263fb13f531caac
parentscene_graph: Introduce sway_scene_descriptor (diff)
downloadsway-9c17cba0b29979ae23c4521b884f7419fd558770.tar.gz
sway-9c17cba0b29979ae23c4521b884f7419fd558770.tar.zst
sway-9c17cba0b29979ae23c4521b884f7419fd558770.zip
renderer: Render scene_graph
-rw-r--r--include/sway/output.h3
-rw-r--r--include/sway/scene_descriptor.h1
-rw-r--r--include/sway/server.h2
-rw-r--r--include/sway/surface.h14
-rw-r--r--sway/desktop/output.c420
-rw-r--r--sway/desktop/surface.c43
-rw-r--r--sway/server.c3
7 files changed, 80 insertions, 406 deletions
diff --git a/include/sway/output.h b/include/sway/output.h
index 691ac8dd..b35f1366 100644
--- a/include/sway/output.h
+++ b/include/sway/output.h
@@ -41,7 +41,6 @@ struct sway_output {
41 struct wl_list shell_layers[4]; // sway_layer_surface::link 41 struct wl_list shell_layers[4]; // sway_layer_surface::link
42 struct wlr_box usable_area; 42 struct wlr_box usable_area;
43 43
44 struct timespec last_frame;
45 struct wlr_damage_ring damage_ring; 44 struct wlr_damage_ring damage_ring;
46 45
47 int lx, ly; // layout coords 46 int lx, ly; // layout coords
@@ -58,9 +57,7 @@ struct sway_output {
58 struct wl_listener destroy; 57 struct wl_listener destroy;
59 struct wl_listener commit; 58 struct wl_listener commit;
60 struct wl_listener present; 59 struct wl_listener present;
61 struct wl_listener damage;
62 struct wl_listener frame; 60 struct wl_listener frame;
63 struct wl_listener needs_frame;
64 struct wl_listener request_state; 61 struct wl_listener request_state;
65 62
66 struct { 63 struct {
diff --git a/include/sway/scene_descriptor.h b/include/sway/scene_descriptor.h
index 13ae81a3..9761c2c0 100644
--- a/include/sway/scene_descriptor.h
+++ b/include/sway/scene_descriptor.h
@@ -11,6 +11,7 @@
11#include <wlr/types/wlr_scene.h> 11#include <wlr/types/wlr_scene.h>
12 12
13enum sway_scene_descriptor_type { 13enum sway_scene_descriptor_type {
14 SWAY_SCENE_DESC_BUFFER_TIMER,
14}; 15};
15 16
16bool scene_descriptor_assign(struct wlr_scene_node *node, 17bool scene_descriptor_assign(struct wlr_scene_node *node,
diff --git a/include/sway/server.h b/include/sway/server.h
index b0e8dfd6..f3d25980 100644
--- a/include/sway/server.h
+++ b/include/sway/server.h
@@ -41,7 +41,6 @@ struct sway_server {
41 struct wlr_allocator *allocator; 41 struct wlr_allocator *allocator;
42 42
43 struct wlr_compositor *compositor; 43 struct wlr_compositor *compositor;
44 struct wl_listener compositor_new_surface;
45 44
46 struct wlr_linux_dmabuf_v1 *linux_dmabuf_v1; 45 struct wlr_linux_dmabuf_v1 *linux_dmabuf_v1;
47 46
@@ -170,7 +169,6 @@ void server_run(struct sway_server *server);
170 169
171void restore_nofile_limit(void); 170void restore_nofile_limit(void);
172 171
173void handle_compositor_new_surface(struct wl_listener *listener, void *data);
174void handle_new_output(struct wl_listener *listener, void *data); 172void handle_new_output(struct wl_listener *listener, void *data);
175 173
176void handle_idle_inhibitor_v1(struct wl_listener *listener, void *data); 174void handle_idle_inhibitor_v1(struct wl_listener *listener, void *data);
diff --git a/include/sway/surface.h b/include/sway/surface.h
index a7a8ec3f..81eb80d5 100644
--- a/include/sway/surface.h
+++ b/include/sway/surface.h
@@ -2,20 +2,6 @@
2#define _SWAY_SURFACE_H 2#define _SWAY_SURFACE_H
3#include <wlr/types/wlr_compositor.h> 3#include <wlr/types/wlr_compositor.h>
4 4
5struct sway_surface {
6 struct wlr_surface *wlr_surface;
7
8 struct wl_listener destroy;
9
10 /**
11 * This timer can be used for issuing delayed frame done callbacks (for
12 * example, to improve presentation latency). Its handler is set to a
13 * function that issues a frame done callback to this surface.
14 */
15 struct wl_event_source *frame_done_timer;
16};
17
18void surface_update_outputs(struct wlr_surface *surface);
19void surface_enter_output(struct wlr_surface *surface, 5void surface_enter_output(struct wlr_surface *surface,
20 struct sway_output *output); 6 struct sway_output *output);
21void surface_leave_output(struct wlr_surface *surface, 7void surface_leave_output(struct wlr_surface *surface,
diff --git a/sway/desktop/output.c b/sway/desktop/output.c
index 288ccc7c..11de25fb 100644
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -26,8 +26,8 @@
26#include "sway/ipc-server.h" 26#include "sway/ipc-server.h"
27#include "sway/layers.h" 27#include "sway/layers.h"
28#include "sway/output.h" 28#include "sway/output.h"
29#include "sway/scene_descriptor.h"
29#include "sway/server.h" 30#include "sway/server.h"
30#include "sway/surface.h"
31#include "sway/tree/arrange.h" 31#include "sway/tree/arrange.h"
32#include "sway/tree/container.h" 32#include "sway/tree/container.h"
33#include "sway/tree/root.h" 33#include "sway/tree/root.h"
@@ -275,104 +275,6 @@ void output_drag_icons_for_each_surface(struct sway_output *output,
275 } 275 }
276} 276}
277 277
278static void for_each_surface_container_iterator(struct sway_container *con,
279 void *_data) {
280 if (!con->view || !view_is_visible(con->view)) {
281 return;
282 }
283
284 struct surface_iterator_data *data = _data;
285 output_view_for_each_surface(data->output, con->view,
286 data->user_iterator, data->user_data);
287}
288
289static void output_for_each_surface(struct sway_output *output,
290 sway_surface_iterator_func_t iterator, void *user_data) {
291 if (server.session_lock.locked) {
292 if (server.session_lock.lock == NULL) {
293 return;
294 }
295 struct wlr_session_lock_surface_v1 *lock_surface;
296 wl_list_for_each(lock_surface, &server.session_lock.lock->surfaces, link) {
297 if (lock_surface->output != output->wlr_output) {
298 continue;
299 }
300 if (!lock_surface->surface->mapped) {
301 continue;
302 }
303
304 output_surface_for_each_surface(output, lock_surface->surface,
305 0.0, 0.0, iterator, user_data);
306 }
307 return;
308 }
309
310 if (output_has_opaque_overlay_layer_surface(output)) {
311 goto overlay;
312 }
313
314 struct surface_iterator_data data = {
315 .user_iterator = iterator,
316 .user_data = user_data,
317 .output = output,
318 .view = NULL,
319 };
320
321 struct sway_workspace *workspace = output_get_active_workspace(output);
322 struct sway_container *fullscreen_con = root->fullscreen_global;
323 if (!fullscreen_con) {
324 if (!workspace) {
325 return;
326 }
327 fullscreen_con = workspace->current.fullscreen;
328 }
329 if (fullscreen_con) {
330 for_each_surface_container_iterator(fullscreen_con, &data);
331 container_for_each_child(fullscreen_con,
332 for_each_surface_container_iterator, &data);
333
334 // TODO: Show transient containers for fullscreen global
335 if (fullscreen_con == workspace->current.fullscreen) {
336 for (int i = 0; i < workspace->current.floating->length; ++i) {
337 struct sway_container *floater =
338 workspace->current.floating->items[i];
339 if (container_is_transient_for(floater, fullscreen_con)) {
340 for_each_surface_container_iterator(floater, &data);
341 }
342 }
343 }
344#if HAVE_XWAYLAND
345 output_unmanaged_for_each_surface(output, &root->xwayland_unmanaged,
346 iterator, user_data);
347#endif
348 } else {
349 output_layer_for_each_surface(output,
350 &output->shell_layers[ZWLR_LAYER_SHELL_V1_LAYER_BACKGROUND],
351 iterator, user_data);
352 output_layer_for_each_surface(output,
353 &output->shell_layers[ZWLR_LAYER_SHELL_V1_LAYER_BOTTOM],
354 iterator, user_data);
355
356 workspace_for_each_container(workspace,
357 for_each_surface_container_iterator, &data);
358
359#if HAVE_XWAYLAND
360 output_unmanaged_for_each_surface(output, &root->xwayland_unmanaged,
361 iterator, user_data);
362#endif
363 output_layer_for_each_surface(output,
364 &output->shell_layers[ZWLR_LAYER_SHELL_V1_LAYER_TOP],
365 iterator, user_data);
366 }
367
368overlay:
369 output_layer_for_each_surface(output,
370 &output->shell_layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY],
371 iterator, user_data);
372 output_drag_icons_for_each_surface(output, &root->drag_icons,
373 iterator, user_data);
374}
375
376static int scale_length(int length, int offset, float scale) { 278static int scale_length(int length, int offset, float scale) {
377 return roundf((offset + length) * scale) - roundf(offset * scale); 279 return roundf((offset + length) * scale) - roundf(offset * scale);
378} 280}
@@ -424,276 +326,137 @@ bool output_has_opaque_overlay_layer_surface(struct sway_output *output) {
424struct send_frame_done_data { 326struct send_frame_done_data {
425 struct timespec when; 327 struct timespec when;
426 int msec_until_refresh; 328 int msec_until_refresh;
329 struct sway_output *output;
427}; 330};
428 331
429static void send_frame_done_iterator(struct sway_output *output, 332struct buffer_timer {
430 struct sway_view *view, struct wlr_surface *surface, 333 struct wl_listener destroy;
431 struct wlr_box *box, void *user_data) { 334 struct wl_event_source *frame_done_timer;
432 int view_max_render_time = 0; 335};
433 if (view != NULL) {
434 view_max_render_time = view->max_render_time;
435 }
436
437 struct send_frame_done_data *data = user_data;
438 336
439 int delay = data->msec_until_refresh - output->max_render_time 337static int handle_buffer_timer(void *data) {
440 - view_max_render_time; 338 struct wlr_scene_buffer *buffer = data;
441 339
442 if (output->max_render_time == 0 || view_max_render_time == 0 || delay < 1) { 340 struct timespec now;
443 wlr_surface_send_frame_done(surface, &data->when); 341 clock_gettime(CLOCK_MONOTONIC, &now);
444 } else { 342 wlr_scene_buffer_send_frame_done(buffer, &now);
445 struct sway_surface *sway_surface = surface->data; 343 return 0;
446 wl_event_source_timer_update(sway_surface->frame_done_timer, delay);
447 }
448} 344}
449 345
450static void send_frame_done(struct sway_output *output, struct send_frame_done_data *data) { 346static void handle_buffer_timer_destroy(struct wl_listener *listener,
451 output_for_each_surface(output, send_frame_done_iterator, data); 347 void *data) {
452} 348 struct buffer_timer *timer = wl_container_of(listener, timer, destroy);
453 349
454static void count_surface_iterator(struct sway_output *output, 350 wl_list_remove(&timer->destroy.link);
455 struct sway_view *view, struct wlr_surface *surface, 351 wl_event_source_remove(timer->frame_done_timer);
456 struct wlr_box *box, void *data) { 352 free(timer);
457 size_t *n = data;
458 (*n)++;
459} 353}
460 354
461static bool scan_out_fullscreen_view(struct sway_output *output, 355static struct buffer_timer *buffer_timer_get_or_create(struct wlr_scene_buffer *buffer) {
462 struct wlr_output_state *pending, struct sway_view *view) { 356 struct buffer_timer *timer =
463 struct wlr_output *wlr_output = output->wlr_output; 357 scene_descriptor_try_get(&buffer->node, SWAY_SCENE_DESC_BUFFER_TIMER);
464 struct sway_workspace *workspace = output->current.active_workspace; 358 if (timer) {
465 if (!sway_assert(workspace, "Expected an active workspace")) { 359 return timer;
466 return false;
467 }
468
469 if (server.session_lock.locked) {
470 return false;
471 } 360 }
472 361
473 if (!wl_list_empty(&view->saved_buffers)) { 362 timer = calloc(1, sizeof(struct buffer_timer));
474 return false; 363 if (!timer) {
364 return NULL;
475 } 365 }
476 366
477 for (int i = 0; i < workspace->current.floating->length; ++i) { 367 timer->frame_done_timer = wl_event_loop_add_timer(server.wl_event_loop,
478 struct sway_container *floater = 368 handle_buffer_timer, buffer);
479 workspace->current.floating->items[i]; 369 if (!timer->frame_done_timer) {
480 if (container_is_transient_for(floater, view->container)) { 370 free(timer);
481 return false; 371 return NULL;
482 }
483 } 372 }
484 373
485#if HAVE_XWAYLAND 374 scene_descriptor_assign(&buffer->node, SWAY_SCENE_DESC_BUFFER_TIMER, timer);
486 if (!wl_list_empty(&root->xwayland_unmanaged)) {
487 return false;
488 }
489#endif
490 375
491 if (!wl_list_empty(&output->shell_layers[ZWLR_LAYER_SHELL_V1_LAYER_OVERLAY])) { 376 timer->destroy.notify = handle_buffer_timer_destroy;
492 return false; 377 wl_signal_add(&buffer->node.events.destroy, &timer->destroy);
493 }
494 if (!wl_list_empty(&root->drag_icons)) {
495 return false;
496 }
497 378
498 struct wlr_surface *surface = view->surface; 379 return timer;
499 if (surface == NULL) { 380}
500 return false;
501 }
502 size_t n_surfaces = 0;
503 output_view_for_each_surface(output, view,
504 count_surface_iterator, &n_surfaces);
505 if (n_surfaces != 1) {
506 return false;
507 }
508 size_t n_popups = 0;
509 output_view_for_each_popup_surface(output, view,
510 count_surface_iterator, &n_popups);
511 if (n_popups > 0) {
512 return false;
513 }
514 381
515 if (surface->buffer == NULL) { 382static void send_frame_done_iterator(struct wlr_scene_buffer *buffer,
516 return false; 383 int x, int y, void *user_data) {
517 } 384 struct send_frame_done_data *data = user_data;
385 struct sway_output *output = data->output;
386 int view_max_render_time = 0;
518 387
519 if ((float)surface->current.scale != wlr_output->scale || 388 if (buffer->primary_output != data->output->scene_output) {
520 surface->current.transform != wlr_output->transform) { 389 return;
521 return false;
522 } 390 }
523 391
524 if (!wlr_output_is_direct_scanout_allowed(wlr_output)) { 392 struct wlr_scene_node *current = &buffer->node;
525 return false;
526 }
527 393
528 wlr_output_state_set_buffer(pending, &surface->buffer->base); 394 while (true) {
395 if (!current->parent) {
396 break;
397 }
529 398
530 if (!wlr_output_test_state(wlr_output, pending)) { 399 current = &current->parent->node;
531 return false;
532 } 400 }
533 401
534 wlr_presentation_surface_scanned_out_on_output(surface, 402 int delay = data->msec_until_refresh - output->max_render_time
535 wlr_output); 403 - view_max_render_time;
536
537 return wlr_output_commit_state(wlr_output, pending);
538}
539
540static void get_frame_damage(struct sway_output *output,
541 pixman_region32_t *frame_damage) {
542 struct wlr_output *wlr_output = output->wlr_output;
543
544 int width, height;
545 wlr_output_transformed_resolution(wlr_output, &width, &height);
546 404
547 pixman_region32_init(frame_damage); 405 struct buffer_timer *timer = NULL;
548 406
549 enum wl_output_transform transform = 407 if (output->max_render_time != 0 && view_max_render_time != 0 && delay > 0) {
550 wlr_output_transform_invert(wlr_output->transform); 408 timer = buffer_timer_get_or_create(buffer);
551 wlr_region_transform(frame_damage, &output->damage_ring.current, 409 }
552 transform, width, height);
553 410
554 if (debug.damage != DAMAGE_DEFAULT) { 411 if (timer) {
555 pixman_region32_union_rect(frame_damage, frame_damage, 412 wl_event_source_timer_update(timer->frame_done_timer, delay);
556 0, 0, wlr_output->width, wlr_output->height); 413 } else {
414 wlr_scene_buffer_send_frame_done(buffer, &data->when);
557 } 415 }
558} 416}
559 417
560static int output_repaint_timer_handler(void *data) { 418static int output_repaint_timer_handler(void *data) {
561 struct sway_output *output = data; 419 struct sway_output *output = data;
562 struct wlr_output *wlr_output = output->wlr_output;
563 if (wlr_output == NULL) {
564 return 0;
565 }
566 420
567 wlr_output->frame_pending = false; 421 if (!output->enabled) {
568
569 if (!wlr_output->needs_frame &&
570 !output->gamma_lut_changed &&
571 !pixman_region32_not_empty(&output->damage_ring.current)) {
572 return 0;
573 }
574
575 struct sway_workspace *workspace = output->current.active_workspace;
576 if (workspace == NULL) {
577 return 0; 422 return 0;
578 } 423 }
579 424
580 struct sway_container *fullscreen_con = root->fullscreen_global; 425 output->wlr_output->frame_pending = false;
581 if (!fullscreen_con) {
582 fullscreen_con = workspace->current.fullscreen;
583 }
584
585 struct wlr_output_state pending = {0};
586 426
587 if (output->gamma_lut_changed) { 427 if (output->gamma_lut_changed) {
428 struct wlr_output_state pending;
429 wlr_output_state_init(&pending);
430 if (!wlr_scene_output_build_state(output->scene_output, &pending, NULL)) {
431 return 0;
432 }
433
588 output->gamma_lut_changed = false; 434 output->gamma_lut_changed = false;
589 struct wlr_gamma_control_v1 *gamma_control = 435 struct wlr_gamma_control_v1 *gamma_control =
590 wlr_gamma_control_manager_v1_get_control( 436 wlr_gamma_control_manager_v1_get_control(
591 server.gamma_control_manager_v1, wlr_output); 437 server.gamma_control_manager_v1, output->wlr_output);
592 if (!wlr_gamma_control_v1_apply(gamma_control, &pending)) { 438 if (!wlr_gamma_control_v1_apply(gamma_control, &pending)) {
593 goto out;
594 }
595 if (!wlr_output_test_state(wlr_output, &pending)) {
596 wlr_output_state_finish(&pending); 439 wlr_output_state_finish(&pending);
597 pending = (struct wlr_output_state){0}; 440 return 0;
598 wlr_gamma_control_v1_send_failed_and_destroy(gamma_control);
599 }
600 }
601
602 pending.committed |= WLR_OUTPUT_STATE_DAMAGE;
603 get_frame_damage(output, &pending.damage);
604
605 if (fullscreen_con && fullscreen_con->view && !debug.noscanout) {
606 // Try to scan-out the fullscreen view
607 static bool last_scanned_out = false;
608 bool scanned_out =
609 scan_out_fullscreen_view(output, &pending, fullscreen_con->view);
610
611 if (scanned_out && !last_scanned_out) {
612 sway_log(SWAY_DEBUG, "Scanning out fullscreen view on %s",
613 output->wlr_output->name);
614 }
615 if (last_scanned_out && !scanned_out) {
616 sway_log(SWAY_DEBUG, "Stopping fullscreen view scan out on %s",
617 output->wlr_output->name);
618 output_damage_whole(output);
619 } 441 }
620 last_scanned_out = scanned_out;
621 442
622 if (scanned_out) { 443 if (!wlr_output_commit_state(output->wlr_output, &pending)) {
623 goto out; 444 wlr_gamma_control_v1_send_failed_and_destroy(gamma_control);
445 wlr_output_state_finish(&pending);
446 return 0;
624 } 447 }
625 }
626 448
627 if (!wlr_output_configure_primary_swapchain(wlr_output, &pending, &wlr_output->swapchain)) { 449 wlr_output_state_finish(&pending);
628 goto out; 450 return 0;
629 }
630
631 int buffer_age;
632 struct wlr_buffer *buffer = wlr_swapchain_acquire(wlr_output->swapchain, &buffer_age);
633 if (buffer == NULL) {
634 goto out;
635 }
636
637 struct wlr_render_pass *render_pass = wlr_renderer_begin_buffer_pass(
638 wlr_output->renderer, buffer, NULL);
639 if (render_pass == NULL) {
640 wlr_buffer_unlock(buffer);
641 goto out;
642 }
643
644 pixman_region32_t damage;
645 pixman_region32_init(&damage);
646 wlr_damage_ring_get_buffer_damage(&output->damage_ring, buffer_age, &damage);
647
648 if (debug.damage == DAMAGE_RERENDER) {
649 int width, height;
650 wlr_output_transformed_resolution(wlr_output, &width, &height);
651 pixman_region32_union_rect(&damage, &damage, 0, 0, width, height);
652 }
653
654 struct render_context ctx = {
655 .output_damage = &damage,
656 .renderer = wlr_output->renderer,
657 .output = output,
658 .pass = render_pass,
659 };
660
661 struct timespec now;
662 clock_gettime(CLOCK_MONOTONIC, &now);
663
664 output_render(&ctx);
665
666 pixman_region32_fini(&damage);
667
668 if (!wlr_render_pass_submit(render_pass)) {
669 wlr_buffer_unlock(buffer);
670 goto out;
671 } 451 }
672 452
673 wlr_output_state_set_buffer(&pending, buffer); 453 wlr_scene_output_commit(output->scene_output, NULL);
674 wlr_buffer_unlock(buffer);
675
676 if (!wlr_output_commit_state(wlr_output, &pending)) {
677 goto out;
678 }
679 454
680 wlr_damage_ring_rotate(&output->damage_ring); 455 wlr_damage_ring_rotate(&output->damage_ring);
681 output->last_frame = now;
682 456
683out:
684 wlr_output_state_finish(&pending);
685 return 0; 457 return 0;
686} 458}
687 459
688static void handle_damage(struct wl_listener *listener, void *user_data) {
689 struct sway_output *output =
690 wl_container_of(listener, output, damage);
691 struct wlr_output_event_damage *event = user_data;
692 if (wlr_damage_ring_add(&output->damage_ring, event->damage)) {
693 wlr_output_schedule_frame(output->wlr_output);
694 }
695}
696
697static void handle_frame(struct wl_listener *listener, void *user_data) { 460static void handle_frame(struct wl_listener *listener, void *user_data) {
698 struct sway_output *output = 461 struct sway_output *output =
699 wl_container_of(listener, output, frame); 462 wl_container_of(listener, output, frame);
@@ -754,13 +517,8 @@ static void handle_frame(struct wl_listener *listener, void *user_data) {
754 struct send_frame_done_data data = {0}; 517 struct send_frame_done_data data = {0};
755 clock_gettime(CLOCK_MONOTONIC, &data.when); 518 clock_gettime(CLOCK_MONOTONIC, &data.when);
756 data.msec_until_refresh = msec_until_refresh; 519 data.msec_until_refresh = msec_until_refresh;
757 send_frame_done(output, &data); 520 data.output = output;
758} 521 wlr_scene_output_for_each_buffer(output->scene_output, send_frame_done_iterator, &data);
759
760static void handle_needs_frame(struct wl_listener *listener, void *user_data) {
761 struct sway_output *output =
762 wl_container_of(listener, output, needs_frame);
763 wlr_output_schedule_frame(output->wlr_output);
764} 522}
765 523
766void output_damage_whole(struct sway_output *output) { 524void output_damage_whole(struct sway_output *output) {
@@ -904,9 +662,7 @@ static void begin_destroy(struct sway_output *output) {
904 wl_list_remove(&output->destroy.link); 662 wl_list_remove(&output->destroy.link);
905 wl_list_remove(&output->commit.link); 663 wl_list_remove(&output->commit.link);
906 wl_list_remove(&output->present.link); 664 wl_list_remove(&output->present.link);
907 wl_list_remove(&output->damage.link);
908 wl_list_remove(&output->frame.link); 665 wl_list_remove(&output->frame.link);
909 wl_list_remove(&output->needs_frame.link);
910 wl_list_remove(&output->request_state.link); 666 wl_list_remove(&output->request_state.link);
911 667
912 wlr_damage_ring_finish(&output->damage_ring); 668 wlr_damage_ring_finish(&output->damage_ring);
@@ -931,17 +687,6 @@ static void handle_layout_destroy(struct wl_listener *listener, void *data) {
931 begin_destroy(output); 687 begin_destroy(output);
932} 688}
933 689
934static void update_textures(struct sway_container *con, void *data) {
935 container_update_title_textures(con);
936 container_update_marks_textures(con);
937}
938
939static void update_output_scale_iterator(struct sway_output *output,
940 struct sway_view *view, struct wlr_surface *surface,
941 struct wlr_box *box, void *user_data) {
942 surface_update_outputs(surface);
943}
944
945static void handle_commit(struct wl_listener *listener, void *data) { 690static void handle_commit(struct wl_listener *listener, void *data) {
946 struct sway_output *output = wl_container_of(listener, output, commit); 691 struct sway_output *output = wl_container_of(listener, output, commit);
947 struct wlr_output_event_commit *event = data; 692 struct wlr_output_event_commit *event = data;
@@ -950,11 +695,6 @@ static void handle_commit(struct wl_listener *listener, void *data) {
950 return; 695 return;
951 } 696 }
952 697
953 if (event->state->committed & WLR_OUTPUT_STATE_SCALE) {
954 output_for_each_container(output, update_textures, NULL);
955 output_for_each_surface(output, update_output_scale_iterator, NULL);
956 }
957
958 if (event->state->committed & ( 698 if (event->state->committed & (
959 WLR_OUTPUT_STATE_MODE | 699 WLR_OUTPUT_STATE_MODE |
960 WLR_OUTPUT_STATE_TRANSFORM | 700 WLR_OUTPUT_STATE_TRANSFORM |
@@ -1066,12 +806,8 @@ void handle_new_output(struct wl_listener *listener, void *data) {
1066 output->commit.notify = handle_commit; 806 output->commit.notify = handle_commit;
1067 wl_signal_add(&wlr_output->events.present, &output->present); 807 wl_signal_add(&wlr_output->events.present, &output->present);
1068 output->present.notify = handle_present; 808 output->present.notify = handle_present;
1069 wl_signal_add(&wlr_output->events.damage, &output->damage);
1070 output->damage.notify = handle_damage;
1071 wl_signal_add(&wlr_output->events.frame, &output->frame); 809 wl_signal_add(&wlr_output->events.frame, &output->frame);
1072 output->frame.notify = handle_frame; 810 output->frame.notify = handle_frame;
1073 wl_signal_add(&wlr_output->events.needs_frame, &output->needs_frame);
1074 output->needs_frame.notify = handle_needs_frame;
1075 wl_signal_add(&wlr_output->events.request_state, &output->request_state); 811 wl_signal_add(&wlr_output->events.request_state, &output->request_state);
1076 output->request_state.notify = handle_request_state; 812 output->request_state.notify = handle_request_state;
1077 813
diff --git a/sway/desktop/surface.c b/sway/desktop/surface.c
index 5932eaa2..af17a8bb 100644
--- a/sway/desktop/surface.c
+++ b/sway/desktop/surface.c
@@ -1,53 +1,12 @@
1#define _POSIX_C_SOURCE 200112L 1#define _POSIX_C_SOURCE 200112L
2#include <stdlib.h> 2#include <stdlib.h>
3#include <time.h>
4#include <wlr/types/wlr_compositor.h> 3#include <wlr/types/wlr_compositor.h>
5#include <wlr/types/wlr_fractional_scale_v1.h> 4#include <wlr/types/wlr_fractional_scale_v1.h>
6#include "sway/server.h" 5#include "sway/server.h"
7#include "sway/surface.h" 6#include "sway/surface.h"
8#include "sway/output.h" 7#include "sway/output.h"
9 8
10static void handle_destroy(struct wl_listener *listener, void *data) { 9static void surface_update_outputs(struct wlr_surface *surface) {
11 struct sway_surface *surface = wl_container_of(listener, surface, destroy);
12
13 surface->wlr_surface->data = NULL;
14 wl_list_remove(&surface->destroy.link);
15
16 if (surface->frame_done_timer) {
17 wl_event_source_remove(surface->frame_done_timer);
18 }
19
20 free(surface);
21}
22
23static int surface_frame_done_timer_handler(void *data) {
24 struct sway_surface *surface = data;
25
26 struct timespec now;
27 clock_gettime(CLOCK_MONOTONIC, &now);
28 wlr_surface_send_frame_done(surface->wlr_surface, &now);
29
30 return 0;
31}
32
33void handle_compositor_new_surface(struct wl_listener *listener, void *data) {
34 struct wlr_surface *wlr_surface = data;
35
36 struct sway_surface *surface = calloc(1, sizeof(struct sway_surface));
37 surface->wlr_surface = wlr_surface;
38 wlr_surface->data = surface;
39
40 surface->destroy.notify = handle_destroy;
41 wl_signal_add(&wlr_surface->events.destroy, &surface->destroy);
42
43 surface->frame_done_timer = wl_event_loop_add_timer(server.wl_event_loop,
44 surface_frame_done_timer_handler, surface);
45 if (!surface->frame_done_timer) {
46 wl_resource_post_no_memory(wlr_surface->resource);
47 }
48}
49
50void surface_update_outputs(struct wlr_surface *surface) {
51 float scale = 1; 10 float scale = 1;
52 struct wlr_surface_output *surface_output; 11 struct wlr_surface_output *surface_output;
53 wl_list_for_each(surface_output, &surface->current_outputs, link) { 12 wl_list_for_each(surface_output, &surface->current_outputs, link) {
diff --git a/sway/server.c b/sway/server.c
index 4bef4588..33b25000 100644
--- a/sway/server.c
+++ b/sway/server.c
@@ -201,9 +201,6 @@ bool server_init(struct sway_server *server) {
201 201
202 server->compositor = wlr_compositor_create(server->wl_display, 6, 202 server->compositor = wlr_compositor_create(server->wl_display, 6,
203 server->renderer); 203 server->renderer);
204 server->compositor_new_surface.notify = handle_compositor_new_surface;
205 wl_signal_add(&server->compositor->events.new_surface,
206 &server->compositor_new_surface);
207 204
208 wlr_subcompositor_create(server->wl_display); 205 wlr_subcompositor_create(server->wl_display);
209 206