Some texture loading optimizations
This commit is contained in:
parent
54ca97587c
commit
d9a84e083d
12 changed files with 74 additions and 53 deletions
|
@ -9,8 +9,8 @@ resources_gfx_dir = join_paths(resources_pkg_main, 'gfx')
|
|||
# 3. Profile-specific
|
||||
|
||||
preset_webp = [
|
||||
# Leanify doesn't handle webp (yet?), so skip it.
|
||||
'--no-leanify',
|
||||
# Leanify doesn't handle webp (yet?), but it'll work on alphamaps (they are always png)
|
||||
'--leanify',
|
||||
'--format', 'webp',
|
||||
]
|
||||
|
||||
|
|
BIN
resources/00-taisei.pkgdir/gfx/atlas_portraits_0.alphamap.png
Normal file
BIN
resources/00-taisei.pkgdir/gfx/atlas_portraits_0.alphamap.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 106 KiB |
Binary file not shown.
Before Width: | Height: | Size: 83 KiB |
|
@ -1,7 +1,7 @@
|
|||
# Autogenerated by the atlas packer, do not modify
|
||||
|
||||
source = res/gfx/atlas_portraits_0.webp
|
||||
alphamap = res/gfx/atlas_portraits_0.alphamap.webp
|
||||
alphamap = res/gfx/atlas_portraits_0.alphamap.png
|
||||
|
||||
# -- Pasted from the global override file --
|
||||
|
||||
|
|
|
@ -85,7 +85,7 @@ def write_sprite_def(dst, texture, region, texture_dimensions, overrides=None):
|
|||
update_text_file(dst, text)
|
||||
|
||||
|
||||
def write_texture_def(dst, texture, texture_fmt, global_overrides=None, local_overrides=None, have_alphamap=False):
|
||||
def write_texture_def(dst, texture, texture_fmt, global_overrides=None, local_overrides=None, alphamap_tex_fmt=None):
|
||||
dst.parent.mkdir(exist_ok=True, parents=True)
|
||||
|
||||
text = (
|
||||
|
@ -93,8 +93,8 @@ def write_texture_def(dst, texture, texture_fmt, global_overrides=None, local_ov
|
|||
f'source = res/gfx/{texture}.{texture_fmt}\n'
|
||||
)
|
||||
|
||||
if have_alphamap:
|
||||
text += f'alphamap = res/gfx/{texture}.alphamap.{texture_fmt}\n'
|
||||
if alphamap_tex_fmt is not None:
|
||||
text += f'alphamap = res/gfx/{texture}.alphamap.{alphamap_tex_fmt}\n'
|
||||
|
||||
if global_overrides is not None:
|
||||
text += f'\n# -- Pasted from the global override file --\n\n{global_overrides.strip()}\n'
|
||||
|
@ -448,10 +448,17 @@ def gen_atlas(overrides, src, dst, binsize, atlasname, tex_format=texture_format
|
|||
|
||||
if alphamap_path:
|
||||
if alphamap_composite_cmd is None:
|
||||
alphamap_composite_cmd = base_composite_cmd.copy() + ['xc:white']
|
||||
alphamap_composite_cmd = base_composite_cmd.copy() + [
|
||||
'xc:white',
|
||||
'-colorspace', 'Gray',
|
||||
]
|
||||
|
||||
alphamap_composite_cmd += [
|
||||
str(alphamap_path), '-geometry', '{:+}{:+}'.format(rect.x + border, rect.y + border), '-composite'
|
||||
str(alphamap_path),
|
||||
'-geometry', '{:+}{:+}'.format(rect.x + border, rect.y + border),
|
||||
'-channel', 'R',
|
||||
'-separate',
|
||||
'-composite',
|
||||
]
|
||||
|
||||
override_path = overrides / get_override_file_name(name)
|
||||
|
@ -478,10 +485,10 @@ def gen_atlas(overrides, src, dst, binsize, atlasname, tex_format=texture_format
|
|||
tex_format,
|
||||
texture_global_overrides,
|
||||
texture_local_overrides,
|
||||
have_alphamap=alphamap_composite_cmd is not None
|
||||
alphamap_tex_fmt=None if alphamap_composite_cmd is None else 'png'
|
||||
)
|
||||
|
||||
def process(composite_cmd, dstfile):
|
||||
def process(composite_cmd, dstfile, tex_format=tex_format):
|
||||
subprocess.check_call(composite_cmd)
|
||||
|
||||
oldfmt = dstfile.suffix[1:].lower()
|
||||
|
@ -514,7 +521,7 @@ def gen_atlas(overrides, src, dst, binsize, atlasname, tex_format=texture_format
|
|||
|
||||
if alphamap_composite_cmd is not None:
|
||||
alphamap_composite_cmd += [str(dstfile_alphamap)]
|
||||
futures.append(executor.submit(lambda: process(alphamap_composite_cmd, dstfile_alphamap)))
|
||||
futures.append(executor.submit(lambda: process(alphamap_composite_cmd, dstfile_alphamap, tex_format='png')))
|
||||
|
||||
# Wait for subprocesses to complete.
|
||||
wait_for_futures(futures)
|
||||
|
|
|
@ -357,14 +357,14 @@ static void* load_texture_begin(const char *path, uint flags) {
|
|||
}
|
||||
}
|
||||
|
||||
if(!pixmap_load_file(source, &ld.pixmap)) {
|
||||
if(!pixmap_load_file(source, &ld.pixmap, override_format)) {
|
||||
log_error("%s: couldn't load texture image", source);
|
||||
free(source_allocated);
|
||||
free(alphamap_allocated);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if(alphamap_allocated && !pixmap_load_file(alphamap_allocated, &ld.pixmap_alphamap)) {
|
||||
if(alphamap_allocated && !pixmap_load_file(alphamap_allocated, &ld.pixmap_alphamap, PIXMAP_FORMAT_R8)) {
|
||||
log_error("%s: couldn't load texture alphamap", alphamap_allocated);
|
||||
free(source_allocated);
|
||||
free(alphamap_allocated);
|
||||
|
|
|
@ -179,7 +179,7 @@ static struct conversion_def* find_conversion(uint depth_in, uint depth_out) {
|
|||
log_fatal("Pixmap conversion for %upbc -> %upbc undefined, please add", depth_in, depth_out);
|
||||
}
|
||||
|
||||
static void* default_pixel(uint depth) {
|
||||
static void *default_pixel(uint depth) {
|
||||
static uint8_t default_u8[] = { 0, 0, 0, UINT8_MAX };
|
||||
static uint16_t default_u16[] = { 0, 0, 0, UINT16_MAX };
|
||||
static uint32_t default_u32[] = { 0, 0, 0, UINT32_MAX };
|
||||
|
@ -194,7 +194,7 @@ static void* default_pixel(uint depth) {
|
|||
}
|
||||
}
|
||||
|
||||
void* pixmap_alloc_buffer(PixmapFormat format, size_t width, size_t height) {
|
||||
void *pixmap_alloc_buffer(PixmapFormat format, size_t width, size_t height) {
|
||||
assert(width >= 1);
|
||||
assert(height >= 1);
|
||||
size_t pixel_size = PIXMAP_FORMAT_PIXEL_SIZE(format);
|
||||
|
@ -202,11 +202,11 @@ void* pixmap_alloc_buffer(PixmapFormat format, size_t width, size_t height) {
|
|||
return calloc(width * height, pixel_size);
|
||||
}
|
||||
|
||||
void* pixmap_alloc_buffer_for_copy(const Pixmap *src) {
|
||||
void *pixmap_alloc_buffer_for_copy(const Pixmap *src) {
|
||||
return pixmap_alloc_buffer(src->format, src->width, src->height);
|
||||
}
|
||||
|
||||
void* pixmap_alloc_buffer_for_conversion(const Pixmap *src, PixmapFormat format) {
|
||||
void *pixmap_alloc_buffer_for_conversion(const Pixmap *src, PixmapFormat format) {
|
||||
return pixmap_alloc_buffer(format, src->width, src->height);
|
||||
}
|
||||
|
||||
|
@ -339,17 +339,13 @@ void pixmap_flip_to_origin_inplace(Pixmap *src, PixmapOrigin origin) {
|
|||
src->origin = origin;
|
||||
}
|
||||
|
||||
bool pixmap_load_stream_tga(SDL_RWops *stream, Pixmap *dst) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static PixmapLoader *pixmap_loaders[] = {
|
||||
&pixmap_loader_png,
|
||||
&pixmap_loader_webp,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static PixmapLoader* pixmap_loader_for_filename(const char *file) {
|
||||
static PixmapLoader *pixmap_loader_for_filename(const char *file) {
|
||||
char *ext = strrchr(file, '.');
|
||||
|
||||
if(!ext || !*(++ext)) {
|
||||
|
@ -368,13 +364,13 @@ static PixmapLoader* pixmap_loader_for_filename(const char *file) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
bool pixmap_load_stream(SDL_RWops *stream, Pixmap *dst) {
|
||||
bool pixmap_load_stream(SDL_RWops *stream, Pixmap *dst, PixmapFormat preferred_format) {
|
||||
for(PixmapLoader **loader = pixmap_loaders; *loader; ++loader) {
|
||||
bool match = (*loader)->probe(stream);
|
||||
SDL_RWseek(stream, 0, RW_SEEK_SET);
|
||||
|
||||
if(match) {
|
||||
return (*loader)->load(stream, dst);
|
||||
return (*loader)->load(stream, dst, preferred_format);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -382,7 +378,8 @@ bool pixmap_load_stream(SDL_RWops *stream, Pixmap *dst) {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool pixmap_load_file(const char *path, Pixmap *dst) {
|
||||
bool pixmap_load_file(const char *path, Pixmap *dst, PixmapFormat preferred_format) {
|
||||
log_debug("%s %x", path, preferred_format);
|
||||
SDL_RWops *stream = vfs_open(path, VFS_MODE_READ | VFS_MODE_SEEKABLE);
|
||||
|
||||
if(!stream) {
|
||||
|
@ -390,7 +387,7 @@ bool pixmap_load_file(const char *path, Pixmap *dst) {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool result = pixmap_load_stream(stream, dst);
|
||||
bool result = pixmap_load_stream(stream, dst, preferred_format);
|
||||
SDL_RWclose(stream);
|
||||
return result;
|
||||
}
|
||||
|
@ -399,7 +396,7 @@ bool pixmap_check_filename(const char *path) {
|
|||
return (bool)pixmap_loader_for_filename(path);
|
||||
}
|
||||
|
||||
char* pixmap_source_path(const char *prefix, const char *path) {
|
||||
char *pixmap_source_path(const char *prefix, const char *path) {
|
||||
char base_path[strlen(prefix) + strlen(path) + 1];
|
||||
strcpy(base_path, prefix);
|
||||
strcpy(base_path + strlen(prefix), path);
|
||||
|
|
|
@ -150,9 +150,9 @@ typedef struct Pixmap {
|
|||
PixmapOrigin origin;
|
||||
} Pixmap;
|
||||
|
||||
void* pixmap_alloc_buffer(PixmapFormat format, size_t width, size_t height) attr_returns_allocated;
|
||||
void* pixmap_alloc_buffer_for_copy(const Pixmap *src) attr_nonnull(1) attr_returns_allocated;
|
||||
void* pixmap_alloc_buffer_for_conversion(const Pixmap *src, PixmapFormat format) attr_nonnull(1) attr_returns_allocated;
|
||||
void *pixmap_alloc_buffer(PixmapFormat format, size_t width, size_t height) attr_returns_allocated;
|
||||
void *pixmap_alloc_buffer_for_copy(const Pixmap *src) attr_nonnull(1) attr_returns_allocated;
|
||||
void *pixmap_alloc_buffer_for_conversion(const Pixmap *src, PixmapFormat format) attr_nonnull(1) attr_returns_allocated;
|
||||
|
||||
void pixmap_copy(const Pixmap *src, Pixmap *dst) attr_nonnull(1, 2);
|
||||
void pixmap_copy_alloc(const Pixmap *src, Pixmap *dst) attr_nonnull(1, 2);
|
||||
|
@ -171,11 +171,10 @@ void pixmap_flip_to_origin_inplace(Pixmap *src, PixmapOrigin origin) attr_nonnul
|
|||
|
||||
size_t pixmap_data_size(const Pixmap *px) attr_nonnull(1);
|
||||
|
||||
bool pixmap_load_file(const char *path, Pixmap *dst) attr_nonnull(1, 2) attr_nodiscard;
|
||||
bool pixmap_load_stream(SDL_RWops *stream, Pixmap *dst) attr_nonnull(1, 2) attr_nodiscard;
|
||||
bool pixmap_load_stream_tga(SDL_RWops *stream, Pixmap *dst) attr_nonnull(1, 2) attr_nodiscard;
|
||||
bool pixmap_load_file(const char *path, Pixmap *dst, PixmapFormat preferred_format) attr_nonnull(1, 2) attr_nodiscard;
|
||||
bool pixmap_load_stream(SDL_RWops *stream, Pixmap *dst, PixmapFormat preferred_format) attr_nonnull(1, 2) attr_nodiscard;
|
||||
|
||||
bool pixmap_check_filename(const char *path);
|
||||
char* pixmap_source_path(const char *prefix, const char *path) attr_nodiscard;
|
||||
char *pixmap_source_path(const char *prefix, const char *path) attr_nodiscard;
|
||||
|
||||
#endif // IGUARD_util_pixmap_h
|
||||
|
|
|
@ -27,7 +27,9 @@ static void _CONV_FUNCNAME(
|
|||
}
|
||||
} else if(_CONV_OUT_IS_FLOAT) {
|
||||
fill = *buf_in++ * (1.0f / (float)_CONV_IN_MAX);
|
||||
} else if(_CONV_OUT_MAX >= _CONV_IN_MAX) {
|
||||
} else if(_CONV_OUT_MAX == _CONV_IN_MAX) {
|
||||
fill = *buf_in++;
|
||||
} else if(_CONV_OUT_MAX > _CONV_IN_MAX) {
|
||||
fill = *buf_in++ * (_CONV_OUT_MAX / _CONV_IN_MAX);
|
||||
} else {
|
||||
// TODO use fixed point math
|
||||
|
|
|
@ -20,7 +20,17 @@ static bool px_png_probe(SDL_RWops *stream) {
|
|||
return !memcmp(magic, png_magic, sizeof(magic));
|
||||
}
|
||||
|
||||
static bool px_png_load(SDL_RWops *stream, Pixmap *pixmap) {
|
||||
static inline PixmapLayout clrtype_to_layout(png_byte color_type) {
|
||||
switch(color_type) {
|
||||
case PNG_COLOR_TYPE_RGB: return PIXMAP_LAYOUT_RGB;
|
||||
case PNG_COLOR_TYPE_RGB_ALPHA: return PIXMAP_LAYOUT_RGBA;
|
||||
case PNG_COLOR_TYPE_GRAY: return PIXMAP_LAYOUT_R;
|
||||
}
|
||||
|
||||
UNREACHABLE;
|
||||
}
|
||||
|
||||
static bool px_png_load(SDL_RWops *stream, Pixmap *pixmap, PixmapFormat preferred_format) {
|
||||
png_structp png = NULL;
|
||||
png_infop png_info = NULL;
|
||||
const char *volatile error = NULL;
|
||||
|
@ -50,23 +60,26 @@ static bool px_png_load(SDL_RWops *stream, Pixmap *pixmap) {
|
|||
|
||||
png_set_alpha_mode(png, PNG_ALPHA_PNG, PNG_DEFAULT_sRGB);
|
||||
|
||||
if(color_type == PNG_COLOR_TYPE_PALETTE) {
|
||||
png_set_palette_to_rgb(png);
|
||||
}
|
||||
/*
|
||||
* Expand palette into RGB
|
||||
* Expand grayscale to full 8 bits
|
||||
* Expand transparency to full RGBA
|
||||
*/
|
||||
png_set_expand(png);
|
||||
|
||||
if(png_get_valid(png, png_info, PNG_INFO_tRNS)) {
|
||||
png_set_tRNS_to_alpha(png);
|
||||
}
|
||||
// avoid unnecessary back-and-forth conversion
|
||||
bool keep_gray = (
|
||||
color_type == PNG_COLOR_TYPE_GRAY &&
|
||||
PIXMAP_FORMAT_LAYOUT(preferred_format) == PIXMAP_LAYOUT_R
|
||||
);
|
||||
|
||||
if(color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) {
|
||||
png_set_expand_gray_1_2_4_to_8(png);
|
||||
}
|
||||
|
||||
if(color_type == PNG_COLOR_TYPE_GRAY || color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
|
||||
if(!keep_gray) {
|
||||
png_set_gray_to_rgb(png);
|
||||
}
|
||||
|
||||
png_set_expand(png);
|
||||
if(PIXMAP_FORMAT_DEPTH(preferred_format) == 16) {
|
||||
png_set_expand_16(png);
|
||||
}
|
||||
|
||||
#if SDL_BYTEORDER == SDL_LIL_ENDIAN
|
||||
png_set_swap(png);
|
||||
|
@ -79,14 +92,17 @@ static bool px_png_load(SDL_RWops *stream, Pixmap *pixmap) {
|
|||
color_type = png_get_color_type(png, png_info);
|
||||
bit_depth = png_get_bit_depth(png, png_info);
|
||||
|
||||
assert(color_type == PNG_COLOR_TYPE_RGB || color_type == PNG_COLOR_TYPE_RGBA);
|
||||
assert(
|
||||
(color_type == PNG_COLOR_TYPE_RGB && channels == 3) ||
|
||||
(color_type == PNG_COLOR_TYPE_RGB_ALPHA && channels == 4) ||
|
||||
(color_type == PNG_COLOR_TYPE_GRAY && channels == 1)
|
||||
);
|
||||
assert(bit_depth == 8 || bit_depth == 16);
|
||||
assert(channels == 3 || channels == 4);
|
||||
|
||||
pixmap->width = png_get_image_width(png, png_info);
|
||||
pixmap->height = png_get_image_height(png, png_info);
|
||||
pixmap->format = PIXMAP_MAKE_FORMAT(
|
||||
channels == 3 ? PIXMAP_LAYOUT_RGB : PIXMAP_LAYOUT_RGBA,
|
||||
clrtype_to_layout(color_type),
|
||||
bit_depth
|
||||
);
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ static inline const char* webp_error_str(VP8StatusCode code) {
|
|||
return "Unknown error";
|
||||
}
|
||||
|
||||
static bool px_webp_load(SDL_RWops *stream, Pixmap *pixmap) {
|
||||
static bool px_webp_load(SDL_RWops *stream, Pixmap *pixmap, PixmapFormat preferred_format) {
|
||||
WebPDecoderConfig config;
|
||||
int status = WebPInitDecoderConfig(&config);
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
|
||||
typedef struct PixmapLoader {
|
||||
bool (*probe)(SDL_RWops *stream);
|
||||
bool (*load)(SDL_RWops *stream, Pixmap *pixmap);
|
||||
bool (*load)(SDL_RWops *stream, Pixmap *pixmap, PixmapFormat preferred_format);
|
||||
const char **filename_exts;
|
||||
} PixmapLoader;
|
||||
|
||||
|
|
Loading…
Reference in a new issue