Files @ r9583:b6e25a00b908
Branch filter:

Location: cpp/openttd-patchpack/source/src/blitter/32bpp_anim.cpp - annotation

rubidium
(svn r13621) -Fix: building roadbits in the wrong direction on bridges or building roadbits from underneath the bridge to the bridgehead is impossible, so don't silently ignore that error when building over houses and industries is not ignored.
r8091:d63ba361d6b8
r8091:d63ba361d6b8
r9111:983de9c5a848
r9111:983de9c5a848
r6971:b3bdb012053e
r8130:bece2e5c7460
r9548:44248dc324db
r8123:dde0a9a84019
r8123:dde0a9a84019
r6971:b3bdb012053e
r7170:38b143754b40
r6971:b3bdb012053e
r6971:b3bdb012053e
r8264:d493cb51fe8a
r8264:d493cb51fe8a
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r8249:a0dc5dc66483
r7556:1a8ee18dd1eb
r7556:1a8ee18dd1eb
r7556:1a8ee18dd1eb
r7556:1a8ee18dd1eb
r7557:1821f4ba38b6
r6971:b3bdb012053e
r6971:b3bdb012053e
r7556:1a8ee18dd1eb
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r7553:1f8dacb4cfbd
r7553:1f8dacb4cfbd
r7553:1f8dacb4cfbd
r7553:1f8dacb4cfbd
r7553:1f8dacb4cfbd
r7556:1a8ee18dd1eb
r7553:1f8dacb4cfbd
r7553:1f8dacb4cfbd
r7553:1f8dacb4cfbd
r7553:1f8dacb4cfbd
r7553:1f8dacb4cfbd
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r7553:1f8dacb4cfbd
r7555:a0fc6844d889
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r7555:a0fc6844d889
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r7553:1f8dacb4cfbd
r7555:a0fc6844d889
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r7553:1f8dacb4cfbd
r7553:1f8dacb4cfbd
r7553:1f8dacb4cfbd
r7555:a0fc6844d889
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r7556:1a8ee18dd1eb
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r8249:a0dc5dc66483
r8249:a0dc5dc66483
r8249:a0dc5dc66483
r8249:a0dc5dc66483
r8249:a0dc5dc66483
r8249:a0dc5dc66483
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r7552:47c4bace5157
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r8249:a0dc5dc66483
r8249:a0dc5dc66483
r8249:a0dc5dc66483
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r8249:a0dc5dc66483
r8249:a0dc5dc66483
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r8249:a0dc5dc66483
r8249:a0dc5dc66483
r8249:a0dc5dc66483
r8249:a0dc5dc66483
r8249:a0dc5dc66483
r8249:a0dc5dc66483
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r8249:a0dc5dc66483
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r8249:a0dc5dc66483
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6986:f09d57f6b2d7
r6986:f09d57f6b2d7
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6985:c27a9a2405aa
r6971:b3bdb012053e
r6971:b3bdb012053e
r8249:a0dc5dc66483
r8249:a0dc5dc66483
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6988:8026972849a3
r6988:8026972849a3
r6988:8026972849a3
r6988:8026972849a3
r6988:8026972849a3
r6971:b3bdb012053e
r6971:b3bdb012053e
r8249:a0dc5dc66483
r6971:b3bdb012053e
r6979:c72bc9ef55cf
r9548:44248dc324db
r9548:44248dc324db
r9548:44248dc324db
r9548:44248dc324db
r9548:44248dc324db
r9548:44248dc324db
r9548:44248dc324db
r6979:c72bc9ef55cf
r6971:b3bdb012053e
r9548:44248dc324db
r9548:44248dc324db
r9548:44248dc324db
r9548:44248dc324db
r6971:b3bdb012053e
r9548:44248dc324db
r6971:b3bdb012053e
r9548:44248dc324db
r6971:b3bdb012053e
r6971:b3bdb012053e
r9550:6041b660ac25
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r7170:38b143754b40
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
r6971:b3bdb012053e
/* $Id$ */

/** @file 32bpp_anim.cpp Implementation of the optimized 32 bpp blitter with animation support. */

#include "../stdafx.h"
#include "../core/alloc_func.hpp"
#include "../core/math_func.hpp"
#include "../gfx_func.h"
#include "../zoom_func.h"
#include "../debug.h"
#include "../video/video_driver.hpp"
#include "32bpp_anim.hpp"

#include "../table/sprites.h"

