Add --renderer for displays with no usable GPU; gate the header reading
GTK4 defaults to Vulkan, and an X11-forwarded display has no device to make a swapchain from; the plot is a GtkGLArea, so it then asks for a GL context that is not there either. --renderer cairo is the software preset for that display: it exports GSK_RENDERER=cairo and LIBGL_ALWAYS_SOFTWARE=1 in main() before gtk_init()/adw_init(), because both are read when the renderer and the context are created. --renderer gl is the faster choice when indirect GL works, and --renderer vulkan makes the default explicit. Nothing is exported, and GTK's own choice stands, when the option is absent. The once-a-second header line is now behind UDPSCOPE_PROBE_HEADER, following the [notrace] rule: its widths are still sampled for the exit dump, but the line is detail behind that reading rather than output every run prints. UDPSCOPE_PROBE_RENDERER prints the exported pair before GTK starts and the GskRenderer GTK actually built. README, the manual's overview and docs/claude record the two symptoms and the cure.
This commit is contained in:
1 parent
ac054a30c9
commit
fcf268d249
9 files changed
+151
-7
No files matched your search
+26
-3
@@ -3465,6 +3465,22 @@ gboolean tick(gpointer user) {
|
||||
ScopeModel& model = *app->model;
|
||||
const gint64 tick_start_us = g_get_monotonic_time();
|
||||
|
||||
// The renderer GTK actually built, printed once and only under the probe: `--renderer` exports
|
||||
// `GSK_RENDERER` before any GTK call, and this is the other half of that claim -- the class GTK
|
||||
// chose, not the name it was asked for. The renderer is null until the window is realized, so a
|
||||
// tick that finds none simply tries again.
|
||||
{
|
||||
static const bool renderer_probe = g_getenv("UDPSCOPE_PROBE_RENDERER") != nullptr;
|
||||
static bool renderer_printed = false;
|
||||
if (renderer_probe && !renderer_printed) {
|
||||
if (GskRenderer* r = gtk_native_get_renderer(GTK_NATIVE(app->window))) {
|
||||
std::fprintf(stderr, "[renderer] realized=%s\n", G_OBJECT_TYPE_NAME(r));
|
||||
std::fflush(stderr);
|
||||
renderer_printed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// The paint probe's clock, claimed on the first tick that finds one: a widget has no
|
||||
// frame clock until it is realized, and the area is realized on its first draw.
|
||||
if (app->dbg_clock == nullptr && app->area_widget != nullptr) {
|
||||
@@ -3500,14 +3516,21 @@ gboolean tick(gpointer user) {
|
||||
// the title's centre box, i.e. window_button_w tracked the window width).
|
||||
if (app->window_button != nullptr) {
|
||||
static gint64 next_header_log = 0;
|
||||
// The widths stay sampled on this one-second cadence whatever the environment, because the
|
||||
// exit dump's `header:` line reads them; only the *line* is behind a variable. A reading
|
||||
// printed on every run is a log flood and not a reading -- the same rule the `[notrace]`
|
||||
// per-paint line follows.
|
||||
static const bool header_print = g_getenv("UDPSCOPE_PROBE_HEADER") != nullptr;
|
||||
const gint64 now = g_get_monotonic_time();
|
||||
if (now >= next_header_log) {
|
||||
next_header_log = now + G_TIME_SPAN_SECOND;
|
||||
app->dbg_win_btn_w = gtk_widget_get_width(app->window_button);
|
||||
app->dbg_bar_w = gtk_widget_get_width(app->window);
|
||||
std::fprintf(stderr, "[udpscope] header: window_button_w=%d bar_w=%d\n",
|
||||
app->dbg_win_btn_w, app->dbg_bar_w);
|
||||
std::fflush(stderr);
|
||||
if (header_print) {
|
||||
std::fprintf(stderr, "[udpscope] header: window_button_w=%d bar_w=%d\n",
|
||||
app->dbg_win_btn_w, app->dbg_bar_w);
|
||||
std::fflush(stderr);
|
||||
}
|
||||
}
|
||||
}
|
||||
// The help layer's own readings and the bounds the help's annotated figures crop, on the same
|
||||
|
||||
Reference in new issue
Block a user