Skip to content

Commit be12569

Browse files
committed
Added performance mode settings so that Texture2D's can be downsized at runtime for performance reasons
1 parent 0c51ede commit be12569

11 files changed

Lines changed: 264 additions & 10 deletions

File tree

core/io/image.cpp

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -455,6 +455,18 @@ Size2i Image::get_size() const {
455455
return Size2i(width, height);
456456
}
457457

458+
int Image::get_original_width() const {
459+
return original_width;
460+
}
461+
462+
int Image::get_original_height() const {
463+
return original_height;
464+
}
465+
466+
Size2i Image::get_original_size() const {
467+
return Size2i(original_width, original_height);
468+
}
469+
458470
bool Image::has_mipmaps() const {
459471
return mipmaps;
460472
}
@@ -765,6 +777,102 @@ void Image::convert(Format p_new_format) {
765777
_copy_internals_from(new_img);
766778
}
767779

780+
Image::PerformanceMode Image::get_performance_mode() const {
781+
return performance_mode;
782+
}
783+
784+
Error Image::set_performance_mode(PerformanceMode p_performance_mode) {
785+
switch (performance_mode) {
786+
case PERFORMANCE_MODE_ORIGINAL_SIZE:
787+
break;
788+
789+
default:
790+
ERR_FAIL_V_MSG(FAILED, "Image's performance_mode has already been set. It needs to be reloaded/recreated before it can be set again");
791+
}
792+
793+
performance_mode = p_performance_mode;
794+
795+
Size2i size = get_size();
796+
Vector2i desired_size = size;
797+
798+
switch (performance_mode) {
799+
case PERFORMANCE_MODE_ORIGINAL_SIZE:
800+
break;
801+
802+
case PERFORMANCE_MODE_MAX_SIZE: {
803+
Vector2i max_size = GLOBAL_GET("rendering/textures/performance/max_size");
804+
805+
if (desired_size.x > max_size.x) {
806+
desired_size.x = max_size.x;
807+
}
808+
809+
if (desired_size.y > max_size.y) {
810+
desired_size.y = max_size.y;
811+
}
812+
813+
break;
814+
}
815+
816+
case PERFORMANCE_MODE_DOWNSCALE_SIZE: {
817+
int factor = GLOBAL_GET("rendering/textures/performance/downscale_factor");
818+
factor = CLAMP(factor, 1, 14);
819+
820+
desired_size.x >>= factor;
821+
desired_size.y >>= factor;
822+
823+
break;
824+
}
825+
826+
default:
827+
ERR_FAIL_V_MSG(FAILED, vformat("Unknown image performance mode '%i'", performance_mode));
828+
}
829+
830+
desired_size = desired_size.max(Vector2i(1, 1));
831+
832+
if (desired_size == size) {
833+
return OK;
834+
}
835+
836+
if (is_compressed()) {
837+
Format current_format = get_format();
838+
839+
Error err = decompress();
840+
841+
if (err != OK) {
842+
ERR_FAIL_V_MSG(FAILED, vformat("Cannot decompress image format '%s'", current_format));
843+
}
844+
845+
resize(desired_size.x, desired_size.y);
846+
847+
Image::CompressMode compress_mode = COMPRESS_MAX;
848+
849+
if ((current_format >= FORMAT_DXT1 && current_format <= FORMAT_RGTC_RG) || (current_format == FORMAT_DXT5_RA_AS_RG)) {
850+
compress_mode = COMPRESS_S3TC;
851+
} else if (current_format >= FORMAT_BPTC_RGBA && current_format <= FORMAT_BPTC_RGBFU) {
852+
compress_mode = COMPRESS_BPTC;
853+
} else if (current_format == FORMAT_ETC) {
854+
compress_mode = COMPRESS_ETC;
855+
} else if (current_format >= FORMAT_ETC2_R11 && current_format <= FORMAT_ETC2_RA_AS_RG) {
856+
compress_mode = COMPRESS_ETC2;
857+
} else if (current_format >= FORMAT_ASTC_4x4 && current_format <= FORMAT_ASTC_8x8_HDR) {
858+
compress_mode = COMPRESS_ASTC;
859+
}
860+
861+
if (compress_mode != COMPRESS_MAX) {
862+
compress(compress_mode);
863+
} else {
864+
ERR_PRINT(vformat("Cannot recompress image format '%s'", current_format));
865+
}
866+
} else {
867+
resize(desired_size.x, desired_size.y);
868+
}
869+
870+
original_width = size.x;
871+
original_height = size.y;
872+
873+
return OK;
874+
}
875+
768876
Image::Format Image::get_format() const {
769877
return format;
770878
}
@@ -1429,6 +1537,7 @@ void Image::resize(int p_width, int p_height, Interpolation p_interpolation) {
14291537
}
14301538

