GUI: implement canvas caching

This commit is contained in:
Jyrki Vesterinen 2017-08-06 13:39:03 +03:00
parent 29519406be
commit 6110fb59db
4 changed files with 45 additions and 8 deletions

View file

@ -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:

View file

@ -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

View file

@ -34,6 +34,8 @@
#include "video.hpp"
#include "wml_exception.hpp"
#include <iterator>
namespace gui2
{
@ -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_);
@ -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;
@ -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 ***** ***** ***** ***** *****/

View file

@ -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.
*/
@ -121,6 +118,7 @@ public:
void set_cfg(const config& cfg, const bool force = false)
{
clear_shapes(force);
invalidate_cache();
parse_cfg(cfg);
}
@ -142,6 +140,7 @@ public:
{
w_ = width;
set_is_dirty(true);
invalidate_cache();
}
unsigned get_width() const
@ -153,6 +152,7 @@ public:
{
h_ = height;
set_is_dirty(true);
invalidate_cache();
}
unsigned get_height() const
@ -169,6 +169,7 @@ public:
{
variables_.add(key, value);
set_is_dirty(true);
invalidate_cache();
}
void set_is_dirty(const bool is_dirty)
@ -180,6 +181,10 @@ private:
/** 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.
*
@ -223,6 +228,7 @@ private:
void parse_cfg(const config& cfg);
void clear_shapes(const bool force);
void invalidate_cache();
};
} // namespace gui2