swayfx-mosaic/tooling/probes/step20c-presentation-identity/presentation-events.patch

142 lines
6.2 KiB
Diff

diff --git a/include/sway/output.h b/include/sway/output.h
index 3d1d1ad1..34aa33e1 100644
--- a/include/sway/output.h
+++ b/include/sway/output.h
@@ -64,6 +64,8 @@ struct sway_output {
struct wl_listener layout_destroy;
struct wl_listener destroy;
struct wl_listener present;
+ // Private STEP20C trace: removed before output destruction.
+ struct wl_listener presentation_probe_commit;
struct wl_listener frame;
struct wl_listener request_state;
diff --git a/sway/desktop/output.c b/sway/desktop/output.c
index cd5eed21..fdf93421 100644
--- a/sway/desktop/output.c
+++ b/sway/desktop/output.c
@@ -37,6 +37,7 @@
#include "sway/tree/root.h"
#include "sway/tree/view.h"
#include "sway/tree/workspace.h"
+#include "sway/tree/mosaic.h"
#if WLR_HAS_DRM_BACKEND
#include <wlr/backend/drm.h>
@@ -365,6 +366,83 @@ static bool output_can_tear(struct sway_output *output) {
// INVARIANT: repaint and commit decisions are unchanged by the trace.
static uint64_t temporal_output_commit_ordinal;
+// WHY: the private headless experiment needs native output event identity.
+// CONTRACT: all scene values are read while their owning output is alive;
+// this trace never changes render, damage, clipping or commit decisions.
+// INVARIANT: event.commit sees the accepted native commit_seq, while a
+// later present event can only be paired by (output, commit_seq).
+static uint64_t presentation_probe_now_ns(void) {
+ struct timespec now;
+ clock_gettime(CLOCK_MONOTONIC, &now);
+ return (uint64_t)now.tv_sec * UINT64_C(1000000000) + now.tv_nsec;
+}
+
+static void presentation_probe_scene(struct sway_output *output) {
+ struct sway_workspace *ws = output->current.active_workspace;
+ if (!ws) {
+ sway_log(SWAY_INFO, "PI_SCENE output=%s workspace=none ns=%" PRIu64,
+ output->wlr_output->name, presentation_probe_now_ns());
+ return;
+ }
+ struct wlr_box clip = {0};
+ bool has_clip = wlr_scene_tree_get_clip(ws->layers.tiling, &clip);
+ double scroll = -1;
+ if (ws->current.layout == L_MOSAIC && ws->mosaic && ws->mosaic->rows->length) {
+ struct mosaic_row *row = ws->mosaic->rows->items[0];
+ scroll = row->state.scroll_x;
+ }
+ sway_log(SWAY_INFO, "PI_SCENE output=%s ns=%" PRIu64
+ " workspace=%zu layout=%d scroll=%.0f tile_scene=%d,%d"
+ " clip_valid=%d clip=%d,%d,%d,%d",
+ output->wlr_output->name, presentation_probe_now_ns(), ws->node.id,
+ ws->current.layout, scroll, ws->layers.tiling->node.x,
+ ws->layers.tiling->node.y, has_clip,
+ clip.x, clip.y, clip.width, clip.height);
+ if (ws->current.tiling) {
+ for (int i = 0; i < ws->current.tiling->length; i++) {
+ struct sway_container *con = ws->current.tiling->items[i];
+ int x = 0, y = 0;
+ bool coords = con->scene_tree &&
+ wlr_scene_node_coords(&con->scene_tree->node, &x, &y);
+ sway_log(SWAY_INFO, "PI_OWNER output=%s ns=%" PRIu64
+ " id=%zu current=%.0f,%.0f,%.0f,%.0f"
+ " scene_valid=%d scene=%d,%d applied_size=%d,%d",
+ output->wlr_output->name, presentation_probe_now_ns(),
+ con->node.id, con->current.x, con->current.y,
+ con->current.width, con->current.height, coords, x, y,
+ con->animation_state.current_width,
+ con->animation_state.current_height);
+ }
+ }
+ if (root->layers.popup) {
+ struct wlr_scene_node *node;
+ unsigned popup_index = 0;
+ wl_list_for_each(node, &root->layers.popup->children, link) {
+ if (!scene_descriptor_try_get(node, SWAY_SCENE_DESC_POPUP)) continue;
+ struct wlr_scene_tree *tree = wlr_scene_tree_from_node(node);
+ struct wlr_box box = {0};
+ bool valid = wlr_scene_tree_get_clip(tree, &box);
+ sway_log(SWAY_INFO, "PI_POPUP output=%s ns=%" PRIu64
+ " local_index=%u tree=%p enabled=%d clip_valid=%d clip=%d,%d,%d,%d",
+ output->wlr_output->name, presentation_probe_now_ns(),
+ ++popup_index, (void *)tree, node->enabled, valid,
+ box.x, box.y, box.width, box.height);
+ }
+ }
+}
+
+static void presentation_probe_handle_commit(struct wl_listener *listener, void *data) {
+ struct sway_output *output = wl_container_of(listener, output, presentation_probe_commit);
+ const struct wlr_output_event_commit *event = data;
+ sway_log(SWAY_INFO, "PI_OUTPUT_COMMIT output=%s commit_seq=%" PRIu32
+ " ns=%" PRIu64 " event_ns=%" PRIu64 " has_buffer=%d",
+ output->wlr_output->name, output->wlr_output->commit_seq,
+ presentation_probe_now_ns(),
+ (uint64_t)event->when.tv_sec * UINT64_C(1000000000) + event->when.tv_nsec,
+ !!(event->state->committed & WLR_OUTPUT_STATE_BUFFER));
+ presentation_probe_scene(output);
+}
+
static int output_repaint_timer_handler(void *data) {
struct sway_output *output = data;
@@ -540,6 +618,7 @@ static void begin_destroy(struct sway_output *output) {
wl_list_remove(&output->layout_destroy.link);
wl_list_remove(&output->destroy.link);
wl_list_remove(&output->present.link);
+ wl_list_remove(&output->presentation_probe_commit.link);
wl_list_remove(&output->frame.link);
wl_list_remove(&output->request_state.link);
@@ -576,6 +655,15 @@ static void handle_layout_destroy(struct wl_listener *listener, void *data) {
static void handle_present(struct wl_listener *listener, void *data) {
struct sway_output *output = wl_container_of(listener, output, present);
struct wlr_output_event_present *output_event = data;
+ sway_log(SWAY_INFO, "PI_OUTPUT_PRESENT output=%s commit_seq=%" PRIu32
+ " ns=%" PRIu64 " event_ns=%" PRIu64
+ " presented=%d seq=%u refresh=%d flags=%" PRIu32,
+ output->wlr_output->name, output_event->commit_seq,
+ presentation_probe_now_ns(),
+ (uint64_t)output_event->when.tv_sec * UINT64_C(1000000000) +
+ output_event->when.tv_nsec,
+ output_event->presented, output_event->seq,
+ output_event->refresh, output_event->flags);
if (!output->enabled || !output_event->presented) {
return;
@@ -690,6 +778,8 @@ void handle_new_output(struct wl_listener *listener, void *data) {
output->layout_destroy.notify = handle_layout_destroy;
wl_signal_add(&wlr_output->events.destroy, &output->destroy);
output->destroy.notify = handle_destroy;
+ wl_signal_add(&wlr_output->events.commit, &output->presentation_probe_commit);
+ output->presentation_probe_commit.notify = presentation_probe_handle_commit;
wl_signal_add(&wlr_output->events.present, &output->present);
output->present.notify = handle_present;
wl_signal_add(&wlr_output->events.frame, &output->frame);