mirror of
				https://github.com/swaywm/sway.git
				synced 2025-11-03 09:01:43 -05:00 
			
		
		
		
	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
					
				
					 7 changed files with 64 additions and 78 deletions
				
			
		| 
						 | 
				
			
			@ -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,22 +829,18 @@ 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) {
 | 
			
		||||
	if (debug.highlight_damage) {
 | 
			
		||||
		wlr_renderer_clear(renderer, (float[]){1, 1, 0, 1});
 | 
			
		||||
			damage_whole_before_swap = true;
 | 
			
		||||
		} else if (strcmp(damage_debug, "rerender") == 0) {
 | 
			
		||||
	} 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);
 | 
			
		||||
	struct sway_container *fullscreen_con = workspace->current.ws_fullscreen;
 | 
			
		||||
| 
						 | 
				
			
			@ -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,16 +336,13 @@ 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);
 | 
			
		||||
	}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	instruction->container->instruction = NULL;
 | 
			
		||||
	if (!txn_debug) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										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…
	
	Add table
		Add a link
		
	
		Reference in a new issue