Skip to content

Commit

Permalink
GUI: implement canvas caching
Browse files Browse the repository at this point in the history
  • Loading branch information
jyrkive committed Aug 6, 2017
1 parent 2951940 commit 6110fb5
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 8 deletions.
2 changes: 2 additions & 0 deletions changelog
Expand Up @@ -47,6 +47,8 @@ Version 1.13.8+dev:
* Fixed delay or clients gettings stuck when starting a mp game (Bug #1674)
* Performance:
* Rewrote the FPS cap implementation. This greatly improves smoothness ingame.
* Implemented GUI canvas caching. It speeds up multiple areas, but especially
the story screen.
* Units:
* Added new lvl0 Giant Scorpling, leveling into the Giant Scorpion.
* User Interface:
Expand Down
2 changes: 2 additions & 0 deletions players_changelog
Expand Up @@ -32,6 +32,8 @@ Version 1.13.8+dev:

* Performance:
* Rewrote the FPS cap implementation. This greatly improves smoothness ingame.
* Implemented GUI canvas caching. It speeds up multiple areas, but especially
the story screen.

* User Interface:
* Unit recall dialog now sorts the units by both level and required XP for
Expand Down
37 changes: 32 additions & 5 deletions src/gui/core/canvas.cpp
Expand Up @@ -34,6 +34,8 @@
#include "video.hpp"
#include "wml_exception.hpp"

#include <iterator>

namespace gui2
{

Expand Down Expand Up @@ -1391,9 +1393,13 @@ void canvas::draw(const bool force)
variables_.add("height", wfl::variant(h_));
}

// create surface
DBG_GUI_D << "Canvas: create new empty canvas.\n";
canvas_.assign(create_neutral_surface(w_, h_));
if(!canvas_.null()) {
DBG_GUI_D << "Canvas: use cached canvas.\n";
} else {
// create surface
DBG_GUI_D << "Canvas: create new empty canvas.\n";
canvas_.assign(create_neutral_surface(w_, h_));
}

SDL_DestroyRenderer(renderer_);

Expand All @@ -1407,6 +1413,10 @@ void canvas::draw(const bool force)
shape->draw(canvas_, renderer_, variables_);
}

// The shapes have been drawn and the draw result has been cached. Clear the list.
std::copy(shapes_.begin(), shapes_.end(), std::back_inserter(drawn_shapes_));
shapes_.clear();

SDL_RenderPresent(renderer_);

is_dirty_ = false;
Expand Down Expand Up @@ -1484,12 +1494,29 @@ void canvas::parse_cfg(const config& cfg)

void canvas::clear_shapes(const bool force)
{
const auto iter = std::remove_if(shapes_.begin(), shapes_.end(), [&force](const shape_ptr s)
auto iter = std::remove_if(shapes_.begin(), shapes_.end(), [force](const shape_ptr s)
{
return !s->immutable() && !force;
});

shapes_.erase(iter, shapes_.end());

iter = std::remove_if(drawn_shapes_.begin(), drawn_shapes_.end(), [force](const shape_ptr s)
{
return !s->immutable() && !force;
});
drawn_shapes_.erase(iter, drawn_shapes_.end());
}

void canvas::invalidate_cache()
{
canvas_.assign(nullptr);

if(shapes_.empty()) {
shapes_.swap(drawn_shapes_);
} else {
std::copy(drawn_shapes_.begin(), drawn_shapes_.end(), std::inserter(shapes_, shapes_.begin()));
drawn_shapes_.clear();
}
}

/***** ***** ***** ***** ***** SHAPE ***** ***** ***** ***** *****/
Expand Down
12 changes: 9 additions & 3 deletions src/gui/core/canvas.hpp
Expand Up @@ -35,9 +35,6 @@ namespace gui2
*
* The class has a config which contains what to draw.
*
* NOTE we might add some caching in a later state, for now every draw cycle
* does a full redraw.
*
* The copy constructor does a shallow copy of the shapes to draw.
* a clone() will be implemented if really needed.
*/
Expand Down Expand Up @@ -121,6 +118,7 @@ class canvas
void set_cfg(const config& cfg, const bool force = false)
{
clear_shapes(force);
invalidate_cache();
parse_cfg(cfg);
}

Expand All @@ -142,6 +140,7 @@ class canvas
{
w_ = width;
set_is_dirty(true);
invalidate_cache();
}

unsigned get_width() const
Expand All @@ -153,6 +152,7 @@ class canvas
{
h_ = height;
set_is_dirty(true);
invalidate_cache();
}

unsigned get_height() const
Expand All @@ -169,6 +169,7 @@ class canvas
{
variables_.add(key, value);
set_is_dirty(true);
invalidate_cache();
}

void set_is_dirty(const bool is_dirty)
Expand All @@ -180,6 +181,10 @@ class canvas
/** Vector with the shapes to draw. */
std::vector<shape_ptr> shapes_;

/** All shapes which have been already drawn. Kept around in case
* the cache needs to be invalidated. */
std::vector<shape_ptr> drawn_shapes_;

/**
* The depth of the blur to use in the pre committing.
*
Expand Down Expand Up @@ -223,6 +228,7 @@ class canvas
void parse_cfg(const config& cfg);

void clear_shapes(const bool force);
void invalidate_cache();
};

} // namespace gui2

0 comments on commit 6110fb5

Please sign in to comment.