Skip to content

Commit

Permalink
Moved GUI2's per-frame drawing trigger to global scope
Browse files Browse the repository at this point in the history
This is derived from work originally done by @aginor (48bcb27). I cherry-picked that commit and made a few alterations.
  • Loading branch information
Vultraz committed Jul 26, 2017
1 parent b225b8d commit dc9f923
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 96 deletions.
3 changes: 2 additions & 1 deletion src/controller_base.cpp
Expand Up @@ -30,7 +30,8 @@ static lg::log_domain log_display("display");
#define ERR_DP LOG_STREAM(err, log_display)

controller_base::controller_base(const config& game_config)
: game_config_(game_config)
: draw_layering(false)
, game_config_(game_config)
, key_()
, scrolling_(false)
, scroll_up_(false)
Expand Down
2 changes: 2 additions & 0 deletions src/editor/controller/editor_controller.cpp
Expand Up @@ -85,6 +85,8 @@ editor_controller::editor_controller(const config &game_config, CVideo& video)
get_current_map_context().set_starting_position_labels(gui());
cursor::set(cursor::NORMAL);

join();

gui().create_buttons();
gui().redraw_everything();
events::raise_draw_event();
Expand Down
58 changes: 58 additions & 0 deletions src/events.cpp
Expand Up @@ -402,6 +402,54 @@ static bool remove_on_resize(const SDL_Event& a)
return false;
}

/**
* The interval between draw events.
*
* When the window is shown this value is set, the callback function always
* uses this value instead of the parameter send, that way the window can stop
* drawing when it wants.
*/
static int draw_interval = 0;

SDL_TimerID draw_timer_id;

/**
* SDL_AddTimer() callback for the draw event.
*
* When this callback is called it pushes a new draw event in the event queue.
*
* @returns The new timer interval, 0 to stop.
*/
static Uint32 draw_timer(Uint32, void*)
{
// DBG_GUI_E << "Pushing draw event in queue.\n";

SDL_Event event;
SDL_UserEvent data;

data.type = DRAW_EVENT;
data.code = 0;
data.data1 = NULL;
data.data2 = NULL;

event.type = DRAW_EVENT;
event.user = data;

SDL_PushEvent(&event);
return draw_interval;
}

void initialise()
{
draw_interval = 20;
draw_timer_id = SDL_AddTimer(draw_interval, draw_timer, NULL);
}

void finalize()
{
SDL_RemoveTimer(draw_timer_id);
}

// TODO: I'm uncertain if this is always safe to call at static init; maybe set in main() instead?
static const boost::thread::id main_thread = boost::this_thread::get_id();

Expand Down Expand Up @@ -610,6 +658,12 @@ void pump()
}
}

const bool is_draw_event = event.type == DRAW_EVENT || event.type == DRAW_ALL_EVENT;

if(is_draw_event) {
CVideo::get_singleton().clear_screen();
}

for(auto global_handler : event_contexts.front().handlers) {
global_handler->handle_event(event);
}
Expand All @@ -619,6 +673,10 @@ void pump()
handler->handle_event(event);
}
}

if(is_draw_event) {
CVideo::get_singleton().render_screen();
}
}

// Inform the pump monitors that an events::pump() has occurred
Expand Down
3 changes: 3 additions & 0 deletions src/events.hpp
Expand Up @@ -151,6 +151,9 @@ class pump_monitor {
virtual void process(pump_info& info) = 0;
};

void initialise();
void finalize();

void raise_process_event();
void raise_resize_event();
void raise_draw_event();
Expand Down
10 changes: 0 additions & 10 deletions src/gui/core/event/handler.cpp
Expand Up @@ -532,13 +532,6 @@ void sdl_event_handler::draw(const bool /*force*/)
return;
}

CVideo& video = dynamic_cast<window&>(*dispatchers_.back()).video();

/**
* Clear the renderer before beginning the draw cycle.
*/
video.clear_screen();

/**
* @todo Need to evaluate which windows really to redraw.
*
Expand All @@ -548,9 +541,6 @@ void sdl_event_handler::draw(const bool /*force*/)
{
dispatcher->fire(DRAW, dynamic_cast<widget&>(*dispatcher));
}

// Finally, render the screen.
video.render_screen();
}