14311539
_copy_internals_from(dst);
1540+
performance_mode = PERFORMANCE_MODE_ORIGINAL_SIZE;
14321541
}
14331542

14341543
void Image::crop_from_point(int p_x, int p_y, int p_width, int p_height) {
@@ -1592,6 +1701,10 @@ void Image::rotate_90(ClockDirection p_direction) {
15921701

15931702
width = h;
15941703
height = w;
1704+
int o_h = original_height;
1705+
int o_w = original_width;
1706+
original_height = o_w;
1707+
original_width = o_h;
15951708
}
15961709

15971710
#undef PREV_INDEX_IN_CYCLE
@@ -1902,6 +2015,8 @@ void Image::shrink_x2() {
19022015

19032016
width = MAX(width / 2, 1);
19042017
height = MAX(height / 2, 1);
2018+
original_width = width;
2019+
original_height = height;
19052020
data = new_data;
19062021
}
19072022

@@ -2193,6 +2308,8 @@ void Image::initialize_data(int p_width, int p_height, bool p_use_mipmaps, Forma
21932308

21942309
width = p_width;
21952310
height = p_height;
2311+
original_width = p_width;
2312+
original_height = p_height;
21962313
mipmaps = p_use_mipmaps;
21972314
format = p_format;
21982315
}
@@ -2229,10 +2346,14 @@ void Image::initialize_data(int p_width, int p_height, bool p_use_mipmaps, Forma
22292346

22302347
height = p_height;
22312348
width = p_width;
2349+
original_height = p_height;
2350+
original_width = p_width;
22322351
format = p_format;
22332352
data = p_data;
22342353

22352354
mipmaps = p_use_mipmaps;
2355+
2356+
performance_mode = PERFORMANCE_MODE_ORIGINAL_SIZE;
22362357
}
22372358

22382359
void Image::initialize_data(const char **p_xpm) {
@@ -2242,6 +2363,8 @@ void Image::initialize_data(const char **p_xpm) {
22422363
mipmaps = false;
22432364
bool has_alpha = false;
22442365

2366+
performance_mode = PERFORMANCE_MODE_ORIGINAL_SIZE;
2367+
22452368
enum Status {
22462369
READING_HEADER,
22472370
READING_COLORS,
@@ -2775,6 +2898,8 @@ Error Image::compress_from_channels(CompressMode p_mode, UsedChannels p_channels
27752898
Image::Image(const char **p_xpm) {
27762899
width = 0;
27772900
height = 0;
2901+
original_width = 0;
2902+
original_height = 0;
27782903
mipmaps = false;
27792904
format = FORMAT_L8;
27802905

@@ -2784,6 +2909,8 @@ Image::Image(const char **p_xpm) {
27842909
Image::Image(int p_width, int p_height, bool p_use_mipmaps, Format p_format) {
27852910
width = 0;
27862911
height = 0;
2912+
original_width = 0;
2913+
original_height = 0;
27872914
mipmaps = p_use_mipmaps;
27882915
format = FORMAT_L8;
27892916

@@ -2793,6 +2920,8 @@ Image::Image(int p_width, int p_height, bool p_use_mipmaps, Format p_format) {
27932920
Image::Image(int p_width, int p_height, bool p_mipmaps, Format p_format, const Vector<uint8_t> &p_data) {
27942921
width = 0;
27952922
height = 0;
2923+
original_width = 0;
2924+
original_height = 0;
27962925
mipmaps = p_mipmaps;
27972926
format = FORMAT_L8;
27982927

@@ -3113,6 +3242,8 @@ void Image::fill_rect(const Rect2i &p_rect, const Color &p_color) {
31133242
void Image::_set_data(const Dictionary &p_data) {
31143243
ERR_FAIL_COND(!p_data.has("width"));
31153244
ERR_FAIL_COND(!p_data.has("height"));
3245+
ERR_FAIL_COND(!p_data.has("original_width"));
3246+
ERR_FAIL_COND(!p_data.has("original_height"));
31163247
ERR_FAIL_COND(!p_data.has("format"));
31173248
ERR_FAIL_COND(!p_data.has("mipmaps"));
31183249
ERR_FAIL_COND(!p_data.has("data"));
@@ -3133,12 +3264,17 @@ void Image::_set_data(const Dictionary &p_data) {
31333264
ERR_FAIL_COND(ddformat == FORMAT_MAX);
31343265

31353266
initialize_data(dwidth, dheight, dmipmaps, ddformat, ddata);
3267+
3268+
original_width = p_data["original_width"];
3269+
original_height = p_data["original_height"];
31363270
}
31373271

31383272
Dictionary Image::_get_data() const {
31393273
Dictionary d;
31403274
d["width"] = width;
31413275
d["height"] = height;
3276+
d["original_width"] = original_width;
3277+
d["original_height"] = original_height;
31423278
d["format"] = get_format_name(format);
31433279
d["mipmaps"] = mipmaps;
31443280
d["data"] = data;
@@ -3153,6 +3289,8 @@ void Image::_copy_internals_from(const Image &p_image) {
31533289
format = p_image.format;
31543290
width = p_image.width;
31553291
height = p_image.height;
3292+
original_width = p_image.original_width;
3293+
original_height = p_image.original_height;
31563294
mipmaps = p_image.mipmaps;
31573295
data = p_image.data;
31583296
}
@@ -3515,7 +3653,12 @@ void Image::_bind_methods() {
35153653
ClassDB::bind_method(D_METHOD("get_width"), &Image::get_width);
35163654
ClassDB::bind_method(D_METHOD("get_height"), &Image::get_height);
35173655
ClassDB::bind_method(D_METHOD("get_size"), &Image::get_size);
3656+
ClassDB::bind_method(D_METHOD("get_original_width"), &Image::get_original_width);
3657+
ClassDB::bind_method(D_METHOD("get_original_height"), &Image::get_original_height);
3658+
ClassDB::bind_method(D_METHOD("get_original_size"), &Image::get_original_size);
35183659
ClassDB::bind_method(D_METHOD("has_mipmaps"), &Image::has_mipmaps);
3660+
ClassDB::bind_method(D_METHOD("get_performance_mode"), &Image::get_performance_mode);
3661+
ClassDB::bind_method(D_METHOD("set_performance_mode", "performance_mode"), &Image::set_performance_mode);
35193662
ClassDB::bind_method(D_METHOD("get_format"), &Image::get_format);
35203663
ClassDB::bind_method(D_METHOD("get_data"), &Image::get_data);
35213664
ClassDB::bind_method(D_METHOD("get_data_size"), &Image::get_data_size);
@@ -3618,6 +3761,9 @@ void Image::_bind_methods() {
36183761
BIND_CONSTANT(MAX_WIDTH);
36193762
BIND_CONSTANT(MAX_HEIGHT);
36203763

3764+
BIND_ENUM_CONSTANT(PERFORMANCE_MODE_ORIGINAL_SIZE);
3765+
BIND_ENUM_CONSTANT(PERFORMANCE_MODE_MAX_SIZE);
3766+
BIND_ENUM_CONSTANT(PERFORMANCE_MODE_DOWNSCALE_SIZE);
36213767
BIND_ENUM_CONSTANT(FORMAT_L8);
36223768
BIND_ENUM_CONSTANT(FORMAT_LA8);
36233769
BIND_ENUM_CONSTANT(FORMAT_R8);
@@ -3748,6 +3894,8 @@ Ref<Image> Image::get_image_from_mipmap(int p_mipmap) const {
37483894
image.instantiate();
37493895
image->width = w;
37503896
image->height = h;
3897+
image->original_width = w;
3898+
image->original_height = h;
37513899
image->format = format;
37523900
image->data = new_data;
37533901

@@ -4249,6 +4397,8 @@ void Image::renormalize_rgbe9995(uint32_t *p_rgb) {
42494397
Image::Image(const uint8_t *p_mem_png_jpg, int p_len) {
42504398
width = 0;
42514399
height = 0;
4400+
original_width = 0;
4401+
original_height = 0;
42524402
mipmaps = false;
42534403
format = FORMAT_L8;
42544404

@@ -4281,6 +4431,8 @@ void Image::copy_internals_from(const Ref<Image> &p_image) {
42814431
format = p_image->format;
42824432
width = p_image->width;
42834433
height = p_image->height;
4434+
original_width = p_image->original_width;
4435+
original_height = p_image->original_height;
42844436
mipmaps = p_image->mipmaps;
42854437
data = p_image->data;
42864438
}

core/io/image.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,12 @@ class Image : public Resource {
7171
MAX_PIXELS = 268435456 // 16384 ^ 2
7272
};
7373

74+
enum PerformanceMode {
75+
PERFORMANCE_MODE_ORIGINAL_SIZE,
76+
PERFORMANCE_MODE_MAX_SIZE,
77+
PERFORMANCE_MODE_DOWNSCALE_SIZE
78+
};
79+
7480
enum Format : int32_t {
7581
FORMAT_L8, // Luminance
7682
FORMAT_LA8, // Luminance-Alpha
@@ -249,10 +255,13 @@ class Image : public Resource {
249255
static void _bind_methods();
250256

251257
private:
258+
PerformanceMode performance_mode = PERFORMANCE_MODE_ORIGINAL_SIZE;
252259
Format format = FORMAT_L8;
253260
Vector<uint8_t> data;
254261
int width = 0;
255262
int height = 0;
263+
int original_width = 0;
264+
int original_height = 0;
256265
bool mipmaps = false;
257266

258267
void _copy_internals_from(const Image &p_image);
@@ -291,12 +300,18 @@ class Image : public Resource {
291300
int get_width() const;
292301
int get_height() const;
293302
Size2i get_size() const;
303+
int get_original_width() const;
304+
int get_original_height() const;
305+
Size2i get_original_size() const;
294306
bool has_mipmaps() const;
295307
int get_mipmap_count() const;
296308

297309
// Convert the image to another format, conversion only to raw byte format.
298310
void convert(Format p_new_format);
299311

312+
PerformanceMode get_performance_mode() const;
313+
Error set_performance_mode(PerformanceMode p_performance_mode);
314+
300315
Format get_format() const;
301316

302317
// Get where the mipmap begins in data.
@@ -448,6 +463,7 @@ class Image : public Resource {
448463
Dictionary compute_image_metrics(const Ref<Image> p_compared_image, bool p_luma_metric = true);
449464
};
450465

466+
VARIANT_ENUM_CAST(Image::PerformanceMode)
451467
VARIANT_ENUM_CAST(Image::Format)
452468
VARIANT_ENUM_CAST(Image::Interpolation)
453469
VARIANT_ENUM_CAST(Image::CompressMode)

0 commit comments

Comments
 (0)