diff options
author | 2023-12-04 06:33:57 -0500 | |
---|---|---|
committer | 2024-01-18 18:36:54 +0300 | |
commit | 9c17cba0b29979ae23c4521b884f7419fd558770 (patch) | |
tree | db563b9ebcc9eda7afed3e5cd263fb13f531caac | |
parent | scene_graph: Introduce sway_scene_descriptor (diff) | |
download | sway-9c17cba0b29979ae23c4521b884f7419fd558770.tar.gz sway-9c17cba0b29979ae23c4521b884f7419fd558770.tar.zst sway-9c17cba0b29979ae23c4521b884f7419fd558770.zip |
renderer: Render scene_graph
-rw-r--r-- | include/sway/output.h | 3 | ||||
-rw-r--r-- | include/sway/scene_descriptor.h | 1 | ||||
-rw-r--r-- | include/sway/server.h | 2 | ||||
-rw-r--r-- | include/sway/surface.h | 14 | ||||
-rw-r--r-- | sway/desktop/output.c | 420 | ||||
-rw-r--r-- | sway/desktop/surface.c | 43 | ||||
-rw-r--r-- | sway/server.c | 3 |
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 | ||
13 | enum sway_scene_descriptor_type { | 13 | enum sway_scene_descriptor_type { |
14 | SWAY_SCENE_DESC_BUFFER_TIMER, | ||
14 | }; | 15 | }; |
15 | 16 | ||
16 | bool scene_descriptor_assign(struct wlr_scene_node *node, | 17 | bool 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 | ||
171 | void restore_nofile_limit(void); | 170 | void restore_nofile_limit(void); |
172 | 171 | ||
173 | void handle_compositor_new_surface(struct wl_listener *listener, void *data); | ||
174 | void handle_new_output(struct wl_listener *listener, void *data); | 172 | void handle_new_output(struct wl_listener *listener, void *data); |
175 | 173 | ||
176 | void handle_idle_inhibitor_v1(struct wl_listener *listener, void *data); | 174 | void 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 | ||
5 | struct 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 | |||
18 | void surface_update_outputs(struct wlr_surface *surface); | ||
19 | void surface_enter_output(struct wlr_surface *surface, | 5 | void surface_enter_output(struct wlr_surface *surface, |
20 | struct sway_output *output); | 6 | struct sway_output *output); |
21 | void surface_leave_output(struct wlr_surface *surface, | 7 | void 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 | ||
278 | static 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 | |||
289 | static 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 | |||
368 | overlay: | ||
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 | |||
376 | static int scale_length(int length, int offset, float scale) { | 278 | static 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) { | |||
424 | struct send_frame_done_data { | 326 | struct 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 | ||
429 | static void send_frame_done_iterator(struct sway_output *output, | 332 | struct 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 | 337 | static 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 | ||
450 | static void send_frame_done(struct sway_output *output, struct send_frame_done_data *data) { | 346 | static 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 | ||
454 | static 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 | ||
461 | static bool scan_out_fullscreen_view(struct sway_output *output, | 355 | static 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) { | 382 | static 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 = ¤t->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 | |||
540 | static 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 | ||
560 | static int output_repaint_timer_handler(void *data) { | 418 | static 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 | ||
683 | out: | ||
684 | wlr_output_state_finish(&pending); | ||
685 | return 0; | 457 | return 0; |
686 | } | 458 | } |
687 | 459 | ||
688 | static 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 | |||
697 | static void handle_frame(struct wl_listener *listener, void *user_data) { | 460 | static 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 | |||
760 | static 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 | ||
766 | void output_damage_whole(struct sway_output *output) { | 524 | void 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 | ||
934 | static void update_textures(struct sway_container *con, void *data) { | ||
935 | container_update_title_textures(con); | ||
936 | container_update_marks_textures(con); | ||
937 | } | ||
938 | |||
939 | static 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 | |||
945 | static void handle_commit(struct wl_listener *listener, void *data) { | 690 | static 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 | ||
10 | static void handle_destroy(struct wl_listener *listener, void *data) { | 9 | static 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 | |||
23 | static 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 | |||
33 | void 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 | |||
50 | void 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 | ||