summaryrefslogtreecommitdiff
path: root/src/blitter
diff options
context:
space:
mode:
authortruelight <truelight@openttd.org>2007-09-09 23:16:01 +0000
committertruelight <truelight@openttd.org>2007-09-09 23:16:01 +0000
commit34e48f788684ce4e1d41adc1b05037beb3a78e13 (patch)
treefe46e704df372bfa17f9bda4128052013ebf40ab /src/blitter
parent89bdfaacd93f543a72c37adbb277531f5e39482c (diff)
downloadopenttd-34e48f788684ce4e1d41adc1b05037beb3a78e13.tar.xz
(svn r11078) -Add: added 32bpp-optimized, which is almost twice as fast as 32bpp-simple (based on the work of frosch)
-Add: let 32bpp-anim use 32bpp-optimizeds, so he profits from the speed-up too
Diffstat (limited to 'src/blitter')
-rw-r--r--src/blitter/32bpp_anim.cpp31
-rw-r--r--src/blitter/32bpp_anim.hpp4
-rw-r--r--src/blitter/32bpp_optimized.cpp108
-rw-r--r--src/blitter/32bpp_optimized.hpp26
4 files changed, 156 insertions, 13 deletions
diff --git a/src/blitter/32bpp_anim.cpp b/src/blitter/32bpp_anim.cpp
index 7f8fe7651..f3f60b337 100644
--- a/src/blitter/32bpp_anim.cpp
+++ b/src/blitter/32bpp_anim.cpp
@@ -38,11 +38,24 @@ void Blitter_32bppAnim::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomL
anim_line += this->anim_buf_width;
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);
+
+ dst += skip;
+ /* Make sure the anim-buffer is cleared */
+ memset(anim, 0, skip);
+ anim += skip;
+ x += skip - 1;
+ src += ScaleByZoom(1, zoom) * skip;
+ continue;
+ }
+
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) {
- if (src->a != 0) *dst = ComposeColourRGBA(src->r, src->g, src->b, src->a, *dst);
+ *dst = ComposeColourRGBA(src->r, src->g, src->b, src->a, *dst);
*anim = 0;
} else {
if (bp->remap[src->m] != 0) {
@@ -58,19 +71,15 @@ 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 */
- if (src->a != 0) {
- *dst = MakeTransparent(*dst, 192);
- *anim = bp->remap[*anim];
- }
+ *dst = MakeTransparent(*dst, 192);
+ *anim = bp->remap[*anim];
break;
default:
- if (src->a != 0) {
- /* 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;
- }
+ /* 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;
break;
}
dst++;
diff --git a/src/blitter/32bpp_anim.hpp b/src/blitter/32bpp_anim.hpp
index 1da06af21..255cca48b 100644
--- a/src/blitter/32bpp_anim.hpp
+++ b/src/blitter/32bpp_anim.hpp
@@ -5,10 +5,10 @@
#ifndef BLITTER_32BPP_ANIM_HPP
#define BLITTER_32BPP_ANIM_HPP
-#include "32bpp_simple.hpp"
+#include "32bpp_optimized.hpp"
#include "factory.hpp"
-class Blitter_32bppAnim : public Blitter_32bppSimple {
+class Blitter_32bppAnim : public Blitter_32bppOptimized {
private:
uint8 *anim_buf; ///< In this buffer we keep track of the 8bpp indexes so we can do palette animation
int anim_buf_width;
diff --git a/src/blitter/32bpp_optimized.cpp b/src/blitter/32bpp_optimized.cpp
new file mode 100644
index 000000000..460e7ad0e
--- /dev/null
+++ b/src/blitter/32bpp_optimized.cpp
@@ -0,0 +1,108 @@
+#include "../stdafx.h"
+#include "../zoom.hpp"
+#include "../gfx.h"
+#include "../debug.h"
+#include "../table/sprites.h"
+#include "32bpp_optimized.hpp"
+
+static FBlitter_32bppOptimized iFBlitter_32bppOptimized;
+
+void Blitter_32bppOptimized::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom)
+{
+ const SpriteLoader::CommonPixel *src, *src_line;
+ uint32 *dst, *dst_line;
+
+ /* 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;
+
+ for (int y = 0; y < bp->height; y++) {
+ dst = dst_line;
+ dst_line += bp->pitch;
+
+ src = src_line;
+ src_line += bp->sprite_width * ScaleByZoom(1, zoom);
+
+ 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);
+
+ dst += skip;
+ x += skip - 1;
+ src += ScaleByZoom(1, zoom) * skip;
+ continue;
+ }
+
+ 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);
+ } else {
+ if (bp->remap[src->m] != 0) *dst = ComposeColourPA(this->LookupColourInPalette(bp->remap[src->m]), src->a, *dst);
+ }
+ break;
+
+ case BM_TRANSPARENT:
+ /* TODO -- We make an assumption here that the remap in fact is transparency, not some color.
+ * This is never a problem with the code we produce, but newgrfs can make it fail... or at least:
+ * 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);
+ break;
+
+ default:
+ *dst = ComposeColourRGBA(src->r, src->g, src->b, src->a, *dst);
+ break;
+ }
+ dst++;
+ src += ScaleByZoom(1, zoom);
+ }
+ }
+}
+
+Sprite *Blitter_32bppOptimized::Encode(SpriteLoader::Sprite *sprite, Blitter::AllocatorProc *allocator)
+{
+ Sprite *dest_sprite;
+ SpriteLoader::CommonPixel *dst;
+ dest_sprite = (Sprite *)allocator(sizeof(*dest_sprite) + sprite->height * sprite->width * sizeof(SpriteLoader::CommonPixel));
+
+ dest_sprite->height = sprite->height;
+ dest_sprite->width = sprite->width;
+ dest_sprite->x_offs = sprite->x_offs;
+ dest_sprite->y_offs = sprite->y_offs;
+
+ dst = (SpriteLoader::CommonPixel *)dest_sprite->data;
+
+ memcpy(dst, sprite->data, sprite->height * sprite->width * sizeof(SpriteLoader::CommonPixel));
+ /* Skip to the end of the array, and work backwards to find transparent blocks */
+ dst = dst + sprite->height * sprite->width - 1;
+
+ for (uint y = sprite->height; y > 0; y--) {
+ int trans = 0;
+ /* Process sprite line backwards, to compute lengths of transparent blocks */
+ for (uint x = sprite->width; x > 0; x--) {
+ if (dst->a == 0) {
+ /* Save transparent block length in red channel; max value is 255 the red channel can contain */
+ if (trans < 255) trans++;
+ dst->r = trans;
+ dst->g = 0;
+ dst->b = 0;
+ dst->m = 0;
+ } else {
+ trans = 0;
+ if (dst->m != 0) {
+ /* Pre-convert the mapping channel to a RGB value */
+ uint color = this->LookupColourInPalette(dst->m);
+ dst->r = GB(color, 16, 8);
+ dst->g = GB(color, 8, 8);
+ dst->b = GB(color, 0, 8);
+ }
+ }
+ dst--;
+ }
+ }
+ return dest_sprite;
+}
diff --git a/src/blitter/32bpp_optimized.hpp b/src/blitter/32bpp_optimized.hpp
new file mode 100644
index 000000000..d437dcdab
--- /dev/null
+++ b/src/blitter/32bpp_optimized.hpp
@@ -0,0 +1,26 @@
+/* $Id$ */
+
+/** @file 32bpp_optimized.hpp */
+
+#ifndef BLITTER_32BPP_OPTIMIZED_HPP
+#define BLITTER_32BPP_OPTIMIZED_HPP
+
+#include "32bpp_simple.hpp"
+#include "factory.hpp"
+
+class Blitter_32bppOptimized : public Blitter_32bppSimple {
+public:
+ /* virtual */ void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom);
+ /* virtual */ Sprite *Encode(SpriteLoader::Sprite *sprite, Blitter::AllocatorProc *allocator);
+
+ /* virtual */ const char *GetName() { return "32bpp-optimized"; }
+};
+
+class FBlitter_32bppOptimized: public BlitterFactory<FBlitter_32bppOptimized> {
+public:
+ /* virtual */ const char *GetName() { return "32bpp-optimized"; }
+ /* virtual */ const char *GetDescription() { return "32bpp Optimized Blitter (no palette animation)"; }
+ /* virtual */ Blitter *CreateInstance() { return new Blitter_32bppOptimized(); }
+};
+
+#endif /* BLITTER_32BPP_OPTIMIZED_HPP */