image: Use get_surface to load texture images.

The texture-only code was missing huge sections, and otherwise a
direct duplication.

If it is desired that surfaces do not get cached when loading
textures, then an option should be added to get_surface to explicitly
disable caching.
This commit is contained in:
Tommy 2022-06-10 22:58:38 +12:00
parent cb164b4d82
commit 3530d6f3ff

View file

@ -1122,8 +1122,9 @@ save_result save_image(const surface& surf, const std::string& filename)
/*
* TEXTURE INTERFACE ======================================================================
*
* I'm keeping this separate from the surface-based handling above since the two approaches
* are so different. Might move this to a file of its own in the future.
* The only important difference here is that textures must have their
* scale quality set before creation. All other handling is done by
* get_surface.
*/
namespace
{
@ -1136,161 +1137,6 @@ void set_scale_quality_pre_texture_creation(scale_quality quality)
set_texture_scale_quality(quality == scale_quality::nearest ? n_scale_str : l_scale_str);
}
/** Loads a new texture directly from disk. */
texture create_texture_from_file(const image::locator& loc)
{
texture res;
// We need the window renderer to load the texture.
SDL_Renderer* renderer = CVideo::get_singleton().get_renderer();
if(!renderer) {
return res;
}
std::string location = filesystem::get_binary_file_location("images", loc.get_filename());
if(!location.empty()) {
#if 0
// Check if there is a localized image.
const std::string loc_location = get_localized_path(location);
if(!loc_location.empty()) {
location = loc_location;
}
#endif
// TODO: if we need to use SDL_RWops we should use IMG_LoadTexture_RW here instead.
{
res.assign(IMG_LoadTexture(renderer, location.c_str()));
}
// TODO: decide what to do about this.
#if 0
// If there was no standalone localized image, check if there is an overlay.
if(!res.null() && loc_location.empty()) {
const std::string ovr_location = get_localized_path(location, "--overlay");
if(!ovr_location.empty()) {
add_localized_overlay(ovr_location, res);
}
}
#endif
}
if(!res && !loc.get_filename().empty()) {
ERR_DP << "Could not load texture for image '" << loc.get_filename() << "'" << std::endl;
// Also decide what to do here.
#if 0
if(game_config::debug && loc.get_filename() != game_config::images::missing) {
return get_texture(game_config::images::missing, UNSCALED);
}
#endif
}
return res;
}
/**
* Handle IPF manipulation. Since we don't have shaders yet, we need to use the surface
* modification code for now. It appears each result is saved in the relevant cache,
* so this should hopefully only result in a small slowdown when first processing the
* results.
*/
texture create_texture_from_sub_file(const image::locator& loc)
{
surface surf = get_image(loc.get_filename(), UNSCALED);
if(surf == nullptr) {
return texture();
}
modification_queue mods = modification::decode(loc.get_modifications());
while(!mods.empty()) {
modification* mod = mods.top();
try {
surf = (*mod)(surf);
} catch(const image::modification::imod_exception& e) {
std::ostringstream ss;
ss << "\n";
for(const std::string& mod2 : utils::parenthetical_split(loc.get_modifications(), '~')) {
ss << "\t" << mod2 << "\n";
}
ERR_CFG << "Failed to apply a modification to an image:\n"
<< "Image: " << loc.get_filename() << "\n"
<< "Modifications: " << ss.str() << "\n"
<< "Error: " << e.message << "\n";
}
// NOTE: do this *after* applying the mod or you'll get crashes!
mods.pop();
}
#if 0
if(loc.get_loc().valid()) {
SDL_Rect srcrect = sdl::create_rect(
((tile_size * 3) / 4) * loc.get_loc().x,
tile_size * loc.get_loc().y + (tile_size / 2) * (loc.get_loc().x % 2),
tile_size,
tile_size
);
if(loc.get_center_x() >= 0 && loc.get_center_y() >= 0) {
srcrect.x += surf->w / 2 - loc.get_center_x();
srcrect.y += surf->h / 2 - loc.get_center_y();
}
// cut and hex mask, but also check and cache if empty result
surface cut(cut_surface(surf, srcrect));
bool is_empty = false;
surf = mask_surface(cut, get_hexmask(), &is_empty);
// discard empty images to free memory
if(is_empty) {
// Safe because those images are only used by terrain rendering
// and it filters them out.
// A safer and more general way would be to keep only one copy of it
surf = nullptr;
}
loc.add_to_cache(is_empty_hex_, is_empty);
}
#endif
return texture(surf);
}
/**
* Small wrapper for creating a texture after applying a specific type of surface op.
* Won't be necessary once we get shader support.
*/
texture create_texture_post_surface_op(const image::locator& i_locator, TYPE type)
{
surface surf = get_image(i_locator, type);
if(!surf) {
return texture();
}
return texture(surf);
}
texture create_texture_from_disk(const locator& loc)
{
switch(loc.get_type()) {
case locator::FILE:
if(loc.is_data_uri()){
return texture(load_image_data_uri(loc));
} else {
return create_texture_from_file(loc);
}
case locator::SUB_FILE:
return create_texture_from_sub_file(loc);
default:
return texture();
}
}
} // namespace
texture get_texture(const image::locator& i_locator, TYPE type)
@ -1307,8 +1153,7 @@ texture get_texture(const image::locator& i_locator, scale_quality quality, TYPE
return res;
}
// FIXME
//type = simplify_type(i_locator, type);
type = simplify_type(i_locator, type);
//
// Select the appropriate cache. We don't need caches for every single image types,
@ -1344,43 +1189,10 @@ texture get_texture(const image::locator& i_locator, scale_quality quality, TYPE
//
set_scale_quality_pre_texture_creation(quality);
switch(type) {
case TOD_COLORED:
case HEXED:
res = create_texture_post_surface_op(i_locator, type);
break;
default:
res = create_texture_from_disk(i_locator);
}
// Get it from the surface cache.
res = texture(get_surface(i_locator, type));
// If the texture is null at this point, return without any further action (like caching).
if(!res) {
return res;
}
//
// Apply the appropriate render flags. (TODO)
//
#if 0
switch(type) {
case SCALED_TO_ZOOM:
break;
case SCALED_TO_HEX:
break;
case BRIGHTENED:
break;
default:
// Ignore other types.
break;
}
#endif
//
// And finally add the texture to the cache.
//
// Cache the texture.
i_locator.add_to_cache(*cache, res);
return res;