(svn r13639) -Codechange: rewrite 32bpp-anim and 32bpp-optimized drawing and encoding so it uses similiar scheme as 8bpp-optimized

All zoom levels are stored and a kind of RLE is used. Together with further changes and reducing number of variables, drawing is ~50% faster in average.
This commit is contained in:
smatz
2008-06-26 15:46:19 +00:00
parent 6f3b1745c2
commit faebe10d81
7 changed files with 544 additions and 159 deletions

View File

@@ -15,64 +15,118 @@
static FBlitter_32bppAnim iFBlitter_32bppAnim;
void Blitter_32bppAnim::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom)
template <BlitterMode mode>
inline void Blitter_32bppAnim::Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom)
{
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() */
Blitter_32bppOptimized::Draw(bp, mode, zoom);
return;
const SpriteData *src = (const SpriteData *)bp->sprite;
const Colour *src_px = (const Colour *)(src->data + src->offset[zoom][0]);
const uint8 *src_n = (const uint8 *)(src->data + src->offset[zoom][1]);
for (uint i = bp->skip_top; i != 0; i--) {
src_px = (const Colour *)((const byte *)src_px + *(const uint32 *)src_px);
src_n += *(const uint32 *)src_n;
}
const SpriteLoader::CommonPixel *src, *src_line;
uint32 *dst, *dst_line;
uint8 *anim, *anim_line;
uint32 *dst = (uint32 *)bp->dst + bp->top * bp->pitch + bp->left;
uint8 *anim = this->anim_buf + ((uint32 *)bp->dst - (uint32 *)_screen.dst_ptr) + bp->top * this->anim_buf_width + bp->left;
if (_screen.width != this->anim_buf_width || _screen.height != this->anim_buf_height) {
/* The size of the screen changed; we can assume we can wipe all data from our buffer */
free(this->anim_buf);
this->anim_buf = CallocT<uint8>(_screen.width * _screen.height);
this->anim_buf_width = _screen.width;
this->anim_buf_height = _screen.height;
}
/* Find where to start reading in the source sprite */
src_line = (const SpriteLoader::CommonPixel *)bp->sprite + (bp->skip_top * bp->sprite_width + bp->skip_left) * ScaleByZoom(1, zoom);
dst_line = (uint32 *)bp->dst + bp->top * bp->pitch + bp->left;
anim_line = this->anim_buf + ((uint32 *)bp->dst - (uint32 *)_screen.dst_ptr) + bp->top * this->anim_buf_width + bp->left;
const byte *remap = bp->remap; // store so we don't have to access it via bp everytime
for (int y = 0; y < bp->height; y++) {
dst = dst_line;
dst_line += bp->pitch;
uint32 *dst_ln = dst + bp->pitch;
uint8 *anim_ln = anim + this->anim_buf_width;
src = src_line;
src_line += bp->sprite_width * ScaleByZoom(1, zoom);
const Colour *src_px_ln = (const Colour *)((const byte *)src_px + *(const uint32 *)src_px);
src_px++;
anim = anim_line;
anim_line += this->anim_buf_width;
const uint8 *src_n_ln = src_n + *(uint32 *)src_n;
src_n += 4;
for (int x = 0; x < bp->width; x++) {
if (src->a == 0) {
/* src->r is 'misused' here to indicate how much more pixels are following with an alpha of 0 */
int skip = UnScaleByZoom(src->r, zoom);
uint32 *dst_end = dst + bp->skip_left;
dst += skip;
anim += skip;
x += skip - 1;
src += ScaleByZoom(1, zoom) * skip;
uint n;
while (dst < dst_end) {
n = *src_n++;
if (src_px->a == 0) {
dst += n;
src_px ++;
src_n++;
if (dst > dst_end) anim += dst - dst_end;
} else {
if (dst + n > dst_end) {
uint d = dst_end - dst;
src_px += d;
src_n += d;
dst = dst_end - bp->skip_left;
dst_end = dst + bp->width;
n = min<uint>(n - d, (uint)bp->width);
goto draw;
}
dst += n;
src_px += n;
src_n += n;
}
}
dst -= bp->skip_left;
dst_end -= bp->skip_left;
dst_end += bp->width;
while (dst < dst_end) {
n = min<uint>(*src_n++, (uint)(dst_end - dst));
if (src_px->a == 0) {
anim += n;
dst += n;
src_px++;
src_n++;
continue;
}
draw:;
switch (mode) {
case BM_COLOUR_REMAP:
/* In case the m-channel is zero, do not remap this pixel in any way */
if (src->m == 0) {
*dst = ComposeColourRGBA(src->r, src->g, src->b, src->a, *dst);
*anim = 0;
if (src_px->a == 255) {
do {
uint m = *src_n;
/* In case the m-channel is zero, do not remap this pixel in any way */
if (m == 0) {
*dst = *src_px;
*anim = 0;
} else {
uint r = remap[m];
*anim = r;
if (r != 0) *dst = this->LookupColourInPalette(r);
}
anim++;
dst++;
src_px++;
src_n++;
} while (--n != 0);
} else {
if (bp->remap[src->m] != 0) {
*dst = ComposeColourPA(this->LookupColourInPalette(bp->remap[src->m]), src->a, *dst);
*anim = bp->remap[src->m];
}
do {
uint m = *src_n;
if (m == 0) {
*dst = ComposeColourRGBANoCheck(src_px->r, src_px->g, src_px->b, src_px->a, *dst);
*anim = 0;
} else {
uint r = remap[m];
*anim = r;
if (r != 0) *dst = ComposeColourPANoCheck(this->LookupColourInPalette(r), src_px->a, *dst);
}
anim++;
dst++;
src_px++;
src_n++;
} while (--n != 0);
}
break;
@@ -82,21 +136,72 @@ void Blitter_32bppAnim::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomL
* we produce a result the newgrf maker didn't expect ;) */
/* Make the current color a bit more black, so it looks like this image is transparent */
*dst = MakeTransparent(*dst, 192);
*anim = bp->remap[*anim];
src_px += n;
src_n += n;
do {
*dst = MakeTransparent(*dst, 192);
*anim = remap[*anim];
anim++;
dst++;
} while (--n != 0);
break;
default:
/* Above 217 is palette animation */
if (src->m >= 217) *dst = ComposeColourPA(this->LookupColourInPalette(src->m), src->a, *dst);
else *dst = ComposeColourRGBA(src->r, src->g, src->b, src->a, *dst);
*anim = src->m;
if (src_px->a == 255) {
do {
/* Compiler assumes pointer aliasing, can't optimise this on its own */
uint m = *src_n++;
/* Above 217 is palette animation */
*anim++ = m;
*dst++ = (m >= 217) ? this->LookupColourInPalette(m) : *src_px;
src_px++;
} while (--n != 0);
} else {
do {
uint m = *src_n++;
*anim++ = m;
if (m >= 217) {
*dst = ComposeColourPANoCheck(this->LookupColourInPalette(m), src_px->a, *dst);
} else {
*dst = ComposeColourRGBANoCheck(src_px->r, src_px->g, src_px->b, src_px->a, *dst);
}
dst++;
src_px++;
} while (--n != 0);
}
break;
}
dst++;
anim++;
src += ScaleByZoom(1, zoom);
}
anim = anim_ln;
dst = dst_ln;
src_px = src_px_ln;
src_n = src_n_ln;
}
}
void Blitter_32bppAnim::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom)
{
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() */
Blitter_32bppOptimized::Draw(bp, mode, zoom);
return;
}
if (_screen.width != this->anim_buf_width || _screen.height != this->anim_buf_height) {
/* The size of the screen changed; we can assume we can wipe all data from our buffer */
free(this->anim_buf);
this->anim_buf = CallocT<uint8>(_screen.width * _screen.height);
this->anim_buf_width = _screen.width;
this->anim_buf_height = _screen.height;
}
switch (mode) {
default: NOT_REACHED();
case BM_NORMAL: Draw<BM_NORMAL> (bp, zoom); return;
case BM_COLOUR_REMAP: Draw<BM_COLOUR_REMAP>(bp, zoom); return;
case BM_TRANSPARENT: Draw<BM_TRANSPARENT> (bp, zoom); return;
}
}