The Battle for Wesnoth  1.19.7+dev
draw_manager.hpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2007 - 2024
3  Part of the Battle for Wesnoth Project https://www.wesnoth.org/
4 
5  This program is free software; you can redistribute it and/or modify
6  it under the terms of the GNU General Public License as published by
7  the Free Software Foundation; either version 2 of the License, or
8  (at your option) any later version.
9  This program is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY.
11 
12  See the COPYING file for more details.
13 */
14 
15 #pragma once
16 
17 #include "sdl/rect.hpp"
18 
19 #include <chrono>
20 
21 namespace gui2 { class top_level_drawable; }
22 
23 /**
24  * A global draw management interface.
25  *
26  * This interface governs drawing things to the screen in the correct order.
27  * Drawable objects must inherit from gui2::top_level_drawable, and may be
28  * referred to as "TLD"s.
29  *
30  * There is an absolute requirement that events happen in a certain order.
31  * This is mostly managed by this interface, which calls the TLD methods in
32  * order at most once every vsync.
33  *
34  * The order of events is:
35  * 1. General event processing. This is governed by events::pump()
36  * and is currently independent of this interface.
37  * 2. Layout and animation. TLDs should ensure their layout information
38  * is up-to-date inside gui2::top_level_drawable::layout(). After
39  * this call they should know where they are on the screen, and be
40  * ready to report it via gui2::top_level_drawable::screen_location().
41  * Animation can also be performed during this stage.
42  * 3. Offscreen rendering. TLDs should perform any offscreen rendering
43  * during gui2::top_level_drawable::render(). After this call, all
44  * internal drawing buffers should be in a state ready for display.
45  * 4. Drawing to the screen. Drawing to the screen should only ever happen
46  * inside gui2::top_level_drawable::expose(). Drawing to the screen at
47  * any other point is an error.
48  *
49  * The draw manager will call layout(), render() and expose() in the correct
50  * order to ensure all TLD objects are laid out correctly and drawn in the
51  * correct order.
52  *
53  * Drawing order of TLDs is initially set by creation time, but a TLD may
54  * be raised to the top of the drawing stack by calling
55  * draw_manager::raise_drawable() manually. register_drawable() and
56  * deregister_drawable() are called automatically by gui2::top_level_drawable
57  * in its constructor and destructor, and do not need to be manually managed.
58  *
59  * The drawing process happens inside draw_manager::sparkle(). In general,
60  * a game loop should perform two basic steps.
61  * 1. call events::pump() to process events. Anything other than drawing
62  * to the screen may happen during this step.
63  * 2. call draw_manager::sparkle() to draw the screen, if necessary.
64  *
65  * The main sparkle() function will also rate-limit, so callers do not need
66  * to add their own delay to their loops. If vsync is disabled, drawing will
67  * happen as frequently as possible. If vsync is enabled, this function will
68  * wait for the next screen refresh before drawing. In both cases, if nothing
69  * needs to be drawn the function will block for an appropriate length of
70  * time before returning.
71  *
72  * To ensure they are presented for drawing, any drawable object must call
73  * draw_manager::invalidate_region() to indicate that an area of the screen
74  * needs to be redrawn. This may be called during any phase other than the
75  * draw phase. Invalidating regions during the draw phase is an error and
76  * will throw an exception.
77  */
78 namespace draw_manager
79 {
80 
81 /**
82  * Mark a region of the screen as requiring redraw.
83  *
84  * This should be called any time an item changes in such a way as to
85  * require redrawing.
86  *
87  * This may only be called outside the Draw phase.
88  *
89  * Regions are combined to result in a minimal number of draw calls,
90  * so this may be called for every invalidation without much concern.
91  */
92 void invalidate_region(const rect& region);
93 
94 /** Mark the entire screen as requiring redraw. */
95 void invalidate_all();
96 
97 /**
98  * Request an extra render pass.
99  *
100  * This is used for blur effects, which need to first render what's
101  * underneath so that it can be blurred.
102  *
103  * There is not currently any limit to the number of extra render passes,
104  * but do try to keep it finite.
105  */
107 
108 /**
109  * Ensure that everything which needs to be drawn is drawn.
110  *
111  * This includes making sure window sizes and locations are up to date,
112  * updating animation frames, and drawing whatever regions of the screen
113  * need drawing or redrawing.
114  *
115  * If vsync is enabled, this function will block until the next vblank.
116  * If nothing is drawn, it will still block for an appropriate amount of
117  * time to simulate vsync, even if vsync is disabled.
118  */
119 void sparkle();
120 
121 /**
122  * Returns the length of one display frame, in milliseconds.
123  *
124  * This will usually be determined by the active monitor's refresh rate.
125  */
126 std::chrono::milliseconds get_frame_length();
127 
128 /** Register a top-level drawable.
129  *
130  * Registered drawables will be drawn in the order of registration,
131  * so the most recently-registered drawable will be "on top".
132  */
134 
135 /** Remove a top-level drawable from the drawing stack. */
137 
138 /** Raise a TLD to the top of the drawing stack. */
140 
141 } // namespace draw_manager
A top-level drawable item (TLD), such as a window.
A global draw management interface.
void invalidate_region(const rect &region)
Mark a region of the screen as requiring redraw.
void request_extra_render_pass()
Request an extra render pass.
void register_drawable(top_level_drawable *tld)
Register a top-level drawable.
void deregister_drawable(top_level_drawable *tld)
Remove a top-level drawable from the drawing stack.
void invalidate_all()
Mark the entire screen as requiring redraw.
void sparkle()
Ensure that everything which needs to be drawn is drawn.
std::chrono::milliseconds get_frame_length()
Returns the length of one display frame, in milliseconds.
void raise_drawable(top_level_drawable *tld)
Raise a TLD to the top of the drawing stack.
Generic file dialog.
Contains the SDL_Rect helper code.
An abstract description of a rectangle with integer coordinates.
Definition: rect.hpp:47