Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Texture speedups #6762

Merged
merged 20 commits into from
Jun 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion data/campaigns/World_Conquest/gui/help_dialog.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
{gui/macros}

#define FORMULA_GUI_SCALE_RESOLUTION SIZE
"(max({SIZE}, floor({SIZE} * 265 * 2 / (3 * screen_pitch_microns))))"
"({SIZE})"
#enddef

[resolution]
Expand Down
9 changes: 3 additions & 6 deletions data/gui/macros/_initial.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -373,14 +373,11 @@
window_height = 900
#enddef

# The magic number 265 in the below formula is the pixel pitch in microns
# corresponding to 96 dpi, which the old layout seems to have been based on.
# The extra factor of 2/3 in the formula is a fudge factor based on the guess
# that the old fonts took up approximately 1.5 pixels per point size at 96
# dpi. It came out looking pretty decent on my 90-micron monitor.
# scaling based on physical DPI has been disabled. This macro remains,
# and may still be used in the future for adaptive or manual UI scaling.

#define GUI_SCALE_RESOLUTION SIZE
(max({SIZE}, floor({SIZE} * 265 * 2 / (3 * screen_pitch_microns))))
({SIZE})
#enddef

#define GUI_WINDOW_PERC_FIXED_SIZE_CENTERED PERC_W PERC_H WIDTH HEIGHT
Expand Down
2 changes: 1 addition & 1 deletion src/arrow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -142,7 +142,7 @@ void arrow::draw_hex(const map_location& hex)
{
display* disp = display::get_singleton();
disp->render_image(disp->get_location_x(hex), disp->get_location_y(hex), layer_,
hex, image::get_image(symbols_map_[hex], image::SCALED_TO_ZOOM));
hex, symbols_map_[hex]);
}
}

Expand Down
13 changes: 0 additions & 13 deletions src/build_info.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -568,17 +568,6 @@ list_formatter video_settings_report_internal(const std::string& heading = "")
const auto& current_driver = CVideo::current_driver();
auto drivers = CVideo::enumerate_drivers();

const auto& dpi = video.get_dpi();
const auto& scale = video.get_dpi_scale_factor();
std::string dpi_report, scale_report;

if(dpi.first == 0.0f || dpi.second == 0.0f) {
scale_report = dpi_report = "<unknown>";
} else {
dpi_report = geometry_to_string(dpi.first, dpi.second);
scale_report = geometry_to_string(scale.first, scale.second);
}

fmt.insert("SDL video drivers", format_sdl_driver_list(drivers, current_driver));
fmt.insert("Window size", geometry_to_string(
video.current_resolution().x, video.current_resolution().y));
Expand All @@ -587,8 +576,6 @@ list_formatter video_settings_report_internal(const std::string& heading = "")
fmt.insert("Final render target size", geometry_to_string(
video.output_size().x, video.output_size().y));
fmt.insert("Screen refresh rate", std::to_string(video.current_refresh_rate()));
fmt.insert("Screen dots per inch", dpi_report);
fmt.insert("Screen dpi scale factor", scale_report);

return fmt;
}
Expand Down
196 changes: 113 additions & 83 deletions src/display.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -804,8 +804,8 @@ surface display::screenshot(bool map_screenshot)
LOG_DP << "creating " << area.w << " by " << area.h
<< " texture for map screenshot" << std::endl;
texture output_texture(area.w, area.h, SDL_TEXTUREACCESS_TARGET);
auto target_setter = video().set_render_target(output_texture);
auto clipper = video().set_clip(area);
auto target_setter = draw::set_render_target(output_texture);
auto clipper = draw::set_clip(area);

map_screenshot_ = true;
dirty_ = true;
Expand Down Expand Up @@ -1050,6 +1050,7 @@ std::vector<texture> display::get_fog_shroud_images(const map_location& loc, ima
return res;
}

