Standardise debug variables
This makes all debug options stored in a single struct rather than in various places, changes/fixes the behaviour of existing options, and introduces some new options. * Fixes damage issues with `-Drender-tree` texture (by removing scissor) * Offsets the render tree overlay's `y` position for those who have swaybar at the top * Replaces `-Ddamage=rerender` with `-Dnodamage` * Replaces `-Ddamage=highlight` with `-Dhighlight-damage` * Replaces `-Dtxn-debug` with `-Dtxn-wait` * Introduces `-Dnoatomic` * Removes the `create_time` and `ms_arranging` figures from transactions and the log message. Transactions are created after arranging and the create time is of no significance. * Fixes `-Dtxn-debug` (now `-Dtxn-wait`) not working.
This commit is contained in:
parent
389d159c81
commit
8d1dd03823
|
@ -1,15 +1,18 @@
|
|||
#ifndef SWAY_DEBUG_H
|
||||
#define SWAY_DEBUG_H
|
||||
#include <stdbool.h>
|
||||
|
||||
struct sway_debug {
|
||||
bool highlight_damage; // Highlight regions of the screen being damaged
|
||||
bool noatomic; // Ignore atomic layout updates
|
||||
bool nodamage; // Render the full output on each frame
|
||||
bool render_tree; // Render the tree overlay
|
||||
bool txn_timings; // Log verbose messages about transactions
|
||||
bool txn_wait; // Always wait for the timeout before applying
|
||||
};
|
||||
|
||||
extern struct sway_debug debug;
|
||||
|
||||
// Tree
|
||||
extern bool enable_debug_tree;
|
||||
void update_debug_tree();
|
||||
|
||||
// Damage
|
||||
extern const char *damage_debug;
|
||||
|
||||
// Transactions
|
||||
extern int txn_timeout_ms;
|
||||
extern bool txn_debug;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -54,8 +54,7 @@ struct sway_server {
|
|||
struct wl_listener server_decoration;
|
||||
struct wl_list decorations; // sway_server_decoration::link
|
||||
|
||||
bool debug_txn_timings;
|
||||
|
||||
size_t txn_timeout_ms;
|
||||
list_t *transactions;
|
||||
list_t *dirty_containers;
|
||||
};
|
||||
|
|
|
@ -3,8 +3,10 @@
|
|||
#include <wlr/render/wlr_texture.h>
|
||||
#include <wlr/util/log.h>
|
||||
#include "config.h"
|
||||
#include "sway/debug.h"
|
||||
#include "sway/input/input-manager.h"
|
||||
#include "sway/input/seat.h"
|
||||
#include "sway/output.h"
|
||||
#include "sway/server.h"
|
||||
#include "sway/tree/container.h"
|
||||
#include "sway/tree/layout.h"
|
||||
|
@ -12,6 +14,8 @@
|
|||
#include "config.h"
|
||||
#include "pango.h"
|
||||
|
||||
struct sway_debug debug;
|
||||
|
||||
static const char *layout_to_str(enum sway_container_layout layout) {
|
||||
switch (layout) {
|
||||
case L_HORIZ:
|
||||
|
@ -69,10 +73,8 @@ static int draw_container(cairo_t *cairo, struct sway_container *container,
|
|||
return height;
|
||||
}
|
||||
|
||||
bool enable_debug_tree = false;
|
||||
|
||||
void update_debug_tree() {
|
||||
if (!enable_debug_tree) {
|
||||
if (!debug.render_tree) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -816,8 +816,6 @@ static void render_floating(struct sway_output *soutput,
|
|||
}
|
||||
}
|
||||
|
||||
const char *damage_debug = NULL;
|
||||
|
||||
void output_render(struct sway_output *output, struct timespec *when,
|
||||
pixman_region32_t *damage) {
|
||||
struct wlr_output *wlr_output = output->wlr_output;
|
||||
|
@ -831,21 +829,17 @@ void output_render(struct sway_output *output, struct timespec *when,
|
|||
|
||||
wlr_renderer_begin(renderer, wlr_output->width, wlr_output->height);
|
||||
|
||||
bool damage_whole_before_swap = false;
|
||||
if (!pixman_region32_not_empty(damage)) {
|
||||
// Output isn't damaged but needs buffer swap
|
||||
goto renderer_end;
|
||||
}
|
||||
|
||||
if (damage_debug != NULL) {
|
||||
if (strcmp(damage_debug, "highlight") == 0) {
|
||||
wlr_renderer_clear(renderer, (float[]){1, 1, 0, 1});
|
||||
damage_whole_before_swap = true;
|
||||
} else if (strcmp(damage_debug, "rerender") == 0) {
|
||||
int width, height;
|
||||
wlr_output_transformed_resolution(wlr_output, &width, &height);
|
||||
pixman_region32_union_rect(damage, damage, 0, 0, width, height);
|
||||
}
|
||||
if (debug.highlight_damage) {
|
||||
wlr_renderer_clear(renderer, (float[]){1, 1, 0, 1});
|
||||
} else if (debug.nodamage) {
|
||||
int width, height;
|
||||
wlr_output_transformed_resolution(wlr_output, &width, &height);
|
||||
pixman_region32_union_rect(damage, damage, 0, 0, width, height);
|
||||
}
|
||||
|
||||
struct sway_container *workspace = output_get_active_workspace(output);
|
||||
|
@ -919,12 +913,12 @@ render_overlay:
|
|||
render_drag_icons(output, damage, &root_container.sway_root->drag_icons);
|
||||
|
||||
renderer_end:
|
||||
if (root_container.sway_root->debug_tree) {
|
||||
if (debug.render_tree) {
|
||||
wlr_renderer_scissor(renderer, NULL);
|
||||
wlr_render_texture(renderer, root_container.sway_root->debug_tree,
|
||||
wlr_output->transform_matrix, 0, 0, 1);
|
||||
wlr_output->transform_matrix, 0, 40, 1);
|
||||
}
|
||||
|
||||
if (damage_whole_before_swap || root_container.sway_root->debug_tree) {
|
||||
if (debug.highlight_damage) {
|
||||
int width, height;
|
||||
wlr_output_transformed_resolution(wlr_output, &width, &height);
|
||||
pixman_region32_union_rect(damage, damage, 0, 0, width, height);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#define _POSIX_C_SOURCE 200809L
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
@ -16,26 +17,12 @@
|
|||
#include "list.h"
|
||||
#include "log.h"
|
||||
|
||||
/**
|
||||
* How long we should wait for views to respond to the configure before giving
|
||||
* up and applying the transaction anyway.
|
||||
*/
|
||||
int txn_timeout_ms = 200;
|
||||
|
||||
/**
|
||||
* If enabled, sway will always wait for the transaction timeout before
|
||||
* applying it, rather than applying it when the views are ready. This allows us
|
||||
* to observe the rendered state while a transaction is in progress.
|
||||
*/
|
||||
bool txn_debug = false;
|
||||
|
||||
struct sway_transaction {
|
||||
struct wl_event_source *timer;
|
||||
list_t *instructions; // struct sway_transaction_instruction *
|
||||
size_t num_waiting;
|
||||
size_t num_configures;
|
||||
uint32_t con_ids; // Bitwise XOR of view container IDs
|
||||
struct timespec create_time;
|
||||
struct timespec commit_time;
|
||||
};
|
||||
|
||||
|
@ -53,9 +40,6 @@ static struct sway_transaction *transaction_create() {
|
|||
return NULL;
|
||||
}
|
||||
transaction->instructions = create_list();
|
||||
if (server.debug_txn_timings) {
|
||||
clock_gettime(CLOCK_MONOTONIC, &transaction->create_time);
|
||||
}
|
||||
return transaction;
|
||||
}
|
||||
|
||||
|
@ -149,19 +133,14 @@ static void transaction_add_container(struct sway_transaction *transaction,
|
|||
*/
|
||||
static void transaction_apply(struct sway_transaction *transaction) {
|
||||
wlr_log(WLR_DEBUG, "Applying transaction %p", transaction);
|
||||
if (server.debug_txn_timings) {
|
||||
if (debug.txn_timings) {
|
||||
struct timespec now;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
struct timespec *create = &transaction->create_time;
|
||||
struct timespec *commit = &transaction->commit_time;
|
||||
float ms_arranging = (commit->tv_sec - create->tv_sec) * 1000 +
|
||||
(commit->tv_nsec - create->tv_nsec) / 1000000.0;
|
||||
float ms_waiting = (now.tv_sec - commit->tv_sec) * 1000 +
|
||||
float ms = (now.tv_sec - commit->tv_sec) * 1000 +
|
||||
(now.tv_nsec - commit->tv_nsec) / 1000000.0;
|
||||
float ms_total = ms_arranging + ms_waiting;
|
||||
wlr_log(WLR_DEBUG, "Transaction %p: %.1fms arranging, %.1fms waiting, "
|
||||
"%.1fms total (%.1f frames if 60Hz)", transaction,
|
||||
ms_arranging, ms_waiting, ms_total, ms_total / (1000.0f / 60));
|
||||
wlr_log(WLR_DEBUG, "Transaction %p: %.1fms waiting "
|
||||
"(%.1f frames if 60Hz)", transaction, ms, ms / (1000.0f / 60));
|
||||
}
|
||||
|
||||
// Apply the instruction state to the container's current state
|
||||
|
@ -310,25 +289,30 @@ static void transaction_commit(struct sway_transaction *transaction) {
|
|||
con->instruction = instruction;
|
||||
}
|
||||
transaction->num_configures = transaction->num_waiting;
|
||||
if (server.debug_txn_timings) {
|
||||
if (debug.txn_timings) {
|
||||
clock_gettime(CLOCK_MONOTONIC, &transaction->commit_time);
|
||||
}
|
||||
if (debug.noatomic) {
|
||||
transaction->num_waiting = 0;
|
||||
} else if (debug.txn_wait) {
|
||||
// Force the transaction to time out even if all views are ready.
|
||||
// We do this by inflating the waiting counter.
|
||||
transaction->num_waiting += 1000000;
|
||||
}
|
||||
|
||||
if (transaction->num_waiting) {
|
||||
// Set up a timer which the views must respond within
|
||||
transaction->timer = wl_event_loop_add_timer(server.wl_event_loop,
|
||||
handle_timeout, transaction);
|
||||
if (transaction->timer) {
|
||||
wl_event_source_timer_update(transaction->timer, txn_timeout_ms);
|
||||
wl_event_source_timer_update(transaction->timer,
|
||||
server.txn_timeout_ms);
|
||||
} else {
|
||||
wlr_log(WLR_ERROR, "Unable to create transaction timer (%s). "
|
||||
"Some imperfect frames might be rendered.",
|
||||
strerror(errno));
|
||||
handle_timeout(transaction);
|
||||
transaction->num_waiting = 0;
|
||||
}
|
||||
} else {
|
||||
wlr_log(WLR_DEBUG,
|
||||
"Transaction %p has nothing to wait for", transaction);
|
||||
}
|
||||
|
||||
// The debug tree shows the pending/live tree. Here is a good place to
|
||||
|
@ -341,7 +325,7 @@ static void set_instruction_ready(
|
|||
struct sway_transaction_instruction *instruction) {
|
||||
struct sway_transaction *transaction = instruction->transaction;
|
||||
|
||||
if (server.debug_txn_timings) {
|
||||
if (debug.txn_timings) {
|
||||
struct timespec now;
|
||||
clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
struct timespec *start = &transaction->commit_time;
|
||||
|
@ -352,15 +336,12 @@ static void set_instruction_ready(
|
|||
transaction->num_configures - transaction->num_waiting + 1,
|
||||
transaction->num_configures, ms,
|
||||
instruction->container->name);
|
||||
|
||||
}
|
||||
|
||||
// If the transaction has timed out then its num_waiting will be 0 already.
|
||||
if (transaction->num_waiting > 0 && --transaction->num_waiting == 0) {
|
||||
if (!txn_debug) {
|
||||
wlr_log(WLR_DEBUG, "Transaction %p is ready", transaction);
|
||||
wl_event_source_timer_update(transaction->timer, 0);
|
||||
}
|
||||
wlr_log(WLR_DEBUG, "Transaction %p is ready", transaction);
|
||||
wl_event_source_timer_update(transaction->timer, 0);
|
||||
}
|
||||
|
||||
instruction->container->instruction = NULL;
|
||||
|
|
20
sway/main.c
20
sway/main.c
|
@ -235,14 +235,20 @@ static void drop_permissions(bool keep_caps) {
|
|||
}
|
||||
|
||||
void enable_debug_flag(const char *flag) {
|
||||
if (strcmp(flag, "render-tree") == 0) {
|
||||
enable_debug_tree = true;
|
||||
} else if (strncmp(flag, "damage=", 7) == 0) {
|
||||
damage_debug = &flag[7];
|
||||
} else if (strcmp(flag, "txn-debug") == 0) {
|
||||
txn_debug = true;
|
||||
if (strcmp(flag, "highlight-damage") == 0) {
|
||||
debug.highlight_damage = true;
|
||||
} else if (strcmp(flag, "noatomic") == 0) {
|
||||
debug.noatomic = true;
|
||||
} else if (strcmp(flag, "nodamage") == 0) {
|
||||
debug.nodamage = true;
|
||||
} else if (strcmp(flag, "render-tree") == 0) {
|
||||
debug.render_tree = true;
|
||||
} else if (strcmp(flag, "txn-wait") == 0) {
|
||||
debug.txn_wait = true;
|
||||
} else if (strcmp(flag, "txn-timings") == 0) {
|
||||
debug.txn_timings = true;
|
||||
} else if (strncmp(flag, "txn-timeout=", 12) == 0) {
|
||||
txn_timeout_ms = atoi(&flag[12]);
|
||||
server.txn_timeout_ms = atoi(&flag[12]);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -128,10 +128,11 @@ bool server_init(struct sway_server *server) {
|
|||
return false;
|
||||
}
|
||||
|
||||
const char *debug = getenv("SWAY_DEBUG");
|
||||
if (debug != NULL && strcmp(debug, "txn_timings") == 0) {
|
||||
server->debug_txn_timings = true;
|
||||
// This may have been set already via -Dtxn-timeout
|
||||
if (!server->txn_timeout_ms) {
|
||||
server->txn_timeout_ms = 200;
|
||||
}
|
||||
|
||||
server->dirty_containers = create_list();
|
||||
server->transactions = create_list();
|
||||
|
||||
|
|
Loading…
Reference in a new issue