static FBlitter_32bppAnim iFBlitter_32bppAnim;

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;
	}

	const SpriteLoader::CommonPixel *src, *src_line;
	uint32 *dst, *dst_line;
	uint8 *anim, *anim_line;

	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;

	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);

		anim = anim_line;
		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;
				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) {
						*dst = ComposeColourRGBA(src->r, src->g, src->b, src->a, *dst);
						*anim = 0;
					} else {
						if (bp->remap[src->m] != 0) {
							*dst = ComposeColourPA(this->LookupColourInPalette(bp->remap[src->m]), src->a, *dst);
							*anim = bp->remap[src->m];
						}
					}
					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);
					*anim = bp->remap[*anim];
					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;
					break;
			}
			dst++;
			anim++;
			src += ScaleByZoom(1, zoom);
		}
	}
}

void Blitter_32bppAnim::DrawColorMappingRect(void *dst, int width, int height, int pal)
{
	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 DrawColorMappingRect() */
		Blitter_32bppOptimized::DrawColorMappingRect(dst, width, height, pal);
		return;
	}

	uint32 *udst = (uint32 *)dst;
	uint8 *anim;

	anim = this->anim_buf + ((uint32 *)dst - (uint32 *)_screen.dst_ptr);

	if (pal == PALETTE_TO_TRANSPARENT) {
		do {
			for (int i = 0; i != width; i++) {
				*udst = MakeTransparent(*udst, 154);
				*anim = 0;
				udst++;
				anim++;
			}
			udst = udst - width + _screen.pitch;
			anim = anim - width + this->anim_buf_width;
		} while (--height);
		return;
	}
	if (pal == PALETTE_TO_STRUCT_GREY) {
		do {
			for (int i = 0; i != width; i++) {
				*udst = MakeGrey(*udst);
				*anim = 0;
				udst++;
				anim++;
			}
			udst = udst - width + _screen.pitch;
			anim = anim - width + this->anim_buf_width;
		} while (--height);
		return;
	}

	DEBUG(misc, 0, "32bpp blitter doesn't know how to draw this color table ('%d')", pal);
}

void Blitter_32bppAnim::SetPixel(void *video, int x, int y, uint8 color)
{
	*((uint32 *)video + x + y * _screen.pitch) = LookupColourInPalette(color);

	/* Set the color in the anim-buffer too, if we are rendering to the screen */
	if (_screen_disable_anim) return;
	this->anim_buf[((uint32 *)video - (uint32 *)_screen.dst_ptr) + x + y * this->anim_buf_width] = color;
}

void Blitter_32bppAnim::SetPixelIfEmpty(void *video, int x, int y, uint8 color)
{
	uint32 *dst = (uint32 *)video + x + y * _screen.pitch;
	if (*dst == 0) {
		*dst = LookupColourInPalette(color);
		/* Set the color in the anim-buffer too, if we are rendering to the screen */
		if (_screen_disable_anim) return;
		this->anim_buf[((uint32 *)video - (uint32 *)_screen.dst_ptr) + x + y * this->anim_buf_width] = color;
	}
}

void Blitter_32bppAnim::DrawRect(void *video, int width, int height, uint8 color)
{
	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 DrawRect() */
		Blitter_32bppOptimized::DrawRect(video, width, height, color);
		return;
	}

	uint32 color32 = LookupColourInPalette(color);
	uint8 *anim_line;

	anim_line = ((uint32 *)video - (uint32 *)_screen.dst_ptr) + this->anim_buf;

	do {
		uint32 *dst = (uint32 *)video;
		uint8 *anim = anim_line;

		for (int i = width; i > 0; i--) {
			*dst = color32;
			/* Set the color in the anim-buffer too */
			*anim = color;
			dst++;
			anim++;
		}
		video = (uint32 *)video + _screen.pitch;
		anim_line += this->anim_buf_width;
	} while (--height);
}

void Blitter_32bppAnim::CopyFromBuffer(void *video, const void *src, int width, int height)
{
	assert(!_screen_disable_anim);
	assert(video >= _screen.dst_ptr && video <= (uint32 *)_screen.dst_ptr + _screen.width + _screen.height * _screen.pitch);
	uint32 *dst = (uint32 *)video;
	uint32 *usrc = (uint32 *)src;
	uint8 *anim_line;

	anim_line = ((uint32 *)video - (uint32 *)_screen.dst_ptr) + this->anim_buf;

	for (; height > 0; height--) {
		memcpy(dst, usrc, width * sizeof(uint32));
		usrc += width;
		dst += _screen.pitch;
		/* Copy back the anim-buffer */
		memcpy(anim_line, usrc, width * sizeof(uint8));
		usrc = (uint32 *)((uint8 *)usrc + width);
		anim_line += this->anim_buf_width;
	}

	/* We update the palette (or the pixels that do animation) immediatly, to avoid graphical glitches */
	this->PaletteAnimate(217, _use_dos_palette ? 38 : 28);
}

