Skip to content

Commit

Permalink
Allowed IPFs to work again when using the texture cache
Browse files Browse the repository at this point in the history
See create_texture_from_sub_file doc comment for more info.
  • Loading branch information
Vultraz committed Mar 8, 2018
1 parent fc720ec commit 238ba67
Show file tree
Hide file tree
Showing 2 changed files with 81 additions and 4 deletions.
84 changes: 80 additions & 4 deletions src/image.cpp
Expand Up @@ -1377,7 +1377,7 @@ bool update_from_preferences()
*/

/** Loads a new texture directly from disk. */
static texture load_texture_from_disk(const image::locator& loc)
static texture create_texture_from_file(const image::locator& loc)
{
texture res;

Expand All @@ -1398,8 +1398,7 @@ static texture load_texture_from_disk(const image::locator& loc)
}
#endif

// TODO: do we need SDL_RWops after all? Not sure if SDL_image even has a RWops load
// function for textures?
// TODO: if we need to use SDL_RWops we should use IMG_LoadTexture_RW here instead.
{
texture temp(IMG_LoadTexture(renderer, location.c_str()));
res = temp;
Expand Down Expand Up @@ -1431,6 +1430,83 @@ static texture load_texture_from_disk(const image::locator& loc)
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.
*/
static 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) {
ERR_CFG << "Failed to apply a modification to an image:\n"
<< "Image: " << loc.get_filename() << ".\n"
<< "Modifications: " << loc.get_modifications() << ".\n"
<< "Error: " << e.message;
}

// 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);
}

texture create_texture_from_disk(const locator& loc)
{
switch(loc.get_type()) {
case locator::FILE:
return create_texture_from_file(loc);
case locator::SUB_FILE:
return create_texture_from_sub_file(loc);
default:
return texture();
}
}

/**
* Small wrapper for creating a texture after applying a specific type of surface op.
* Won't be necessary once we get shader support.
Expand Down Expand Up @@ -1503,7 +1579,7 @@ texture get_texture(const image::locator& i_locator, TYPE type)
res = create_texture_post_surface_op(i_locator, type);
break;
default:
res = load_texture_from_disk(i_locator);
res = create_texture_from_disk(i_locator);
}

// If the texture is null at this point, return without any further action (like caching).
Expand Down
1 change: 1 addition & 0 deletions src/image.hpp
Expand Up @@ -125,6 +125,7 @@ namespace image {
};

surface load_from_disk(const locator &loc);
texture create_texture_from_disk(const locator& loc);

typedef cache_type<surface> image_cache;
typedef cache_type<texture> texture_cache;
Expand Down

0 comments on commit 238ba67

Please sign in to comment.