Skip to content

Commit fe18b47

Browse files
authored
KTX1 / ETC2 Compressed textures support (#7070)
* Initial KTX1/ETC2 support * Conditional glad include * remove unused function * define glenum for non opengl build * remove unused param * fix qtbuild * change ktx format to enum * use nullptr * ktx: support the same etc2 formats available in amd compressonator * add comments and missing include * correct flag type * clarify variable name for clang * cleanup * update glad loader to GL4.3
1 parent 04f0410 commit fe18b47

11 files changed

Lines changed: 2393 additions & 246 deletions

File tree

code/bmpman/bm_internal.h

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ struct bitmap_entry {
7070
// Stuff to keep track of usage
7171
ubyte preloaded; //!< If set, then this was loaded from the lst file
7272
int preload_count; //!< how many times this gets used in game, for unlocking
73-
ushort used_flags; //!< What flags it was accessed thru
73+
uint used_flags; //!< What flags it was accessed thru
7474
int load_count;
7575

7676
bitmap bm; //!< Bitmap info
@@ -93,14 +93,15 @@ struct bitmap_slot {
9393
};
9494

9595
// image specific lock functions
96-
void bm_lock_ani( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ushort flags );
97-
void bm_lock_dds( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ushort flags );
98-
void bm_lock_png( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ushort flags );
99-
void bm_lock_apng( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ushort flags );
100-
void bm_lock_jpg( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ushort flags );
101-
void bm_lock_pcx( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ushort flags );
102-
void bm_lock_tga( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ushort flags );
103-
void bm_lock_user( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ushort flags, bool convert = true );
96+
void bm_lock_ani( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, uint flags );
97+
void bm_lock_dds( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, uint flags );
98+
void bm_lock_png( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, uint flags );
99+
void bm_lock_apng( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, uint flags );
100+
void bm_lock_jpg( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, uint flags );
101+
void bm_lock_pcx( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, uint flags );
102+
void bm_lock_tga( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, uint flags );
103+
void bm_lock_user( int handle, bitmap_slot *bs, bitmap *bmp, int bpp, uint flags, bool convert = true );
104+
void bm_lock_ktx1(int handle, bitmap_slot* bs, bitmap* bmp, int bpp, uint flags);
104105

105106
const size_t BM_BLOCK_SIZE = 4096;
106107

code/bmpman/bmpman.cpp

Lines changed: 124 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@
3232
#include "tgautils/tgautils.h"
3333
#include "tracing/Monitor.h"
3434
#include "tracing/tracing.h"
35+
#include "ktxutils/ktxutils.h"
3536

3637
#include <cctype>
3738
#include <climits>
@@ -59,8 +60,8 @@ size_t bm_texture_ram = 0;
5960
int Bm_paging = 0;
6061

6162
// Extension type lists
62-
const BM_TYPE bm_type_list[] = { BM_TYPE_DDS, BM_TYPE_TGA, BM_TYPE_PNG, BM_TYPE_JPG, BM_TYPE_PCX };
63-
const char *bm_ext_list[] = { ".dds", ".tga", ".png", ".jpg", ".pcx" };
63+
const BM_TYPE bm_type_list[] = { BM_TYPE_DDS, BM_TYPE_TGA, BM_TYPE_PNG, BM_TYPE_JPG, BM_TYPE_PCX, BM_TYPE_KTX };
64+
const char* bm_ext_list[] = { ".dds", ".tga", ".png", ".jpg", ".pcx", ".ktx" };
6465
const int BM_NUM_TYPES = sizeof(bm_type_list) / sizeof(bm_type_list[0]);
6566

6667
const BM_TYPE bm_ani_type_list[] = { BM_TYPE_EFF, BM_TYPE_ANI, BM_TYPE_PNG };
@@ -205,7 +206,7 @@ void clear_bm_lookup_cache() {
205206
/**
206207
* Converts the bitmap referenced by bmp to the type specified by flags
207208
*/
208-
static void bm_convert_format(bitmap *bmp, ushort flags);
209+
static void bm_convert_format(bitmap *bmp, uint flags);
209210

210211
/**
211212
* Frees a bitmap's data if it can
@@ -639,7 +640,7 @@ int bm_create_3d(int bpp, int w, int h, int d, void* data) {
639640
return n;
640641
}
641642

642-
void bm_convert_format(bitmap *bmp, ushort flags) {
643+
void bm_convert_format(bitmap *bmp, uint flags) {
643644
int idx;
644645

645646
// no transparency for 24 bpp images
@@ -901,7 +902,7 @@ void bm_get_frame_usage(int *ntotal, int *nnew) {
901902
#endif
902903
}
903904

904-
int bm_get_info(int handle, int *w, int * h, ushort* flags, int *nframes, int *fps) {
905+
int bm_get_info(int handle, int *w, int * h, uint* flags, int *nframes, int *fps) {
905906
bitmap * bmp;
906907

907908
if (!bm_inited) return -1;
@@ -1055,6 +1056,24 @@ int bm_is_compressed(int num) {
10551056
case BM_TYPE_CUBEMAP_DXT5:
10561057
return DDS_CUBEMAP_DXT5;
10571058

1059+
case BM_TYPE_ETC2_RGB:
1060+
return KTX_ETC2_RGB;
1061+
1062+
case BM_TYPE_ETC2_SRGB:
1063+
return KTX_ETC2_SRGB;
1064+
1065+
case BM_TYPE_ETC2_RGBA_EAC:
1066+
return KTX_ETC2_RGBA_EAC;
1067+
1068+
case BM_TYPE_ETC2_SRGBA_EAC:
1069+
return KTX_ETC2_SRGBA_EAC;
1070+
1071+
case BM_TYPE_ETC2_RGBA1:
1072+
return KTX_ETC2_RGB_A1;
1073+
1074+
case BM_TYPE_ETC2_SRGBA1:
1075+
return KTX_ETC2_SRGB_A1;
1076+
10581077
default:
10591078
return 0;
10601079
}
@@ -1148,6 +1167,16 @@ static int bm_load_info(BM_TYPE type, const char *filename, CFILE *img_cfp, int
11481167
return -1;
11491168
}
11501169
}
1170+
// its a KTX file
1171+
else if (type == BM_TYPE_KTX) {
1172+
int ktx_ct;
1173+
int ktx_error = ktx1_read_header(filename, img_cfp, w, h, bpp, &ktx_ct, mm_lvl, size);
1174+
if (ktx_error != KTX1_ERROR_NONE) {
1175+
mprintf(("ktx: could not open '%s'\n", filename));
1176+
return -1;
1177+
}
1178+
*c_type = (BM_TYPE)ktx_ct;
1179+
}
11511180
// if its a tga file
11521181
else if (type == BM_TYPE_TGA) {
11531182
int tga_error = targa_read_header(filename, img_cfp, w, h, bpp, NULL);
@@ -1361,6 +1390,8 @@ bool bm_load_and_parse_eff(const char *filename, int dir_type, int *nframes, int
13611390
c_type = BM_TYPE_JPG;
13621391
} else if (!stricmp(NOX("pcx"), ext)) {
13631392
c_type = BM_TYPE_PCX;
1393+
} else if (!stricmp(NOX("ktx"), ext)) {
1394+
c_type = BM_TYPE_KTX;
13641395
} else {
13651396
mprintf(("BMPMAN: Unknown file type in EFF parse!\n"));
13661397
return false;
@@ -1390,7 +1421,7 @@ bool bm_load_and_parse_eff(const char *filename, int dir_type, int *nframes, int
13901421
/**
13911422
* Lock an image files data into memory
13921423
*/
1393-
static int bm_load_image_data(int handle, int bpp, ushort flags, bool nodebug)
1424+
static int bm_load_image_data(int handle, int bpp, uint flags, bool nodebug)
13941425
{
13951426
BM_TYPE c_type = BM_TYPE_NONE;
13961427
int true_bpp;
@@ -1482,6 +1513,10 @@ static int bm_load_image_data(int handle, int bpp, ushort flags, bool nodebug)
14821513
bm_lock_user(handle, bs, bmp, true_bpp, flags, false);
14831514
break;
14841515

1516+
case BM_TYPE_KTX:
1517+
bm_lock_ktx1(handle, bs, bmp, true_bpp, flags);
1518+
break;
1519+
14851520
default:
14861521
Warning(LOCATION, "Unsupported type in bm_lock -- %d\n", c_type);
14871522
return -1;
@@ -1941,7 +1976,7 @@ int bm_load_sub_slow(const char *real_filename, const int num_ext, const char **
19411976
return -1;
19421977
}
19431978

1944-
bitmap * bm_lock(int handle, int bpp, ushort flags, bool nodebug) {
1979+
bitmap * bm_lock(int handle, int bpp, uint flags, bool nodebug) {
19451980
bitmap *bmp;
19461981

19471982
Assertion(bm_inited, "bmpman must be initialized before this function can be called!");
@@ -2038,7 +2073,7 @@ bitmap * bm_lock(int handle, int bpp, ushort flags, bool nodebug) {
20382073
return bmp;
20392074
}
20402075

2041-
void bm_lock_ani(int /*handle*/, bitmap_slot *bs, bitmap* /*bmp*/, int bpp, ushort flags) {
2076+
void bm_lock_ani(int /*handle*/, bitmap_slot *bs, bitmap* /*bmp*/, int bpp, uint flags) {
20422077
anim *the_anim;
20432078
anim_instance *the_anim_instance;
20442079
bitmap *bm;
@@ -2164,7 +2199,7 @@ void bm_lock_ani(int /*handle*/, bitmap_slot *bs, bitmap* /*bmp*/, int bpp, usho
21642199
}
21652200

21662201

2167-
void bm_lock_apng(int /*handle*/, bitmap_slot *bs, bitmap *bmp, int bpp, ushort /*flags*/) {
2202+
void bm_lock_apng(int /*handle*/, bitmap_slot *bs, bitmap *bmp, int bpp, uint /*flags*/) {
21682203
auto be = &bs->entry;
21692204
int first_frame = be->info.ani.first_frame;
21702205
auto first_entry = bm_get_entry(first_frame);
@@ -2214,7 +2249,7 @@ void bm_lock_apng(int /*handle*/, bitmap_slot *bs, bitmap *bmp, int bpp, ushort
22142249
}
22152250

22162251

2217-
void bm_lock_dds(int handle, bitmap_slot *bs, bitmap *bmp, int /*bpp*/, ushort /*flags*/) {
2252+
void bm_lock_dds(int handle, bitmap_slot *bs, bitmap *bmp, int /*bpp*/, uint /*flags*/) {
22182253
ubyte *data = NULL;
22192254
int error;
22202255
ubyte dds_bpp = 0;
@@ -2278,7 +2313,7 @@ void bm_lock_dds(int handle, bitmap_slot *bs, bitmap *bmp, int /*bpp*/, ushort /
22782313
#endif
22792314
}
22802315

2281-
void bm_lock_jpg(int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ushort /*flags*/) {
2316+
void bm_lock_jpg(int handle, bitmap_slot *bs, bitmap *bmp, int bpp, uint /*flags*/) {
22822317
ubyte *data = NULL;
22832318
int d_size = 0;
22842319
int jpg_error = JPEG_ERROR_INVALID;
@@ -2325,7 +2360,7 @@ void bm_lock_jpg(int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ushort /*fla
23252360
#endif
23262361
}
23272362

2328-
void bm_lock_pcx(int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ushort flags) {
2363+
void bm_lock_pcx(int handle, bitmap_slot *bs, bitmap *bmp, int bpp, uint flags) {
23292364
ubyte *data;
23302365
int pcx_error;
23312366
char filename[MAX_FILENAME_LEN];
@@ -2370,7 +2405,7 @@ void bm_lock_pcx(int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ushort flags
23702405
bm_convert_format(bmp, flags);
23712406
}
23722407

2373-
void bm_lock_png(int handle, bitmap_slot *bs, bitmap *bmp, int /*bpp*/, ushort /*flags*/) {
2408+
void bm_lock_png(int handle, bitmap_slot *bs, bitmap *bmp, int /*bpp*/, uint /*flags*/) {
23742409
ubyte *data = NULL;
23752410
//assume 32 bit - libpng should expand everything
23762411
int d_size;
@@ -2415,7 +2450,7 @@ void bm_lock_png(int handle, bitmap_slot *bs, bitmap *bmp, int /*bpp*/, ushort /
24152450
#endif
24162451
}
24172452

2418-
void bm_lock_tga(int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ushort flags) {
2453+
void bm_lock_tga(int handle, bitmap_slot *bs, bitmap *bmp, int bpp, uint flags) {
24192454
ubyte *data = NULL;
24202455
int byte_size;
24212456
char filename[MAX_FILENAME_LEN];
@@ -2474,7 +2509,7 @@ void bm_lock_tga(int handle, bitmap_slot *bs, bitmap *bmp, int bpp, ushort flags
24742509
bm_convert_format(bmp, flags);
24752510
}
24762511

2477-
void bm_lock_user(int /*handle*/, bitmap_slot *bs, bitmap *bmp, int bpp, ushort flags, bool convert) {
2512+
void bm_lock_user(int /*handle*/, bitmap_slot *bs, bitmap *bmp, int bpp, uint flags, bool convert) {
24782513
auto be = &bs->entry;
24792514

24802515
// Unload any existing data
@@ -2767,6 +2802,21 @@ void bm_page_in_texture(int bitmapnum, int nframes) {
27672802
frame_entry->used_flags = BMP_TEX_CUBEMAP;
27682803
continue;
27692804

2805+
case BM_TYPE_ETC2_RGB:
2806+
case BM_TYPE_ETC2_SRGB:
2807+
frame_entry->used_flags = BMP_TEX_ETC2_RGB8;
2808+
continue;
2809+
2810+
case BM_TYPE_ETC2_RGBA1:
2811+
case BM_TYPE_ETC2_SRGBA1:
2812+
frame_entry->used_flags = BMP_TEX_ETC2_RGBA1;
2813+
continue;
2814+
2815+
case BM_TYPE_ETC2_RGBA_EAC:
2816+
case BM_TYPE_ETC2_SRGBA_EAC:
2817+
frame_entry->used_flags = BMP_TEX_ETC2_RGBA8;
2818+
continue;
2819+
27702820
default:
27712821
continue;
27722822
}
@@ -2812,6 +2862,21 @@ void bm_page_in_xparent_texture(int bitmapnum, int nframes) {
28122862
entry->used_flags = BMP_TEX_CUBEMAP;
28132863
continue;
28142864

2865+
case BM_TYPE_ETC2_RGB:
2866+
case BM_TYPE_ETC2_SRGB:
2867+
entry->used_flags = BMP_TEX_ETC2_RGB8;
2868+
continue;
2869+
2870+
case BM_TYPE_ETC2_RGBA1:
2871+
case BM_TYPE_ETC2_SRGBA1:
2872+
entry->used_flags = BMP_TEX_ETC2_RGBA1;
2873+
continue;
2874+
2875+
case BM_TYPE_ETC2_RGBA_EAC:
2876+
case BM_TYPE_ETC2_SRGBA_EAC:
2877+
entry->used_flags = BMP_TEX_ETC2_RGBA8;
2878+
continue;
2879+
28152880
default:
28162881
continue;
28172882
}
@@ -3432,3 +3497,47 @@ SDL_Surface* bm_to_sdl_surface(int handle) {
34323497
return bitmapSurface;
34333498

34343499
}
3500+
3501+
// copied bm_lock_dds and adjusted for ktx. missing BIG_ENDIAN
3502+
void bm_lock_ktx1(int handle, bitmap_slot* bs, bitmap* bmp, int bpp, uint flags)
3503+
{
3504+
(void)bpp;
3505+
(void)flags;
3506+
ubyte* data = nullptr;
3507+
ubyte ktx_bpp = 0;
3508+
int ktx_error = KTX1_ERROR_NONE;
3509+
char filename[MAX_FILENAME_LEN];
3510+
3511+
auto be = &bs->entry;
3512+
3513+
bm_free_data(bs);
3514+
3515+
Assert(be->mem_taken > 0);
3516+
Assert(&be->bm == bmp);
3517+
3518+
data = (ubyte*)bm_malloc(handle, be->mem_taken);
3519+
if (!data)
3520+
return;
3521+
memset(data, 0, be->mem_taken);
3522+
3523+
// make sure we are using the correct filename in the case of an EFF.
3524+
// this will populate filename[] whether it's EFF or not
3525+
EFF_FILENAME_CHECK;
3526+
3527+
ktx_error = ktx1_read_bitmap(filename, data, &ktx_bpp);
3528+
3529+
if (ktx_error != KTX1_ERROR_NONE)
3530+
{
3531+
mprintf(("KTX: read_bitmap error=%d file='%s'\n", ktx_error, filename));
3532+
bm_free_data(bs);
3533+
return;
3534+
}
3535+
3536+
bmp->bpp = ktx_bpp;
3537+
bmp->data = (ptr_u)data;
3538+
bmp->flags = 0;
3539+
3540+
#ifdef BMPMAN_NDEBUG
3541+
Assert(be->data_size > 0);
3542+
#endif
3543+
}

code/bmpman/bmpman.h

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434

3535
// Flag positions for bitmap.flags
3636
// ***** NOTE: bitmap.flags is an 8-bit value, no more BMP_TEX_* flags can be added unless the type is changed!! ******
37+
// Update: bitmap.flags type changed to 16-bit
3738
#define BMP_AABITMAP (1<<0) //!< antialiased bitmap
3839
#define BMP_TEX_XPARENT (1<<1) //!< transparent texture
3940
#define BMP_TEX_OTHER (1<<2) //!< so we can identify all "normal" textures
@@ -43,9 +44,14 @@
4344
#define BMP_TEX_BC7 (1<<6) //!< BC7 compressed 8r8g8b8a (32bit)
4445
#define BMP_TEX_CUBEMAP (1<<7) //!< a texture made for cubic environment map
4546
#define BMP_MASK_BITMAP (1<<8) //!< a bitmap that will be used for masking mouse interaction. Typically not used in render operations
47+
#define BMP_TEX_ETC2_RGB8 (1 << 9) //!< ETC2 RGB compressed (24bit, no alpha)
48+
#define BMP_TEX_ETC2_RGBA1 (1 << 10) //!< ETC2 RGBA1 compressed (24bit, 1 alpha)
49+
#define BMP_TEX_ETC2_RGBA8 (1 << 11) //!< ETC2 RGBA8 compressed (32bit, 8 alpha)
50+
4651

4752
// Combined flags
48-
#define BMP_TEX_COMP ( BMP_TEX_DXT1 | BMP_TEX_DXT3 | BMP_TEX_DXT5 | BMP_TEX_BC7 ) //!< Compressed textures
53+
#define BMP_TEX_COMP ( BMP_TEX_DXT1 | BMP_TEX_DXT3 | BMP_TEX_DXT5 | BMP_TEX_BC7 | BMP_TEX_ETC2_RGB8 |\
54+
BMP_TEX_ETC2_RGBA1 | BMP_TEX_ETC2_RGBA8 ) //!< Compressed textures
4955
#define BMP_TEX_NONCOMP ( BMP_TEX_XPARENT | BMP_TEX_OTHER ) //!< Non-compressed textures
5056
#define BMP_TEX_ANY ( BMP_TEX_COMP | BMP_TEX_NONCOMP ) //!< Any texture
5157

@@ -81,7 +87,15 @@ enum BM_TYPE
8187
BM_TYPE_CUBEMAP_DXT3, //!< 32-bit cubemap (compressed cubemap surface)
8288
BM_TYPE_CUBEMAP_DXT5, //!< 32-bit cubemap (compressed cubemap surface)
8389

84-
BM_TYPE_3D //!< 3D in-memory
90+
BM_TYPE_3D, //!< 3D in-memory
91+
92+
BM_TYPE_KTX, //!< generic identifier for KTX1
93+
BM_TYPE_ETC2_RGB, //!< 24 bit, no alpha
94+
BM_TYPE_ETC2_SRGB, //!< 24 bit, no alpha, signed
95+
BM_TYPE_ETC2_RGBA1, //!< 24 bit, 1 bit alpha
96+
BM_TYPE_ETC2_SRGBA1, //!< 24 bit, 1 bit alpha, signed
97+
BM_TYPE_ETC2_RGBA_EAC, //!< 32 bit, 8 bit alpha
98+
BM_TYPE_ETC2_SRGBA_EAC //!< 32 bit, 8 bit alpha, signed
8599
};
86100

87101
/**
@@ -96,7 +110,7 @@ struct bitmap
96110
short rowsize; //!< What you need to add to go to next row
97111
int bpp; //!< Requested bitdepth of each pixel. ( 7, 8, 15, 16, 24, 32)
98112
int true_bpp; //!< The image's actual bitdepth
99-
ushort flags; //!< Various texture type flags. @see BMPMAN_CONSTANTS
113+
uint flags; //!< Various texture type flags. @see BMPMAN_CONSTANTS
100114
ptr_u data; //!< Pointer to data, or maybe offset into VRAM.
101115
ubyte *palette; /**< @brief Pointer to this bitmap's palette (if it has one).
102116
* @details If BMP_NO_PALETTE_MAP flag is cleared, this palette just points to the screen palette. (gr_palette)
@@ -345,7 +359,7 @@ int bm_load_either(const char *filename, int *nframes = NULL, int *fps = NULL, i
345359
* @returns A pointer to the bitmap that's valid until bm_unlock is called if successful, or
346360
* @returns NULL if unsuccessful
347361
*/
348-
bitmap* bm_lock(int handle, int bpp, ushort flags, bool nodebug = false);
362+
bitmap* bm_lock(int handle, int bpp, uint flags, bool nodebug = false);
349363

350364
/**
351365
* @brief Returns the image type of the given bitmap handle
@@ -388,7 +402,7 @@ int bm_is_valid(int handle);
388402
* @returns The handle to the first frame on success, or
389403
* @returns -1 on failure
390404
*/
391-
int bm_get_info(int handle, int *w = nullptr, int * h = nullptr, ushort* flags = nullptr, int *nframes = nullptr, int *fps = nullptr);
405+
int bm_get_info(int handle, int *w = nullptr, int * h = nullptr, uint* flags = nullptr, int *nframes = nullptr, int *fps = nullptr);
392406

393407
/**
394408
* @brief Gets 3D info on the bitmap indexed by handle.

0 commit comments

Comments
 (0)