summaryrefslogtreecommitdiff
path: root/src/gfx.cpp
diff options
context:
space:
mode:
authortruelight <truelight@openttd.org>2007-06-11 11:50:49 +0000
committertruelight <truelight@openttd.org>2007-06-11 11:50:49 +0000
commit6b101cc177a9e689dd193041b82661ab140b817c (patch)
tree2fcb96fde1458283649c1303c0436fcfb369de55 /src/gfx.cpp
parent68c369ea98c4379c25300d055eb206ff8f4442cb (diff)
downloadopenttd-6b101cc177a9e689dd193041b82661ab140b817c.tar.xz
(svn r10092) -Codechange: code-seperated the spriteloader and blitter from the rest of the code
-Add: make it possible to pick your own blitter (-b <blitter>, -h for overview) -Add: added a new optimized 8bpp blitter (default, caches sprites of all zoom-levels) -Add: added a debug 8bpp blitter and a very slow normal 8bpp blitter
Diffstat (limited to 'src/gfx.cpp')
-rw-r--r--src/gfx.cpp286
1 files changed, 46 insertions, 240 deletions
diff --git a/src/gfx.cpp b/src/gfx.cpp
index d529728de..3117d1782 100644
--- a/src/gfx.cpp
+++ b/src/gfx.cpp
@@ -19,6 +19,7 @@
#include "genworld.h"
#include "debug.h"
#include "zoom.hpp"
+#include "blitter/blitter.hpp"
#ifdef _DEBUG
bool _dbg_screen_rect;
@@ -45,14 +46,7 @@ int _pal_last_dirty;
Colour _cur_palette[256];
byte _stringwidth_table[FS_END][224];
-enum BlitterMode {
- BM_NORMAL,
- BM_COLOUR_REMAP,
- BM_TRANSPARENT,
-};
-
-template <BlitterMode Tmode>
-static inline void GfxMainBlitter(const Sprite *sprite, int x, int y);
+static void GfxMainBlitter(const Sprite *sprite, int x, int y, BlitterMode mode);
FontSize _cur_fontsize;
static FontSize _last_fontsize;
@@ -683,7 +677,7 @@ skip_cont:;
if (IsPrintable(c)) {
if (x >= dpi->left + dpi->width) goto skip_char;
if (x + 26 >= dpi->left) {
- GfxMainBlitter<BM_COLOUR_REMAP>(GetGlyph(size, c), x, y);
+ GfxMainBlitter(GetGlyph(size, c), x, y, BM_COLOUR_REMAP);
}
x += GetCharacterWidth(size, c);
} else if (c == '\n') { // newline = {}
@@ -720,269 +714,81 @@ void DrawSprite(SpriteID img, SpriteID pal, int x, int y)
{
if (HASBIT(img, PALETTE_MODIFIER_TRANSPARENT)) {
_color_remap_ptr = GetNonSprite(GB(pal, 0, PALETTE_WIDTH)) + 1;
- GfxMainBlitter<BM_TRANSPARENT>(GetSprite(GB(img, 0, SPRITE_WIDTH)), x, y);
+ GfxMainBlitter(GetSprite(GB(img, 0, SPRITE_WIDTH)), x, y, BM_TRANSPARENT);
} else if (pal != PAL_NONE) {
_color_remap_ptr = GetNonSprite(GB(pal, 0, PALETTE_WIDTH)) + 1;
- GfxMainBlitter<BM_COLOUR_REMAP>(GetSprite(GB(img, 0, SPRITE_WIDTH)), x, y);
+ GfxMainBlitter(GetSprite(GB(img, 0, SPRITE_WIDTH)), x, y, BM_COLOUR_REMAP);
} else {
- GfxMainBlitter<BM_NORMAL>(GetSprite(GB(img, 0, SPRITE_WIDTH)), x, y);
- }
-}
-
-struct BlitterParams {
- int start_x, start_y;
- const byte *sprite;
- Pixel *dst;
- int width, height;
- int width_org;
- int pitch;
-};
-
-template <BlitterMode Tmode, ZoomLevel Tzoom>
-static inline void GfxBlitZoomUncomp(BlitterParams *bp)
-{
- const byte *src = bp->sprite + bp->start_y * bp->width_org + bp->start_x;
- Pixel *dst = bp->dst;
- int height = bp->height;
- int width = bp->width;
- int i;
-
- assert(height > 0);
- assert(width > 0);
-
- height = UnScaleByZoom(height, Tzoom);
-
- switch (Tmode) {
- case BM_COLOUR_REMAP: {
- const byte *ctab = _color_remap_ptr;
-
- for (; height != 0; height--) {
- for (i = 0; i != UnScaleByZoom(width, Tzoom); i++) {
- byte b = ctab[src[ScaleByZoom(i, Tzoom)]];
-
- if (b != 0) dst[i] = b;
- }
- src += ScaleByZoom(bp->width_org, Tzoom);
- dst += bp->pitch;
- }
- break;
- }
-
- case BM_TRANSPARENT: {
- const byte *ctab = _color_remap_ptr;
-
- for (; height != 0; height--) {
- for (i = 0; i != UnScaleByZoom(width, Tzoom); i++)
- if (src[ScaleByZoom(i, Tzoom)] != 0) dst[i] = ctab[dst[i]];
- src += ScaleByZoom(bp->width_org, Tzoom);
- dst += bp->pitch;
- }
- break;
- }
-
- default:
- for (; height != 0; height--) {
- for (i = 0; i != UnScaleByZoom(width, Tzoom); i++)
- if (src[ScaleByZoom(i, Tzoom)] != 0) dst[i] = src[ScaleByZoom(i, Tzoom)];
- src += ScaleByZoom(bp->width_org, Tzoom);
- dst += bp->pitch;
- }
- break;
+ GfxMainBlitter(GetSprite(GB(img, 0, SPRITE_WIDTH)), x, y, BM_NORMAL);
}
}
-template <BlitterMode Tmode, ZoomLevel Tzoom>
-static inline void GfxBlitTileZoom(BlitterParams *bp)
-{
- const byte *src_o = bp->sprite;
- const byte *src;
- int num, skip;
- byte done;
- Pixel *dst;
- const byte *ctab;
-
- src_o += ReadLE16Aligned(src_o + bp->start_y * 2);
-
- for (;;) {
- do {
- done = src_o[0];
- num = done & 0x7F;
- skip = src_o[1];
- src = src_o + 2;
- src_o += num + 2;
-
- dst = bp->dst;
-
- if (Tzoom >= ZOOM_LVL_OUT_2X && (skip & 1)) {
- skip += 1;
- src += 1;
- num -= 1;
- if (num <= 0) continue;
- }
-
- if (Tzoom >= ZOOM_LVL_OUT_4X && (skip & 2)) {
- skip += 2;
- src += 2;
- num -= 2;
- if (num <= 0) continue;
- }
-
- if (Tzoom >= ZOOM_LVL_OUT_8X && (skip & 4)) {
- skip += 4;
- src += 4;
- num -= 4;
- if (num <= 0) continue;
- }
-
- if (Tzoom >= ZOOM_LVL_OUT_16X && (skip & 8)) {
- skip += 8;
- src += 8;
- num -= 8;
- if (num <= 0) continue;
- }
-
- if ( (skip -= bp->start_x) > 0) {
- dst += UnScaleByZoom(skip, Tzoom);
- } else {
- src -= skip;
- num += skip;
- if (num <= 0) continue;
- skip = 0;
- }
-
- skip = skip + num - bp->width;
- if (skip > 0) {
- num -= skip;
- if (num <= 0) continue;
- }
-
- num = UnScaleByZoom(num, Tzoom);
-
- switch (Tmode) {
- case BM_COLOUR_REMAP:
- ctab = _color_remap_ptr;
- for (; num != 0; num--) {
- *dst = ctab[*src];
- dst++;
- src += ScaleByZoom(1, Tzoom);
- }
- break;
-
- case BM_TRANSPARENT:
- ctab = _color_remap_ptr;
- for (; num != 0; num--) {
- *dst = ctab[*dst];
- dst++;
- }
- break;
-
- default:
- if (Tzoom == ZOOM_LVL_NORMAL) {
- memcpy(dst, src, num);
- } else {
- for (; num != 0; num--) {
- *dst = *src;
- dst++;
- src += ScaleByZoom(1, Tzoom);
- }
- }
- break;
- }
-
-
- } while (!(done & 0x80));
-
- bp->dst += bp->pitch;
- if (--bp->height == 0) return;
-
- for (int i = 0; i < ScaleByZoom(1, Tzoom) - 1; i++) {
- do {
- done = src_o[0];
- src_o += (done & 0x7F) + 2;
- } while (!(done & 0x80));
- if (--bp->height == 0) return;
- }
- }
-}
-
-template <BlitterMode Tmode>
-static inline void GfxMainBlitter(const Sprite *sprite, int x, int y)
+static inline void GfxMainBlitter(const Sprite *sprite, int x, int y, BlitterMode mode)
{
const DrawPixelInfo *dpi = _cur_dpi;
- int start_x, start_y;
- BlitterParams bp;
- int zoom_mask = ~(ScaleByZoom(1, dpi->zoom) - 1);
+ Blitter::BlitterParams bp;
- /* decode sprite header */
+ /* Move to the correct offset */
x += sprite->x_offs;
y += sprite->y_offs;
- bp.width_org = bp.width = sprite->width;
- bp.height = sprite->height;
+
+ /* Copy the main data directly from the sprite */
bp.sprite = sprite->data;
+ bp.sprite_width = sprite->width;
+ bp.sprite_height = sprite->height;
+ bp.width = UnScaleByZoom(sprite->width, dpi->zoom);
+ bp.height = UnScaleByZoom(sprite->height, dpi->zoom);
+ bp.top = 0;
+ bp.left = 0;
+ bp.skip_left = 0;
+ bp.skip_top = 0;
bp.dst = dpi->dst_ptr;
bp.pitch = dpi->pitch;
+ bp.remap = _color_remap_ptr;
- assert(bp.height > 0);
- assert(bp.width > 0);
+ assert(sprite->width > 0);
+ assert(sprite->height > 0);
- start_y = 0;
- if (dpi->zoom > ZOOM_LVL_NORMAL) {
- start_y += bp.height & ~zoom_mask;
- bp.height &= zoom_mask;
- if (bp.height == 0) return;
- y &= zoom_mask;
- }
+ if (bp.width <= 0) return;
+ if (bp.height <= 0) return;
- if ( (y -= dpi->top) < 0) {
- bp.height += y;
+ y -= dpi->top;
+ /* Check for top overflow */
+ if (y < 0) {
+ bp.height -= -UnScaleByZoom(y, dpi->zoom);
if (bp.height <= 0) return;
- start_y -= y;
+ bp.skip_top += -UnScaleByZoom(y, dpi->zoom);
y = 0;
} else {
- bp.dst += bp.pitch * UnScaleByZoom(y, dpi->zoom);
+ bp.top = UnScaleByZoom(y, dpi->zoom);
}
- bp.start_y = start_y;
- if ( (y = y + bp.height - dpi->height) > 0) {
- bp.height -= y;
+ /* Check for bottom overflow */
+ y += ScaleByZoom(bp.height, dpi->zoom) - dpi->height;
+ if (y > 0) {
+ bp.height -= UnScaleByZoom(y, dpi->zoom);
if (bp.height <= 0) return;
}
- start_x = 0;
- x &= zoom_mask;
- if ( (x -= dpi->left) < 0) {
- bp.width += x;
+ x -= dpi->left;
+ /* Check for left overflow */
+ if (x < 0) {
+ bp.width -= -UnScaleByZoom(x, dpi->zoom);
if (bp.width <= 0) return;
- start_x -= x;
+ bp.skip_left += -UnScaleByZoom(x, dpi->zoom);
x = 0;
+ } else {
+ bp.left = UnScaleByZoom(x, dpi->zoom);
}
- bp.start_x = start_x;
- bp.dst += UnScaleByZoom(x, dpi->zoom);
- if ( (x = x + bp.width - dpi->width) > 0) {
- bp.width -= x;
+ /* Check for right overflow */
+ x += ScaleByZoom(bp.width, dpi->zoom) - dpi->width;
+ if (x > 0) {
+ bp.width -= UnScaleByZoom(x, dpi->zoom);
if (bp.width <= 0) return;
}
- if (sprite->info & 8) {
- switch (dpi->zoom) {
- case ZOOM_LVL_NORMAL: GfxBlitTileZoom<Tmode, ZOOM_LVL_NORMAL>(&bp); break;
- case ZOOM_LVL_OUT_2X: GfxBlitTileZoom<Tmode, ZOOM_LVL_OUT_2X>(&bp); break;
- case ZOOM_LVL_OUT_4X: GfxBlitTileZoom<Tmode, ZOOM_LVL_OUT_4X>(&bp); break;
- case ZOOM_LVL_OUT_8X: GfxBlitTileZoom<Tmode, ZOOM_LVL_OUT_8X>(&bp); break;
- case ZOOM_LVL_OUT_16X: GfxBlitTileZoom<Tmode, ZOOM_LVL_OUT_16X>(&bp); break;
- default: NOT_REACHED();
- }
- } else {
- switch (dpi->zoom) {
- case ZOOM_LVL_NORMAL: GfxBlitZoomUncomp<Tmode, ZOOM_LVL_NORMAL>(&bp); break;
- case ZOOM_LVL_OUT_2X: GfxBlitZoomUncomp<Tmode, ZOOM_LVL_OUT_2X>(&bp); break;
- case ZOOM_LVL_OUT_4X: GfxBlitZoomUncomp<Tmode, ZOOM_LVL_OUT_4X>(&bp); break;
- case ZOOM_LVL_OUT_8X: GfxBlitZoomUncomp<Tmode, ZOOM_LVL_OUT_8X>(&bp); break;
- case ZOOM_LVL_OUT_16X: GfxBlitZoomUncomp<Tmode, ZOOM_LVL_OUT_16X>(&bp); break;
- default: NOT_REACHED();
- }
- }
+ BlitterFactoryBase::GetCurrentBlitter()->Draw(&bp, mode, dpi->zoom);
}
void DoPaletteAnimations();