// TODO: highdpi - verify these get scaled correctly
void display::get_terrain_images(const map_location& loc, const std::string& timeid, TERRAIN_TYPE terrain_type)
{
terrain_image_vector_.clear();
Expand Down Expand Up @@ -1188,11 +1189,11 @@ void display::get_terrain_images(const map_location& loc, const std::string& tim
|| image.get_modifications().find("NO_TOD_SHIFT()") != std::string::npos);

if(off_map) {
tex = image::get_texture(image, image::SCALED_TO_HEX);
tex = image::get_texture(image, image::HEXED);
} else if(lt.empty()) {
tex = image::get_texture(image, image::SCALED_TO_HEX);
tex = image::get_texture(image, image::HEXED);
} else {
tex = image::get_lighted_texture(image, lt, image::SCALED_TO_HEX);
tex = image::get_lighted_texture(image, lt);
}

if(tex) {
Expand All @@ -1204,17 +1205,21 @@ void display::get_terrain_images(const map_location& loc, const std::string& tim

void display::drawing_buffer_add(const drawing_layer layer,
const map_location& loc, const SDL_Rect& dest, const texture& tex,
const SDL_Rect &clip)
const SDL_Rect &clip, bool hflip, bool vflip, uint8_t alpha_mod)
{
drawing_buffer_.emplace_back(layer, loc, dest, tex, clip);
drawing_buffer_.emplace_back(
layer, loc, dest, tex, clip, hflip, vflip, alpha_mod
);
}

void display::drawing_buffer_add(const drawing_layer layer,
const map_location& loc, const SDL_Rect& dest,
const std::vector<texture> &tex,
const SDL_Rect &clip)
const SDL_Rect &clip, bool hflip, bool vflip, uint8_t alpha_mod)
{
drawing_buffer_.emplace_back(layer, loc, dest, tex, clip);
drawing_buffer_.emplace_back(
layer, loc, dest, tex, clip, hflip, vflip, alpha_mod
);
}

enum {
Expand Down Expand Up @@ -1274,7 +1279,7 @@ void display::drawing_buffer_commit()
// std::list::sort() is a stable sort
drawing_buffer_.sort();

auto clipper = screen_.set_clip(map_area());
auto clipper = draw::set_clip(map_area());

/*
* Info regarding the rendering algorithm.
Expand All @@ -1291,12 +1296,21 @@ void display::drawing_buffer_commit()

// TODO: highdpi - perhaps it might be desirable to optionally apply colour and alpha modifiers here?
for(const blit_helper& blit : drawing_buffer_) {
for(const texture& tex : blit.tex()) {
for(texture tex : blit.tex()) {
const SDL_Rect& src = blit.clip();
const uint8_t alpha_mod = blit.alpha_mod();
const bool hflip = blit.hflip();
const bool vflip = blit.vflip();
if (alpha_mod != SDL_ALPHA_OPAQUE) {
tex.set_alpha_mod(alpha_mod);
}
if (src != sdl::empty_rect) {
draw::blit(tex, blit.dest(), src);
draw::flipped(tex, blit.dest(), src, hflip, vflip);
} else {
draw::blit(tex, blit.dest());
draw::flipped(tex, blit.dest(), hflip, vflip);
}
if (alpha_mod != SDL_ALPHA_OPAQUE) {
tex.set_alpha_mod(SDL_ALPHA_OPAQUE);
}
}
}
Expand Down Expand Up @@ -1501,80 +1515,101 @@ void display::draw_text_in_hex(const map_location& loc,
drawing_buffer_add(layer, loc, {x, y, w, h}, text_surf);
}

//TODO: highdpi - convert this to use sdl::texture
void display::render_image(int x, int y, const display::drawing_layer drawing_layer,
const map_location& loc, surface image,
const map_location& loc, const image::locator& i_locator,
bool hreverse, bool greyscale, int32_t alpha,
color_t blendto, double blend_ratio, double submerged, bool vreverse)
{
if (image==nullptr)
const point image_size = image::get_size(i_locator);
if (!image_size.x || !image_size.y) {
return;
}

SDL_Rect image_rect {x, y, image->w, image->h};
SDL_Rect clip_rect = map_area();
if (!sdl::rects_overlap(image_rect, clip_rect))
// TODO: highdpi - are x,y correct here?
SDL_Rect dest = scaled_to_zoom({x, y, image_size.x, image_size.y});
if (!sdl::rects_overlap(dest, map_area())) {
return;

surface surf(image);

if(hreverse) {
// TODO: highdpi - well this will get removed in due process anyway
surf = flip_surface(surf);
}
if(vreverse) {
surf = flop_surface(surf);
}

if(greyscale) {
surf = greyscale_image(surf);
}
// For now, we add to the existing IPF modifications for the image.
std::string new_modifications;

if(blend_ratio != 0) {
surf = blend_surface(surf, blend_ratio, blendto);
}
if(alpha > floating_to_fixed_point(1.0)) {
surf = brighten_image(surf, alpha);
} else if(alpha != floating_to_fixed_point(1.0)) {
surf = surf.clone();
adjust_surface_alpha(surf, alpha);
if (greyscale) {
new_modifications += "~GS()";
}

if(surf == nullptr) {
ERR_DP << "surface lost..." << std::endl;
return;
if (blend_ratio > 0.0) {
new_modifications += "~BLEND(";
new_modifications += std::to_string(blendto.r);
new_modifications += ",";
new_modifications += std::to_string(blendto.g);
new_modifications += ",";
new_modifications += std::to_string(blendto.b);
new_modifications += ",";
// reduce blend_ratio precision to avoid caching too many options.
if (blend_ratio >= 1.0) {
new_modifications += "1.0";
} else {
new_modifications += "0.";
new_modifications += std::to_string(int(100*blend_ratio));
}
new_modifications += ")";
}

// TODO: highdpi - fix. Probably move all this alpha stuff to image::, so it doesn't have to be recalculated.
texture tex(surf);

if(submerged > 0.0) {
// divide the surface into 2 parts
const int submerge_height = std::max<int>(0, surf->h*(1.0-submerged));
const int depth = surf->h - submerge_height;
SDL_Rect srcrect {0, 0, surf->w, submerge_height};
SDL_Rect dest = {x, y, surf->w, submerge_height};
drawing_buffer_add(drawing_layer, loc, dest, tex, srcrect);

if(submerge_height != surf->h) {
//the lower part will be transparent
float alpha_base = 0.3f; // 30% alpha at surface of water
float alpha_delta = 0.015f; // lose 1.5% per pixel depth
alpha_delta *= zoom_ / DefaultZoom; // adjust with zoom
surf = submerge_alpha(surf, depth, alpha_base, alpha_delta);

srcrect.y = submerge_height;
srcrect.h = surf->h-submerge_height;
dest.y += submerge_height;
dest.h = srcrect.h;

drawing_buffer_add(drawing_layer, loc, dest, tex, srcrect);
}
// TODO: This is not what alpha means. Don't frivolously overload it.
// TODO: highdpi - perhaps this can be done by blitting twice, once in additive blend mode
// Note: this may not be identical to the original calculation,
// which was to multiply the RGB values by (alpha/255).
// But for now it looks close enough.
if(alpha > floating_to_fixed_point(1.0)) {
const std::string brighten_string = std::to_string((alpha - 255)/2);
new_modifications += "~CS(";
new_modifications += brighten_string;
new_modifications += ",";
new_modifications += brighten_string;
new_modifications += ",";
new_modifications += brighten_string;
new_modifications += ")";
}

// general formula for submerged alpha:
// if (y > WATERLINE)
// then min(max(alpha_mod, 0), 1) * alpha
// else alpha
// where alpha_mod = alpha_base - (y - WATERLINE) * alpha_delta
// formula variables: x, y, red, green, blue, alpha, width, height
// full WFL string:
// "~ADJUST_ALPHA(if(y>DL,clamp((AB-(y-DL)*AD),0,1)*alpha,alpha))"
// where DL = submersion line in pixels from top of image
// AB = base alpha proportion at submersion line (30%)
// AD = proportional alpha delta per pixel (1.5%)
if (submerged > 0.0) {
const int submersion_line = image_size.y * (1.0 - submerged);
const std::string sl_string = std::to_string(submersion_line);
new_modifications += "~ADJUST_ALPHA(if(y>";
new_modifications += sl_string;
new_modifications += ",clamp((0.3-(y-";
new_modifications += sl_string;
new_modifications += ")*0.015),0,1)*alpha,alpha))";
}

texture tex;
if (!new_modifications.empty()) {
const image::locator modified_locator(
i_locator.get_filename(),
i_locator.get_modifications() + new_modifications
);
tex = image::get_texture(modified_locator);
} else {
// simple blit
SDL_Rect dest = {x, y, surf->w, surf->h};
drawing_buffer_add(drawing_layer, loc, dest, tex);
tex = image::get_texture(i_locator);
}

// TODO: highdpi - flipping and alpha modification need to be propagated from hreverse, vreverse, alpha
const uint8_t alpha_mod = std::clamp(alpha, 0, 255);
drawing_buffer_add(drawing_layer, loc, dest, tex, sdl::empty_rect,
hreverse, vreverse, alpha_mod);
}

void display::select_hex(map_location hex)
{
invalidate(selectedHex_);
Expand Down Expand Up @@ -1754,7 +1789,7 @@ void display::draw_minimap()
}

// TODO: highdpi - does this really need to set a clipping area?
auto clipper = screen_.set_clip(area);
auto clipper = draw::set_clip(area);

// Draw the minimap background.
draw::fill(area, 31, 31, 23);
Expand Down Expand Up @@ -2479,7 +2514,7 @@ const SDL_Rect& display::get_clip_rect()
void display::draw_invalidated() {
// log_scope("display::draw_invalidated");
SDL_Rect clip_rect = get_clip_rect();
auto clipper = screen_.set_clip(clip_rect);
auto clipper = draw::set_clip(clip_rect);
for (const map_location& loc : invalidated_) {
int xpos = get_location_x(loc);
int ypos = get_location_y(loc);
Expand Down Expand Up @@ -2515,7 +2550,6 @@ void display::draw_hex(const map_location& loc)
{
int xpos = get_location_x(loc);
int ypos = get_location_y(loc);
image::TYPE image_type = get_image_type(loc);
const bool on_map = get_map().on_board(loc);
const time_of_day& tod = get_time_of_day(loc);
const int zoom = int(zoom_);
Expand Down Expand Up @@ -2567,7 +2601,7 @@ void display::draw_hex(const map_location& loc)
if(item_visible_for_team && !(fogged(loc) && !ov.visible_in_fog))
{
const texture tex = ov.image.find("~NO_TOD_SHIFT()") == std::string::npos ?
image::get_lighted_texture(ov.image, lt, image::SCALED_TO_HEX) : image::get_texture(ov.image, image::SCALED_TO_HEX);
image::get_lighted_texture(ov.image, lt) : image::get_texture(ov.image, image::HEXED);
drawing_buffer_add(LAYER_TERRAIN_BG, loc, dest, tex);
}
}
Expand All @@ -2589,7 +2623,7 @@ void display::draw_hex(const map_location& loc)
drawing_buffer_add(LAYER_TERRAIN_FG, loc, dest, texture(tod_hex_mask2));
} else if(!tod_hex_mask.empty()) {
drawing_buffer_add(LAYER_TERRAIN_FG, loc, dest,
image::get_texture(tod_hex_mask,image::SCALED_TO_HEX));
image::get_texture(tod_hex_mask,image::HEXED));
}

// Paint mouseover overlays
Expand All @@ -2615,15 +2649,15 @@ void display::draw_hex(const map_location& loc)
// to shroud the half-hexes too
const std::string& shroud_image = get_variant(shroud_images_, loc);
drawing_buffer_add(LAYER_FOG_SHROUD, loc, dest,
image::get_texture(shroud_image, image_type));
image::get_texture(shroud_image, image::TOD_COLORED));
} else if(fogged(loc)) {
const std::string& fog_image = get_variant(fog_images_, loc);
drawing_buffer_add(LAYER_FOG_SHROUD, loc, dest,
image::get_texture(fog_image, image_type));
image::get_texture(fog_image, image::TOD_COLORED));
}

if(!shrouded(loc)) {
drawing_buffer_add(LAYER_FOG_SHROUD, loc, dest, get_fog_shroud_images(loc, image_type));
drawing_buffer_add(LAYER_FOG_SHROUD, loc, dest, get_fog_shroud_images(loc, image::TOD_COLORED));
}

if (on_map) {
Expand Down Expand Up @@ -2693,15 +2727,11 @@ void display::draw_hex(const map_location& loc)

if(debug_foreground) {
drawing_buffer_add(LAYER_UNIT_DEFAULT, loc, dest,
image::get_texture("terrain/foreground.png", image_type));
image::get_texture("terrain/foreground.png", image::TOD_COLORED));
}

}

image::TYPE display::get_image_type(const map_location& /*loc*/) {
return image::TOD_COLORED;
}

// TODO: highdpi - why is there all this faff to deal with textures that are fill of transparency? Just don't make your textures full of transparency. This should not be a thing.
// Usage of this function has been removed.
// If this turns out to raise no problems, remove the function too.
Expand Down