mirror of https://github.com/OpenTTD/OpenTTD
Codechange: Deduplicate array lookup.
parent
bb767608de
commit
02082a0211
|
@ -417,10 +417,11 @@ Sprite *Blitter_32bppOptimized::EncodeInternal(SpriteType sprite_type, const Spr
|
||||||
|
|
||||||
Sprite *dest_sprite = allocator.Allocate<Sprite>(sizeof(*dest_sprite) + sizeof(SpriteData) + len);
|
Sprite *dest_sprite = allocator.Allocate<Sprite>(sizeof(*dest_sprite) + sizeof(SpriteData) + len);
|
||||||
|
|
||||||
dest_sprite->height = sprite[ZOOM_LVL_MIN].height;
|
const auto &root_sprite = sprite[ZOOM_LVL_MIN];
|
||||||
dest_sprite->width = sprite[ZOOM_LVL_MIN].width;
|
dest_sprite->height = root_sprite.height;
|
||||||
dest_sprite->x_offs = sprite[ZOOM_LVL_MIN].x_offs;
|
dest_sprite->width = root_sprite.width;
|
||||||
dest_sprite->y_offs = sprite[ZOOM_LVL_MIN].y_offs;
|
dest_sprite->x_offs = root_sprite.x_offs;
|
||||||
|
dest_sprite->y_offs = root_sprite.y_offs;
|
||||||
|
|
||||||
SpriteData *dst = (SpriteData *)dest_sprite->data;
|
SpriteData *dst = (SpriteData *)dest_sprite->data;
|
||||||
memset(dst, 0, sizeof(*dst));
|
memset(dst, 0, sizeof(*dst));
|
||||||
|
|
|
@ -117,18 +117,19 @@ void Blitter_32bppSimple::DrawColourMappingRect(void *dst, int width, int height
|
||||||
|
|
||||||
Sprite *Blitter_32bppSimple::Encode(SpriteType, const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator)
|
Sprite *Blitter_32bppSimple::Encode(SpriteType, const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator)
|
||||||
{
|
{
|
||||||
|
const auto &root_sprite = sprite[ZOOM_LVL_MIN];
|
||||||
Blitter_32bppSimple::Pixel *dst;
|
Blitter_32bppSimple::Pixel *dst;
|
||||||
Sprite *dest_sprite = allocator.Allocate<Sprite>(sizeof(*dest_sprite) + static_cast<size_t>(sprite[ZOOM_LVL_MIN].height) * static_cast<size_t>(sprite[ZOOM_LVL_MIN].width) * sizeof(*dst));
|
Sprite *dest_sprite = allocator.Allocate<Sprite>(sizeof(*dest_sprite) + static_cast<size_t>(root_sprite.height) * static_cast<size_t>(root_sprite.width) * sizeof(*dst));
|
||||||
|
|
||||||
dest_sprite->height = sprite[ZOOM_LVL_MIN].height;
|
dest_sprite->height = root_sprite.height;
|
||||||
dest_sprite->width = sprite[ZOOM_LVL_MIN].width;
|
dest_sprite->width = root_sprite.width;
|
||||||
dest_sprite->x_offs = sprite[ZOOM_LVL_MIN].x_offs;
|
dest_sprite->x_offs = root_sprite.x_offs;
|
||||||
dest_sprite->y_offs = sprite[ZOOM_LVL_MIN].y_offs;
|
dest_sprite->y_offs = root_sprite.y_offs;
|
||||||
|
|
||||||
dst = (Blitter_32bppSimple::Pixel *)dest_sprite->data;
|
dst = reinterpret_cast<Blitter_32bppSimple::Pixel *>(dest_sprite->data);
|
||||||
SpriteLoader::CommonPixel *src = (SpriteLoader::CommonPixel *)sprite[ZOOM_LVL_MIN].data;
|
SpriteLoader::CommonPixel *src = reinterpret_cast<SpriteLoader::CommonPixel *>(root_sprite.data);
|
||||||
|
|
||||||
for (int i = 0; i < sprite[ZOOM_LVL_MIN].height * sprite[ZOOM_LVL_MIN].width; i++) {
|
for (int i = 0; i < root_sprite.height * root_sprite.width; i++) {
|
||||||
if (src->m == 0) {
|
if (src->m == 0) {
|
||||||
dst[i].r = src->r;
|
dst[i].r = src->r;
|
||||||
dst[i].g = src->g;
|
dst[i].g = src->g;
|
||||||
|
|
|
@ -39,22 +39,24 @@ Sprite *Blitter_32bppSSE_Base::Encode(SpriteType sprite_type, const SpriteLoader
|
||||||
uint all_sprites_size = 0;
|
uint all_sprites_size = 0;
|
||||||
for (ZoomLevel z = zoom_min; z <= zoom_max; z++) {
|
for (ZoomLevel z = zoom_min; z <= zoom_max; z++) {
|
||||||
const SpriteLoader::Sprite *src_sprite = &sprite[z];
|
const SpriteLoader::Sprite *src_sprite = &sprite[z];
|
||||||
sd.infos[z].sprite_width = src_sprite->width;
|
auto &info = sd.infos[z];
|
||||||
sd.infos[z].sprite_offset = all_sprites_size;
|
info.sprite_width = src_sprite->width;
|
||||||
sd.infos[z].sprite_line_size = sizeof(Colour) * src_sprite->width + sizeof(uint32_t) * META_LENGTH;
|
info.sprite_offset = all_sprites_size;
|
||||||
|
info.sprite_line_size = sizeof(Colour) * src_sprite->width + sizeof(uint32_t) * META_LENGTH;
|
||||||
|
|
||||||
const uint rgba_size = sd.infos[z].sprite_line_size * src_sprite->height;
|
const uint rgba_size = info.sprite_line_size * src_sprite->height;
|
||||||
sd.infos[z].mv_offset = all_sprites_size + rgba_size;
|
info.mv_offset = all_sprites_size + rgba_size;
|
||||||
|
|
||||||
const uint mv_size = sizeof(MapValue) * src_sprite->width * src_sprite->height;
|
const uint mv_size = sizeof(MapValue) * src_sprite->width * src_sprite->height;
|
||||||
all_sprites_size += rgba_size + mv_size;
|
all_sprites_size += rgba_size + mv_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
Sprite *dst_sprite = allocator.Allocate<Sprite>(sizeof(Sprite) + sizeof(SpriteData) + all_sprites_size);
|
Sprite *dst_sprite = allocator.Allocate<Sprite>(sizeof(Sprite) + sizeof(SpriteData) + all_sprites_size);
|
||||||
dst_sprite->height = sprite[ZOOM_LVL_MIN].height;
|
const auto &root_sprite = sprite[ZOOM_LVL_MIN];
|
||||||
dst_sprite->width = sprite[ZOOM_LVL_MIN].width;
|
dst_sprite->height = root_sprite.height;
|
||||||
dst_sprite->x_offs = sprite[ZOOM_LVL_MIN].x_offs;
|
dst_sprite->width = root_sprite.width;
|
||||||
dst_sprite->y_offs = sprite[ZOOM_LVL_MIN].y_offs;
|
dst_sprite->x_offs = root_sprite.x_offs;
|
||||||
|
dst_sprite->y_offs = root_sprite.y_offs;
|
||||||
memcpy(dst_sprite->data, &sd, sizeof(SpriteData));
|
memcpy(dst_sprite->data, &sd, sizeof(SpriteData));
|
||||||
|
|
||||||
/* Copy colours and determine flags. */
|
/* Copy colours and determine flags. */
|
||||||
|
@ -64,8 +66,9 @@ Sprite *Blitter_32bppSSE_Base::Encode(SpriteType sprite_type, const SpriteLoader
|
||||||
for (ZoomLevel z = zoom_min; z <= zoom_max; z++) {
|
for (ZoomLevel z = zoom_min; z <= zoom_max; z++) {
|
||||||
const SpriteLoader::Sprite *src_sprite = &sprite[z];
|
const SpriteLoader::Sprite *src_sprite = &sprite[z];
|
||||||
const SpriteLoader::CommonPixel *src = (const SpriteLoader::CommonPixel *) src_sprite->data;
|
const SpriteLoader::CommonPixel *src = (const SpriteLoader::CommonPixel *) src_sprite->data;
|
||||||
Colour *dst_rgba_line = (Colour *) &dst_sprite->data[sizeof(SpriteData) + sd.infos[z].sprite_offset];
|
const auto &info = sd.infos[z];
|
||||||
MapValue *dst_mv = (MapValue *) &dst_sprite->data[sizeof(SpriteData) + sd.infos[z].mv_offset];
|
Colour *dst_rgba_line = reinterpret_cast<Colour *>(&dst_sprite->data[sizeof(SpriteData) + info.sprite_offset]);
|
||||||
|
MapValue *dst_mv = reinterpret_cast<MapValue *>(&dst_sprite->data[sizeof(SpriteData) + info.mv_offset]);
|
||||||
for (uint y = src_sprite->height; y != 0; y--) {
|
for (uint y = src_sprite->height; y != 0; y--) {
|
||||||
Colour *dst_rgba = dst_rgba_line + META_LENGTH;
|
Colour *dst_rgba = dst_rgba_line + META_LENGTH;
|
||||||
for (uint x = src_sprite->width; x != 0; x--) {
|
for (uint x = src_sprite->width; x != 0; x--) {
|
||||||
|
@ -113,7 +116,7 @@ Sprite *Blitter_32bppSSE_Base::Encode(SpriteType sprite_type, const SpriteLoader
|
||||||
(*dst_rgba_line).data = nb_pix_transp;
|
(*dst_rgba_line).data = nb_pix_transp;
|
||||||
|
|
||||||
Colour *nb_right = dst_rgba_line + 1;
|
Colour *nb_right = dst_rgba_line + 1;
|
||||||
dst_rgba_line = (Colour*) ((uint8_t*) dst_rgba_line + sd.infos[z].sprite_line_size);
|
dst_rgba_line = reinterpret_cast<Colour *>(reinterpret_cast<std::byte *>(dst_rgba_line) + info.sprite_line_size);
|
||||||
|
|
||||||
/* Count the number of transparent pixels from the right. */
|
/* Count the number of transparent pixels from the right. */
|
||||||
dst_rgba = dst_rgba_line - 1;
|
dst_rgba = dst_rgba_line - 1;
|
||||||
|
|
|
@ -153,13 +153,14 @@ Sprite *Blitter_8bppOptimized::Encode(SpriteType sprite_type, const SpriteLoader
|
||||||
|
|
||||||
/* Make the sprites per zoom-level */
|
/* Make the sprites per zoom-level */
|
||||||
for (ZoomLevel i = zoom_min; i <= zoom_max; i++) {
|
for (ZoomLevel i = zoom_min; i <= zoom_max; i++) {
|
||||||
|
const SpriteLoader::Sprite &src_orig = sprite[i];
|
||||||
/* Store the index table */
|
/* Store the index table */
|
||||||
uint offset = dst - temp_dst->data;
|
uint offset = dst - temp_dst->data;
|
||||||
temp_dst->offset[i] = offset;
|
temp_dst->offset[i] = offset;
|
||||||
|
|
||||||
/* cache values, because compiler can't cache it */
|
/* cache values, because compiler can't cache it */
|
||||||
int scaled_height = sprite[i].height;
|
int scaled_height = src_orig.height;
|
||||||
int scaled_width = sprite[i].width;
|
int scaled_width = src_orig.width;
|
||||||
|
|
||||||
for (int y = 0; y < scaled_height; y++) {
|
for (int y = 0; y < scaled_height; y++) {
|
||||||
uint trans = 0;
|
uint trans = 0;
|
||||||
|
@ -168,7 +169,7 @@ Sprite *Blitter_8bppOptimized::Encode(SpriteType sprite_type, const SpriteLoader
|
||||||
uint8_t *count_dst = nullptr;
|
uint8_t *count_dst = nullptr;
|
||||||
|
|
||||||
/* Store the scaled image */
|
/* Store the scaled image */
|
||||||
const SpriteLoader::CommonPixel *src = &sprite[i].data[y * sprite[i].width];
|
const SpriteLoader::CommonPixel *src = &src_orig.data[y * src_orig.width];
|
||||||
|
|
||||||
for (int x = 0; x < scaled_width; x++) {
|
for (int x = 0; x < scaled_width; x++) {
|
||||||
uint colour = src++->m;
|
uint colour = src++->m;
|
||||||
|
@ -220,10 +221,11 @@ Sprite *Blitter_8bppOptimized::Encode(SpriteType sprite_type, const SpriteLoader
|
||||||
/* Allocate the exact amount of memory we need */
|
/* Allocate the exact amount of memory we need */
|
||||||
Sprite *dest_sprite = allocator.Allocate<Sprite>(sizeof(*dest_sprite) + size);
|
Sprite *dest_sprite = allocator.Allocate<Sprite>(sizeof(*dest_sprite) + size);
|
||||||
|
|
||||||
dest_sprite->height = sprite[ZOOM_LVL_MIN].height;
|
const auto &root_sprite = sprite[ZOOM_LVL_MIN];
|
||||||
dest_sprite->width = sprite[ZOOM_LVL_MIN].width;
|
dest_sprite->height = root_sprite.height;
|
||||||
dest_sprite->x_offs = sprite[ZOOM_LVL_MIN].x_offs;
|
dest_sprite->width = root_sprite.width;
|
||||||
dest_sprite->y_offs = sprite[ZOOM_LVL_MIN].y_offs;
|
dest_sprite->x_offs = root_sprite.x_offs;
|
||||||
|
dest_sprite->y_offs = root_sprite.y_offs;
|
||||||
memcpy(dest_sprite->data, temp_dst, size);
|
memcpy(dest_sprite->data, temp_dst, size);
|
||||||
|
|
||||||
return dest_sprite;
|
return dest_sprite;
|
||||||
|
|
|
@ -63,17 +63,18 @@ void Blitter_8bppSimple::Draw(Blitter::BlitterParams *bp, BlitterMode mode, Zoom
|
||||||
|
|
||||||
Sprite *Blitter_8bppSimple::Encode(SpriteType, const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator)
|
Sprite *Blitter_8bppSimple::Encode(SpriteType, const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator)
|
||||||
{
|
{
|
||||||
|
const auto &root_sprite = sprite[ZOOM_LVL_MIN];
|
||||||
Sprite *dest_sprite;
|
Sprite *dest_sprite;
|
||||||
dest_sprite = allocator.Allocate<Sprite>(sizeof(*dest_sprite) + static_cast<size_t>(sprite[ZOOM_LVL_MIN].height) * static_cast<size_t>(sprite[ZOOM_LVL_MIN].width));
|
dest_sprite = allocator.Allocate<Sprite>(sizeof(*dest_sprite) + static_cast<size_t>(root_sprite.height) * static_cast<size_t>(root_sprite.width));
|
||||||
|
|
||||||
dest_sprite->height = sprite[ZOOM_LVL_MIN].height;
|
dest_sprite->height = root_sprite.height;
|
||||||
dest_sprite->width = sprite[ZOOM_LVL_MIN].width;
|
dest_sprite->width = root_sprite.width;
|
||||||
dest_sprite->x_offs = sprite[ZOOM_LVL_MIN].x_offs;
|
dest_sprite->x_offs = root_sprite.x_offs;
|
||||||
dest_sprite->y_offs = sprite[ZOOM_LVL_MIN].y_offs;
|
dest_sprite->y_offs = root_sprite.y_offs;
|
||||||
|
|
||||||
/* Copy over only the 'remap' channel, as that is what we care about in 8bpp */
|
/* Copy over only the 'remap' channel, as that is what we care about in 8bpp */
|
||||||
for (int i = 0; i < sprite[ZOOM_LVL_MIN].height * sprite[ZOOM_LVL_MIN].width; i++) {
|
for (int i = 0; i < root_sprite.height * root_sprite.width; i++) {
|
||||||
dest_sprite->data[i] = sprite[ZOOM_LVL_MIN].data[i].m;
|
dest_sprite->data[i] = root_sprite.data[i].m;
|
||||||
}
|
}
|
||||||
|
|
||||||
return dest_sprite;
|
return dest_sprite;
|
||||||
|
|
|
@ -20,10 +20,11 @@ Sprite *Blitter_Null::Encode(SpriteType, const SpriteLoader::SpriteCollection &s
|
||||||
Sprite *dest_sprite;
|
Sprite *dest_sprite;
|
||||||
dest_sprite = allocator.Allocate<Sprite>(sizeof(*dest_sprite));
|
dest_sprite = allocator.Allocate<Sprite>(sizeof(*dest_sprite));
|
||||||
|
|
||||||
dest_sprite->height = sprite[ZOOM_LVL_MIN].height;
|
const auto &root_sprite = sprite[ZOOM_LVL_MIN];
|
||||||
dest_sprite->width = sprite[ZOOM_LVL_MIN].width;
|
dest_sprite->height = root_sprite.height;
|
||||||
dest_sprite->x_offs = sprite[ZOOM_LVL_MIN].x_offs;
|
dest_sprite->width = root_sprite.width;
|
||||||
dest_sprite->y_offs = sprite[ZOOM_LVL_MIN].y_offs;
|
dest_sprite->x_offs = root_sprite.x_offs;
|
||||||
|
dest_sprite->y_offs = root_sprite.y_offs;
|
||||||
|
|
||||||
return dest_sprite;
|
return dest_sprite;
|
||||||
}
|
}
|
||||||
|
|
|
@ -222,22 +222,24 @@ SpriteID GetMaxSpriteID()
|
||||||
static bool ResizeSpriteIn(SpriteLoader::SpriteCollection &sprite, ZoomLevel src, ZoomLevel tgt)
|
static bool ResizeSpriteIn(SpriteLoader::SpriteCollection &sprite, ZoomLevel src, ZoomLevel tgt)
|
||||||
{
|
{
|
||||||
uint8_t scaled_1 = ScaleByZoom(1, (ZoomLevel)(src - tgt));
|
uint8_t scaled_1 = ScaleByZoom(1, (ZoomLevel)(src - tgt));
|
||||||
|
const auto &src_sprite = sprite[src];
|
||||||
|
auto &dest_sprite = sprite[tgt];
|
||||||
|
|
||||||
/* Check for possible memory overflow. */
|
/* Check for possible memory overflow. */
|
||||||
if (sprite[src].width * scaled_1 > UINT16_MAX || sprite[src].height * scaled_1 > UINT16_MAX) return false;
|
if (src_sprite.width * scaled_1 > UINT16_MAX || src_sprite.height * scaled_1 > UINT16_MAX) return false;
|
||||||
|
|
||||||
sprite[tgt].width = sprite[src].width * scaled_1;
|
dest_sprite.width = src_sprite.width * scaled_1;
|
||||||
sprite[tgt].height = sprite[src].height * scaled_1;
|
dest_sprite.height = src_sprite.height * scaled_1;
|
||||||
sprite[tgt].x_offs = sprite[src].x_offs * scaled_1;
|
dest_sprite.x_offs = src_sprite.x_offs * scaled_1;
|
||||||
sprite[tgt].y_offs = sprite[src].y_offs * scaled_1;
|
dest_sprite.y_offs = src_sprite.y_offs * scaled_1;
|
||||||
sprite[tgt].colours = sprite[src].colours;
|
dest_sprite.colours = src_sprite.colours;
|
||||||
|
|
||||||
sprite[tgt].AllocateData(tgt, static_cast<size_t>(sprite[tgt].width) * sprite[tgt].height);
|
dest_sprite.AllocateData(tgt, static_cast<size_t>(dest_sprite.width) * dest_sprite.height);
|
||||||
|
|
||||||
SpriteLoader::CommonPixel *dst = sprite[tgt].data;
|
SpriteLoader::CommonPixel *dst = dest_sprite.data;
|
||||||
for (int y = 0; y < sprite[tgt].height; y++) {
|
for (int y = 0; y < dest_sprite.height; y++) {
|
||||||
const SpriteLoader::CommonPixel *src_ln = &sprite[src].data[y / scaled_1 * sprite[src].width];
|
const SpriteLoader::CommonPixel *src_ln = &src_sprite.data[y / scaled_1 * src_sprite.width];
|
||||||
for (int x = 0; x < sprite[tgt].width; x++) {
|
for (int x = 0; x < dest_sprite.width; x++) {
|
||||||
*dst = src_ln[x / scaled_1];
|
*dst = src_ln[x / scaled_1];
|
||||||
dst++;
|
dst++;
|
||||||
}
|
}
|
||||||
|
@ -248,23 +250,27 @@ static bool ResizeSpriteIn(SpriteLoader::SpriteCollection &sprite, ZoomLevel src
|
||||||
|
|
||||||
static void ResizeSpriteOut(SpriteLoader::SpriteCollection &sprite, ZoomLevel zoom)
|
static void ResizeSpriteOut(SpriteLoader::SpriteCollection &sprite, ZoomLevel zoom)
|
||||||
{
|
{
|
||||||
|
const auto &root_sprite = sprite[ZOOM_LVL_MIN];
|
||||||
|
const auto &src_sprite = sprite[zoom - 1];
|
||||||
|
auto &dest_sprite = sprite[zoom];
|
||||||
|
|
||||||
/* Algorithm based on 32bpp_Optimized::ResizeSprite() */
|
/* Algorithm based on 32bpp_Optimized::ResizeSprite() */
|
||||||
sprite[zoom].width = UnScaleByZoom(sprite[ZOOM_LVL_MIN].width, zoom);
|
dest_sprite.width = UnScaleByZoom(root_sprite.width, zoom);
|
||||||
sprite[zoom].height = UnScaleByZoom(sprite[ZOOM_LVL_MIN].height, zoom);
|
dest_sprite.height = UnScaleByZoom(root_sprite.height, zoom);
|
||||||
sprite[zoom].x_offs = UnScaleByZoom(sprite[ZOOM_LVL_MIN].x_offs, zoom);
|
dest_sprite.x_offs = UnScaleByZoom(root_sprite.x_offs, zoom);
|
||||||
sprite[zoom].y_offs = UnScaleByZoom(sprite[ZOOM_LVL_MIN].y_offs, zoom);
|
dest_sprite.y_offs = UnScaleByZoom(root_sprite.y_offs, zoom);
|
||||||
sprite[zoom].colours = sprite[ZOOM_LVL_MIN].colours;
|
dest_sprite.colours = root_sprite.colours;
|
||||||
|
|
||||||
sprite[zoom].AllocateData(zoom, static_cast<size_t>(sprite[zoom].height) * sprite[zoom].width);
|
dest_sprite.AllocateData(zoom, static_cast<size_t>(dest_sprite.height) * dest_sprite.width);
|
||||||
|
|
||||||
SpriteLoader::CommonPixel *dst = sprite[zoom].data;
|
SpriteLoader::CommonPixel *dst = dest_sprite.data;
|
||||||
const SpriteLoader::CommonPixel *src = sprite[zoom - 1].data;
|
const SpriteLoader::CommonPixel *src = src_sprite.data;
|
||||||
[[maybe_unused]] const SpriteLoader::CommonPixel *src_end = src + sprite[zoom - 1].height * sprite[zoom - 1].width;
|
[[maybe_unused]] const SpriteLoader::CommonPixel *src_end = src + src_sprite.height * src_sprite.width;
|
||||||
|
|
||||||
for (uint y = 0; y < sprite[zoom].height; y++) {
|
for (uint y = 0; y < dest_sprite.height; y++) {
|
||||||
const SpriteLoader::CommonPixel *src_ln = src + sprite[zoom - 1].width;
|
const SpriteLoader::CommonPixel *src_ln = src + src_sprite.width;
|
||||||
assert(src_ln <= src_end);
|
assert(src_ln <= src_end);
|
||||||
for (uint x = 0; x < sprite[zoom].width; x++) {
|
for (uint x = 0; x < dest_sprite.width; x++) {
|
||||||
assert(src < src_ln);
|
assert(src < src_ln);
|
||||||
if (src + 1 != src_ln && (src + 1)->a != 0) {
|
if (src + 1 != src_ln && (src + 1)->a != 0) {
|
||||||
*dst = *(src + 1);
|
*dst = *(src + 1);
|
||||||
|
@ -274,7 +280,7 @@ static void ResizeSpriteOut(SpriteLoader::SpriteCollection &sprite, ZoomLevel zo
|
||||||
dst++;
|
dst++;
|
||||||
src += 2;
|
src += 2;
|
||||||
}
|
}
|
||||||
src = src_ln + sprite[zoom - 1].width;
|
src = src_ln + src_sprite.width;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -359,15 +365,16 @@ static bool PadSprites(SpriteLoader::SpriteCollection &sprite, uint8_t sprite_av
|
||||||
/* Pad sprites where needed. */
|
/* Pad sprites where needed. */
|
||||||
for (ZoomLevel zoom = ZOOM_LVL_BEGIN; zoom != ZOOM_LVL_END; zoom++) {
|
for (ZoomLevel zoom = ZOOM_LVL_BEGIN; zoom != ZOOM_LVL_END; zoom++) {
|
||||||
if (HasBit(sprite_avail, zoom)) {
|
if (HasBit(sprite_avail, zoom)) {
|
||||||
|
auto &cur_sprite = sprite[zoom];
|
||||||
/* Scaling the sprite dimensions in the blitter is done with rounding up,
|
/* Scaling the sprite dimensions in the blitter is done with rounding up,
|
||||||
* so a negative padding here is not an error. */
|
* so a negative padding here is not an error. */
|
||||||
int pad_left = std::max(0, sprite[zoom].x_offs - UnScaleByZoom(min_xoffs, zoom));
|
int pad_left = std::max(0, cur_sprite.x_offs - UnScaleByZoom(min_xoffs, zoom));
|
||||||
int pad_top = std::max(0, sprite[zoom].y_offs - UnScaleByZoom(min_yoffs, zoom));
|
int pad_top = std::max(0, cur_sprite.y_offs - UnScaleByZoom(min_yoffs, zoom));
|
||||||
int pad_right = std::max(0, UnScaleByZoom(max_width, zoom) - sprite[zoom].width - pad_left);
|
int pad_right = std::max(0, UnScaleByZoom(max_width, zoom) - cur_sprite.width - pad_left);
|
||||||
int pad_bottom = std::max(0, UnScaleByZoom(max_height, zoom) - sprite[zoom].height - pad_top);
|
int pad_bottom = std::max(0, UnScaleByZoom(max_height, zoom) - cur_sprite.height - pad_top);
|
||||||
|
|
||||||
if (pad_left > 0 || pad_right > 0 || pad_top > 0 || pad_bottom > 0) {
|
if (pad_left > 0 || pad_right > 0 || pad_top > 0 || pad_bottom > 0) {
|
||||||
if (!PadSingleSprite(&sprite[zoom], zoom, pad_left, pad_top, pad_right, pad_bottom)) return false;
|
if (!PadSingleSprite(&cur_sprite, zoom, pad_left, pad_top, pad_right, pad_bottom)) return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -393,10 +400,12 @@ static bool ResizeSprites(SpriteLoader::SpriteCollection &sprite, uint8_t sprite
|
||||||
|
|
||||||
if (HasBit(sprite_avail, zoom)) {
|
if (HasBit(sprite_avail, zoom)) {
|
||||||
/* Check that size and offsets match the fully zoomed image. */
|
/* Check that size and offsets match the fully zoomed image. */
|
||||||
assert(sprite[zoom].width == UnScaleByZoom(sprite[ZOOM_LVL_MIN].width, zoom));
|
[[maybe_unused]] const auto &root_sprite = sprite[ZOOM_LVL_MIN];
|
||||||
assert(sprite[zoom].height == UnScaleByZoom(sprite[ZOOM_LVL_MIN].height, zoom));
|
[[maybe_unused]] const auto &dest_sprite = sprite[zoom];
|
||||||
assert(sprite[zoom].x_offs == UnScaleByZoom(sprite[ZOOM_LVL_MIN].x_offs, zoom));
|
assert(dest_sprite.width == UnScaleByZoom(root_sprite.width, zoom));
|
||||||
assert(sprite[zoom].y_offs == UnScaleByZoom(sprite[ZOOM_LVL_MIN].y_offs, zoom));
|
assert(dest_sprite.height == UnScaleByZoom(root_sprite.height, zoom));
|
||||||
|
assert(dest_sprite.x_offs == UnScaleByZoom(root_sprite.x_offs, zoom));
|
||||||
|
assert(dest_sprite.y_offs == UnScaleByZoom(root_sprite.y_offs, zoom));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Zoom level is not available, or unusable, so create it */
|
/* Zoom level is not available, or unusable, so create it */
|
||||||
|
@ -507,15 +516,16 @@ static void *ReadSprite(const SpriteCache *sc, SpriteID id, SpriteType sprite_ty
|
||||||
* Ugly: yes. Other solution: no. Blame the original author or
|
* Ugly: yes. Other solution: no. Blame the original author or
|
||||||
* something ;) The image should really have been a data-stream
|
* something ;) The image should really have been a data-stream
|
||||||
* (so type = 0xFF basically). */
|
* (so type = 0xFF basically). */
|
||||||
uint num = sprite[ZOOM_LVL_MIN].width * sprite[ZOOM_LVL_MIN].height;
|
const auto &root_sprite = sprite[ZOOM_LVL_MIN];
|
||||||
|
uint num = root_sprite.width * root_sprite.height;
|
||||||
|
|
||||||
Sprite *s = allocator.Allocate<Sprite>(sizeof(*s) + num);
|
Sprite *s = allocator.Allocate<Sprite>(sizeof(*s) + num);
|
||||||
s->width = sprite[ZOOM_LVL_MIN].width;
|
s->width = root_sprite.width;
|
||||||
s->height = sprite[ZOOM_LVL_MIN].height;
|
s->height = root_sprite.height;
|
||||||
s->x_offs = sprite[ZOOM_LVL_MIN].x_offs;
|
s->x_offs = root_sprite.x_offs;
|
||||||
s->y_offs = sprite[ZOOM_LVL_MIN].y_offs;
|
s->y_offs = root_sprite.y_offs;
|
||||||
|
|
||||||
SpriteLoader::CommonPixel *src = sprite[ZOOM_LVL_MIN].data;
|
SpriteLoader::CommonPixel *src = root_sprite.data;
|
||||||
uint8_t *dest = s->data;
|
uint8_t *dest = s->data;
|
||||||
while (num-- > 0) {
|
while (num-- > 0) {
|
||||||
*dest++ = src->m;
|
*dest++ = src->m;
|
||||||
|
|
|
@ -231,23 +231,24 @@ uint8_t LoadSpriteV1(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, s
|
||||||
if (type == 0xFF) return 0;
|
if (type == 0xFF) return 0;
|
||||||
|
|
||||||
ZoomLevel zoom_lvl = (sprite_type != SpriteType::MapGen) ? ZOOM_LVL_NORMAL : ZOOM_LVL_MIN;
|
ZoomLevel zoom_lvl = (sprite_type != SpriteType::MapGen) ? ZOOM_LVL_NORMAL : ZOOM_LVL_MIN;
|
||||||
|
auto &dest_sprite = sprite[zoom_lvl];
|
||||||
|
|
||||||
sprite[zoom_lvl].height = file.ReadByte();
|
dest_sprite.height = file.ReadByte();
|
||||||
sprite[zoom_lvl].width = file.ReadWord();
|
dest_sprite.width = file.ReadWord();
|
||||||
sprite[zoom_lvl].x_offs = file.ReadWord();
|
dest_sprite.x_offs = file.ReadWord();
|
||||||
sprite[zoom_lvl].y_offs = file.ReadWord();
|
dest_sprite.y_offs = file.ReadWord();
|
||||||
sprite[zoom_lvl].colours = SpriteComponent::Palette;
|
dest_sprite.colours = SpriteComponent::Palette;
|
||||||
|
|
||||||
if (sprite[zoom_lvl].width > INT16_MAX) {
|
if (dest_sprite.width > INT16_MAX) {
|
||||||
WarnCorruptSprite(file, file_pos, __LINE__);
|
WarnCorruptSprite(file, file_pos, __LINE__);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 0x02 indicates it is a compressed sprite, so we can't rely on 'num' to be valid.
|
/* 0x02 indicates it is a compressed sprite, so we can't rely on 'num' to be valid.
|
||||||
* In case it is uncompressed, the size is 'num' - 8 (header-size). */
|
* In case it is uncompressed, the size is 'num' - 8 (header-size). */
|
||||||
num = (type & 0x02) ? sprite[zoom_lvl].width * sprite[zoom_lvl].height : num - 8;
|
num = (type & 0x02) ? dest_sprite.width * dest_sprite.height : num - 8;
|
||||||
|
|
||||||
if (DecodeSingleSprite(&sprite[zoom_lvl], file, file_pos, sprite_type, num, type, zoom_lvl, SpriteComponent::Palette, 1)) {
|
if (DecodeSingleSprite(&dest_sprite, file, file_pos, sprite_type, num, type, zoom_lvl, SpriteComponent::Palette, 1)) {
|
||||||
SetBit(avail_8bpp, zoom_lvl);
|
SetBit(avail_8bpp, zoom_lvl);
|
||||||
return avail_8bpp;
|
return avail_8bpp;
|
||||||
}
|
}
|
||||||
|
@ -317,12 +318,13 @@ uint8_t LoadSpriteV2(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, s
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
sprite[zoom_lvl].height = file.ReadWord();
|
auto &dest_sprite = sprite[zoom_lvl];
|
||||||
sprite[zoom_lvl].width = file.ReadWord();
|
dest_sprite.height = file.ReadWord();
|
||||||
sprite[zoom_lvl].x_offs = file.ReadWord();
|
dest_sprite.width = file.ReadWord();
|
||||||
sprite[zoom_lvl].y_offs = file.ReadWord();
|
dest_sprite.x_offs = file.ReadWord();
|
||||||
|
dest_sprite.y_offs = file.ReadWord();
|
||||||
|
|
||||||
if (sprite[zoom_lvl].width > INT16_MAX || sprite[zoom_lvl].height > INT16_MAX) {
|
if (dest_sprite.width > INT16_MAX || dest_sprite.height > INT16_MAX) {
|
||||||
WarnCorruptSprite(file, file_pos, __LINE__);
|
WarnCorruptSprite(file, file_pos, __LINE__);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -333,13 +335,13 @@ uint8_t LoadSpriteV2(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, s
|
||||||
if (colour.Test(SpriteComponent::Alpha)) bpp++;
|
if (colour.Test(SpriteComponent::Alpha)) bpp++;
|
||||||
if (colour.Test(SpriteComponent::Palette)) bpp++;
|
if (colour.Test(SpriteComponent::Palette)) bpp++;
|
||||||
|
|
||||||
sprite[zoom_lvl].colours = colour;
|
dest_sprite.colours = colour;
|
||||||
|
|
||||||
/* For chunked encoding we store the decompressed size in the file,
|
/* For chunked encoding we store the decompressed size in the file,
|
||||||
* otherwise we can calculate it from the image dimensions. */
|
* otherwise we can calculate it from the image dimensions. */
|
||||||
uint decomp_size = (type & 0x08) ? file.ReadDword() : sprite[zoom_lvl].width * sprite[zoom_lvl].height * bpp;
|
uint decomp_size = (type & 0x08) ? file.ReadDword() : dest_sprite.width * dest_sprite.height * bpp;
|
||||||
|
|
||||||
bool valid = DecodeSingleSprite(&sprite[zoom_lvl], file, file_pos, sprite_type, decomp_size, type, zoom_lvl, colour, 2);
|
bool valid = DecodeSingleSprite(&dest_sprite, file, file_pos, sprite_type, decomp_size, type, zoom_lvl, colour, 2);
|
||||||
if (file.GetPos() != start_pos + num) {
|
if (file.GetPos() != start_pos + num) {
|
||||||
WarnCorruptSprite(file, file_pos, __LINE__);
|
WarnCorruptSprite(file, file_pos, __LINE__);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -1408,10 +1408,11 @@ OpenGLSprite::OpenGLSprite(SpriteType sprite_type, const SpriteLoader::SpriteCol
|
||||||
_glActiveTexture(GL_TEXTURE0);
|
_glActiveTexture(GL_TEXTURE0);
|
||||||
_glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
_glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0);
|
||||||
|
|
||||||
|
const auto &root_sprite = sprite[ZOOM_LVL_MIN];
|
||||||
for (int t = TEX_RGBA; t < NUM_TEX; t++) {
|
for (int t = TEX_RGBA; t < NUM_TEX; t++) {
|
||||||
/* Sprite component present? */
|
/* Sprite component present? */
|
||||||
if (t == TEX_RGBA && sprite[ZOOM_LVL_MIN].colours == SpriteComponent::Palette) continue;
|
if (t == TEX_RGBA && root_sprite.colours == SpriteComponent::Palette) continue;
|
||||||
if (t == TEX_REMAP && !sprite[ZOOM_LVL_MIN].colours.Test(SpriteComponent::Palette)) continue;
|
if (t == TEX_REMAP && !root_sprite.colours.Test(SpriteComponent::Palette)) continue;
|
||||||
|
|
||||||
/* Allocate texture. */
|
/* Allocate texture. */
|
||||||
_glGenTextures(1, &this->tex[t]);
|
_glGenTextures(1, &this->tex[t]);
|
||||||
|
@ -1436,7 +1437,8 @@ OpenGLSprite::OpenGLSprite(SpriteType sprite_type, const SpriteLoader::SpriteCol
|
||||||
|
|
||||||
/* Upload texture data. */
|
/* Upload texture data. */
|
||||||
for (int i = 0; i < (sprite_type == SpriteType::Font ? 1 : ZOOM_LVL_END); i++) {
|
for (int i = 0; i < (sprite_type == SpriteType::Font ? 1 : ZOOM_LVL_END); i++) {
|
||||||
this->Update(sprite[i].width, sprite[i].height, i, sprite[i].data);
|
const auto &src_sprite = sprite[i];
|
||||||
|
this->Update(src_sprite.width, src_sprite.height, i, src_sprite.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
assert(_glGetError() == GL_NO_ERROR);
|
assert(_glGetError() == GL_NO_ERROR);
|
||||||
|
|
Loading…
Reference in New Issue