void Blitter_32bppAnim::CopyToBuffer(const void *video, void *dst, int width, int height)
{
	assert(!_screen_disable_anim);
	assert(video >= _screen.dst_ptr && video <= (uint32 *)_screen.dst_ptr + _screen.width + _screen.height * _screen.pitch);
	uint32 *udst = (uint32 *)dst;
	uint32 *src = (uint32 *)video;
	uint8 *anim_line;

	if (this->anim_buf == NULL) return;

	anim_line = ((uint32 *)video - (uint32 *)_screen.dst_ptr) + this->anim_buf;

	for (; height > 0; height--) {
		memcpy(udst, src, width * sizeof(uint32));
		src += _screen.pitch;
		udst += width;
		/* Copy the anim-buffer */
		memcpy(udst, anim_line, width * sizeof(uint8));
		udst = (uint32 *)((uint8 *)udst + width);
		anim_line += this->anim_buf_width;
	}
}

void Blitter_32bppAnim::ScrollBuffer(void *video, int &left, int &top, int &width, int &height, int scroll_x, int scroll_y)
{
	assert(!_screen_disable_anim);
	assert(video >= _screen.dst_ptr && video <= (uint32 *)_screen.dst_ptr + _screen.width + _screen.height * _screen.pitch);
	uint8 *dst, *src;

	/* We need to scroll the anim-buffer too */
	if (scroll_y > 0) {
		dst = this->anim_buf + left + (top + height - 1) * this->anim_buf_width;
		src = dst - scroll_y * this->anim_buf_width;

		/* Adjust left & width */
		if (scroll_x >= 0) dst += scroll_x;
		else               src -= scroll_x;

		uint tw = width + (scroll_x >= 0 ? -scroll_x : scroll_x);
		uint th = height - scroll_y;
		for (; th > 0; th--) {
			memcpy(dst, src, tw * sizeof(uint8));
			src -= this->anim_buf_width;
			dst -= this->anim_buf_width;
		}
	} else {
		/* Calculate pointers */
		dst = this->anim_buf + left + top * this->anim_buf_width;
		src = dst - scroll_y * this->anim_buf_width;

		/* Adjust left & width */
		if (scroll_x >= 0) dst += scroll_x;
		else               src -= scroll_x;

		/* the y-displacement may be 0 therefore we have to use memmove,
		 * because source and destination may overlap */
		uint tw = width + (scroll_x >= 0 ? -scroll_x : scroll_x);
		uint th = height + scroll_y;
		for (; th > 0; th--) {
			memmove(dst, src, tw * sizeof(uint8));
			src += this->anim_buf_width;
			dst += this->anim_buf_width;
		}
	}

	Blitter_32bppBase::ScrollBuffer(video, left, top, width, height, scroll_x, scroll_y);
}

int Blitter_32bppAnim::BufferSize(int width, int height)
{
	return width * height * (sizeof(uint32) + sizeof(uint8));
}

void Blitter_32bppAnim::PaletteAnimate(uint start, uint count)
{
	assert(!_screen_disable_anim);

	/* Never repaint the transparency pixel */
	if (start == 0) {
		start++;
		count--;
	}

	const uint8 *anim = this->anim_buf;
	uint32 *dst = (uint32 *)_screen.dst_ptr;

	/* Let's walk the anim buffer and try to find the pixels */
	for (int y = this->anim_buf_height; y != 0 ; y--) {
		for (int x = this->anim_buf_width; x != 0 ; x--) {
			uint colour = *anim;
			if (IsInsideBS(colour, start, count)) {
				/* Update this pixel */
				*dst = LookupColourInPalette(colour);
			}
			dst++;
			anim++;
		}
		dst += _screen.pitch - this->anim_buf_width;
	}

	/* Make sure the backend redraws the whole screen */
	_video_driver->MakeDirty(0, 0, _screen.width, _screen.height);
}

Blitter::PaletteAnimation Blitter_32bppAnim::UsePaletteAnimation()
{
	return Blitter::PALETTE_ANIMATION_BLITTER;
}