mirror of https://github.com/OpenTTD/OpenTTD
Merge 51fd00684b
into a46a3a97f3
commit
31fa0833b8
|
@ -21,12 +21,12 @@
|
||||||
static FBlitter_32bppAnim iFBlitter_32bppAnim;
|
static FBlitter_32bppAnim iFBlitter_32bppAnim;
|
||||||
|
|
||||||
template <BlitterMode mode>
|
template <BlitterMode mode>
|
||||||
inline void Blitter_32bppAnim::Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom)
|
inline void Blitter_32bppAnim::Draw(const Blitter::BlitterParams *bp, SpriteCollKey sck)
|
||||||
{
|
{
|
||||||
const SpriteData *src = (const SpriteData *)bp->sprite;
|
const SpriteData *src = (const SpriteData *)bp->sprite;
|
||||||
|
|
||||||
const Colour *src_px = reinterpret_cast<const Colour *>(src->data + src->offset[0][zoom]);
|
const Colour *src_px = reinterpret_cast<const Colour *>(src->data + src->offset[0][sck]);
|
||||||
const uint16_t *src_n = reinterpret_cast<const uint16_t *>(src->data + src->offset[1][zoom]);
|
const uint16_t *src_n = reinterpret_cast<const uint16_t *>(src->data + src->offset[1][sck]);
|
||||||
|
|
||||||
for (uint i = bp->skip_top; i != 0; i--) {
|
for (uint i = bp->skip_top; i != 0; i--) {
|
||||||
src_px = (const Colour *)((const uint8_t *)src_px + *(const uint32_t *)src_px);
|
src_px = (const Colour *)((const uint8_t *)src_px + *(const uint32_t *)src_px);
|
||||||
|
@ -261,22 +261,22 @@ inline void Blitter_32bppAnim::Draw(const Blitter::BlitterParams *bp, ZoomLevel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Blitter_32bppAnim::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom)
|
void Blitter_32bppAnim::Draw(Blitter::BlitterParams *bp, BlitterMode mode, SpriteCollKey sck)
|
||||||
{
|
{
|
||||||
if (_screen_disable_anim) {
|
if (_screen_disable_anim) {
|
||||||
/* This means our output is not to the screen, so we can't be doing any animation stuff, so use our parent Draw() */
|
/* This means our output is not to the screen, so we can't be doing any animation stuff, so use our parent Draw() */
|
||||||
Blitter_32bppOptimized::Draw(bp, mode, zoom);
|
Blitter_32bppOptimized::Draw(bp, mode, sck);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
default: NOT_REACHED();
|
default: NOT_REACHED();
|
||||||
case BlitterMode::Normal: Draw<BlitterMode::Normal>(bp, zoom); return;
|
case BlitterMode::Normal: Draw<BlitterMode::Normal>(bp, sck); return;
|
||||||
case BlitterMode::ColourRemap: Draw<BlitterMode::ColourRemap>(bp, zoom); return;
|
case BlitterMode::ColourRemap: Draw<BlitterMode::ColourRemap>(bp, sck); return;
|
||||||
case BlitterMode::Transparent: Draw<BlitterMode::Transparent>(bp, zoom); return;
|
case BlitterMode::Transparent: Draw<BlitterMode::Transparent>(bp, sck); return;
|
||||||
case BlitterMode::TransparentRemap: Draw<BlitterMode::TransparentRemap>(bp, zoom); return;
|
case BlitterMode::TransparentRemap: Draw<BlitterMode::TransparentRemap>(bp, sck); return;
|
||||||
case BlitterMode::CrashRemap: Draw<BlitterMode::CrashRemap>(bp, zoom); return;
|
case BlitterMode::CrashRemap: Draw<BlitterMode::CrashRemap>(bp, sck); return;
|
||||||
case BlitterMode::BlackRemap: Draw<BlitterMode::BlackRemap>(bp, zoom); return;
|
case BlitterMode::BlackRemap: Draw<BlitterMode::BlackRemap>(bp, sck); return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ public:
|
||||||
this->palette = _cur_palette;
|
this->palette = _cur_palette;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom) override;
|
void Draw(Blitter::BlitterParams *bp, BlitterMode mode, SpriteCollKey sck) override;
|
||||||
void DrawColourMappingRect(void *dst, int width, int height, PaletteID pal) override;
|
void DrawColourMappingRect(void *dst, int width, int height, PaletteID pal) override;
|
||||||
void SetPixel(void *video, int x, int y, uint8_t colour) override;
|
void SetPixel(void *video, int x, int y, uint8_t colour) override;
|
||||||
void DrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, uint8_t colour, int width, int dash) override;
|
void DrawLine(void *video, int x, int y, int x2, int y2, int screen_width, int screen_height, uint8_t colour, int width, int dash) override;
|
||||||
|
@ -64,7 +64,7 @@ public:
|
||||||
return across + (lines * this->anim_buf_pitch);
|
return across + (lines * this->anim_buf_pitch);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <BlitterMode mode> void Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom);
|
template <BlitterMode mode> void Draw(const Blitter::BlitterParams *bp, SpriteCollKey sck);
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Factory for the 32bpp blitter with animation. */
|
/** Factory for the 32bpp blitter with animation. */
|
||||||
|
|
|
@ -26,12 +26,12 @@ static FBlitter_32bppSSE4_Anim iFBlitter_32bppSSE4_Anim;
|
||||||
*
|
*
|
||||||
* @tparam mode blitter mode
|
* @tparam mode blitter mode
|
||||||
* @param bp further blitting parameters
|
* @param bp further blitting parameters
|
||||||
* @param zoom zoom level at which we are drawing
|
* @param sck sprite collection key to draw
|
||||||
*/
|
*/
|
||||||
IGNORE_UNINITIALIZED_WARNING_START
|
IGNORE_UNINITIALIZED_WARNING_START
|
||||||
template <BlitterMode mode, Blitter_32bppSSE2::ReadMode read_mode, Blitter_32bppSSE2::BlockType bt_last, bool translucent, bool animated>
|
template <BlitterMode mode, Blitter_32bppSSE2::ReadMode read_mode, Blitter_32bppSSE2::BlockType bt_last, bool translucent, bool animated>
|
||||||
GNU_TARGET("sse4.1")
|
GNU_TARGET("sse4.1")
|
||||||
inline void Blitter_32bppSSE4_Anim::Draw(const BlitterParams *bp, ZoomLevel zoom)
|
inline void Blitter_32bppSSE4_Anim::Draw(const BlitterParams *bp, SpriteCollKey sck)
|
||||||
{
|
{
|
||||||
const uint8_t * const remap = bp->remap;
|
const uint8_t * const remap = bp->remap;
|
||||||
Colour *dst_line = (Colour *) bp->dst + bp->top * bp->pitch + bp->left;
|
Colour *dst_line = (Colour *) bp->dst + bp->top * bp->pitch + bp->left;
|
||||||
|
@ -40,7 +40,7 @@ inline void Blitter_32bppSSE4_Anim::Draw(const BlitterParams *bp, ZoomLevel zoom
|
||||||
|
|
||||||
/* Find where to start reading in the source sprite. */
|
/* Find where to start reading in the source sprite. */
|
||||||
const Blitter_32bppSSE_Base::SpriteData * const sd = (const Blitter_32bppSSE_Base::SpriteData *) bp->sprite;
|
const Blitter_32bppSSE_Base::SpriteData * const sd = (const Blitter_32bppSSE_Base::SpriteData *) bp->sprite;
|
||||||
const SpriteInfo * const si = &sd->infos[zoom];
|
const SpriteInfo *const si = &sd->infos[sck];
|
||||||
const MapValue *src_mv_line = (const MapValue *) &sd->data[si->mv_offset] + bp->skip_top * si->sprite_width;
|
const MapValue *src_mv_line = (const MapValue *) &sd->data[si->mv_offset] + bp->skip_top * si->sprite_width;
|
||||||
const Colour *src_rgba_line = (const Colour *) ((const uint8_t *) &sd->data[si->sprite_offset] + bp->skip_top * si->sprite_line_size);
|
const Colour *src_rgba_line = (const Colour *) ((const uint8_t *) &sd->data[si->sprite_offset] + bp->skip_top * si->sprite_line_size);
|
||||||
|
|
||||||
|
@ -380,13 +380,13 @@ IGNORE_UNINITIALIZED_WARNING_STOP
|
||||||
*
|
*
|
||||||
* @param bp further blitting parameters
|
* @param bp further blitting parameters
|
||||||
* @param mode blitter mode
|
* @param mode blitter mode
|
||||||
* @param zoom zoom level at which we are drawing
|
* @param sck sprite collection key to draw
|
||||||
*/
|
*/
|
||||||
void Blitter_32bppSSE4_Anim::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom)
|
void Blitter_32bppSSE4_Anim::Draw(Blitter::BlitterParams *bp, BlitterMode mode, SpriteCollKey sck)
|
||||||
{
|
{
|
||||||
if (_screen_disable_anim) {
|
if (_screen_disable_anim) {
|
||||||
/* This means our output is not to the screen, so we can't be doing any animation stuff, so use our parent Draw() */
|
/* This means our output is not to the screen, so we can't be doing any animation stuff, so use our parent Draw() */
|
||||||
Blitter_32bppSSE4::Draw(bp, mode, zoom);
|
Blitter_32bppSSE4::Draw(bp, mode, sck);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -397,24 +397,24 @@ bm_normal:
|
||||||
if (bp->skip_left != 0 || bp->width <= MARGIN_NORMAL_THRESHOLD) {
|
if (bp->skip_left != 0 || bp->width <= MARGIN_NORMAL_THRESHOLD) {
|
||||||
const BlockType bt_last = (BlockType) (bp->width & 1);
|
const BlockType bt_last = (BlockType) (bp->width & 1);
|
||||||
if (bt_last == BT_EVEN) {
|
if (bt_last == BT_EVEN) {
|
||||||
if (sprite_flags.Test(SpriteFlag::NoAnim)) Draw<BlitterMode::Normal, RM_WITH_SKIP, BT_EVEN, true, false>(bp, zoom);
|
if (sprite_flags.Test(SpriteFlag::NoAnim)) Draw<BlitterMode::Normal, RM_WITH_SKIP, BT_EVEN, true, false>(bp, sck);
|
||||||
else Draw<BlitterMode::Normal, RM_WITH_SKIP, BT_EVEN, true, true>(bp, zoom);
|
else Draw<BlitterMode::Normal, RM_WITH_SKIP, BT_EVEN, true, true>(bp, sck);
|
||||||
} else {
|
} else {
|
||||||
if (sprite_flags.Test(SpriteFlag::NoAnim)) Draw<BlitterMode::Normal, RM_WITH_SKIP, BT_ODD, true, false>(bp, zoom);
|
if (sprite_flags.Test(SpriteFlag::NoAnim)) Draw<BlitterMode::Normal, RM_WITH_SKIP, BT_ODD, true, false>(bp, sck);
|
||||||
else Draw<BlitterMode::Normal, RM_WITH_SKIP, BT_ODD, true, true>(bp, zoom);
|
else Draw<BlitterMode::Normal, RM_WITH_SKIP, BT_ODD, true, true>(bp, sck);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
#ifdef POINTER_IS_64BIT
|
#ifdef POINTER_IS_64BIT
|
||||||
if (sprite_flags.Test(SpriteFlag::Translucent)) {
|
if (sprite_flags.Test(SpriteFlag::Translucent)) {
|
||||||
if (sprite_flags.Test(SpriteFlag::NoAnim)) Draw<BlitterMode::Normal, RM_WITH_MARGIN, BT_NONE, true, false>(bp, zoom);
|
if (sprite_flags.Test(SpriteFlag::NoAnim)) Draw<BlitterMode::Normal, RM_WITH_MARGIN, BT_NONE, true, false>(bp, sck);
|
||||||
else Draw<BlitterMode::Normal, RM_WITH_MARGIN, BT_NONE, true, true>(bp, zoom);
|
else Draw<BlitterMode::Normal, RM_WITH_MARGIN, BT_NONE, true, true>(bp, sck);
|
||||||
} else {
|
} else {
|
||||||
if (sprite_flags.Test(SpriteFlag::NoAnim)) Draw<BlitterMode::Normal, RM_WITH_MARGIN, BT_NONE, false, false>(bp, zoom);
|
if (sprite_flags.Test(SpriteFlag::NoAnim)) Draw<BlitterMode::Normal, RM_WITH_MARGIN, BT_NONE, false, false>(bp, sck);
|
||||||
else Draw<BlitterMode::Normal, RM_WITH_MARGIN, BT_NONE, false, true>(bp, zoom);
|
else Draw<BlitterMode::Normal, RM_WITH_MARGIN, BT_NONE, false, true>(bp, sck);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (sprite_flags.Test(SpriteFlag::NoAnim)) Draw<BlitterMode::Normal, RM_WITH_MARGIN, BT_NONE, true, false>(bp, zoom);
|
if (sprite_flags.Test(SpriteFlag::NoAnim)) Draw<BlitterMode::Normal, RM_WITH_MARGIN, BT_NONE, true, false>(bp, sck);
|
||||||
else Draw<BlitterMode::Normal, RM_WITH_MARGIN, BT_NONE, true, true>(bp, zoom);
|
else Draw<BlitterMode::Normal, RM_WITH_MARGIN, BT_NONE, true, true>(bp, sck);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -422,17 +422,17 @@ bm_normal:
|
||||||
case BlitterMode::ColourRemap:
|
case BlitterMode::ColourRemap:
|
||||||
if (sprite_flags.Test(SpriteFlag::NoRemap)) goto bm_normal;
|
if (sprite_flags.Test(SpriteFlag::NoRemap)) goto bm_normal;
|
||||||
if (bp->skip_left != 0 || bp->width <= MARGIN_REMAP_THRESHOLD) {
|
if (bp->skip_left != 0 || bp->width <= MARGIN_REMAP_THRESHOLD) {
|
||||||
if (sprite_flags.Test(SpriteFlag::NoAnim)) Draw<BlitterMode::ColourRemap, RM_WITH_SKIP, BT_NONE, true, false>(bp, zoom);
|
if (sprite_flags.Test(SpriteFlag::NoAnim)) Draw<BlitterMode::ColourRemap, RM_WITH_SKIP, BT_NONE, true, false>(bp, sck);
|
||||||
else Draw<BlitterMode::ColourRemap, RM_WITH_SKIP, BT_NONE, true, true>(bp, zoom);
|
else Draw<BlitterMode::ColourRemap, RM_WITH_SKIP, BT_NONE, true, true>(bp, sck);
|
||||||
} else {
|
} else {
|
||||||
if (sprite_flags.Test(SpriteFlag::NoAnim)) Draw<BlitterMode::ColourRemap, RM_WITH_MARGIN, BT_NONE, true, false>(bp, zoom);
|
if (sprite_flags.Test(SpriteFlag::NoAnim)) Draw<BlitterMode::ColourRemap, RM_WITH_MARGIN, BT_NONE, true, false>(bp, sck);
|
||||||
else Draw<BlitterMode::ColourRemap, RM_WITH_MARGIN, BT_NONE, true, true>(bp, zoom);
|
else Draw<BlitterMode::ColourRemap, RM_WITH_MARGIN, BT_NONE, true, true>(bp, sck);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case BlitterMode::Transparent: Draw<BlitterMode::Transparent, RM_NONE, BT_NONE, true, true>(bp, zoom); return;
|
case BlitterMode::Transparent: Draw<BlitterMode::Transparent, RM_NONE, BT_NONE, true, true>(bp, sck); return;
|
||||||
case BlitterMode::TransparentRemap: Draw<BlitterMode::TransparentRemap, RM_NONE, BT_NONE, true, true>(bp, zoom); return;
|
case BlitterMode::TransparentRemap: Draw<BlitterMode::TransparentRemap, RM_NONE, BT_NONE, true, true>(bp, sck); return;
|
||||||
case BlitterMode::CrashRemap: Draw<BlitterMode::CrashRemap, RM_NONE, BT_NONE, true, true>(bp, zoom); return;
|
case BlitterMode::CrashRemap: Draw<BlitterMode::CrashRemap, RM_NONE, BT_NONE, true, true>(bp, sck); return;
|
||||||
case BlitterMode::BlackRemap: Draw<BlitterMode::BlackRemap, RM_NONE, BT_NONE, true, true>(bp, zoom); return;
|
case BlitterMode::BlackRemap: Draw<BlitterMode::BlackRemap, RM_NONE, BT_NONE, true, true>(bp, sck); return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,12 +37,12 @@ private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template <BlitterMode mode, Blitter_32bppSSE_Base::ReadMode read_mode, Blitter_32bppSSE_Base::BlockType bt_last, bool translucent, bool animated>
|
template <BlitterMode mode, Blitter_32bppSSE_Base::ReadMode read_mode, Blitter_32bppSSE_Base::BlockType bt_last, bool translucent, bool animated>
|
||||||
void Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom);
|
void Draw(const Blitter::BlitterParams *bp, SpriteCollKey sck);
|
||||||
void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom) override;
|
void Draw(Blitter::BlitterParams *bp, BlitterMode mode, SpriteCollKey sck) override;
|
||||||
|
|
||||||
Sprite *Encode(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator) override
|
Sprite *Encode(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, bool has_rtl, SpriteAllocator &allocator) override
|
||||||
{
|
{
|
||||||
return Blitter_32bppSSE_Base::Encode(sprite_type, sprite, allocator);
|
return Blitter_32bppSSE_Base::Encode(sprite_type, sprite, has_rtl, allocator);
|
||||||
}
|
}
|
||||||
std::string_view GetName() override { return "32bpp-sse4-anim"; }
|
std::string_view GetName() override { return "32bpp-sse4-anim"; }
|
||||||
using Blitter_32bppSSE2_Anim::LookupColourInPalette;
|
using Blitter_32bppSSE2_Anim::LookupColourInPalette;
|
||||||
|
|
|
@ -23,20 +23,20 @@ static FBlitter_32bppOptimized iFBlitter_32bppOptimized;
|
||||||
*
|
*
|
||||||
* @tparam mode blitter mode
|
* @tparam mode blitter mode
|
||||||
* @param bp further blitting parameters
|
* @param bp further blitting parameters
|
||||||
* @param zoom zoom level at which we are drawing
|
* @param sck sprite collection key to draw
|
||||||
*/
|
*/
|
||||||
template <BlitterMode mode, bool Tpal_to_rgb>
|
template <BlitterMode mode, bool Tpal_to_rgb>
|
||||||
inline void Blitter_32bppOptimized::Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom)
|
inline void Blitter_32bppOptimized::Draw(const Blitter::BlitterParams *bp, SpriteCollKey sck)
|
||||||
{
|
{
|
||||||
const SpriteData *src = (const SpriteData *)bp->sprite;
|
const SpriteData *src = (const SpriteData *)bp->sprite;
|
||||||
|
|
||||||
/* src_px : each line begins with uint32_t n = 'number of bytes in this line',
|
/* src_px : each line begins with uint32_t n = 'number of bytes in this line',
|
||||||
* then n times is the Colour struct for this line */
|
* then n times is the Colour struct for this line */
|
||||||
const Colour *src_px = reinterpret_cast<const Colour *>(src->data + src->offset[0][zoom]);
|
const Colour *src_px = reinterpret_cast<const Colour *>(src->data + src->offset[0][sck]);
|
||||||
/* src_n : each line begins with uint32_t n = 'number of bytes in this line',
|
/* src_n : each line begins with uint32_t n = 'number of bytes in this line',
|
||||||
* then interleaved stream of 'm' and 'n' channels. 'm' is remap,
|
* then interleaved stream of 'm' and 'n' channels. 'm' is remap,
|
||||||
* 'n' is number of bytes with the same alpha channel class */
|
* 'n' is number of bytes with the same alpha channel class */
|
||||||
const uint16_t *src_n = reinterpret_cast<const uint16_t *>(src->data + src->offset[1][zoom]);
|
const uint16_t *src_n = reinterpret_cast<const uint16_t *>(src->data + src->offset[1][sck]);
|
||||||
|
|
||||||
/* skip upper lines in src_px and src_n */
|
/* skip upper lines in src_px and src_n */
|
||||||
for (uint i = bp->skip_top; i != 0; i--) {
|
for (uint i = bp->skip_top; i != 0; i--) {
|
||||||
|
@ -257,36 +257,36 @@ inline void Blitter_32bppOptimized::Draw(const Blitter::BlitterParams *bp, ZoomL
|
||||||
}
|
}
|
||||||
|
|
||||||
template <bool Tpal_to_rgb>
|
template <bool Tpal_to_rgb>
|
||||||
void Blitter_32bppOptimized::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom)
|
void Blitter_32bppOptimized::Draw(Blitter::BlitterParams *bp, BlitterMode mode, SpriteCollKey sck)
|
||||||
{
|
{
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
default: NOT_REACHED();
|
default: NOT_REACHED();
|
||||||
case BlitterMode::Normal: Draw<BlitterMode::Normal, Tpal_to_rgb>(bp, zoom); return;
|
case BlitterMode::Normal: Draw<BlitterMode::Normal, Tpal_to_rgb>(bp, sck); return;
|
||||||
case BlitterMode::ColourRemap: Draw<BlitterMode::ColourRemap, Tpal_to_rgb>(bp, zoom); return;
|
case BlitterMode::ColourRemap: Draw<BlitterMode::ColourRemap, Tpal_to_rgb>(bp, sck); return;
|
||||||
case BlitterMode::Transparent: Draw<BlitterMode::Transparent, Tpal_to_rgb>(bp, zoom); return;
|
case BlitterMode::Transparent: Draw<BlitterMode::Transparent, Tpal_to_rgb>(bp, sck); return;
|
||||||
case BlitterMode::TransparentRemap: Draw<BlitterMode::TransparentRemap, Tpal_to_rgb>(bp, zoom); return;
|
case BlitterMode::TransparentRemap: Draw<BlitterMode::TransparentRemap, Tpal_to_rgb>(bp, sck); return;
|
||||||
case BlitterMode::CrashRemap: Draw<BlitterMode::CrashRemap, Tpal_to_rgb>(bp, zoom); return;
|
case BlitterMode::CrashRemap: Draw<BlitterMode::CrashRemap, Tpal_to_rgb>(bp, sck); return;
|
||||||
case BlitterMode::BlackRemap: Draw<BlitterMode::BlackRemap, Tpal_to_rgb>(bp, zoom); return;
|
case BlitterMode::BlackRemap: Draw<BlitterMode::BlackRemap, Tpal_to_rgb>(bp, sck); return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template void Blitter_32bppOptimized::Draw<true>(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom);
|
template void Blitter_32bppOptimized::Draw<true>(Blitter::BlitterParams *bp, BlitterMode mode, SpriteCollKey sck);
|
||||||
template void Blitter_32bppOptimized::Draw<false>(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom);
|
template void Blitter_32bppOptimized::Draw<false>(Blitter::BlitterParams *bp, BlitterMode mode, SpriteCollKey sck);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draws a sprite to a (screen) buffer. Calls adequate templated function.
|
* Draws a sprite to a (screen) buffer. Calls adequate templated function.
|
||||||
*
|
*
|
||||||
* @param bp further blitting parameters
|
* @param bp further blitting parameters
|
||||||
* @param mode blitter mode
|
* @param mode blitter mode
|
||||||
* @param zoom zoom level at which we are drawing
|
* @param sck sprite collection key to draw
|
||||||
*/
|
*/
|
||||||
void Blitter_32bppOptimized::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom)
|
void Blitter_32bppOptimized::Draw(Blitter::BlitterParams *bp, BlitterMode mode, SpriteCollKey sck)
|
||||||
{
|
{
|
||||||
this->Draw<false>(bp, mode, zoom);
|
this->Draw<false>(bp, mode, sck);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <bool Tpal_to_rgb>
|
template <bool Tpal_to_rgb>
|
||||||
Sprite *Blitter_32bppOptimized::EncodeInternal(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator)
|
Sprite *Blitter_32bppOptimized::EncodeInternal(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, bool has_rtl, SpriteAllocator &allocator)
|
||||||
{
|
{
|
||||||
/* streams of pixels (a, r, g, b channels)
|
/* streams of pixels (a, r, g, b channels)
|
||||||
*
|
*
|
||||||
|
@ -316,16 +316,16 @@ Sprite *Blitter_32bppOptimized::EncodeInternal(SpriteType sprite_type, const Spr
|
||||||
if (zoom_max == zoom_min) zoom_max = ZoomLevel::Max;
|
if (zoom_max == zoom_min) zoom_max = ZoomLevel::Max;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ZoomLevel z = zoom_min; z <= zoom_max; z++) {
|
for (auto sck : SpriteCollKeyRange(zoom_min, zoom_max, has_rtl)) {
|
||||||
const SpriteLoader::Sprite *src_orig = &sprite[z];
|
const SpriteLoader::Sprite *src_orig = &sprite[sck];
|
||||||
|
|
||||||
uint size = src_orig->height * src_orig->width;
|
uint size = src_orig->height * src_orig->width;
|
||||||
|
|
||||||
dst_px_orig[z] = std::make_unique<Colour[]>(size + src_orig->height * 2);
|
dst_px_orig[sck] = std::make_unique<Colour[]>(size + src_orig->height * 2);
|
||||||
dst_n_orig[z] = std::make_unique<uint16_t[]>(size * 2 + src_orig->height * 4 * 2);
|
dst_n_orig[sck] = std::make_unique<uint16_t[]>(size * 2 + src_orig->height * 4 * 2);
|
||||||
|
|
||||||
uint32_t *dst_px_ln = reinterpret_cast<uint32_t *>(dst_px_orig[z].get());
|
uint32_t *dst_px_ln = reinterpret_cast<uint32_t *>(dst_px_orig[sck].get());
|
||||||
uint32_t *dst_n_ln = reinterpret_cast<uint32_t *>(dst_n_orig[z].get());
|
uint32_t *dst_n_ln = reinterpret_cast<uint32_t *>(dst_n_orig[sck].get());
|
||||||
|
|
||||||
const SpriteLoader::CommonPixel *src = (const SpriteLoader::CommonPixel *)src_orig->data;
|
const SpriteLoader::CommonPixel *src = (const SpriteLoader::CommonPixel *)src_orig->data;
|
||||||
|
|
||||||
|
@ -406,43 +406,50 @@ Sprite *Blitter_32bppOptimized::EncodeInternal(SpriteType sprite_type, const Spr
|
||||||
dst_n_ln = (uint32_t *)dst_n;
|
dst_n_ln = (uint32_t *)dst_n;
|
||||||
}
|
}
|
||||||
|
|
||||||
lengths[0][z] = reinterpret_cast<uint8_t *>(dst_px_ln) - reinterpret_cast<uint8_t *>(dst_px_orig[z].get()); // all are aligned to 4B boundary
|
lengths[0][sck] = reinterpret_cast<uint8_t *>(dst_px_ln) - reinterpret_cast<uint8_t *>(dst_px_orig[sck].get()); // all are aligned to 4B boundary
|
||||||
lengths[1][z] = reinterpret_cast<uint8_t *>(dst_n_ln) - reinterpret_cast<uint8_t *>(dst_n_orig[z].get());
|
lengths[1][sck] = reinterpret_cast<uint8_t *>(dst_n_ln) - reinterpret_cast<uint8_t *>(dst_n_orig[sck].get());
|
||||||
}
|
}
|
||||||
|
|
||||||
uint len = 0; // total length of data
|
uint len = 0; // total length of data
|
||||||
for (ZoomLevel z = zoom_min; z <= zoom_max; z++) {
|
for (auto sck : SpriteCollKeyRange(zoom_min, zoom_max, has_rtl)) {
|
||||||
len += lengths[0][z] + lengths[1][z];
|
len += lengths[0][sck] + lengths[1][sck];
|
||||||
}
|
}
|
||||||
|
|
||||||
Sprite *dest_sprite = allocator.Allocate<Sprite>(sizeof(*dest_sprite) + sizeof(SpriteData) + len);
|
Sprite *dest_sprite = allocator.Allocate<Sprite>(sizeof(*dest_sprite) + sizeof(SpriteData) + len);
|
||||||
|
|
||||||
const auto &root_sprite = sprite.Root();
|
const auto &root_sprite = sprite.Root(false);
|
||||||
dest_sprite->height = root_sprite.height;
|
dest_sprite->height = root_sprite.height;
|
||||||
dest_sprite->width = root_sprite.width;
|
dest_sprite->width = root_sprite.width;
|
||||||
dest_sprite->x_offs = root_sprite.x_offs;
|
dest_sprite->x_offs = root_sprite.x_offs;
|
||||||
dest_sprite->y_offs = root_sprite.y_offs;
|
dest_sprite->y_offs = root_sprite.y_offs;
|
||||||
|
dest_sprite->has_rtl = has_rtl;
|
||||||
|
|
||||||
SpriteData *dst = (SpriteData *)dest_sprite->data;
|
SpriteData *dst = (SpriteData *)dest_sprite->data;
|
||||||
|
|
||||||
uint32_t offset = 0;
|
uint32_t offset = 0;
|
||||||
for (ZoomLevel z = zoom_min; z <= zoom_max; z++) {
|
for (auto sck : SpriteCollKeyRange(zoom_min, zoom_max, has_rtl)) {
|
||||||
dst->offset[0][z] = offset;
|
dst->offset[0][sck] = offset;
|
||||||
offset += lengths[0][z];
|
offset += lengths[0][sck];
|
||||||
dst->offset[1][z] = offset;
|
dst->offset[1][sck] = offset;
|
||||||
offset += lengths[1][z];
|
offset += lengths[1][sck];
|
||||||
|
if (!has_rtl) {
|
||||||
|
/* Duplicate the sprite for RTL */
|
||||||
|
SpriteCollKey rtl{sck.zoom, true};
|
||||||
|
dst->offset[0][rtl] = dst->offset[0][sck];
|
||||||
|
dst->offset[1][rtl] = dst->offset[1][sck];
|
||||||
|
}
|
||||||
|
|
||||||
std::copy_n(reinterpret_cast<uint8_t *>(dst_px_orig[z].get()), lengths[0][z], dst->data + dst->offset[0][z]);
|
std::copy_n(reinterpret_cast<uint8_t *>(dst_px_orig[sck].get()), lengths[0][sck], dst->data + dst->offset[0][sck]);
|
||||||
std::copy_n(reinterpret_cast<uint8_t *>(dst_n_orig[z].get()), lengths[1][z], dst->data + dst->offset[1][z]);
|
std::copy_n(reinterpret_cast<uint8_t *>(dst_n_orig[sck].get()), lengths[1][sck], dst->data + dst->offset[1][sck]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return dest_sprite;
|
return dest_sprite;
|
||||||
}
|
}
|
||||||
|
|
||||||
template Sprite *Blitter_32bppOptimized::EncodeInternal<true>(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator);
|
template Sprite *Blitter_32bppOptimized::EncodeInternal<true>(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, bool has_rtl, SpriteAllocator &allocator);
|
||||||
template Sprite *Blitter_32bppOptimized::EncodeInternal<false>(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator);
|
template Sprite *Blitter_32bppOptimized::EncodeInternal<false>(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, bool has_rtl, SpriteAllocator &allocator);
|
||||||
|
|
||||||
Sprite *Blitter_32bppOptimized::Encode(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator)
|
Sprite *Blitter_32bppOptimized::Encode(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, bool has_rtl, SpriteAllocator &allocator)
|
||||||
{
|
{
|
||||||
return this->EncodeInternal<true>(sprite_type, sprite, allocator);
|
return this->EncodeInternal<true>(sprite_type, sprite, has_rtl, allocator);
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,16 +21,16 @@ public:
|
||||||
uint8_t data[]; ///< Data, all zoomlevels.
|
uint8_t data[]; ///< Data, all zoomlevels.
|
||||||
};
|
};
|
||||||
|
|
||||||
void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom) override;
|
void Draw(Blitter::BlitterParams *bp, BlitterMode mode, SpriteCollKey sck) override;
|
||||||
Sprite *Encode(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator) override;
|
Sprite *Encode(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, bool has_rtl, SpriteAllocator &allocator) override;
|
||||||
|
|
||||||
std::string_view GetName() override { return "32bpp-optimized"; }
|
std::string_view GetName() override { return "32bpp-optimized"; }
|
||||||
|
|
||||||
template <BlitterMode mode, bool Tpal_to_rgb = false> void Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom);
|
template <BlitterMode mode, bool Tpal_to_rgb = false> void Draw(const Blitter::BlitterParams *bp, SpriteCollKey sck);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
template <bool Tpal_to_rgb> void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom);
|
template <bool Tpal_to_rgb> void Draw(Blitter::BlitterParams *bp, BlitterMode mode, SpriteCollKey sck);
|
||||||
template <bool Tpal_to_rgb> Sprite *EncodeInternal(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator);
|
template <bool Tpal_to_rgb> Sprite *EncodeInternal(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, bool has_rtl, SpriteAllocator &allocator);
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Factory for the optimised 32 bpp blitter (without palette animation). */
|
/** Factory for the optimised 32 bpp blitter (without palette animation). */
|
||||||
|
|
|
@ -19,13 +19,13 @@
|
||||||
/** Instantiation of the simple 32bpp blitter factory. */
|
/** Instantiation of the simple 32bpp blitter factory. */
|
||||||
static FBlitter_32bppSimple iFBlitter_32bppSimple;
|
static FBlitter_32bppSimple iFBlitter_32bppSimple;
|
||||||
|
|
||||||
void Blitter_32bppSimple::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom)
|
void Blitter_32bppSimple::Draw(Blitter::BlitterParams *bp, BlitterMode mode, SpriteCollKey sck)
|
||||||
{
|
{
|
||||||
const Blitter_32bppSimple::Pixel *src, *src_line;
|
const Blitter_32bppSimple::Pixel *src, *src_line;
|
||||||
Colour *dst, *dst_line;
|
Colour *dst, *dst_line;
|
||||||
|
|
||||||
/* Find where to start reading in the source sprite */
|
/* Find where to start reading in the source sprite */
|
||||||
src_line = (const Blitter_32bppSimple::Pixel *)bp->sprite + (bp->skip_top * bp->sprite_width + bp->skip_left) * ScaleByZoom(1, zoom);
|
src_line = (const Blitter_32bppSimple::Pixel *)bp->sprite + (bp->skip_top * bp->sprite_width + bp->skip_left) * ScaleByZoom(1, sck.zoom);
|
||||||
dst_line = (Colour *)bp->dst + bp->top * bp->pitch + bp->left;
|
dst_line = (Colour *)bp->dst + bp->top * bp->pitch + bp->left;
|
||||||
|
|
||||||
for (int y = 0; y < bp->height; y++) {
|
for (int y = 0; y < bp->height; y++) {
|
||||||
|
@ -33,7 +33,7 @@ void Blitter_32bppSimple::Draw(Blitter::BlitterParams *bp, BlitterMode mode, Zoo
|
||||||
dst_line += bp->pitch;
|
dst_line += bp->pitch;
|
||||||
|
|
||||||
src = src_line;
|
src = src_line;
|
||||||
src_line += bp->sprite_width * ScaleByZoom(1, zoom);
|
src_line += bp->sprite_width * ScaleByZoom(1, sck.zoom);
|
||||||
|
|
||||||
for (int x = 0; x < bp->width; x++) {
|
for (int x = 0; x < bp->width; x++) {
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
|
@ -82,7 +82,7 @@ void Blitter_32bppSimple::Draw(Blitter::BlitterParams *bp, BlitterMode mode, Zoo
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
dst++;
|
dst++;
|
||||||
src += ScaleByZoom(1, zoom);
|
src += ScaleByZoom(1, sck.zoom);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -115,9 +115,9 @@ void Blitter_32bppSimple::DrawColourMappingRect(void *dst, int width, int height
|
||||||
Debug(misc, 0, "32bpp blitter doesn't know how to draw this colour table ('{}')", pal);
|
Debug(misc, 0, "32bpp blitter doesn't know how to draw this colour table ('{}')", pal);
|
||||||
}
|
}
|
||||||
|
|
||||||
Sprite *Blitter_32bppSimple::Encode(SpriteType, const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator)
|
Sprite *Blitter_32bppSimple::Encode(SpriteType, const SpriteLoader::SpriteCollection &sprite, bool, SpriteAllocator &allocator)
|
||||||
{
|
{
|
||||||
const auto &root_sprite = sprite.Root();
|
const auto &root_sprite = sprite.Root(false);
|
||||||
Blitter_32bppSimple::Pixel *dst;
|
Blitter_32bppSimple::Pixel *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));
|
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));
|
||||||
|
|
||||||
|
@ -125,6 +125,7 @@ Sprite *Blitter_32bppSimple::Encode(SpriteType, const SpriteLoader::SpriteCollec
|
||||||
dest_sprite->width = root_sprite.width;
|
dest_sprite->width = root_sprite.width;
|
||||||
dest_sprite->x_offs = root_sprite.x_offs;
|
dest_sprite->x_offs = root_sprite.x_offs;
|
||||||
dest_sprite->y_offs = root_sprite.y_offs;
|
dest_sprite->y_offs = root_sprite.y_offs;
|
||||||
|
dest_sprite->has_rtl = false;
|
||||||
|
|
||||||
dst = reinterpret_cast<Blitter_32bppSimple::Pixel *>(dest_sprite->data);
|
dst = reinterpret_cast<Blitter_32bppSimple::Pixel *>(dest_sprite->data);
|
||||||
SpriteLoader::CommonPixel *src = reinterpret_cast<SpriteLoader::CommonPixel *>(root_sprite.data);
|
SpriteLoader::CommonPixel *src = reinterpret_cast<SpriteLoader::CommonPixel *>(root_sprite.data);
|
||||||
|
|
|
@ -24,9 +24,9 @@ class Blitter_32bppSimple : public Blitter_32bppBase {
|
||||||
uint8_t v; ///< Brightness-channel
|
uint8_t v; ///< Brightness-channel
|
||||||
};
|
};
|
||||||
public:
|
public:
|
||||||
void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom) override;
|
void Draw(Blitter::BlitterParams *bp, BlitterMode mode, SpriteCollKey sck) override;
|
||||||
void DrawColourMappingRect(void *dst, int width, int height, PaletteID pal) override;
|
void DrawColourMappingRect(void *dst, int width, int height, PaletteID pal) override;
|
||||||
Sprite *Encode(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator) override;
|
Sprite *Encode(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, bool has_rtl, SpriteAllocator &allocator) override;
|
||||||
|
|
||||||
std::string_view GetName() override { return "32bpp-simple"; }
|
std::string_view GetName() override { return "32bpp-simple"; }
|
||||||
};
|
};
|
||||||
|
|
|
@ -20,7 +20,7 @@
|
||||||
/** Instantiation of the SSE2 32bpp blitter factory. */
|
/** Instantiation of the SSE2 32bpp blitter factory. */
|
||||||
static FBlitter_32bppSSE2 iFBlitter_32bppSSE2;
|
static FBlitter_32bppSSE2 iFBlitter_32bppSSE2;
|
||||||
|
|
||||||
Sprite *Blitter_32bppSSE_Base::Encode(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator)
|
Sprite *Blitter_32bppSSE_Base::Encode(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, bool has_rtl, SpriteAllocator &allocator)
|
||||||
{
|
{
|
||||||
/* First uint32_t of a line = the number of transparent pixels from the left.
|
/* First uint32_t of a line = the number of transparent pixels from the left.
|
||||||
* Second uint32_t of a line = the number of transparent pixels from the right.
|
* Second uint32_t of a line = the number of transparent pixels from the right.
|
||||||
|
@ -37,9 +37,9 @@ Sprite *Blitter_32bppSSE_Base::Encode(SpriteType sprite_type, const SpriteLoader
|
||||||
/* Calculate sizes and allocate. */
|
/* Calculate sizes and allocate. */
|
||||||
SpriteData sd{};
|
SpriteData sd{};
|
||||||
uint all_sprites_size = 0;
|
uint all_sprites_size = 0;
|
||||||
for (ZoomLevel z = zoom_min; z <= zoom_max; z++) {
|
for (auto sck : SpriteCollKeyRange(zoom_min, zoom_max, has_rtl)) {
|
||||||
const SpriteLoader::Sprite *src_sprite = &sprite[z];
|
const SpriteLoader::Sprite *src_sprite = &sprite[sck];
|
||||||
auto &info = sd.infos[z];
|
auto &info = sd.infos[sck];
|
||||||
info.sprite_width = src_sprite->width;
|
info.sprite_width = src_sprite->width;
|
||||||
info.sprite_offset = all_sprites_size;
|
info.sprite_offset = all_sprites_size;
|
||||||
info.sprite_line_size = sizeof(Colour) * src_sprite->width + sizeof(uint32_t) * META_LENGTH;
|
info.sprite_line_size = sizeof(Colour) * src_sprite->width + sizeof(uint32_t) * META_LENGTH;
|
||||||
|
@ -47,26 +47,33 @@ Sprite *Blitter_32bppSSE_Base::Encode(SpriteType sprite_type, const SpriteLoader
|
||||||
const uint rgba_size = info.sprite_line_size * src_sprite->height;
|
const uint rgba_size = info.sprite_line_size * src_sprite->height;
|
||||||
info.mv_offset = all_sprites_size + rgba_size;
|
info.mv_offset = all_sprites_size + rgba_size;
|
||||||
|
|
||||||
|
if (!has_rtl) {
|
||||||
|
/* Duplicate the sprite for RTL */
|
||||||
|
SpriteCollKey rtl{sck.zoom, true};
|
||||||
|
sd.infos[rtl] = info;
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
||||||
const auto &root_sprite = sprite.Root();
|
const auto &root_sprite = sprite.Root(false);
|
||||||
dst_sprite->height = root_sprite.height;
|
dst_sprite->height = root_sprite.height;
|
||||||
dst_sprite->width = root_sprite.width;
|
dst_sprite->width = root_sprite.width;
|
||||||
dst_sprite->x_offs = root_sprite.x_offs;
|
dst_sprite->x_offs = root_sprite.x_offs;
|
||||||
dst_sprite->y_offs = root_sprite.y_offs;
|
dst_sprite->y_offs = root_sprite.y_offs;
|
||||||
|
dst_sprite->has_rtl = has_rtl;
|
||||||
std::copy_n(reinterpret_cast<std::byte *>(&sd), sizeof(SpriteData), dst_sprite->data);
|
std::copy_n(reinterpret_cast<std::byte *>(&sd), sizeof(SpriteData), dst_sprite->data);
|
||||||
|
|
||||||
/* Copy colours and determine flags. */
|
/* Copy colours and determine flags. */
|
||||||
bool has_remap = false;
|
bool has_remap = false;
|
||||||
bool has_anim = false;
|
bool has_anim = false;
|
||||||
bool has_translucency = false;
|
bool has_translucency = false;
|
||||||
for (ZoomLevel z = zoom_min; z <= zoom_max; z++) {
|
for (auto sck : SpriteCollKeyRange(zoom_min, zoom_max, has_rtl)) {
|
||||||
const SpriteLoader::Sprite *src_sprite = &sprite[z];
|
const SpriteLoader::Sprite *src_sprite = &sprite[sck];
|
||||||
const SpriteLoader::CommonPixel *src = (const SpriteLoader::CommonPixel *) src_sprite->data;
|
const SpriteLoader::CommonPixel *src = (const SpriteLoader::CommonPixel *) src_sprite->data;
|
||||||
const auto &info = sd.infos[z];
|
const auto &info = sd.infos[sck];
|
||||||
Colour *dst_rgba_line = reinterpret_cast<Colour *>(&dst_sprite->data[sizeof(SpriteData) + info.sprite_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]);
|
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--) {
|
||||||
|
|
|
@ -77,19 +77,19 @@ public:
|
||||||
uint8_t data[]; ///< Data, all zoomlevels.
|
uint8_t data[]; ///< Data, all zoomlevels.
|
||||||
};
|
};
|
||||||
|
|
||||||
Sprite *Encode(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator);
|
Sprite *Encode(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, bool has_rtl, SpriteAllocator &allocator);
|
||||||
};
|
};
|
||||||
|
|
||||||
/** The SSE2 32 bpp blitter (without palette animation). */
|
/** The SSE2 32 bpp blitter (without palette animation). */
|
||||||
class Blitter_32bppSSE2 : public Blitter_32bppSimple, public Blitter_32bppSSE_Base {
|
class Blitter_32bppSSE2 : public Blitter_32bppSimple, public Blitter_32bppSSE_Base {
|
||||||
public:
|
public:
|
||||||
void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom) override;
|
void Draw(Blitter::BlitterParams *bp, BlitterMode mode, SpriteCollKey sck) override;
|
||||||
template <BlitterMode mode, Blitter_32bppSSE_Base::ReadMode read_mode, Blitter_32bppSSE_Base::BlockType bt_last, bool translucent>
|
template <BlitterMode mode, Blitter_32bppSSE_Base::ReadMode read_mode, Blitter_32bppSSE_Base::BlockType bt_last, bool translucent>
|
||||||
void Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom);
|
void Draw(const Blitter::BlitterParams *bp, SpriteCollKey sck);
|
||||||
|
|
||||||
Sprite *Encode(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator) override
|
Sprite *Encode(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, bool has_rtl, SpriteAllocator &allocator) override
|
||||||
{
|
{
|
||||||
return Blitter_32bppSSE_Base::Encode(sprite_type, sprite, allocator);
|
return Blitter_32bppSSE_Base::Encode(sprite_type, sprite, has_rtl, allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string_view GetName() override { return "32bpp-sse2"; }
|
std::string_view GetName() override { return "32bpp-sse2"; }
|
||||||
|
|
|
@ -29,9 +29,9 @@
|
||||||
/** The SSE4 32 bpp blitter (without palette animation). */
|
/** The SSE4 32 bpp blitter (without palette animation). */
|
||||||
class Blitter_32bppSSE4 : public Blitter_32bppSSSE3 {
|
class Blitter_32bppSSE4 : public Blitter_32bppSSSE3 {
|
||||||
public:
|
public:
|
||||||
void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom) override;
|
void Draw(Blitter::BlitterParams *bp, BlitterMode mode, SpriteCollKey sck) override;
|
||||||
template <BlitterMode mode, Blitter_32bppSSE_Base::ReadMode read_mode, Blitter_32bppSSE_Base::BlockType bt_last, bool translucent>
|
template <BlitterMode mode, Blitter_32bppSSE_Base::ReadMode read_mode, Blitter_32bppSSE_Base::BlockType bt_last, bool translucent>
|
||||||
void Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom);
|
void Draw(const Blitter::BlitterParams *bp, SpriteCollKey sck);
|
||||||
std::string_view GetName() override { return "32bpp-sse4"; }
|
std::string_view GetName() override { return "32bpp-sse4"; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -208,17 +208,17 @@ INTERNAL_LINKAGE inline __m128i AdjustBrightnessOfTwoPixels([[maybe_unused]] __m
|
||||||
*
|
*
|
||||||
* @tparam mode blitter mode
|
* @tparam mode blitter mode
|
||||||
* @param bp further blitting parameters
|
* @param bp further blitting parameters
|
||||||
* @param zoom zoom level at which we are drawing
|
* @param sck sprite collection key to draw
|
||||||
*/
|
*/
|
||||||
IGNORE_UNINITIALIZED_WARNING_START
|
IGNORE_UNINITIALIZED_WARNING_START
|
||||||
template <BlitterMode mode, Blitter_32bppSSE2::ReadMode read_mode, Blitter_32bppSSE2::BlockType bt_last, bool translucent>
|
template <BlitterMode mode, Blitter_32bppSSE2::ReadMode read_mode, Blitter_32bppSSE2::BlockType bt_last, bool translucent>
|
||||||
GNU_TARGET(SSE_TARGET)
|
GNU_TARGET(SSE_TARGET)
|
||||||
#if (SSE_VERSION == 2)
|
#if (SSE_VERSION == 2)
|
||||||
inline void Blitter_32bppSSE2::Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom)
|
inline void Blitter_32bppSSE2::Draw(const Blitter::BlitterParams *bp, SpriteCollKey sck)
|
||||||
#elif (SSE_VERSION == 3)
|
#elif (SSE_VERSION == 3)
|
||||||
inline void Blitter_32bppSSSE3::Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom)
|
inline void Blitter_32bppSSSE3::Draw(const Blitter::BlitterParams *bp, SpriteCollKey sck)
|
||||||
#elif (SSE_VERSION == 4)
|
#elif (SSE_VERSION == 4)
|
||||||
inline void Blitter_32bppSSE4::Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom)
|
inline void Blitter_32bppSSE4::Draw(const Blitter::BlitterParams *bp, SpriteCollKey sck)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
const uint8_t * const remap = bp->remap;
|
const uint8_t * const remap = bp->remap;
|
||||||
|
@ -227,7 +227,7 @@ inline void Blitter_32bppSSE4::Draw(const Blitter::BlitterParams *bp, ZoomLevel
|
||||||
|
|
||||||
/* Find where to start reading in the source sprite. */
|
/* Find where to start reading in the source sprite. */
|
||||||
const SpriteData * const sd = (const SpriteData *) bp->sprite;
|
const SpriteData * const sd = (const SpriteData *) bp->sprite;
|
||||||
const SpriteInfo * const si = &sd->infos[zoom];
|
const SpriteInfo *const si = &sd->infos[sck];
|
||||||
const MapValue *src_mv_line = (const MapValue *) &sd->data[si->mv_offset] + bp->skip_top * si->sprite_width;
|
const MapValue *src_mv_line = (const MapValue *) &sd->data[si->mv_offset] + bp->skip_top * si->sprite_width;
|
||||||
const Colour *src_rgba_line = (const Colour *) ((const uint8_t *) &sd->data[si->sprite_offset] + bp->skip_top * si->sprite_line_size);
|
const Colour *src_rgba_line = (const Colour *) ((const uint8_t *) &sd->data[si->sprite_offset] + bp->skip_top * si->sprite_line_size);
|
||||||
|
|
||||||
|
@ -453,14 +453,14 @@ IGNORE_UNINITIALIZED_WARNING_STOP
|
||||||
*
|
*
|
||||||
* @param bp further blitting parameters
|
* @param bp further blitting parameters
|
||||||
* @param mode blitter mode
|
* @param mode blitter mode
|
||||||
* @param zoom zoom level at which we are drawing
|
* @param sck sprite collection key to draw
|
||||||
*/
|
*/
|
||||||
#if (SSE_VERSION == 2)
|
#if (SSE_VERSION == 2)
|
||||||
void Blitter_32bppSSE2::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom)
|
void Blitter_32bppSSE2::Draw(Blitter::BlitterParams *bp, BlitterMode mode, SpriteCollKey sck)
|
||||||
#elif (SSE_VERSION == 3)
|
#elif (SSE_VERSION == 3)
|
||||||
void Blitter_32bppSSSE3::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom)
|
void Blitter_32bppSSSE3::Draw(Blitter::BlitterParams *bp, BlitterMode mode, SpriteCollKey sck)
|
||||||
#elif (SSE_VERSION == 4)
|
#elif (SSE_VERSION == 4)
|
||||||
void Blitter_32bppSSE4::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom)
|
void Blitter_32bppSSE4::Draw(Blitter::BlitterParams *bp, BlitterMode mode, SpriteCollKey sck)
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
|
@ -469,14 +469,14 @@ void Blitter_32bppSSE4::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomL
|
||||||
bm_normal:
|
bm_normal:
|
||||||
const BlockType bt_last = (BlockType) (bp->width & 1);
|
const BlockType bt_last = (BlockType) (bp->width & 1);
|
||||||
switch (bt_last) {
|
switch (bt_last) {
|
||||||
default: Draw<BlitterMode::Normal, RM_WITH_SKIP, BT_EVEN, true>(bp, zoom); return;
|
default: Draw<BlitterMode::Normal, RM_WITH_SKIP, BT_EVEN, true>(bp, sck); return;
|
||||||
case BT_ODD: Draw<BlitterMode::Normal, RM_WITH_SKIP, BT_ODD, true>(bp, zoom); return;
|
case BT_ODD: Draw<BlitterMode::Normal, RM_WITH_SKIP, BT_ODD, true>(bp, sck); return;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (((const Blitter_32bppSSE_Base::SpriteData *) bp->sprite)->flags.Test(SpriteFlag::Translucent)) {
|
if (((const Blitter_32bppSSE_Base::SpriteData *) bp->sprite)->flags.Test(SpriteFlag::Translucent)) {
|
||||||
Draw<BlitterMode::Normal, RM_WITH_MARGIN, BT_NONE, true>(bp, zoom);
|
Draw<BlitterMode::Normal, RM_WITH_MARGIN, BT_NONE, true>(bp, sck);
|
||||||
} else {
|
} else {
|
||||||
Draw<BlitterMode::Normal, RM_WITH_MARGIN, BT_NONE, false>(bp, zoom);
|
Draw<BlitterMode::Normal, RM_WITH_MARGIN, BT_NONE, false>(bp, sck);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -485,14 +485,14 @@ bm_normal:
|
||||||
case BlitterMode::ColourRemap:
|
case BlitterMode::ColourRemap:
|
||||||
if (((const Blitter_32bppSSE_Base::SpriteData *) bp->sprite)->flags.Test(SpriteFlag::NoRemap)) goto bm_normal;
|
if (((const Blitter_32bppSSE_Base::SpriteData *) bp->sprite)->flags.Test(SpriteFlag::NoRemap)) goto bm_normal;
|
||||||
if (bp->skip_left != 0 || bp->width <= MARGIN_REMAP_THRESHOLD) {
|
if (bp->skip_left != 0 || bp->width <= MARGIN_REMAP_THRESHOLD) {
|
||||||
Draw<BlitterMode::ColourRemap, RM_WITH_SKIP, BT_NONE, true>(bp, zoom); return;
|
Draw<BlitterMode::ColourRemap, RM_WITH_SKIP, BT_NONE, true>(bp, sck); return;
|
||||||
} else {
|
} else {
|
||||||
Draw<BlitterMode::ColourRemap, RM_WITH_MARGIN, BT_NONE, true>(bp, zoom); return;
|
Draw<BlitterMode::ColourRemap, RM_WITH_MARGIN, BT_NONE, true>(bp, sck); return;
|
||||||
}
|
}
|
||||||
case BlitterMode::Transparent: Draw<BlitterMode::Transparent, RM_NONE, BT_NONE, true>(bp, zoom); return;
|
case BlitterMode::Transparent: Draw<BlitterMode::Transparent, RM_NONE, BT_NONE, true>(bp, sck); return;
|
||||||
case BlitterMode::TransparentRemap: Draw<BlitterMode::TransparentRemap, RM_NONE, BT_NONE, true>(bp, zoom); return;
|
case BlitterMode::TransparentRemap: Draw<BlitterMode::TransparentRemap, RM_NONE, BT_NONE, true>(bp, sck); return;
|
||||||
case BlitterMode::CrashRemap: Draw<BlitterMode::CrashRemap, RM_NONE, BT_NONE, true>(bp, zoom); return;
|
case BlitterMode::CrashRemap: Draw<BlitterMode::CrashRemap, RM_NONE, BT_NONE, true>(bp, sck); return;
|
||||||
case BlitterMode::BlackRemap: Draw<BlitterMode::BlackRemap, RM_NONE, BT_NONE, true>(bp, zoom); return;
|
case BlitterMode::BlackRemap: Draw<BlitterMode::BlackRemap, RM_NONE, BT_NONE, true>(bp, sck); return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* FULL_ANIMATION */
|
#endif /* FULL_ANIMATION */
|
||||||
|
|
|
@ -28,7 +28,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define META_LENGTH 2 ///< Number of uint32_t inserted before each line of pixels in a sprite.
|
#define META_LENGTH 2 ///< Number of uint32_t inserted before each line of pixels in a sprite.
|
||||||
#define MARGIN_NORMAL_THRESHOLD (zoom == ZoomLevel::Out8x ? 8 : 4) ///< Minimum width to use margins with BlitterMode::Normal.
|
#define MARGIN_NORMAL_THRESHOLD (sck.zoom == ZoomLevel::Out8x ? 8 : 4) ///< Minimum width to use margins with BlitterMode::Normal.
|
||||||
#define MARGIN_REMAP_THRESHOLD 4 ///< Minimum width to use margins with BlitterMode::ColourRemap.
|
#define MARGIN_REMAP_THRESHOLD 4 ///< Minimum width to use margins with BlitterMode::ColourRemap.
|
||||||
|
|
||||||
typedef union alignas(16) um128i {
|
typedef union alignas(16) um128i {
|
||||||
|
|
|
@ -29,9 +29,9 @@
|
||||||
/** The SSSE3 32 bpp blitter (without palette animation). */
|
/** The SSSE3 32 bpp blitter (without palette animation). */
|
||||||
class Blitter_32bppSSSE3 : public Blitter_32bppSSE2 {
|
class Blitter_32bppSSSE3 : public Blitter_32bppSSE2 {
|
||||||
public:
|
public:
|
||||||
void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom) override;
|
void Draw(Blitter::BlitterParams *bp, BlitterMode mode, SpriteCollKey sck) override;
|
||||||
template <BlitterMode mode, Blitter_32bppSSE_Base::ReadMode read_mode, Blitter_32bppSSE_Base::BlockType bt_last, bool translucent>
|
template <BlitterMode mode, Blitter_32bppSSE_Base::ReadMode read_mode, Blitter_32bppSSE_Base::BlockType bt_last, bool translucent>
|
||||||
void Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom);
|
void Draw(const Blitter::BlitterParams *bp, SpriteCollKey sck);
|
||||||
std::string_view GetName() override { return "32bpp-ssse3"; }
|
std::string_view GetName() override { return "32bpp-ssse3"; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -87,20 +87,20 @@ void Blitter_40bppAnim::DrawLine(void *video, int x, int y, int x2, int y2, int
|
||||||
*
|
*
|
||||||
* @tparam mode blitter mode
|
* @tparam mode blitter mode
|
||||||
* @param bp further blitting parameters
|
* @param bp further blitting parameters
|
||||||
* @param zoom zoom level at which we are drawing
|
* @param sck sprite collection key to draw
|
||||||
*/
|
*/
|
||||||
template <BlitterMode mode>
|
template <BlitterMode mode>
|
||||||
inline void Blitter_40bppAnim::Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom)
|
inline void Blitter_40bppAnim::Draw(const Blitter::BlitterParams *bp, SpriteCollKey sck)
|
||||||
{
|
{
|
||||||
const SpriteData *src = (const SpriteData *)bp->sprite;
|
const SpriteData *src = (const SpriteData *)bp->sprite;
|
||||||
|
|
||||||
/* src_px : each line begins with uint32_t n = 'number of bytes in this line',
|
/* src_px : each line begins with uint32_t n = 'number of bytes in this line',
|
||||||
* then n times is the Colour struct for this line */
|
* then n times is the Colour struct for this line */
|
||||||
const Colour *src_px = reinterpret_cast<const Colour *>(src->data + src->offset[0][zoom]);
|
const Colour *src_px = reinterpret_cast<const Colour *>(src->data + src->offset[0][sck]);
|
||||||
/* src_n : each line begins with uint32_t n = 'number of bytes in this line',
|
/* src_n : each line begins with uint32_t n = 'number of bytes in this line',
|
||||||
* then interleaved stream of 'm' and 'n' channels. 'm' is remap,
|
* then interleaved stream of 'm' and 'n' channels. 'm' is remap,
|
||||||
* 'n' is number of bytes with the same alpha channel class */
|
* 'n' is number of bytes with the same alpha channel class */
|
||||||
const uint16_t *src_n = reinterpret_cast<const uint16_t *>(src->data + src->offset[1][zoom]);
|
const uint16_t *src_n = reinterpret_cast<const uint16_t *>(src->data + src->offset[1][sck]);
|
||||||
|
|
||||||
/* skip upper lines in src_px and src_n */
|
/* skip upper lines in src_px and src_n */
|
||||||
for (uint i = bp->skip_top; i != 0; i--) {
|
for (uint i = bp->skip_top; i != 0; i--) {
|
||||||
|
@ -325,26 +325,26 @@ inline void Blitter_40bppAnim::Draw(const Blitter::BlitterParams *bp, ZoomLevel
|
||||||
*
|
*
|
||||||
* @param bp further blitting parameters
|
* @param bp further blitting parameters
|
||||||
* @param mode blitter mode
|
* @param mode blitter mode
|
||||||
* @param zoom zoom level at which we are drawing
|
* @param sck sprite collection key to draw
|
||||||
*/
|
*/
|
||||||
void Blitter_40bppAnim::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom)
|
void Blitter_40bppAnim::Draw(Blitter::BlitterParams *bp, BlitterMode mode, SpriteCollKey sck)
|
||||||
{
|
{
|
||||||
assert(_screen.dst_ptr != nullptr);
|
assert(_screen.dst_ptr != nullptr);
|
||||||
|
|
||||||
if (_screen_disable_anim || VideoDriver::GetInstance()->GetAnimBuffer() == nullptr) {
|
if (_screen_disable_anim || VideoDriver::GetInstance()->GetAnimBuffer() == nullptr) {
|
||||||
/* This means our output is not to the screen, so we can't be doing any animation stuff, so use our parent Draw() */
|
/* This means our output is not to the screen, so we can't be doing any animation stuff, so use our parent Draw() */
|
||||||
Blitter_32bppOptimized::Draw<true>(bp, mode, zoom);
|
Blitter_32bppOptimized::Draw<true>(bp, mode, sck);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (mode) {
|
switch (mode) {
|
||||||
default: NOT_REACHED();
|
default: NOT_REACHED();
|
||||||
case BlitterMode::Normal: Draw<BlitterMode::Normal>(bp, zoom); return;
|
case BlitterMode::Normal: Draw<BlitterMode::Normal>(bp, sck); return;
|
||||||
case BlitterMode::ColourRemap: Draw<BlitterMode::ColourRemap>(bp, zoom); return;
|
case BlitterMode::ColourRemap: Draw<BlitterMode::ColourRemap>(bp, sck); return;
|
||||||
case BlitterMode::Transparent: Draw<BlitterMode::Transparent>(bp, zoom); return;
|
case BlitterMode::Transparent: Draw<BlitterMode::Transparent>(bp, sck); return;
|
||||||
case BlitterMode::TransparentRemap: Draw<BlitterMode::TransparentRemap>(bp, zoom); return;
|
case BlitterMode::TransparentRemap: Draw<BlitterMode::TransparentRemap>(bp, sck); return;
|
||||||
case BlitterMode::CrashRemap: Draw<BlitterMode::CrashRemap>(bp, zoom); return;
|
case BlitterMode::CrashRemap: Draw<BlitterMode::CrashRemap>(bp, sck); return;
|
||||||
case BlitterMode::BlackRemap: Draw<BlitterMode::BlackRemap>(bp, zoom); return;
|
case BlitterMode::BlackRemap: Draw<BlitterMode::BlackRemap>(bp, sck); return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -400,9 +400,9 @@ void Blitter_40bppAnim::DrawColourMappingRect(void *dst, int width, int height,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Sprite *Blitter_40bppAnim::Encode(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator)
|
Sprite *Blitter_40bppAnim::Encode(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, bool has_rtl, SpriteAllocator &allocator)
|
||||||
{
|
{
|
||||||
return this->EncodeInternal<false>(sprite_type, sprite, allocator);
|
return this->EncodeInternal<false>(sprite_type, sprite, has_rtl, allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -25,16 +25,16 @@ public:
|
||||||
void CopyToBuffer(const void *video, void *dst, int width, int height) override;
|
void CopyToBuffer(const void *video, void *dst, int width, int height) override;
|
||||||
void CopyImageToBuffer(const void *video, void *dst, int width, int height, int dst_pitch) override;
|
void CopyImageToBuffer(const void *video, void *dst, int width, int height, int dst_pitch) override;
|
||||||
void ScrollBuffer(void *video, int &left, int &top, int &width, int &height, int scroll_x, int scroll_y) override;
|
void ScrollBuffer(void *video, int &left, int &top, int &width, int &height, int scroll_x, int scroll_y) override;
|
||||||
void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom) override;
|
void Draw(Blitter::BlitterParams *bp, BlitterMode mode, SpriteCollKey sck) override;
|
||||||
void DrawColourMappingRect(void *dst, int width, int height, PaletteID pal) override;
|
void DrawColourMappingRect(void *dst, int width, int height, PaletteID pal) override;
|
||||||
Sprite *Encode(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator) override;
|
Sprite *Encode(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, bool has_rtl, SpriteAllocator &allocator) override;
|
||||||
size_t BufferSize(uint width, uint height) override;
|
size_t BufferSize(uint width, uint height) override;
|
||||||
Blitter::PaletteAnimation UsePaletteAnimation() override;
|
Blitter::PaletteAnimation UsePaletteAnimation() override;
|
||||||
bool NeedsAnimationBuffer() override;
|
bool NeedsAnimationBuffer() override;
|
||||||
|
|
||||||
std::string_view GetName() override { return "40bpp-anim"; }
|
std::string_view GetName() override { return "40bpp-anim"; }
|
||||||
|
|
||||||
template <BlitterMode mode> void Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom);
|
template <BlitterMode mode> void Draw(const Blitter::BlitterParams *bp, SpriteCollKey sck);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
static inline Colour RealizeBlendedColour(uint8_t anim, Colour c)
|
static inline Colour RealizeBlendedColour(uint8_t anim, Colour c)
|
||||||
|
|
|
@ -18,11 +18,11 @@
|
||||||
/** Instantiation of the 8bpp optimised blitter factory. */
|
/** Instantiation of the 8bpp optimised blitter factory. */
|
||||||
static FBlitter_8bppOptimized iFBlitter_8bppOptimized;
|
static FBlitter_8bppOptimized iFBlitter_8bppOptimized;
|
||||||
|
|
||||||
void Blitter_8bppOptimized::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom)
|
void Blitter_8bppOptimized::Draw(Blitter::BlitterParams *bp, BlitterMode mode, SpriteCollKey sck)
|
||||||
{
|
{
|
||||||
/* Find the offset of this zoom-level */
|
/* Find the offset of this zoom-level */
|
||||||
const SpriteData *sprite_src = (const SpriteData *)bp->sprite;
|
const SpriteData *sprite_src = (const SpriteData *)bp->sprite;
|
||||||
uint offset = sprite_src->offset[zoom];
|
uint offset = sprite_src->offset[sck];
|
||||||
|
|
||||||
/* Find where to start reading in the source sprite */
|
/* Find where to start reading in the source sprite */
|
||||||
const uint8_t *src = sprite_src->data + offset;
|
const uint8_t *src = sprite_src->data + offset;
|
||||||
|
@ -119,7 +119,7 @@ void Blitter_8bppOptimized::Draw(Blitter::BlitterParams *bp, BlitterMode mode, Z
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Sprite *Blitter_8bppOptimized::Encode(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator)
|
Sprite *Blitter_8bppOptimized::Encode(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, bool has_rtl, SpriteAllocator &allocator)
|
||||||
{
|
{
|
||||||
/* Make memory for all zoom-levels */
|
/* Make memory for all zoom-levels */
|
||||||
uint memory = sizeof(SpriteData);
|
uint memory = sizeof(SpriteData);
|
||||||
|
@ -136,8 +136,8 @@ Sprite *Blitter_8bppOptimized::Encode(SpriteType sprite_type, const SpriteLoader
|
||||||
if (zoom_max == zoom_min) zoom_max = ZoomLevel::Max;
|
if (zoom_max == zoom_min) zoom_max = ZoomLevel::Max;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (ZoomLevel i = zoom_min; i <= zoom_max; i++) {
|
for (auto sck : SpriteCollKeyRange(zoom_min, zoom_max, has_rtl)) {
|
||||||
memory += sprite[i].width * sprite[i].height;
|
memory += sprite[sck].width * sprite[sck].height;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We have no idea how much memory we really need, so just guess something */
|
/* We have no idea how much memory we really need, so just guess something */
|
||||||
|
@ -151,11 +151,16 @@ Sprite *Blitter_8bppOptimized::Encode(SpriteType sprite_type, const SpriteLoader
|
||||||
uint8_t *dst = temp_dst->data;
|
uint8_t *dst = temp_dst->data;
|
||||||
|
|
||||||
/* Make the sprites per zoom-level */
|
/* Make the sprites per zoom-level */
|
||||||
for (ZoomLevel i = zoom_min; i <= zoom_max; i++) {
|
for (auto sck : SpriteCollKeyRange(zoom_min, zoom_max, has_rtl)) {
|
||||||
const SpriteLoader::Sprite &src_orig = sprite[i];
|
const SpriteLoader::Sprite &src_orig = sprite[sck];
|
||||||
/* 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[sck] = offset;
|
||||||
|
if (!has_rtl) {
|
||||||
|
/* Duplicate the sprite for RTL */
|
||||||
|
SpriteCollKey rtl{sck.zoom, true};
|
||||||
|
temp_dst->offset[rtl] = offset;
|
||||||
|
}
|
||||||
|
|
||||||
/* cache values, because compiler can't cache it */
|
/* cache values, because compiler can't cache it */
|
||||||
int scaled_height = src_orig.height;
|
int scaled_height = src_orig.height;
|
||||||
|
@ -220,11 +225,12 @@ 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);
|
||||||
|
|
||||||
const auto &root_sprite = sprite.Root();
|
const auto &root_sprite = sprite.Root(false);
|
||||||
dest_sprite->height = root_sprite.height;
|
dest_sprite->height = root_sprite.height;
|
||||||
dest_sprite->width = root_sprite.width;
|
dest_sprite->width = root_sprite.width;
|
||||||
dest_sprite->x_offs = root_sprite.x_offs;
|
dest_sprite->x_offs = root_sprite.x_offs;
|
||||||
dest_sprite->y_offs = root_sprite.y_offs;
|
dest_sprite->y_offs = root_sprite.y_offs;
|
||||||
|
dest_sprite->has_rtl = has_rtl;
|
||||||
std::copy_n(reinterpret_cast<std::byte *>(temp_dst), size, dest_sprite->data);
|
std::copy_n(reinterpret_cast<std::byte *>(temp_dst), size, dest_sprite->data);
|
||||||
|
|
||||||
return dest_sprite;
|
return dest_sprite;
|
||||||
|
|
|
@ -22,8 +22,8 @@ public:
|
||||||
uint8_t data[]; ///< Data, all zoomlevels.
|
uint8_t data[]; ///< Data, all zoomlevels.
|
||||||
};
|
};
|
||||||
|
|
||||||
void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom) override;
|
void Draw(Blitter::BlitterParams *bp, BlitterMode mode, SpriteCollKey sck) override;
|
||||||
Sprite *Encode(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator) override;
|
Sprite *Encode(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, bool has_rtl, SpriteAllocator &allocator) override;
|
||||||
|
|
||||||
std::string_view GetName() override { return "8bpp-optimized"; }
|
std::string_view GetName() override { return "8bpp-optimized"; }
|
||||||
};
|
};
|
||||||
|
|
|
@ -16,13 +16,13 @@
|
||||||
/** Instantiation of the simple 8bpp blitter factory. */
|
/** Instantiation of the simple 8bpp blitter factory. */
|
||||||
static FBlitter_8bppSimple iFBlitter_8bppSimple;
|
static FBlitter_8bppSimple iFBlitter_8bppSimple;
|
||||||
|
|
||||||
void Blitter_8bppSimple::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom)
|
void Blitter_8bppSimple::Draw(Blitter::BlitterParams *bp, BlitterMode mode, SpriteCollKey sck)
|
||||||
{
|
{
|
||||||
const uint8_t *src, *src_line;
|
const uint8_t *src, *src_line;
|
||||||
uint8_t *dst, *dst_line;
|
uint8_t *dst, *dst_line;
|
||||||
|
|
||||||
/* Find where to start reading in the source sprite */
|
/* Find where to start reading in the source sprite */
|
||||||
src_line = (const uint8_t *)bp->sprite + (bp->skip_top * bp->sprite_width + bp->skip_left) * ScaleByZoom(1, zoom);
|
src_line = (const uint8_t *)bp->sprite + (bp->skip_top * bp->sprite_width + bp->skip_left) * ScaleByZoom(1, sck.zoom);
|
||||||
dst_line = (uint8_t *)bp->dst + bp->top * bp->pitch + bp->left;
|
dst_line = (uint8_t *)bp->dst + bp->top * bp->pitch + bp->left;
|
||||||
|
|
||||||
for (int y = 0; y < bp->height; y++) {
|
for (int y = 0; y < bp->height; y++) {
|
||||||
|
@ -30,7 +30,7 @@ void Blitter_8bppSimple::Draw(Blitter::BlitterParams *bp, BlitterMode mode, Zoom
|
||||||
dst_line += bp->pitch;
|
dst_line += bp->pitch;
|
||||||
|
|
||||||
src = src_line;
|
src = src_line;
|
||||||
src_line += bp->sprite_width * ScaleByZoom(1, zoom);
|
src_line += bp->sprite_width * ScaleByZoom(1, sck.zoom);
|
||||||
|
|
||||||
for (int x = 0; x < bp->width; x++) {
|
for (int x = 0; x < bp->width; x++) {
|
||||||
uint colour = 0;
|
uint colour = 0;
|
||||||
|
@ -56,14 +56,14 @@ void Blitter_8bppSimple::Draw(Blitter::BlitterParams *bp, BlitterMode mode, Zoom
|
||||||
}
|
}
|
||||||
if (colour != 0) *dst = colour;
|
if (colour != 0) *dst = colour;
|
||||||
dst++;
|
dst++;
|
||||||
src += ScaleByZoom(1, zoom);
|
src += ScaleByZoom(1, sck.zoom);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Sprite *Blitter_8bppSimple::Encode(SpriteType, const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator)
|
Sprite *Blitter_8bppSimple::Encode(SpriteType, const SpriteLoader::SpriteCollection &sprite, bool, SpriteAllocator &allocator)
|
||||||
{
|
{
|
||||||
const auto &root_sprite = sprite.Root();
|
const auto &root_sprite = sprite.Root(false);
|
||||||
Sprite *dest_sprite;
|
Sprite *dest_sprite;
|
||||||
dest_sprite = allocator.Allocate<Sprite>(sizeof(*dest_sprite) + static_cast<size_t>(root_sprite.height) * static_cast<size_t>(root_sprite.width));
|
dest_sprite = allocator.Allocate<Sprite>(sizeof(*dest_sprite) + static_cast<size_t>(root_sprite.height) * static_cast<size_t>(root_sprite.width));
|
||||||
|
|
||||||
|
@ -71,6 +71,7 @@ Sprite *Blitter_8bppSimple::Encode(SpriteType, const SpriteLoader::SpriteCollect
|
||||||
dest_sprite->width = root_sprite.width;
|
dest_sprite->width = root_sprite.width;
|
||||||
dest_sprite->x_offs = root_sprite.x_offs;
|
dest_sprite->x_offs = root_sprite.x_offs;
|
||||||
dest_sprite->y_offs = root_sprite.y_offs;
|
dest_sprite->y_offs = root_sprite.y_offs;
|
||||||
|
dest_sprite->has_rtl = false;
|
||||||
|
|
||||||
/* 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 */
|
||||||
uint8_t *dst = reinterpret_cast<uint8_t *>(dest_sprite->data);
|
uint8_t *dst = reinterpret_cast<uint8_t *>(dest_sprite->data);
|
||||||
|
|
|
@ -16,8 +16,8 @@
|
||||||
/** Most trivial 8bpp blitter. */
|
/** Most trivial 8bpp blitter. */
|
||||||
class Blitter_8bppSimple final : public Blitter_8bppBase {
|
class Blitter_8bppSimple final : public Blitter_8bppBase {
|
||||||
public:
|
public:
|
||||||
void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom) override;
|
void Draw(Blitter::BlitterParams *bp, BlitterMode mode, SpriteCollKey sck) override;
|
||||||
Sprite *Encode(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator) override;
|
Sprite *Encode(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, bool has_rtl, SpriteAllocator &allocator) override;
|
||||||
|
|
||||||
std::string_view GetName() override { return "8bpp-simple"; }
|
std::string_view GetName() override { return "8bpp-simple"; }
|
||||||
};
|
};
|
||||||
|
|
|
@ -67,7 +67,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* Draw an image to the screen, given an amount of params defined above.
|
* Draw an image to the screen, given an amount of params defined above.
|
||||||
*/
|
*/
|
||||||
virtual void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom) = 0;
|
virtual void Draw(Blitter::BlitterParams *bp, BlitterMode mode, SpriteCollKey sck) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Draw a colourtable to the screen. This is: the colour of the screen is read
|
* Draw a colourtable to the screen. This is: the colour of the screen is read
|
||||||
|
|
|
@ -15,16 +15,17 @@
|
||||||
/** Instantiation of the null blitter factory. */
|
/** Instantiation of the null blitter factory. */
|
||||||
static FBlitter_Null iFBlitter_Null;
|
static FBlitter_Null iFBlitter_Null;
|
||||||
|
|
||||||
Sprite *Blitter_Null::Encode(SpriteType, const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator)
|
Sprite *Blitter_Null::Encode(SpriteType, const SpriteLoader::SpriteCollection &sprite, bool, SpriteAllocator &allocator)
|
||||||
{
|
{
|
||||||
Sprite *dest_sprite;
|
Sprite *dest_sprite;
|
||||||
dest_sprite = allocator.Allocate<Sprite>(sizeof(*dest_sprite));
|
dest_sprite = allocator.Allocate<Sprite>(sizeof(*dest_sprite));
|
||||||
|
|
||||||
const auto &root_sprite = sprite.Root();
|
const auto &root_sprite = sprite.Root(false);
|
||||||
dest_sprite->height = root_sprite.height;
|
dest_sprite->height = root_sprite.height;
|
||||||
dest_sprite->width = root_sprite.width;
|
dest_sprite->width = root_sprite.width;
|
||||||
dest_sprite->x_offs = root_sprite.x_offs;
|
dest_sprite->x_offs = root_sprite.x_offs;
|
||||||
dest_sprite->y_offs = root_sprite.y_offs;
|
dest_sprite->y_offs = root_sprite.y_offs;
|
||||||
|
dest_sprite->has_rtl = false;
|
||||||
|
|
||||||
return dest_sprite;
|
return dest_sprite;
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,9 +16,9 @@
|
||||||
class Blitter_Null : public Blitter {
|
class Blitter_Null : public Blitter {
|
||||||
public:
|
public:
|
||||||
uint8_t GetScreenDepth() override { return 0; }
|
uint8_t GetScreenDepth() override { return 0; }
|
||||||
void Draw(Blitter::BlitterParams *, BlitterMode, ZoomLevel) override {};
|
void Draw(Blitter::BlitterParams *, BlitterMode, SpriteCollKey) override {};
|
||||||
void DrawColourMappingRect(void *, int, int, PaletteID) override {};
|
void DrawColourMappingRect(void *, int, int, PaletteID) override {};
|
||||||
Sprite *Encode(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator) override;
|
Sprite *Encode(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, bool has_rtl, SpriteAllocator &allocator) override;
|
||||||
void *MoveTo(void *, int, int) override { return nullptr; };
|
void *MoveTo(void *, int, int) override { return nullptr; };
|
||||||
void SetPixel(void *, int, int, uint8_t) override {};
|
void SetPixel(void *, int, int, uint8_t) override {};
|
||||||
void DrawRect(void *, int, int, uint8_t) override {};
|
void DrawRect(void *, int, int, uint8_t) override {};
|
||||||
|
|
|
@ -242,8 +242,8 @@ const Sprite *FreeTypeFontCache::InternalGetGlyph(GlyphID key, bool aa)
|
||||||
|
|
||||||
/* FreeType has rendered the glyph, now we allocate a sprite and copy the image into it */
|
/* FreeType has rendered the glyph, now we allocate a sprite and copy the image into it */
|
||||||
SpriteLoader::SpriteCollection spritecollection;
|
SpriteLoader::SpriteCollection spritecollection;
|
||||||
SpriteLoader::Sprite &sprite = spritecollection[ZoomLevel::Min];
|
SpriteLoader::Sprite &sprite = spritecollection.Root(false);
|
||||||
sprite.AllocateData(ZoomLevel::Min, static_cast<size_t>(width) * height);
|
sprite.AllocateData(SpriteCollKey::Root(false), static_cast<size_t>(width) * height);
|
||||||
sprite.colours = SpriteComponent::Palette;
|
sprite.colours = SpriteComponent::Palette;
|
||||||
if (aa) sprite.colours.Set(SpriteComponent::Alpha);
|
if (aa) sprite.colours.Set(SpriteComponent::Alpha);
|
||||||
sprite.width = width;
|
sprite.width = width;
|
||||||
|
@ -273,7 +273,7 @@ const Sprite *FreeTypeFontCache::InternalGetGlyph(GlyphID key, bool aa)
|
||||||
}
|
}
|
||||||
|
|
||||||
UniquePtrSpriteAllocator allocator;
|
UniquePtrSpriteAllocator allocator;
|
||||||
BlitterFactory::GetCurrentBlitter()->Encode(SpriteType::Font, spritecollection, allocator);
|
BlitterFactory::GetCurrentBlitter()->Encode(SpriteType::Font, spritecollection, false, allocator);
|
||||||
|
|
||||||
GlyphEntry new_glyph;
|
GlyphEntry new_glyph;
|
||||||
new_glyph.data = std::move(allocator.data);
|
new_glyph.data = std::move(allocator.data);
|
||||||
|
|
|
@ -1167,7 +1167,7 @@ static void GfxBlitter(const Sprite * const sprite, int x, int y, BlitterMode mo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BlitterFactory::GetCurrentBlitter()->Draw(&bp, mode, zoom);
|
BlitterFactory::GetCurrentBlitter()->Draw(&bp, mode, SpriteCollKey{zoom, _current_text_dir == TD_RTL});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -229,8 +229,8 @@ const Sprite *CoreTextFontCache::InternalGetGlyph(GlyphID key, bool use_aa)
|
||||||
if (width > MAX_GLYPH_DIM || height > MAX_GLYPH_DIM) UserError("Font glyph is too large");
|
if (width > MAX_GLYPH_DIM || height > MAX_GLYPH_DIM) UserError("Font glyph is too large");
|
||||||
|
|
||||||
SpriteLoader::SpriteCollection spritecollection;
|
SpriteLoader::SpriteCollection spritecollection;
|
||||||
SpriteLoader::Sprite &sprite = spritecollection[ZoomLevel::Min];
|
SpriteLoader::Sprite &sprite = spritecollection.Root(false);
|
||||||
sprite.AllocateData(ZoomLevel::Min, width * height);
|
sprite.AllocateData(SpriteCollKey::Root(false), width * height);
|
||||||
sprite.colours = SpriteComponent::Palette;
|
sprite.colours = SpriteComponent::Palette;
|
||||||
if (use_aa) sprite.colours.Set(SpriteComponent::Alpha);
|
if (use_aa) sprite.colours.Set(SpriteComponent::Alpha);
|
||||||
sprite.width = width;
|
sprite.width = width;
|
||||||
|
@ -278,7 +278,7 @@ const Sprite *CoreTextFontCache::InternalGetGlyph(GlyphID key, bool use_aa)
|
||||||
}
|
}
|
||||||
|
|
||||||
UniquePtrSpriteAllocator allocator;
|
UniquePtrSpriteAllocator allocator;
|
||||||
BlitterFactory::GetCurrentBlitter()->Encode(SpriteType::Font, spritecollection, allocator);
|
BlitterFactory::GetCurrentBlitter()->Encode(SpriteType::Font, spritecollection, false, allocator);
|
||||||
|
|
||||||
GlyphEntry new_glyph;
|
GlyphEntry new_glyph;
|
||||||
new_glyph.data = std::move(allocator.data);
|
new_glyph.data = std::move(allocator.data);
|
||||||
|
|
|
@ -224,8 +224,8 @@ void Win32FontCache::ClearFontCache()
|
||||||
|
|
||||||
/* GDI has rendered the glyph, now we allocate a sprite and copy the image into it. */
|
/* GDI has rendered the glyph, now we allocate a sprite and copy the image into it. */
|
||||||
SpriteLoader::SpriteCollection spritecollection;
|
SpriteLoader::SpriteCollection spritecollection;
|
||||||
SpriteLoader::Sprite &sprite = spritecollection[ZoomLevel::Min];
|
SpriteLoader::Sprite &sprite = spritecollection.Root(false);
|
||||||
sprite.AllocateData(ZoomLevel::Min, width * height);
|
sprite.AllocateData(SpriteCollKey::Root(false), width * height);
|
||||||
sprite.colours = SpriteComponent::Palette;
|
sprite.colours = SpriteComponent::Palette;
|
||||||
if (aa) sprite.colours.Set(SpriteComponent::Alpha);
|
if (aa) sprite.colours.Set(SpriteComponent::Alpha);
|
||||||
sprite.width = width;
|
sprite.width = width;
|
||||||
|
@ -264,7 +264,7 @@ void Win32FontCache::ClearFontCache()
|
||||||
}
|
}
|
||||||
|
|
||||||
UniquePtrSpriteAllocator allocator;
|
UniquePtrSpriteAllocator allocator;
|
||||||
BlitterFactory::GetCurrentBlitter()->Encode(SpriteType::Font, spritecollection, allocator);
|
BlitterFactory::GetCurrentBlitter()->Encode(SpriteType::Font, spritecollection, false, allocator);
|
||||||
|
|
||||||
GlyphEntry new_glyph;
|
GlyphEntry new_glyph;
|
||||||
new_glyph.data = std::move(allocator.data);
|
new_glyph.data = std::move(allocator.data);
|
||||||
|
|
|
@ -1414,6 +1414,7 @@ struct GameOptionsWindow : Window {
|
||||||
CheckForMissingGlyphs();
|
CheckForMissingGlyphs();
|
||||||
ClearAllCachedNames();
|
ClearAllCachedNames();
|
||||||
UpdateAllVirtCoords();
|
UpdateAllVirtCoords();
|
||||||
|
VideoDriver::GetInstance()->ClearSystemSprites(); // relevant if _current_text_dir changes
|
||||||
CheckBlitter();
|
CheckBlitter();
|
||||||
ReInitAllWindows(false);
|
ReInitAllWindows(false);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -204,9 +204,9 @@ SpriteID GetMaxSpriteID()
|
||||||
return static_cast<SpriteID>(_spritecache.size());
|
return static_cast<SpriteID>(_spritecache.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ResizeSpriteIn(SpriteLoader::SpriteCollection &sprite, ZoomLevel src, ZoomLevel tgt)
|
static bool ResizeSpriteIn(SpriteLoader::SpriteCollection &sprite, SpriteCollKey src, SpriteCollKey tgt)
|
||||||
{
|
{
|
||||||
uint8_t scaled_1 = AdjustByZoom(1, src - tgt);
|
uint8_t scaled_1 = AdjustByZoom(1, src.zoom - tgt.zoom);
|
||||||
const auto &src_sprite = sprite[src];
|
const auto &src_sprite = sprite[src];
|
||||||
auto &dest_sprite = sprite[tgt];
|
auto &dest_sprite = sprite[tgt];
|
||||||
|
|
||||||
|
@ -233,20 +233,20 @@ static bool ResizeSpriteIn(SpriteLoader::SpriteCollection &sprite, ZoomLevel src
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ResizeSpriteOut(SpriteLoader::SpriteCollection &sprite, ZoomLevel zoom)
|
static void ResizeSpriteOut(SpriteLoader::SpriteCollection &sprite, SpriteCollKey sck)
|
||||||
{
|
{
|
||||||
const auto &root_sprite = sprite.Root();
|
const auto &root_sprite = sprite.Root(sck.rtl);
|
||||||
const auto &src_sprite = sprite[zoom - 1];
|
const auto &src_sprite = sprite[SpriteCollKey{sck.zoom - 1, sck.rtl}];
|
||||||
auto &dest_sprite = sprite[zoom];
|
auto &dest_sprite = sprite[sck];
|
||||||
|
|
||||||
/* Algorithm based on 32bpp_Optimized::ResizeSprite() */
|
/* Algorithm based on 32bpp_Optimized::ResizeSprite() */
|
||||||
dest_sprite.width = UnScaleByZoom(root_sprite.width, zoom);
|
dest_sprite.width = UnScaleByZoom(root_sprite.width, sck.zoom);
|
||||||
dest_sprite.height = UnScaleByZoom(root_sprite.height, zoom);
|
dest_sprite.height = UnScaleByZoom(root_sprite.height, sck.zoom);
|
||||||
dest_sprite.x_offs = UnScaleByZoom(root_sprite.x_offs, zoom);
|
dest_sprite.x_offs = UnScaleByZoom(root_sprite.x_offs, sck.zoom);
|
||||||
dest_sprite.y_offs = UnScaleByZoom(root_sprite.y_offs, zoom);
|
dest_sprite.y_offs = UnScaleByZoom(root_sprite.y_offs, sck.zoom);
|
||||||
dest_sprite.colours = root_sprite.colours;
|
dest_sprite.colours = root_sprite.colours;
|
||||||
|
|
||||||
dest_sprite.AllocateData(zoom, static_cast<size_t>(dest_sprite.height) * dest_sprite.width);
|
dest_sprite.AllocateData(sck, static_cast<size_t>(dest_sprite.height) * dest_sprite.width);
|
||||||
|
|
||||||
SpriteLoader::CommonPixel *dst = dest_sprite.data;
|
SpriteLoader::CommonPixel *dst = dest_sprite.data;
|
||||||
const SpriteLoader::CommonPixel *src = src_sprite.data;
|
const SpriteLoader::CommonPixel *src = src_sprite.data;
|
||||||
|
@ -269,7 +269,7 @@ static void ResizeSpriteOut(SpriteLoader::SpriteCollection &sprite, ZoomLevel zo
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool PadSingleSprite(SpriteLoader::Sprite *sprite, ZoomLevel zoom, uint pad_left, uint pad_top, uint pad_right, uint pad_bottom)
|
static bool PadSingleSprite(SpriteLoader::Sprite *sprite, SpriteCollKey sck, uint pad_left, uint pad_top, uint pad_right, uint pad_bottom)
|
||||||
{
|
{
|
||||||
uint width = sprite->width + pad_left + pad_right;
|
uint width = sprite->width + pad_left + pad_right;
|
||||||
uint height = sprite->height + pad_top + pad_bottom;
|
uint height = sprite->height + pad_top + pad_bottom;
|
||||||
|
@ -279,7 +279,7 @@ static bool PadSingleSprite(SpriteLoader::Sprite *sprite, ZoomLevel zoom, uint p
|
||||||
/* Copy source data and reallocate sprite memory. */
|
/* Copy source data and reallocate sprite memory. */
|
||||||
size_t sprite_size = static_cast<size_t>(sprite->width) * sprite->height;
|
size_t sprite_size = static_cast<size_t>(sprite->width) * sprite->height;
|
||||||
std::vector<SpriteLoader::CommonPixel> src_data(sprite->data, sprite->data + sprite_size);
|
std::vector<SpriteLoader::CommonPixel> src_data(sprite->data, sprite->data + sprite_size);
|
||||||
sprite->AllocateData(zoom, static_cast<size_t>(width) * height);
|
sprite->AllocateData(sck, static_cast<size_t>(width) * height);
|
||||||
|
|
||||||
/* Copy with padding to destination. */
|
/* Copy with padding to destination. */
|
||||||
SpriteLoader::CommonPixel *src = src_data.data();
|
SpriteLoader::CommonPixel *src = src_data.data();
|
||||||
|
@ -318,25 +318,25 @@ static bool PadSingleSprite(SpriteLoader::Sprite *sprite, ZoomLevel zoom, uint p
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool PadSprites(SpriteLoader::SpriteCollection &sprite, ZoomLevels sprite_avail, SpriteEncoder *encoder)
|
static bool PadSprites(SpriteLoader::SpriteCollection &sprite, SpriteCollKeys sprite_avail, SpriteEncoder *encoder)
|
||||||
{
|
{
|
||||||
/* Get minimum top left corner coordinates. */
|
/* Get minimum top left corner coordinates. */
|
||||||
int min_xoffs = INT32_MAX;
|
int min_xoffs = INT32_MAX;
|
||||||
int min_yoffs = INT32_MAX;
|
int min_yoffs = INT32_MAX;
|
||||||
for (ZoomLevel zoom = ZoomLevel::Begin; zoom != ZoomLevel::End; zoom++) {
|
for (auto sck : SpriteCollKeyRange(ZoomLevel::Min, ZoomLevel::Max, true)) {
|
||||||
if (sprite_avail.Test(zoom)) {
|
if (sprite_avail.Test(sck)) {
|
||||||
min_xoffs = std::min(min_xoffs, ScaleByZoom(sprite[zoom].x_offs, zoom));
|
min_xoffs = std::min(min_xoffs, ScaleByZoom(sprite[sck].x_offs, sck.zoom));
|
||||||
min_yoffs = std::min(min_yoffs, ScaleByZoom(sprite[zoom].y_offs, zoom));
|
min_yoffs = std::min(min_yoffs, ScaleByZoom(sprite[sck].y_offs, sck.zoom));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get maximum dimensions taking necessary padding at the top left into account. */
|
/* Get maximum dimensions taking necessary padding at the top left into account. */
|
||||||
int max_width = INT32_MIN;
|
int max_width = INT32_MIN;
|
||||||
int max_height = INT32_MIN;
|
int max_height = INT32_MIN;
|
||||||
for (ZoomLevel zoom = ZoomLevel::Begin; zoom != ZoomLevel::End; zoom++) {
|
for (auto sck : SpriteCollKeyRange(ZoomLevel::Min, ZoomLevel::Max, true)) {
|
||||||
if (sprite_avail.Test(zoom)) {
|
if (sprite_avail.Test(sck)) {
|
||||||
max_width = std::max(max_width, ScaleByZoom(sprite[zoom].width + sprite[zoom].x_offs - UnScaleByZoom(min_xoffs, zoom), zoom));
|
max_width = std::max(max_width, ScaleByZoom(sprite[sck].width + sprite[sck].x_offs - UnScaleByZoom(min_xoffs, sck.zoom), sck.zoom));
|
||||||
max_height = std::max(max_height, ScaleByZoom(sprite[zoom].height + sprite[zoom].y_offs - UnScaleByZoom(min_yoffs, zoom), zoom));
|
max_height = std::max(max_height, ScaleByZoom(sprite[sck].height + sprite[sck].y_offs - UnScaleByZoom(min_yoffs, sck.zoom), sck.zoom));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -348,18 +348,18 @@ static bool PadSprites(SpriteLoader::SpriteCollection &sprite, ZoomLevels sprite
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Pad sprites where needed. */
|
/* Pad sprites where needed. */
|
||||||
for (ZoomLevel zoom = ZoomLevel::Begin; zoom != ZoomLevel::End; zoom++) {
|
for (auto sck : SpriteCollKeyRange(ZoomLevel::Min, ZoomLevel::Max, true)) {
|
||||||
if (sprite_avail.Test(zoom)) {
|
if (sprite_avail.Test(sck)) {
|
||||||
auto &cur_sprite = sprite[zoom];
|
auto &cur_sprite = sprite[sck];
|
||||||
/* 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, cur_sprite.x_offs - UnScaleByZoom(min_xoffs, zoom));
|
int pad_left = std::max(0, cur_sprite.x_offs - UnScaleByZoom(min_xoffs, sck.zoom));
|
||||||
int pad_top = std::max(0, cur_sprite.y_offs - UnScaleByZoom(min_yoffs, zoom));
|
int pad_top = std::max(0, cur_sprite.y_offs - UnScaleByZoom(min_yoffs, sck.zoom));
|
||||||
int pad_right = std::max(0, UnScaleByZoom(max_width, zoom) - cur_sprite.width - pad_left);
|
int pad_right = std::max(0, UnScaleByZoom(max_width, sck.zoom) - cur_sprite.width - pad_left);
|
||||||
int pad_bottom = std::max(0, UnScaleByZoom(max_height, zoom) - cur_sprite.height - pad_top);
|
int pad_bottom = std::max(0, UnScaleByZoom(max_height, sck.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(&cur_sprite, zoom, pad_left, pad_top, pad_right, pad_bottom)) return false;
|
if (!PadSingleSprite(&cur_sprite, sck, pad_left, pad_top, pad_right, pad_bottom)) return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -367,45 +367,56 @@ static bool PadSprites(SpriteLoader::SpriteCollection &sprite, ZoomLevels sprite
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool ResizeSprites(SpriteLoader::SpriteCollection &sprite, ZoomLevels sprite_avail, SpriteEncoder *encoder)
|
static bool ResizeSprites(SpriteLoader::SpriteCollection &sprite, SpriteCollKeys sprite_avail, SpriteEncoder *encoder)
|
||||||
{
|
{
|
||||||
|
assert(sprite_avail.AnyLtr());
|
||||||
|
bool has_rtl = sprite_avail.AnyRtl();
|
||||||
|
|
||||||
/* Create a fully zoomed image if it does not exist */
|
/* Create a fully zoomed image if it does not exist */
|
||||||
ZoomLevel first_avail;
|
ZoomLevel first_avail[2];
|
||||||
for (ZoomLevel zoom = ZoomLevel::Min; zoom <= ZoomLevel::Max; ++zoom) {
|
for (bool rtl : {false, true}) {
|
||||||
if (!sprite_avail.Test(zoom)) continue;
|
if (rtl && !has_rtl) continue;
|
||||||
first_avail = zoom;
|
for (ZoomLevel zoom = ZoomLevel::Min; zoom <= ZoomLevel::Max; ++zoom) {
|
||||||
if (zoom != ZoomLevel::Min) {
|
SpriteCollKey src_sck{zoom, rtl};
|
||||||
if (!ResizeSpriteIn(sprite, zoom, ZoomLevel::Min)) return false;
|
if (!sprite_avail.Test(src_sck)) continue;
|
||||||
sprite_avail.Set(ZoomLevel::Min);
|
first_avail[rtl ? 1 : 0] = zoom;
|
||||||
|
if (zoom != ZoomLevel::Min) {
|
||||||
|
auto root_sck = SpriteCollKey::Root(rtl);
|
||||||
|
if (!ResizeSpriteIn(sprite, src_sck, root_sck)) return false;
|
||||||
|
sprite_avail.Set(root_sck);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Pad sprites to make sizes match. */
|
/* Pad sprites to make sizes match. */
|
||||||
if (!PadSprites(sprite, sprite_avail, encoder)) return false;
|
if (!PadSprites(sprite, sprite_avail, encoder)) return false;
|
||||||
|
|
||||||
/* Create other missing zoom levels */
|
/* Create other missing zoom levels */
|
||||||
for (ZoomLevel zoom = ZoomLevel::Begin; zoom != ZoomLevel::End; zoom++) {
|
for (auto sck : SpriteCollKeyRange(ZoomLevel::Min + 1, ZoomLevel::Max, has_rtl)) {
|
||||||
if (zoom == ZoomLevel::Min) continue;
|
if (sprite_avail.Test(sck)) {
|
||||||
|
|
||||||
if (sprite_avail.Test(zoom)) {
|
|
||||||
/* Check that size and offsets match the fully zoomed image. */
|
/* Check that size and offsets match the fully zoomed image. */
|
||||||
[[maybe_unused]] const auto &root_sprite = sprite[ZoomLevel::Min];
|
[[maybe_unused]] const auto &root_sprite = sprite.Root(sck.rtl);
|
||||||
[[maybe_unused]] const auto &dest_sprite = sprite[zoom];
|
[[maybe_unused]] const auto &dest_sprite = sprite[sck];
|
||||||
assert(dest_sprite.width == UnScaleByZoom(root_sprite.width, zoom));
|
assert(dest_sprite.width == UnScaleByZoom(root_sprite.width, sck.zoom));
|
||||||
assert(dest_sprite.height == UnScaleByZoom(root_sprite.height, zoom));
|
assert(dest_sprite.height == UnScaleByZoom(root_sprite.height, sck.zoom));
|
||||||
assert(dest_sprite.x_offs == UnScaleByZoom(root_sprite.x_offs, zoom));
|
assert(dest_sprite.x_offs == UnScaleByZoom(root_sprite.x_offs, sck.zoom));
|
||||||
assert(dest_sprite.y_offs == UnScaleByZoom(root_sprite.y_offs, zoom));
|
assert(dest_sprite.y_offs == UnScaleByZoom(root_sprite.y_offs, sck.zoom));
|
||||||
} else {
|
} else {
|
||||||
/* Zoom level is not available, or unusable, so create it */
|
/* Zoom level is not available, or unusable, so create it */
|
||||||
ResizeSpriteOut(sprite, zoom);
|
ResizeSpriteOut(sprite, sck);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Replace sprites with higher resolution than the desired maximum source resolution with scaled up sprites, if not already done. */
|
/* Replace sprites with higher resolution than the desired maximum source resolution with scaled up sprites, if not already done. */
|
||||||
if (first_avail < _settings_client.gui.sprite_zoom_min) {
|
for (bool rtl : {false, true}) {
|
||||||
for (ZoomLevel zoom = std::min(ZoomLevel::Normal, _settings_client.gui.sprite_zoom_min); zoom > ZoomLevel::Min; --zoom) {
|
if (rtl && !has_rtl) continue;
|
||||||
ResizeSpriteIn(sprite, zoom, zoom - 1);
|
if (first_avail[rtl ? 1 : 0] < _settings_client.gui.sprite_zoom_min) {
|
||||||
|
for (ZoomLevel zoom = std::min(ZoomLevel::Normal, _settings_client.gui.sprite_zoom_min); zoom > ZoomLevel::Min; --zoom) {
|
||||||
|
const SpriteCollKey src_sck{zoom, rtl};
|
||||||
|
const SpriteCollKey dest_sck{zoom - 1, rtl};
|
||||||
|
ResizeSpriteIn(sprite, src_sck, dest_sck);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -473,25 +484,25 @@ static void *ReadSprite(const SpriteCache *sc, SpriteID id, SpriteType sprite_ty
|
||||||
Debug(sprite, 9, "Load sprite {}", id);
|
Debug(sprite, 9, "Load sprite {}", id);
|
||||||
|
|
||||||
SpriteLoader::SpriteCollection sprite;
|
SpriteLoader::SpriteCollection sprite;
|
||||||
ZoomLevels sprite_avail;
|
SpriteCollKeys sprite_avail;
|
||||||
ZoomLevels avail_8bpp;
|
SpriteCollKeys avail_8bpp;
|
||||||
ZoomLevels avail_32bpp;
|
SpriteCollKeys avail_32bpp;
|
||||||
|
|
||||||
SpriteLoaderGrf sprite_loader(file.GetContainerVersion());
|
SpriteLoaderGrf sprite_loader(file.GetContainerVersion());
|
||||||
if (sprite_type != SpriteType::MapGen && encoder->Is32BppSupported()) {
|
if (sprite_type != SpriteType::MapGen && encoder->Is32BppSupported()) {
|
||||||
/* Try for 32bpp sprites first. */
|
/* Try for 32bpp sprites first. */
|
||||||
sprite_avail = sprite_loader.LoadSprite(sprite, file, file_pos, sprite_type, true, sc->control_flags, avail_8bpp, avail_32bpp);
|
sprite_avail = sprite_loader.LoadSprite(sprite, file, file_pos, sprite_type, true, sc->control_flags, avail_8bpp, avail_32bpp);
|
||||||
}
|
}
|
||||||
if (sprite_avail.None()) {
|
if (sprite_avail.NoLtr()) {
|
||||||
sprite_avail = sprite_loader.LoadSprite(sprite, file, file_pos, sprite_type, false, sc->control_flags, avail_8bpp, avail_32bpp);
|
sprite_avail = sprite_loader.LoadSprite(sprite, file, file_pos, sprite_type, false, sc->control_flags, avail_8bpp, avail_32bpp);
|
||||||
if (sprite_type == SpriteType::Normal && avail_32bpp.Any() && !encoder->Is32BppSupported() && sprite_avail.None()) {
|
if (sprite_type == SpriteType::Normal && avail_32bpp.AnyLtr() && !encoder->Is32BppSupported() && sprite_avail.NoLtr()) {
|
||||||
/* No 8bpp available, try converting from 32bpp. */
|
/* No 8bpp available, try converting from 32bpp. */
|
||||||
SpriteLoaderMakeIndexed make_indexed(sprite_loader);
|
SpriteLoaderMakeIndexed make_indexed(sprite_loader);
|
||||||
sprite_avail = make_indexed.LoadSprite(sprite, file, file_pos, sprite_type, true, sc->control_flags, sprite_avail, avail_32bpp);
|
sprite_avail = make_indexed.LoadSprite(sprite, file, file_pos, sprite_type, true, sc->control_flags, sprite_avail, avail_32bpp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sprite_avail.None()) {
|
if (sprite_avail.NoLtr()) {
|
||||||
if (sprite_type == SpriteType::MapGen) return nullptr;
|
if (sprite_type == SpriteType::MapGen) return nullptr;
|
||||||
if (id == SPR_IMG_QUERY) UserError("Okay... something went horribly wrong. I couldn't load the fallback sprite. What should I do?");
|
if (id == SPR_IMG_QUERY) UserError("Okay... something went horribly wrong. I couldn't load the fallback sprite. What should I do?");
|
||||||
return (void*)GetRawSprite(SPR_IMG_QUERY, SpriteType::Normal, &allocator, encoder);
|
return (void*)GetRawSprite(SPR_IMG_QUERY, SpriteType::Normal, &allocator, encoder);
|
||||||
|
@ -507,7 +518,7 @@ 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). */
|
||||||
const auto &root_sprite = sprite.Root();
|
const auto &root_sprite = sprite.Root(false);
|
||||||
uint num = root_sprite.width * root_sprite.height;
|
uint num = root_sprite.width * root_sprite.height;
|
||||||
|
|
||||||
Sprite *s = allocator.Allocate<Sprite>(sizeof(*s) + num);
|
Sprite *s = allocator.Allocate<Sprite>(sizeof(*s) + num);
|
||||||
|
@ -533,10 +544,12 @@ static void *ReadSprite(const SpriteCache *sc, SpriteID id, SpriteType sprite_ty
|
||||||
|
|
||||||
if (sprite_type == SpriteType::Font && _font_zoom != ZoomLevel::Min) {
|
if (sprite_type == SpriteType::Font && _font_zoom != ZoomLevel::Min) {
|
||||||
/* Make ZoomLevel::Min be ZOOM_LVL_GUI */
|
/* Make ZoomLevel::Min be ZOOM_LVL_GUI */
|
||||||
sprite[ZoomLevel::Min] = sprite[_font_zoom];
|
SpriteCollKey min_sck{ZoomLevel::Min, false};
|
||||||
|
SpriteCollKey font_sck{_font_zoom, false};
|
||||||
|
sprite[min_sck] = sprite[font_sck];
|
||||||
}
|
}
|
||||||
|
|
||||||
return encoder->Encode(sprite_type, sprite, allocator);
|
return encoder->Encode(sprite_type, sprite, sprite_avail.AnyRtl(), allocator);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct GrfSpriteOffset {
|
struct GrfSpriteOffset {
|
||||||
|
|
|
@ -19,6 +19,7 @@ struct Sprite {
|
||||||
uint16_t width; ///< Width of the sprite.
|
uint16_t width; ///< Width of the sprite.
|
||||||
int16_t x_offs; ///< Number of pixels to shift the sprite to the right.
|
int16_t x_offs; ///< Number of pixels to shift the sprite to the right.
|
||||||
int16_t y_offs; ///< Number of pixels to shift the sprite downwards.
|
int16_t y_offs; ///< Number of pixels to shift the sprite downwards.
|
||||||
|
bool has_rtl; ///< Whether the sprite is textdir aware.
|
||||||
std::byte data[]; ///< Sprite data.
|
std::byte data[]; ///< Sprite data.
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -52,12 +52,12 @@ static bool WarnCorruptSprite(const SpriteFile &file, size_t file_pos, int line)
|
||||||
* @param sprite_type Type of the sprite we're decoding.
|
* @param sprite_type Type of the sprite we're decoding.
|
||||||
* @param num Size of the decompressed sprite.
|
* @param num Size of the decompressed sprite.
|
||||||
* @param type Type of the encoded sprite.
|
* @param type Type of the encoded sprite.
|
||||||
* @param zoom_lvl Requested zoom level.
|
* @param sck Key for allocator.
|
||||||
* @param colour_fmt Colour format of the sprite.
|
* @param colour_fmt Colour format of the sprite.
|
||||||
* @param container_format Container format of the GRF this sprite is in.
|
* @param container_format Container format of the GRF this sprite is in.
|
||||||
* @return True if the sprite was successfully loaded.
|
* @return True if the sprite was successfully loaded.
|
||||||
*/
|
*/
|
||||||
bool DecodeSingleSprite(SpriteLoader::Sprite *sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, int64_t num, uint8_t type, ZoomLevel zoom_lvl, SpriteComponents colour_fmt, uint8_t container_format)
|
bool DecodeSingleSprite(SpriteLoader::Sprite *sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, int64_t num, uint8_t type, SpriteCollKey sck, SpriteComponents colour_fmt, uint8_t container_format)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Original sprite height was max 255 pixels, with 4x extra zoom => 1020 pixels.
|
* Original sprite height was max 255 pixels, with 4x extra zoom => 1020 pixels.
|
||||||
|
@ -101,7 +101,7 @@ bool DecodeSingleSprite(SpriteLoader::Sprite *sprite, SpriteFile &file, size_t f
|
||||||
|
|
||||||
if (num != 0) return WarnCorruptSprite(file, file_pos, __LINE__);
|
if (num != 0) return WarnCorruptSprite(file, file_pos, __LINE__);
|
||||||
|
|
||||||
sprite->AllocateData(zoom_lvl, static_cast<size_t>(sprite->width) * sprite->height);
|
sprite->AllocateData(sck, static_cast<size_t>(sprite->width) * sprite->height);
|
||||||
|
|
||||||
/* Convert colour depth to pixel size. */
|
/* Convert colour depth to pixel size. */
|
||||||
int bpp = 0;
|
int bpp = 0;
|
||||||
|
@ -215,7 +215,7 @@ bool DecodeSingleSprite(SpriteLoader::Sprite *sprite, SpriteFile &file, size_t f
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ZoomLevels LoadSpriteV1(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool load_32bpp, ZoomLevels &avail_8bpp)
|
static SpriteCollKeys LoadSpriteV1(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool load_32bpp, SpriteCollKeys &avail_8bpp)
|
||||||
{
|
{
|
||||||
/* Check the requested colour depth. */
|
/* Check the requested colour depth. */
|
||||||
if (load_32bpp) return {};
|
if (load_32bpp) return {};
|
||||||
|
@ -230,8 +230,8 @@ static ZoomLevels LoadSpriteV1(SpriteLoader::SpriteCollection &sprite, SpriteFil
|
||||||
/* Type 0xFF indicates either a colourmap or some other non-sprite info; we do not handle them here */
|
/* Type 0xFF indicates either a colourmap or some other non-sprite info; we do not handle them here */
|
||||||
if (type == 0xFF) return {};
|
if (type == 0xFF) return {};
|
||||||
|
|
||||||
ZoomLevel zoom_lvl = (sprite_type != SpriteType::MapGen) ? ZoomLevel::Normal : ZoomLevel::Min;
|
const SpriteCollKey sck{(sprite_type != SpriteType::MapGen) ? ZoomLevel::Normal : ZoomLevel::Min, false};
|
||||||
auto &dest_sprite = sprite[zoom_lvl];
|
auto &dest_sprite = sprite[sck];
|
||||||
|
|
||||||
dest_sprite.height = file.ReadByte();
|
dest_sprite.height = file.ReadByte();
|
||||||
dest_sprite.width = file.ReadWord();
|
dest_sprite.width = file.ReadWord();
|
||||||
|
@ -248,15 +248,15 @@ static ZoomLevels LoadSpriteV1(SpriteLoader::SpriteCollection &sprite, SpriteFil
|
||||||
* 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) ? dest_sprite.width * dest_sprite.height : num - 8;
|
num = (type & 0x02) ? dest_sprite.width * dest_sprite.height : num - 8;
|
||||||
|
|
||||||
if (DecodeSingleSprite(&dest_sprite, file, file_pos, sprite_type, num, type, zoom_lvl, SpriteComponent::Palette, 1)) {
|
if (DecodeSingleSprite(&dest_sprite, file, file_pos, sprite_type, num, type, sck, SpriteComponent::Palette, 1)) {
|
||||||
avail_8bpp.Set(zoom_lvl);
|
avail_8bpp.Set(sck);
|
||||||
return avail_8bpp;
|
return avail_8bpp;
|
||||||
}
|
}
|
||||||
|
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
static ZoomLevels LoadSpriteV2(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool load_32bpp, uint8_t control_flags, ZoomLevels &avail_8bpp, ZoomLevels &avail_32bpp)
|
static SpriteCollKeys LoadSpriteV2(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool load_32bpp, uint8_t control_flags, SpriteCollKeys &avail_8bpp, SpriteCollKeys &avail_32bpp)
|
||||||
{
|
{
|
||||||
static const ZoomLevel zoom_lvl_map[6] = {ZoomLevel::Normal, ZoomLevel::In4x, ZoomLevel::In2x, ZoomLevel::Out2x, ZoomLevel::Out4x, ZoomLevel::Out8x};
|
static const ZoomLevel zoom_lvl_map[6] = {ZoomLevel::Normal, ZoomLevel::In4x, ZoomLevel::In2x, ZoomLevel::Out2x, ZoomLevel::Out4x, ZoomLevel::Out8x};
|
||||||
|
|
||||||
|
@ -268,7 +268,7 @@ static ZoomLevels LoadSpriteV2(SpriteLoader::SpriteCollection &sprite, SpriteFil
|
||||||
|
|
||||||
uint32_t id = file.ReadDword();
|
uint32_t id = file.ReadDword();
|
||||||
|
|
||||||
ZoomLevels loaded_sprites;
|
SpriteCollKeys loaded_sprites;
|
||||||
do {
|
do {
|
||||||
int64_t num = file.ReadDword();
|
int64_t num = file.ReadDword();
|
||||||
size_t start_pos = file.GetPos();
|
size_t start_pos = file.GetPos();
|
||||||
|
@ -280,6 +280,7 @@ static ZoomLevels LoadSpriteV2(SpriteLoader::SpriteCollection &sprite, SpriteFil
|
||||||
SpriteComponents colour{type};
|
SpriteComponents colour{type};
|
||||||
/* Mask out colour component information from type. */
|
/* Mask out colour component information from type. */
|
||||||
type &= ~SpriteComponents::MASK;
|
type &= ~SpriteComponents::MASK;
|
||||||
|
bool rtl = type & 0x10;
|
||||||
|
|
||||||
uint8_t zoom = file.ReadByte();
|
uint8_t zoom = file.ReadByte();
|
||||||
|
|
||||||
|
@ -288,18 +289,18 @@ static ZoomLevels LoadSpriteV2(SpriteLoader::SpriteCollection &sprite, SpriteFil
|
||||||
|
|
||||||
if (sprite_type != SpriteType::MapGen) {
|
if (sprite_type != SpriteType::MapGen) {
|
||||||
if (zoom < lengthof(zoom_lvl_map)) {
|
if (zoom < lengthof(zoom_lvl_map)) {
|
||||||
ZoomLevel zoom_lvl = zoom_lvl_map[zoom];
|
const SpriteCollKey sck{zoom_lvl_map[zoom], rtl};
|
||||||
if (colour == SpriteComponent::Palette) avail_8bpp.Set(zoom_lvl);
|
if (colour == SpriteComponent::Palette) avail_8bpp.Set(sck);
|
||||||
if (colour != SpriteComponent::Palette) avail_32bpp.Set(zoom_lvl);
|
if (colour != SpriteComponent::Palette) avail_32bpp.Set(sck);
|
||||||
|
|
||||||
is_wanted_zoom_lvl = true;
|
is_wanted_zoom_lvl = true;
|
||||||
ZoomLevel zoom_min = sprite_type == SpriteType::Font ? ZoomLevel::Min : _settings_client.gui.sprite_zoom_min;
|
ZoomLevel zoom_min = sprite_type == SpriteType::Font ? ZoomLevel::Min : _settings_client.gui.sprite_zoom_min;
|
||||||
if (zoom_min >= ZoomLevel::In2x &&
|
if (zoom_min >= ZoomLevel::In2x &&
|
||||||
HasBit(control_flags, load_32bpp ? SCCF_ALLOW_ZOOM_MIN_2X_32BPP : SCCF_ALLOW_ZOOM_MIN_2X_PAL) && zoom_lvl < ZoomLevel::In2x) {
|
HasBit(control_flags, load_32bpp ? SCCF_ALLOW_ZOOM_MIN_2X_32BPP : SCCF_ALLOW_ZOOM_MIN_2X_PAL) && sck.zoom < ZoomLevel::In2x) {
|
||||||
is_wanted_zoom_lvl = false;
|
is_wanted_zoom_lvl = false;
|
||||||
}
|
}
|
||||||
if (zoom_min >= ZoomLevel::Normal &&
|
if (zoom_min >= ZoomLevel::Normal &&
|
||||||
HasBit(control_flags, load_32bpp ? SCCF_ALLOW_ZOOM_MIN_1X_32BPP : SCCF_ALLOW_ZOOM_MIN_1X_PAL) && zoom_lvl < ZoomLevel::Normal) {
|
HasBit(control_flags, load_32bpp ? SCCF_ALLOW_ZOOM_MIN_1X_32BPP : SCCF_ALLOW_ZOOM_MIN_1X_PAL) && sck.zoom < ZoomLevel::Normal) {
|
||||||
is_wanted_zoom_lvl = false;
|
is_wanted_zoom_lvl = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -309,17 +310,19 @@ static ZoomLevels LoadSpriteV2(SpriteLoader::SpriteCollection &sprite, SpriteFil
|
||||||
is_wanted_zoom_lvl = (zoom == 0);
|
is_wanted_zoom_lvl = (zoom == 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_wanted_colour_depth && is_wanted_zoom_lvl) {
|
bool is_wanted_textdir = !rtl || sprite_type == SpriteType::Normal;
|
||||||
ZoomLevel zoom_lvl = (sprite_type != SpriteType::MapGen) ? zoom_lvl_map[zoom] : ZoomLevel::Min;
|
|
||||||
|
|
||||||
if (loaded_sprites.Test(zoom_lvl)) {
|
if (is_wanted_colour_depth && is_wanted_zoom_lvl && is_wanted_textdir) {
|
||||||
|
const SpriteCollKey sck{sprite_type != SpriteType::MapGen ? zoom_lvl_map[zoom] : ZoomLevel::Min, rtl};
|
||||||
|
|
||||||
|
if (loaded_sprites.Test(sck)) {
|
||||||
/* We already have this zoom level, skip sprite. */
|
/* We already have this zoom level, skip sprite. */
|
||||||
Debug(sprite, 1, "Ignoring duplicate zoom level sprite {} from {}", id, file.GetSimplifiedFilename());
|
Debug(sprite, 1, "Ignoring duplicate zoom level sprite {} from {}", id, file.GetSimplifiedFilename());
|
||||||
file.SkipBytes(num - 2);
|
file.SkipBytes(num - 2);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto &dest_sprite = sprite[zoom_lvl];
|
auto &dest_sprite = sprite[sck];
|
||||||
dest_sprite.height = file.ReadWord();
|
dest_sprite.height = file.ReadWord();
|
||||||
dest_sprite.width = file.ReadWord();
|
dest_sprite.width = file.ReadWord();
|
||||||
dest_sprite.x_offs = file.ReadWord();
|
dest_sprite.x_offs = file.ReadWord();
|
||||||
|
@ -342,13 +345,13 @@ static ZoomLevels LoadSpriteV2(SpriteLoader::SpriteCollection &sprite, SpriteFil
|
||||||
* 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() : dest_sprite.width * dest_sprite.height * bpp;
|
uint decomp_size = (type & 0x08) ? file.ReadDword() : dest_sprite.width * dest_sprite.height * bpp;
|
||||||
|
|
||||||
bool valid = DecodeSingleSprite(&dest_sprite, 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, sck, 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 {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
if (valid) loaded_sprites.Set(zoom_lvl);
|
if (valid) loaded_sprites.Set(sck);
|
||||||
} else {
|
} else {
|
||||||
/* Not the wanted zoom level or colour depth, continue searching. */
|
/* Not the wanted zoom level or colour depth, continue searching. */
|
||||||
file.SkipBytes(num - 2);
|
file.SkipBytes(num - 2);
|
||||||
|
@ -359,7 +362,7 @@ static ZoomLevels LoadSpriteV2(SpriteLoader::SpriteCollection &sprite, SpriteFil
|
||||||
return loaded_sprites;
|
return loaded_sprites;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZoomLevels SpriteLoaderGrf::LoadSprite(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool load_32bpp, uint8_t control_flags, ZoomLevels &avail_8bpp, ZoomLevels &avail_32bpp)
|
SpriteCollKeys SpriteLoaderGrf::LoadSprite(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool load_32bpp, uint8_t control_flags, SpriteCollKeys &avail_8bpp, SpriteCollKeys &avail_32bpp)
|
||||||
{
|
{
|
||||||
if (this->container_ver >= 2) {
|
if (this->container_ver >= 2) {
|
||||||
return LoadSpriteV2(sprite, file, file_pos, sprite_type, load_32bpp, control_flags, avail_8bpp, avail_32bpp);
|
return LoadSpriteV2(sprite, file, file_pos, sprite_type, load_32bpp, control_flags, avail_8bpp, avail_32bpp);
|
||||||
|
|
|
@ -17,7 +17,7 @@ class SpriteLoaderGrf : public SpriteLoader {
|
||||||
uint8_t container_ver;
|
uint8_t container_ver;
|
||||||
public:
|
public:
|
||||||
SpriteLoaderGrf(uint8_t container_ver) : container_ver(container_ver) {}
|
SpriteLoaderGrf(uint8_t container_ver) : container_ver(container_ver) {}
|
||||||
ZoomLevels LoadSprite(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool load_32bpp, uint8_t control_flags, ZoomLevels &avail_8bpp, ZoomLevels &avail_32bpp) override;
|
SpriteCollKeys LoadSprite(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool load_32bpp, uint8_t control_flags, SpriteCollKeys &avail_8bpp, SpriteCollKeys &avail_32bpp) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* SPRITELOADER_GRF_HPP */
|
#endif /* SPRITELOADER_GRF_HPP */
|
||||||
|
|
|
@ -48,12 +48,12 @@ static void Convert32bppTo8bpp(SpriteLoader::Sprite &sprite)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ZoomLevels SpriteLoaderMakeIndexed::LoadSprite(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool, uint8_t control_flags, ZoomLevels &avail_8bpp, ZoomLevels &avail_32bpp)
|
SpriteCollKeys SpriteLoaderMakeIndexed::LoadSprite(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool, uint8_t control_flags, SpriteCollKeys &avail_8bpp, SpriteCollKeys &avail_32bpp)
|
||||||
{
|
{
|
||||||
ZoomLevels avail = this->baseloader.LoadSprite(sprite, file, file_pos, sprite_type, true, control_flags, avail_8bpp, avail_32bpp);
|
SpriteCollKeys avail = this->baseloader.LoadSprite(sprite, file, file_pos, sprite_type, true, control_flags, avail_8bpp, avail_32bpp);
|
||||||
|
|
||||||
for (ZoomLevel zoom = ZoomLevel::Begin; zoom != ZoomLevel::End; zoom++) {
|
for (auto sck : SpriteCollKeyRange(ZoomLevel::Min, ZoomLevel::Max, true)) {
|
||||||
if (avail.Test(zoom)) Convert32bppTo8bpp(sprite[zoom]);
|
if (avail.Test(sck)) Convert32bppTo8bpp(sprite[sck]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return avail;
|
return avail;
|
||||||
|
|
|
@ -17,7 +17,7 @@ class SpriteLoaderMakeIndexed : public SpriteLoader {
|
||||||
SpriteLoader &baseloader;
|
SpriteLoader &baseloader;
|
||||||
public:
|
public:
|
||||||
SpriteLoaderMakeIndexed(SpriteLoader &baseloader) : baseloader(baseloader) {}
|
SpriteLoaderMakeIndexed(SpriteLoader &baseloader) : baseloader(baseloader) {}
|
||||||
ZoomLevels LoadSprite(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool load_32bpp, uint8_t control_flags, ZoomLevels &avail_8bpp, ZoomLevels &avail_32bpp) override;
|
SpriteCollKeys LoadSprite(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool load_32bpp, uint8_t control_flags, SpriteCollKeys &avail_8bpp, SpriteCollKeys &avail_32bpp) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* SPRITELOADER_MAKEINDEXED_H */
|
#endif /* SPRITELOADER_MAKEINDEXED_H */
|
||||||
|
|
|
@ -27,17 +27,114 @@ enum class SpriteComponent : uint8_t {
|
||||||
using SpriteComponents = EnumBitSet<SpriteComponent, uint8_t, SpriteComponent::End>;
|
using SpriteComponents = EnumBitSet<SpriteComponent, uint8_t, SpriteComponent::End>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Map zoom level to data.
|
* Key into sprite collections.
|
||||||
|
*/
|
||||||
|
class SpriteCollKey {
|
||||||
|
public:
|
||||||
|
bool rtl;
|
||||||
|
ZoomLevel zoom;
|
||||||
|
|
||||||
|
inline constexpr SpriteCollKey(ZoomLevel zoom, bool rtl) : rtl(rtl), zoom(zoom) {}
|
||||||
|
|
||||||
|
inline constexpr bool operator==(const SpriteCollKey &rhs) const = default;
|
||||||
|
inline constexpr std::strong_ordering operator<=>(const SpriteCollKey &rhs) const = default;
|
||||||
|
|
||||||
|
static SpriteCollKey Root(bool rtl) { return SpriteCollKey(ZoomLevel::Min, rtl); }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set of sprite collection keys.
|
||||||
|
*/
|
||||||
|
class SpriteCollKeys {
|
||||||
|
ZoomLevels ltr, rtl;
|
||||||
|
public:
|
||||||
|
inline constexpr SpriteCollKeys() = default;
|
||||||
|
inline constexpr void Set(const SpriteCollKey &sck) { (sck.rtl ? this->rtl : this->ltr).Set(sck.zoom); }
|
||||||
|
inline constexpr bool Test(const SpriteCollKey &sck) const { return (sck.rtl ? this->rtl : this->ltr).Test(sck.zoom); }
|
||||||
|
inline constexpr bool AnyLtr() const { return this->ltr.Any(); }
|
||||||
|
inline constexpr bool AnyRtl() const { return this->rtl.Any(); }
|
||||||
|
inline constexpr bool NoLtr() const { return this->ltr.None(); }
|
||||||
|
inline constexpr bool NoRtl() const { return this->rtl.None(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Map sprite collection keys to data.
|
||||||
*/
|
*/
|
||||||
template <class T>
|
template <class T>
|
||||||
class SpriteCollMap {
|
class SpriteCollMap {
|
||||||
std::array<T, to_underlying(ZoomLevel::End)> data{};
|
std::array<T, to_underlying(ZoomLevel::End)> ltr{}, rtl{};
|
||||||
public:
|
public:
|
||||||
inline constexpr T &operator[](const ZoomLevel &zoom) { return this->data[to_underlying(zoom)]; }
|
inline constexpr T &operator[](const SpriteCollKey &sck) { return (sck.rtl ? this->rtl : this->ltr)[to_underlying(sck.zoom)]; }
|
||||||
inline constexpr const T &operator[](const ZoomLevel &zoom) const { return this->data[to_underlying(zoom)]; }
|
inline constexpr const T &operator[](const SpriteCollKey &sck) const { return (sck.rtl ? this->rtl : this->ltr)[to_underlying(sck.zoom)]; }
|
||||||
|
|
||||||
T &Root() { return this->data[to_underlying(ZoomLevel::Min)]; }
|
T &Root(bool rtl) { return (rtl ? this->rtl : this->ltr)[to_underlying(ZoomLevel::Min)]; }
|
||||||
const T &Root() const { return this->data[to_underlying(ZoomLevel::Min)]; }
|
const T &Root(bool rtl) const { return (rtl ? this->rtl : this->ltr)[to_underlying(ZoomLevel::Min)]; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Range of sprite collection keys.
|
||||||
|
*/
|
||||||
|
class SpriteCollKeyRange {
|
||||||
|
public:
|
||||||
|
class Iterator {
|
||||||
|
ZoomLevel zoom_min, zoom_max;
|
||||||
|
SpriteCollKey pos;
|
||||||
|
public:
|
||||||
|
using value_type = SpriteCollKey;
|
||||||
|
using difference_type = std::ptrdiff_t;
|
||||||
|
using iterator_category = std::bidirectional_iterator_tag;
|
||||||
|
using pointer = void;
|
||||||
|
using reference = void;
|
||||||
|
|
||||||
|
Iterator(ZoomLevel zoom_min, ZoomLevel zoom_max, SpriteCollKey pos) : zoom_min(zoom_min), zoom_max(zoom_max), pos(pos) {}
|
||||||
|
bool operator==(const Iterator &rhs) const { return this->pos == rhs.pos; }
|
||||||
|
std::strong_ordering operator<=>(const Iterator &rhs) const { return this->pos <=> rhs.pos; }
|
||||||
|
const SpriteCollKey &operator*() const { return this->pos; }
|
||||||
|
|
||||||
|
Iterator& operator++()
|
||||||
|
{
|
||||||
|
if (!this->pos.rtl && this->pos.zoom == this->zoom_max) {
|
||||||
|
this->pos.zoom = this->zoom_min;
|
||||||
|
this->pos.rtl = true;
|
||||||
|
} else {
|
||||||
|
++this->pos.zoom;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator operator++(int)
|
||||||
|
{
|
||||||
|
Iterator result = *this;
|
||||||
|
++*this;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator& operator--()
|
||||||
|
{
|
||||||
|
if (this->pos.zoom == this->zoom_min) {
|
||||||
|
this->pos.zoom = this->zoom_max;
|
||||||
|
this->pos.rtl = false;
|
||||||
|
} else {
|
||||||
|
--this->pos.zoom;
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
Iterator operator--(int)
|
||||||
|
{
|
||||||
|
Iterator result = *this;
|
||||||
|
--*this;
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
SpriteCollKeyRange(ZoomLevel zoom_min, ZoomLevel zoom_max, bool has_rtl) : zoom_min(zoom_min), zoom_max(zoom_max), has_rtl(has_rtl) {}
|
||||||
|
Iterator begin() const { return Iterator{this->zoom_min, this->zoom_max, SpriteCollKey{this->zoom_min, false}}; }
|
||||||
|
Iterator end() const { return ++Iterator{this->zoom_min, this->zoom_max, SpriteCollKey{this->zoom_max, this->has_rtl}}; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
ZoomLevel zoom_min, zoom_max;
|
||||||
|
bool has_rtl;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Interface for the loader of our sprites. */
|
/** Interface for the loader of our sprites. */
|
||||||
|
@ -68,17 +165,17 @@ public:
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Allocate the sprite data of this sprite.
|
* Allocate the sprite data of this sprite.
|
||||||
* @param zoom Zoom level to allocate the data for.
|
* @param sck Key to allocate the data for.
|
||||||
* @param size the minimum size of the data field.
|
* @param size the minimum size of the data field.
|
||||||
*/
|
*/
|
||||||
void AllocateData(ZoomLevel zoom, size_t size) { this->data = Sprite::buffer[zoom].ZeroAllocate(size); }
|
void AllocateData(SpriteCollKey sck, size_t size) { this->data = Sprite::buffer[sck].ZeroAllocate(size); }
|
||||||
private:
|
private:
|
||||||
/** Allocated memory to pass sprite data around */
|
/** Allocated memory to pass sprite data around */
|
||||||
static SpriteCollMap<ReusableBuffer<SpriteLoader::CommonPixel>> buffer;
|
static SpriteCollMap<ReusableBuffer<SpriteLoader::CommonPixel>> buffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Type defining a collection of sprites, one for each zoom level.
|
* Type defining a collection of sprites, one for each key.
|
||||||
*/
|
*/
|
||||||
using SpriteCollection = SpriteCollMap<Sprite>;
|
using SpriteCollection = SpriteCollMap<Sprite>;
|
||||||
|
|
||||||
|
@ -94,7 +191,7 @@ public:
|
||||||
* @param[out] avail_32bpp Available 32bpp sprites.
|
* @param[out] avail_32bpp Available 32bpp sprites.
|
||||||
* @return Available sprites matching \a load_32bpp.
|
* @return Available sprites matching \a load_32bpp.
|
||||||
*/
|
*/
|
||||||
virtual ZoomLevels LoadSprite(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool load_32bpp, uint8_t control_flags, ZoomLevels &avail_8bpp, ZoomLevels &avail_32bpp) = 0;
|
virtual SpriteCollKeys LoadSprite(SpriteLoader::SpriteCollection &sprite, SpriteFile &file, size_t file_pos, SpriteType sprite_type, bool load_32bpp, uint8_t control_flags, SpriteCollKeys &avail_8bpp, SpriteCollKeys &avail_32bpp) = 0;
|
||||||
|
|
||||||
virtual ~SpriteLoader() = default;
|
virtual ~SpriteLoader() = default;
|
||||||
};
|
};
|
||||||
|
@ -139,7 +236,7 @@ public:
|
||||||
/**
|
/**
|
||||||
* Convert a sprite from the loader to our own format.
|
* Convert a sprite from the loader to our own format.
|
||||||
*/
|
*/
|
||||||
virtual Sprite *Encode(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator) = 0;
|
virtual Sprite *Encode(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, bool has_rtl, SpriteAllocator &allocator) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the value which the height and width on a sprite have to be aligned by.
|
* Get the value which the height and width on a sprite have to be aligned by.
|
||||||
|
|
|
@ -34,6 +34,7 @@
|
||||||
#include "../debug.h"
|
#include "../debug.h"
|
||||||
#include "../blitter/factory.hpp"
|
#include "../blitter/factory.hpp"
|
||||||
#include "../zoom_func.h"
|
#include "../zoom_func.h"
|
||||||
|
#include "../strings_func.h"
|
||||||
#include "../core/string_consumer.hpp"
|
#include "../core/string_consumer.hpp"
|
||||||
|
|
||||||
#include "../table/opengl_shader.h"
|
#include "../table/opengl_shader.h"
|
||||||
|
@ -1258,11 +1259,11 @@ void OpenGLBackend::ReleaseAnimBuffer(const Rect &update_rect)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* virtual */ Sprite *OpenGLBackend::Encode(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator)
|
/* virtual */ Sprite *OpenGLBackend::Encode(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, bool has_rtl, SpriteAllocator &allocator)
|
||||||
{
|
{
|
||||||
/* This encoding is only called for mouse cursors. We don't need real sprites but OpenGLSprites to show as cursor. These need to be put in the LRU cache. */
|
/* This encoding is only called for mouse cursors. We don't need real sprites but OpenGLSprites to show as cursor. These need to be put in the LRU cache. */
|
||||||
OpenGLSpriteAllocator &gl_allocator = static_cast<OpenGLSpriteAllocator&>(allocator);
|
OpenGLSpriteAllocator &gl_allocator = static_cast<OpenGLSpriteAllocator&>(allocator);
|
||||||
gl_allocator.lru.Insert(gl_allocator.sprite, std::make_unique<OpenGLSprite>(sprite_type, sprite));
|
gl_allocator.lru.Insert(gl_allocator.sprite, std::make_unique<OpenGLSprite>(sprite_type, sprite, has_rtl && _current_text_dir == TD_RTL));
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -1397,9 +1398,9 @@ void OpenGLBackend::RenderOglSprite(const OpenGLSprite *gl_sprite, PaletteID pal
|
||||||
* Create an OpenGL sprite with a palette remap part.
|
* Create an OpenGL sprite with a palette remap part.
|
||||||
* @param sprite The sprite to create the OpenGL sprite for
|
* @param sprite The sprite to create the OpenGL sprite for
|
||||||
*/
|
*/
|
||||||
OpenGLSprite::OpenGLSprite(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite)
|
OpenGLSprite::OpenGLSprite(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, bool rtl)
|
||||||
{
|
{
|
||||||
const auto &root_sprite = sprite.Root();
|
const auto &root_sprite = sprite.Root(rtl);
|
||||||
this->dim.width = root_sprite.width;
|
this->dim.width = root_sprite.width;
|
||||||
this->dim.height = root_sprite.height;
|
this->dim.height = root_sprite.height;
|
||||||
this->x_offs = root_sprite.x_offs;
|
this->x_offs = root_sprite.x_offs;
|
||||||
|
@ -1441,7 +1442,7 @@ OpenGLSprite::OpenGLSprite(SpriteType sprite_type, const SpriteLoader::SpriteCol
|
||||||
|
|
||||||
/* Upload texture data. */
|
/* Upload texture data. */
|
||||||
for (ZoomLevel zoom = ZoomLevel::Min; zoom <= (sprite_type == SpriteType::Font ? ZoomLevel::Min : ZoomLevel::Max); ++zoom) {
|
for (ZoomLevel zoom = ZoomLevel::Min; zoom <= (sprite_type == SpriteType::Font ? ZoomLevel::Min : ZoomLevel::Max); ++zoom) {
|
||||||
const auto &src_sprite = sprite[zoom];
|
const auto &src_sprite = sprite[SpriteCollKey{zoom, rtl}];
|
||||||
this->Update(src_sprite.width, src_sprite.height, to_underlying(zoom), src_sprite.data);
|
this->Update(src_sprite.width, src_sprite.height, to_underlying(zoom), src_sprite.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -108,7 +108,7 @@ public:
|
||||||
|
|
||||||
bool Is32BppSupported() override { return true; }
|
bool Is32BppSupported() override { return true; }
|
||||||
uint GetSpriteAlignment() override { return 1u << to_underlying(ZoomLevel::Max); }
|
uint GetSpriteAlignment() override { return 1u << to_underlying(ZoomLevel::Max); }
|
||||||
Sprite *Encode(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, SpriteAllocator &allocator) override;
|
Sprite *Encode(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, bool has_rtl, SpriteAllocator &allocator) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -139,7 +139,7 @@ private:
|
||||||
bool BindTextures() const;
|
bool BindTextures() const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
OpenGLSprite(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite);
|
OpenGLSprite(SpriteType sprite_type, const SpriteLoader::SpriteCollection &sprite, bool rtl);
|
||||||
|
|
||||||
/* No support for moving/copying the textures is implemented. */
|
/* No support for moving/copying the textures is implemented. */
|
||||||
OpenGLSprite(const OpenGLSprite&) = delete;
|
OpenGLSprite(const OpenGLSprite&) = delete;
|
||||||
|
|
Loading…
Reference in New Issue