GUI2/Canvas: optimized cached texture management

Instead of throwing out the cached texture every time the canvas was dirty, I've added a flag so that
only happens if its size has actually changed. There still seem to be some issues in GUI2 where canvas
objects keep getting reset, but I'm not sure why. Will have to look into that.

Anyway, the addition of the SDL_RenderClear call also seems to have fixed the weird graphics bleed-through
I was getting when running the game with the OGL driver.

I don't know if the canvas copy or move ctors are needed for anything. I added them for a test, but I'll
leave them for now in case I need them later.
This commit is contained in:
Charles Dang 2017-07-23 09:04:54 +11:00
parent 5e35f6dbfe
commit c7ed5559a0
2 changed files with 38 additions and 6 deletions

View file

@ -1367,6 +1367,7 @@ canvas::canvas()
, variables_()
, functions_()
, is_dirty_(true)
, size_changed_(true)
{
}
@ -1381,6 +1382,7 @@ canvas::canvas(canvas&& c)
, variables_(c.variables_)
, functions_(c.functions_)
, is_dirty_(c.is_dirty_)
, size_changed_(c.size_changed_)
{
// Needed to ensure the other object doesn't destroy our software renderer prematurely.
c.renderer_ = nullptr;
@ -1417,14 +1419,29 @@ void canvas::draw(const bool force)
}
#endif
// Recreate the texture. Will print an error if creation fails.
texture_.reset(w_, h_, SDL_TEXTUREACCESS_TARGET);
// If cached texture is null or size has changed, throw it out and create a new one.
if(!texture_ || size_changed_) {
texture_.reset(w_, h_, SDL_TEXTUREACCESS_TARGET);
size_changed_ = false;
}
// Something went wrong! Bail! The texture ctor will print the error if applicable.
if(!texture_) {
return;
}
// Set the render target. *Must* be called after the above block in case the texture's
// been recreated or else the game will crash upon trying to write to a null texture.
render_target_setter target_setter(texture_);
// Clear the texture. SDL_RenderClear operates on the current rendering target, so the
// cached texture will be filled in even if it wasn't recreated. This prevents weird
// graphics bleed-through with certain driver configurations.
set_draw_color(renderer_, 0, 0, 0, 0);
SDL_RenderClear(renderer_); // TODO: move to its own wrapper.
// Draw items.
for(auto& shape : shapes_) {
lg::scope_logger inner_scope_logging_object__(log_gui_draw, "Canvas: draw shape.");
@ -1547,6 +1564,16 @@ void canvas::invalidate_cache()
}
}
void canvas::update_size(unsigned int& value, unsigned int new_value)
{
if(value != new_value) {
value = new_value;
size_changed_ = true;
set_is_dirty(true);
}
}
/***** ***** ***** ***** ***** SHAPE ***** ***** ***** ***** *****/
} // namespace gui2

View file

@ -139,8 +139,7 @@ public:
void set_width(const unsigned width)
{
w_ = width;
set_is_dirty(true);
update_size(w_, width);
invalidate_cache();
}
@ -151,8 +150,7 @@ public:
void set_height(const unsigned height)
{
h_ = height;
set_is_dirty(true);
update_size(h_, height);
invalidate_cache();
}
@ -212,6 +210,9 @@ private:
/** The dirty state of the canvas. */
bool is_dirty_;
/** Whether canvas dimensions changed. */
bool size_changed_;
/**
* Parses a config object.
*
@ -225,7 +226,11 @@ private:
void parse_cfg(const config& cfg);
void clear_shapes(const bool force);
void invalidate_cache();
/** Small helper to handle size variable update logic. */
void update_size(unsigned int& value, unsigned int new_value);
};
} // namespace gui2