From 8d6b9fad80dcfea80ea88c61218acc396355ce5d Mon Sep 17 00:00:00 2001 From: Charles Dang Date: Thu, 22 Jun 2017 07:26:06 +1100 Subject: [PATCH] Split texture caches into linear and NN scaled versions With textures, you can't change render scale quality once they've been created. To rectify this, I've made the texture caches a map of caches, sorted by scale quality. This should result in no performance overhead, since an image is simply added to the appropriate quality cache on creation instead of in a single cache. If a different version of a texture is needed it will be loaded later. By default, load_texture will return images using nearest neighbor scaling. GUI2 always fetches images using linear scaling. This is consistent with the old software rendering method. Plus, we don't have any way (as of now) to specify the render quality on a per-image basis. --- src/gui/core/canvas.cpp | 3 ++- src/image.cpp | 31 +++++++++++++++++++++++++------ src/image.hpp | 3 +++ src/sdl/render_utils.hpp | 11 +++++++++++ src/sdl/window.cpp | 3 --- 5 files changed, 41 insertions(+), 10 deletions(-) diff --git a/src/gui/core/canvas.cpp b/src/gui/core/canvas.cpp index 9501a040b655..168f530eab79 100644 --- a/src/gui/core/canvas.cpp +++ b/src/gui/core/canvas.cpp @@ -1060,7 +1060,8 @@ void image_shape::draw( return; } - image_ = image::get_texture(name); + // NOTE: if we need a key to specify NN scaling it can be added later. + image_ = image::get_texture(name, image::LINEAR); if(!image_) { ERR_GUI_D << "Image: '" << name << "' not found and won't be drawn." << std::endl; diff --git a/src/image.cpp b/src/image.cpp index 8a264a1c82f2..6597fcda16a2 100644 --- a/src/image.cpp +++ b/src/image.cpp @@ -31,6 +31,7 @@ #include "preferences/general.hpp" #include "serialization/string_utils.hpp" #include "sdl/rect.hpp" +#include "sdl/render_utils.hpp" #include "sdl/texture.hpp" #include "utils/general.hpp" @@ -174,7 +175,9 @@ image::image_cache * Texture caches. * Note that the latter two are temporary and should be removed once we have OGL and shader support. */ -image::texture_cache +using texture_cache_map = std::map; + +texture_cache_map textures_, textures_hexed_, texture_tod_colored_; @@ -1393,6 +1396,15 @@ bool update_from_preferences() * are so different. Might move this to a file of its own in the future. */ +/** Sets the texture scale quality hint. Must be called *before* creating textures! */ +static void set_scale_quality_pre_texture_creation(SCALE_QUALITY quality) +{ + static const std::string n_scale_str = "nearest"; + static const std::string l_scale_str = "linear"; + + set_texture_scale_quality(quality == NEAREST ? n_scale_str : l_scale_str); +} + /** Loads a new texture directly from disk. */ static texture create_texture_from_file(const image::locator& loc) { @@ -1538,8 +1550,13 @@ static texture create_texture_post_surface_op(const image::locator& i_locator, T return texture(surf); } -/** Returns a texture for the corresponding image. */ texture get_texture(const image::locator& i_locator, TYPE type) +{ + return get_texture(i_locator, NEAREST, type); +} + +/** Returns a texture for the corresponding image. */ +texture get_texture(const image::locator& i_locator, SCALE_QUALITY quality, TYPE type) { texture res; @@ -1558,13 +1575,13 @@ texture get_texture(const image::locator& i_locator, TYPE type) switch(type) { case HEXED: - cache = &textures_hexed_; + cache = &textures_hexed_[quality]; break; case TOD_COLORED: - cache = &texture_tod_colored_; + cache = &texture_tod_colored_[quality]; break; default: - cache = &textures_; + cache = &textures_[quality]; } // @@ -1586,10 +1603,12 @@ texture get_texture(const image::locator& i_locator, TYPE type) } // - // No texture was cached. In that case, create a new one. The explicit cases require special + // No texture was cached. In that case, create a new one. The explicit cases require special // handling with surfaces in order to generate the desired effect. This shouldn't be the case // once we get OGL and shader support. // + set_scale_quality_pre_texture_creation(quality); + switch(type) { case TOD_COLORED: case HEXED: diff --git a/src/image.hpp b/src/image.hpp index 2e5f51934011..e6a62e3171f9 100644 --- a/src/image.hpp +++ b/src/image.hpp @@ -192,10 +192,13 @@ namespace image { /// BRIGHTENED : same as TOD_COLORED but also brightened enum TYPE { UNSCALED, SCALED_TO_ZOOM, HEXED, SCALED_TO_HEX, TOD_COLORED, BRIGHTENED}; + enum SCALE_QUALITY { NEAREST, LINEAR }; + ///function to get the surface corresponding to an image. surface get_image(const locator& i_locator, TYPE type=UNSCALED); texture get_texture(const image::locator& i_locator, TYPE type = UNSCALED); + texture get_texture(const image::locator& i_locator, SCALE_QUALITY quality, TYPE type = UNSCALED); ///function to get the surface corresponding to an image. ///after applying the lightmap encoded in ls diff --git a/src/sdl/render_utils.hpp b/src/sdl/render_utils.hpp index 454d6c05707d..6ef4bf00a169 100644 --- a/src/sdl/render_utils.hpp +++ b/src/sdl/render_utils.hpp @@ -127,3 +127,14 @@ inline void set_texture_blend_mode(texture& t, SDL_BlendMode mode) { SDL_SetTextureBlendMode(t, mode); } + +/** + * Sets the texture scale quality. Note this should be called *before* a texture + * is created, since the hint has no effect on existing textures or render ops. + * + * @param value The scaling mode. Use either 'linear' or 'nearest'. + */ +inline void set_texture_scale_quality(const std::string& value) +{ + SDL_SetHintWithPriority(SDL_HINT_RENDER_SCALE_QUALITY, value.c_str(), SDL_HINT_OVERRIDE); +} diff --git a/src/sdl/window.cpp b/src/sdl/window.cpp index 799cb88de83c..c9239a82dda0 100644 --- a/src/sdl/window.cpp +++ b/src/sdl/window.cpp @@ -57,9 +57,6 @@ window::window(const std::string& title, // Minimizing was reported as bug #1606 with blocker priority. SDL_SetHint(SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0"); - // Use linear scaling when rendering, if applicable. - SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "linear"); - fill(0,0,0); render();