From d29a08dfe10e4a88e31e7966e3748e9f8adcbf13 Mon Sep 17 00:00:00 2001 From: Jonathan G Rennison Date: Fri, 2 Oct 2020 02:10:09 +0100 Subject: [PATCH] Add gfx_debug console command --- src/console_cmds.cpp | 18 ++++++++++++++++++ src/gfx.cpp | 28 +++++++++++++++++++++++++--- src/gfx_func.h | 6 ++++++ src/viewport.cpp | 2 +- src/window.cpp | 28 ++++++++++++++++------------ 5 files changed, 66 insertions(+), 16 deletions(-) diff --git a/src/console_cmds.cpp b/src/console_cmds.cpp index 169cc557e2..d9183c8648 100644 --- a/src/console_cmds.cpp +++ b/src/console_cmds.cpp @@ -2390,6 +2390,23 @@ DEF_CONSOLE_CMD(ConViewportMarkStationOverlayDirty) return true; } +DEF_CONSOLE_CMD(ConGfxDebug) +{ + if (argc < 1 || argc > 2) { + IConsoleHelp("Debug: gfx flags. Usage: 'gfx_debug []'"); + return true; + } + + extern uint32 _gfx_debug_flags; + if (argc == 1) { + IConsolePrintF(CC_DEFAULT, "Gfx debug flags: %X", _gfx_debug_flags); + } else { + _gfx_debug_flags = strtoul(argv[1], nullptr, 16); + } + + return true; +} + DEF_CONSOLE_CMD(ConCSleep) { if (argc != 2) { @@ -2806,6 +2823,7 @@ void IConsoleStdLibRegister() IConsoleCmdRegister("viewport_debug", ConViewportDebug, nullptr, true); IConsoleCmdRegister("viewport_mark_dirty", ConViewportMarkDirty, nullptr, true); IConsoleCmdRegister("viewport_mark_dirty_st_overlay", ConViewportMarkStationOverlayDirty, nullptr, true); + IConsoleCmdRegister("gfx_debug", ConGfxDebug, nullptr, true); IConsoleCmdRegister("csleep", ConCSleep, nullptr, true); /* NewGRF development stuff */ diff --git a/src/gfx.cpp b/src/gfx.cpp index 62066b5fc8..3c7a3615c6 100644 --- a/src/gfx.cpp +++ b/src/gfx.cpp @@ -85,6 +85,13 @@ bool _gfx_draw_active = false; static std::vector _dirty_blocks; static std::vector _pending_dirty_blocks; +enum GfxDebugFlags { + GDF_SHOW_WINDOW_DIRTY, + GDF_SHOW_WIDGET_DIRTY, + GDF_SHOW_RECT_DIRTY, +}; +uint32 _gfx_debug_flags; + /** * Applies a certain FillRectMode-operation to a rectangle [left, right] x [top, bottom] on the screen. * @@ -1555,7 +1562,7 @@ void DrawDirtyBlocks() DrawPixelInfo bk; _cur_dpi = &bk; - extern void DrawOverlappedWindow(Window *w, int left, int top, int right, int bottom, bool gfx_dirty); + extern void DrawOverlappedWindow(Window *w, int left, int top, int right, int bottom, DrawOverlappedWindowFlags flags); Window *w; FOR_ALL_WINDOWS_FROM_BACK(w) { @@ -1566,14 +1573,24 @@ void DrawDirtyBlocks() if (w->flags & WF_DIRTY) { clear_overlays(); - DrawOverlappedWindow(w, max(0, w->left), max(0, w->top), min(_screen.width, w->left + w->width), min(_screen.height, w->top + w->height), true); + DrawOverlappedWindowFlags flags = DOWF_MARK_DIRTY; + if (unlikely(HasBit(_gfx_debug_flags, GDF_SHOW_WINDOW_DIRTY))) { + flags |= DOWF_SHOW_DEBUG; + _dirty_block_colour++; + } + DrawOverlappedWindow(w, max(0, w->left), max(0, w->top), min(_screen.width, w->left + w->width), min(_screen.height, w->top + w->height), flags); w->flags &= ~(WF_DIRTY | WF_WIDGETS_DIRTY); } else if (w->flags & WF_WIDGETS_DIRTY) { if (w->nested_root != nullptr) { clear_overlays(); w->nested_root->FillDirtyWidgets(dirty_widgets); for (NWidgetBase *widget : dirty_widgets) { - DrawOverlappedWindow(w, max(0, w->left + widget->pos_x), max(0, w->top + widget->pos_y), min(_screen.width, w->left + widget->pos_x + widget->current_x), min(_screen.height, w->top + widget->pos_y + widget->current_y), true); + DrawOverlappedWindowFlags flags = DOWF_MARK_DIRTY; + if (unlikely(HasBit(_gfx_debug_flags, GDF_SHOW_WIDGET_DIRTY))) { + flags |= DOWF_SHOW_DEBUG; + _dirty_block_colour++; + } + DrawOverlappedWindow(w, max(0, w->left + widget->pos_x), max(0, w->top + widget->pos_y), min(_screen.width, w->left + widget->pos_x + widget->current_x), min(_screen.height, w->top + widget->pos_y + widget->current_y), flags); } dirty_widgets.clear(); } @@ -1699,6 +1716,11 @@ void DrawDirtyBlocks() for (const Rect &r : _dirty_blocks) { RedrawScreenRect(r.left, r.top, r.right, r.bottom); } + if (unlikely(HasBit(_gfx_debug_flags, GDF_SHOW_RECT_DIRTY))) { + for (const Rect &r : _dirty_blocks) { + GfxFillRect(r.left, r.top, r.right, r.bottom, _string_colourmap[++_dirty_block_colour & 0xF], FILLRECT_CHECKER); + } + } } _dirty_blocks.clear(); diff --git a/src/gfx_func.h b/src/gfx_func.h index ec105f286a..7ad56faffd 100644 --- a/src/gfx_func.h +++ b/src/gfx_func.h @@ -156,6 +156,12 @@ static inline int CenterBounds(int min, int max, int size) } /* window.cpp */ +enum DrawOverlappedWindowFlags { + DOWF_NONE = 0, + DOWF_MARK_DIRTY = 1 << 0, + DOWF_SHOW_DEBUG = 1 << 1, +}; +DECLARE_ENUM_AS_BIT_SET(DrawOverlappedWindowFlags) void DrawOverlappedWindowForAll(int left, int top, int right, int bottom); void SetMouseCursorBusy(bool busy); diff --git a/src/viewport.cpp b/src/viewport.cpp index 6cfcfc69f3..82634cb50a 100644 --- a/src/viewport.cpp +++ b/src/viewport.cpp @@ -2091,7 +2091,7 @@ void ViewportMapBuildTunnelCache() /** * Draw/colour the blocks that have been redrawn. */ -static void ViewportDrawDirtyBlocks() +void ViewportDrawDirtyBlocks() { Blitter *blitter = BlitterFactory::GetCurrentBlitter(); const DrawPixelInfo *dpi = _cur_dpi; diff --git a/src/window.cpp b/src/window.cpp index e50631f00d..1d940e338a 100644 --- a/src/window.cpp +++ b/src/window.cpp @@ -887,9 +887,9 @@ static void DispatchMouseWheelEvent(Window *w, NWidgetCore *nwid, int wheel) * @param top Top edge of the rectangle that should be repainted * @param right Right edge of the rectangle that should be repainted * @param bottom Bottom edge of the rectangle that should be repainted - * @param gfx_dirty Whether to mark gfx dirty + * @param flags Whether to mark gfx dirty, etc. */ -void DrawOverlappedWindow(Window *w, int left, int top, int right, int bottom, bool gfx_dirty) +void DrawOverlappedWindow(Window *w, int left, int top, int right, int bottom, DrawOverlappedWindowFlags flags) { const Window *v; FOR_ALL_WINDOWS_FROM_BACK_FROM(v, w->z_front) { @@ -902,26 +902,26 @@ void DrawOverlappedWindow(Window *w, int left, int top, int right, int bottom, b int x; if (left < (x = v->left)) { - DrawOverlappedWindow(w, left, top, x, bottom, gfx_dirty); - DrawOverlappedWindow(w, x, top, right, bottom, gfx_dirty); + DrawOverlappedWindow(w, left, top, x, bottom, flags); + DrawOverlappedWindow(w, x, top, right, bottom, flags); return; } if (right > (x = v->left + v->width)) { - DrawOverlappedWindow(w, left, top, x, bottom, gfx_dirty); - DrawOverlappedWindow(w, x, top, right, bottom, gfx_dirty); + DrawOverlappedWindow(w, left, top, x, bottom, flags); + DrawOverlappedWindow(w, x, top, right, bottom, flags); return; } if (top < (x = v->top)) { - DrawOverlappedWindow(w, left, top, right, x, gfx_dirty); - DrawOverlappedWindow(w, left, x, right, bottom, gfx_dirty); + DrawOverlappedWindow(w, left, top, right, x, flags); + DrawOverlappedWindow(w, left, x, right, bottom, flags); return; } if (bottom > (x = v->top + v->height)) { - DrawOverlappedWindow(w, left, top, right, x, gfx_dirty); - DrawOverlappedWindow(w, left, x, right, bottom, gfx_dirty); + DrawOverlappedWindow(w, left, top, right, x, flags); + DrawOverlappedWindow(w, left, x, right, bottom, flags); return; } @@ -939,7 +939,11 @@ void DrawOverlappedWindow(Window *w, int left, int top, int right, int bottom, b dp->dst_ptr = BlitterFactory::GetCurrentBlitter()->MoveTo(_screen.dst_ptr, left, top); dp->zoom = ZOOM_LVL_NORMAL; w->OnPaint(); - if (gfx_dirty) { + if (unlikely(flags & DOWF_SHOW_DEBUG)) { + extern void ViewportDrawDirtyBlocks(); + ViewportDrawDirtyBlocks(); + } + if (flags & DOWF_MARK_DIRTY) { VideoDriver::GetInstance()->MakeDirty(left, top, right - left, bottom - top); UnsetDirtyBlocks(left, top, right, bottom); } @@ -968,7 +972,7 @@ void DrawOverlappedWindowForAll(int left, int top, int right, int bottom) left < w->left + w->width && top < w->top + w->height) { /* Window w intersects with the rectangle => needs repaint */ - DrawOverlappedWindow(w, max(left, w->left), max(top, w->top), min(right, w->left + w->width), min(bottom, w->top + w->height), false); + DrawOverlappedWindow(w, max(left, w->left), max(top, w->top), min(right, w->left + w->width), min(bottom, w->top + w->height), DOWF_NONE); } } _cur_dpi = old_dpi;