void sdl_event_handler::video_resize(const point& new_size)
Expand Down
101 changes: 16 additions & 85 deletions src/gui/widgets/window.cpp
Expand Up @@ -110,46 +110,11 @@ namespace
const unsigned SHOW = debug_layout_graph::SHOW;
const unsigned LAYOUT = debug_layout_graph::LAYOUT;
#else
// values are irrelavant when DEBUG_WINDOW_LAYOUT_GRAPHS is not defined.
// values are irrelevant when DEBUG_WINDOW_LAYOUT_GRAPHS is not defined.
const unsigned SHOW = 0;
const unsigned LAYOUT = 0;
#endif

/**
* The interval between draw events.
*
* When the window is shown this value is set, the callback function always
* uses this value instead of the parameter send, that way the window can stop
* drawing when it wants.
*/
static int draw_interval = 0;

/**
* SDL_AddTimer() callback for the draw event.
*
* When this callback is called it pushes a new draw event in the event queue.
*
* @returns The new timer interval, 0 to stop.
*/
static Uint32 draw_timer(Uint32, void*)
{
// DBG_GUI_E << "Pushing draw event in queue.\n";

SDL_Event event;
SDL_UserEvent data;

data.type = DRAW_EVENT;
data.code = 0;
data.data1 = nullptr;
data.data2 = nullptr;

event.type = DRAW_EVENT;
event.user = data;

SDL_PushEvent(&event);
return draw_interval;
}

/**
* SDL_AddTimer() callback for delay_event.
*
Expand Down Expand Up @@ -461,23 +426,21 @@ void window::update_screen_size()
{
// Only if we're the toplevel window we need to update the size, otherwise
// it's done in the resize event.
if(draw_interval == 0) {
const SDL_Rect rect = screen_area();
settings::screen_width = rect.w;
settings::screen_height = rect.h;

settings::gamemap_width = settings::screen_width;
settings::gamemap_height = settings::screen_height;

display* display = display::get_singleton();
if(display) {
const SDL_Rect rect_gm = display->map_outside_area();

if(rect_gm.w && rect_gm.h) {
settings::gamemap_width = rect_gm.w;
settings::gamemap_height = rect_gm.h;
settings::gamemap_x_offset = rect_gm.x;
}
const SDL_Rect rect = screen_area();
settings::screen_width = rect.w;
settings::screen_height = rect.h;

settings::gamemap_width = settings::screen_width;
settings::gamemap_height = settings::screen_height;

display* display = display::get_singleton();
if(display) {
const SDL_Rect rect_gm = display->map_outside_area();

if(rect_gm.w && rect_gm.h) {
settings::gamemap_width = rect_gm.w;
settings::gamemap_height = rect_gm.h;
settings::gamemap_x_offset = rect_gm.x;
}
}
}
Expand Down Expand Up @@ -559,44 +522,12 @@ int window::show(const bool /*restore*/, const unsigned auto_close_timeout)

show_mode_ = modal;

/**
* Helper class to set and restore the drawing interval.
*
* We need to make sure we restore the value when the function ends, be it
* normally or due to an exception.
*/
class draw_interval_setter
{
public:
draw_interval_setter() : interval_(draw_interval)
{
if(interval_ == 0) {
draw_interval = 20;
SDL_AddTimer(draw_interval, draw_timer, nullptr);

// There might be some time between creation and showing so
// reupdate the sizes.
update_screen_size();
}
}

~draw_interval_setter()
{
draw_interval = interval_;
}

private:
int interval_;
};

log_scope2(log_gui_draw, LOG_SCOPE_HEADER);

generate_dot_file("show", SHOW);

assert(status_ == NEW);

draw_interval_setter draw_interval_setter;

/*
* Before show has been called, some functions might have done some testing
* on the window and called layout, which can give glitches. So
Expand Down
7 changes: 7 additions & 0 deletions src/wesnoth.cpp
Expand Up @@ -616,12 +616,17 @@ static int do_gameloop(const std::vector<std::string>& args)
return 1;
}

events::initialise();
events::pump();

res = image::update_from_preferences();
if(res == false) {
std::cerr << "could not initialize image preferences\n";
return 1;
}

events::pump();

if(preferences::joystick_support_enabled()) {
res = game->init_joystick();
if(res == false) {
Expand All @@ -633,6 +638,8 @@ static int do_gameloop(const std::vector<std::string>& args)
const cursor::manager cursor_manager;
cursor::set(cursor::WAIT);

events::pump();

#if (defined(_X11) && !defined(__APPLE__)) || defined(_WIN32)
SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
#endif
Expand Down

0 comments on commit dc9f923

Please sign in to comment.