mirror of https://github.com/OpenTTD/OpenTTD
Add: 32bpp SSE2 blitter palette animator (#6795)
Create a new blitter mode: 32bpp-sse2-anim, which is 32bpp-anim + this. 32bpp-sse2-anim is now used by default where 32bpp-anim would have been. Also use this with the 32bpp-sse4-anim blitter. See issue #6469.pull/6796/head
parent
306b999cf4
commit
17257b9620
|
@ -1149,6 +1149,8 @@
|
||||||
<ClCompile Include="..\src\script\api\script_window.cpp" />
|
<ClCompile Include="..\src\script\api\script_window.cpp" />
|
||||||
<ClCompile Include="..\src\blitter\32bpp_anim.cpp" />
|
<ClCompile Include="..\src\blitter\32bpp_anim.cpp" />
|
||||||
<ClInclude Include="..\src\blitter\32bpp_anim.hpp" />
|
<ClInclude Include="..\src\blitter\32bpp_anim.hpp" />
|
||||||
|
<ClCompile Include="..\src\blitter\32bpp_anim_sse2.cpp" />
|
||||||
|
<ClInclude Include="..\src\blitter\32bpp_anim_sse2.hpp" />
|
||||||
<ClCompile Include="..\src\blitter\32bpp_anim_sse4.cpp" />
|
<ClCompile Include="..\src\blitter\32bpp_anim_sse4.cpp" />
|
||||||
<ClInclude Include="..\src\blitter\32bpp_anim_sse4.hpp" />
|
<ClInclude Include="..\src\blitter\32bpp_anim_sse4.hpp" />
|
||||||
<ClCompile Include="..\src\blitter\32bpp_base.cpp" />
|
<ClCompile Include="..\src\blitter\32bpp_base.cpp" />
|
||||||
|
|
|
@ -2604,6 +2604,12 @@
|
||||||
<ClInclude Include="..\src\blitter\32bpp_anim.hpp">
|
<ClInclude Include="..\src\blitter\32bpp_anim.hpp">
|
||||||
<Filter>Blitters</Filter>
|
<Filter>Blitters</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClCompile Include="..\src\blitter\32bpp_anim_sse2.cpp">
|
||||||
|
<Filter>Blitters</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClInclude Include="..\src\blitter\32bpp_anim_sse2.hpp">
|
||||||
|
<Filter>Blitters</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClCompile Include="..\src\blitter\32bpp_anim_sse4.cpp">
|
<ClCompile Include="..\src\blitter\32bpp_anim_sse4.cpp">
|
||||||
<Filter>Blitters</Filter>
|
<Filter>Blitters</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|
|
@ -1170,6 +1170,8 @@
|
||||||
<ClCompile Include="..\src\script\api\script_window.cpp" />
|
<ClCompile Include="..\src\script\api\script_window.cpp" />
|
||||||
<ClCompile Include="..\src\blitter\32bpp_anim.cpp" />
|
<ClCompile Include="..\src\blitter\32bpp_anim.cpp" />
|
||||||
<ClInclude Include="..\src\blitter\32bpp_anim.hpp" />
|
<ClInclude Include="..\src\blitter\32bpp_anim.hpp" />
|
||||||
|
<ClCompile Include="..\src\blitter\32bpp_anim_sse2.cpp" />
|
||||||
|
<ClInclude Include="..\src\blitter\32bpp_anim_sse2.hpp" />
|
||||||
<ClCompile Include="..\src\blitter\32bpp_anim_sse4.cpp" />
|
<ClCompile Include="..\src\blitter\32bpp_anim_sse4.cpp" />
|
||||||
<ClInclude Include="..\src\blitter\32bpp_anim_sse4.hpp" />
|
<ClInclude Include="..\src\blitter\32bpp_anim_sse4.hpp" />
|
||||||
<ClCompile Include="..\src\blitter\32bpp_base.cpp" />
|
<ClCompile Include="..\src\blitter\32bpp_base.cpp" />
|
||||||
|
|
|
@ -2604,6 +2604,12 @@
|
||||||
<ClInclude Include="..\src\blitter\32bpp_anim.hpp">
|
<ClInclude Include="..\src\blitter\32bpp_anim.hpp">
|
||||||
<Filter>Blitters</Filter>
|
<Filter>Blitters</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClCompile Include="..\src\blitter\32bpp_anim_sse2.cpp">
|
||||||
|
<Filter>Blitters</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClInclude Include="..\src\blitter\32bpp_anim_sse2.hpp">
|
||||||
|
<Filter>Blitters</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClCompile Include="..\src\blitter\32bpp_anim_sse4.cpp">
|
<ClCompile Include="..\src\blitter\32bpp_anim_sse4.cpp">
|
||||||
<Filter>Blitters</Filter>
|
<Filter>Blitters</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|
|
@ -1170,6 +1170,8 @@
|
||||||
<ClCompile Include="..\src\script\api\script_window.cpp" />
|
<ClCompile Include="..\src\script\api\script_window.cpp" />
|
||||||
<ClCompile Include="..\src\blitter\32bpp_anim.cpp" />
|
<ClCompile Include="..\src\blitter\32bpp_anim.cpp" />
|
||||||
<ClInclude Include="..\src\blitter\32bpp_anim.hpp" />
|
<ClInclude Include="..\src\blitter\32bpp_anim.hpp" />
|
||||||
|
<ClCompile Include="..\src\blitter\32bpp_anim_sse2.cpp" />
|
||||||
|
<ClInclude Include="..\src\blitter\32bpp_anim_sse2.hpp" />
|
||||||
<ClCompile Include="..\src\blitter\32bpp_anim_sse4.cpp" />
|
<ClCompile Include="..\src\blitter\32bpp_anim_sse4.cpp" />
|
||||||
<ClInclude Include="..\src\blitter\32bpp_anim_sse4.hpp" />
|
<ClInclude Include="..\src\blitter\32bpp_anim_sse4.hpp" />
|
||||||
<ClCompile Include="..\src\blitter\32bpp_base.cpp" />
|
<ClCompile Include="..\src\blitter\32bpp_base.cpp" />
|
||||||
|
|
|
@ -2604,6 +2604,12 @@
|
||||||
<ClInclude Include="..\src\blitter\32bpp_anim.hpp">
|
<ClInclude Include="..\src\blitter\32bpp_anim.hpp">
|
||||||
<Filter>Blitters</Filter>
|
<Filter>Blitters</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClCompile Include="..\src\blitter\32bpp_anim_sse2.cpp">
|
||||||
|
<Filter>Blitters</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClInclude Include="..\src\blitter\32bpp_anim_sse2.hpp">
|
||||||
|
<Filter>Blitters</Filter>
|
||||||
|
</ClInclude>
|
||||||
<ClCompile Include="..\src\blitter\32bpp_anim_sse4.cpp">
|
<ClCompile Include="..\src\blitter\32bpp_anim_sse4.cpp">
|
||||||
<Filter>Blitters</Filter>
|
<Filter>Blitters</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
|
|
@ -3850,6 +3850,14 @@
|
||||||
RelativePath=".\..\src\blitter\32bpp_anim.hpp"
|
RelativePath=".\..\src\blitter\32bpp_anim.hpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\..\src\blitter\32bpp_anim_sse2.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\..\src\blitter\32bpp_anim_sse2.hpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\..\src\blitter\32bpp_anim_sse4.cpp"
|
RelativePath=".\..\src\blitter\32bpp_anim_sse4.cpp"
|
||||||
>
|
>
|
||||||
|
|
|
@ -3847,6 +3847,14 @@
|
||||||
RelativePath=".\..\src\blitter\32bpp_anim.hpp"
|
RelativePath=".\..\src\blitter\32bpp_anim.hpp"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\..\src\blitter\32bpp_anim_sse2.cpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\..\src\blitter\32bpp_anim_sse2.hpp"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\..\src\blitter\32bpp_anim_sse4.cpp"
|
RelativePath=".\..\src\blitter\32bpp_anim_sse4.cpp"
|
||||||
>
|
>
|
||||||
|
|
|
@ -913,6 +913,8 @@ script/api/script_window.cpp
|
||||||
blitter/32bpp_anim.cpp
|
blitter/32bpp_anim.cpp
|
||||||
blitter/32bpp_anim.hpp
|
blitter/32bpp_anim.hpp
|
||||||
#if SSE
|
#if SSE
|
||||||
|
blitter/32bpp_anim_sse2.cpp
|
||||||
|
blitter/32bpp_anim_sse2.hpp
|
||||||
blitter/32bpp_anim_sse4.cpp
|
blitter/32bpp_anim_sse4.cpp
|
||||||
blitter/32bpp_anim_sse4.hpp
|
blitter/32bpp_anim_sse4.hpp
|
||||||
#end
|
#end
|
||||||
|
|
|
@ -22,7 +22,7 @@ static FBlitter_32bppAnim iFBlitter_32bppAnim;
|
||||||
|
|
||||||
Blitter_32bppAnim::~Blitter_32bppAnim()
|
Blitter_32bppAnim::~Blitter_32bppAnim()
|
||||||
{
|
{
|
||||||
free(this->anim_buf);
|
free(this->anim_alloc);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <BlitterMode mode>
|
template <BlitterMode mode>
|
||||||
|
@ -39,8 +39,7 @@ inline void Blitter_32bppAnim::Draw(const Blitter::BlitterParams *bp, ZoomLevel
|
||||||
}
|
}
|
||||||
|
|
||||||
Colour *dst = (Colour *)bp->dst + bp->top * bp->pitch + bp->left;
|
Colour *dst = (Colour *)bp->dst + bp->top * bp->pitch + bp->left;
|
||||||
assert(_screen.pitch == this->anim_buf_pitch); // precondition for translating 'bp->dst' into an 'anim_buf' offset below.
|
uint16 *anim = this->anim_buf + this->ScreenToAnimOffset((uint32 *)bp->dst) + bp->top * this->anim_buf_pitch + bp->left;
|
||||||
uint16 *anim = this->anim_buf + ((uint32 *)bp->dst - (uint32 *)_screen.dst_ptr) + bp->top * this->anim_buf_pitch + bp->left;
|
|
||||||
|
|
||||||
const byte *remap = bp->remap; // store so we don't have to access it via bp everytime
|
const byte *remap = bp->remap; // store so we don't have to access it via bp everytime
|
||||||
|
|
||||||
|
@ -280,8 +279,7 @@ void Blitter_32bppAnim::DrawColourMappingRect(void *dst, int width, int height,
|
||||||
}
|
}
|
||||||
|
|
||||||
Colour *udst = (Colour *)dst;
|
Colour *udst = (Colour *)dst;
|
||||||
assert(_screen.pitch == this->anim_buf_pitch); // precondition for translating 'dst' into an 'anim_buf' offset below.
|
uint16 *anim = this->anim_buf + this->ScreenToAnimOffset((uint32 *)dst);
|
||||||
uint16 *anim = this->anim_buf + ((uint32 *)dst - (uint32 *)_screen.dst_ptr);
|
|
||||||
|
|
||||||
if (pal == PALETTE_TO_TRANSPARENT) {
|
if (pal == PALETTE_TO_TRANSPARENT) {
|
||||||
do {
|
do {
|
||||||
|
@ -319,8 +317,8 @@ void Blitter_32bppAnim::SetPixel(void *video, int x, int y, uint8 colour)
|
||||||
|
|
||||||
/* Set the colour in the anim-buffer too, if we are rendering to the screen */
|
/* Set the colour in the anim-buffer too, if we are rendering to the screen */
|
||||||
if (_screen_disable_anim) return;
|
if (_screen_disable_anim) return;
|
||||||
assert(_screen.pitch == this->anim_buf_pitch); // precondition for translating 'video' into an 'anim_buf' offset below.
|
|
||||||
this->anim_buf[((uint32 *)video - (uint32 *)_screen.dst_ptr) + x + y * this->anim_buf_pitch] = colour | (DEFAULT_BRIGHTNESS << 8);
|
this->anim_buf[this->ScreenToAnimOffset((uint32 *)video) + x + y * this->anim_buf_pitch] = colour | (DEFAULT_BRIGHTNESS << 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Blitter_32bppAnim::DrawRect(void *video, int width, int height, uint8 colour)
|
void Blitter_32bppAnim::DrawRect(void *video, int width, int height, uint8 colour)
|
||||||
|
@ -332,8 +330,7 @@ void Blitter_32bppAnim::DrawRect(void *video, int width, int height, uint8 colou
|
||||||
}
|
}
|
||||||
|
|
||||||
Colour colour32 = LookupColourInPalette(colour);
|
Colour colour32 = LookupColourInPalette(colour);
|
||||||
assert(_screen.pitch == this->anim_buf_pitch); // precondition for translating 'video' into an 'anim_buf' offset below.
|
uint16 *anim_line = this->ScreenToAnimOffset((uint32 *)video) + this->anim_buf;
|
||||||
uint16 *anim_line = ((uint32 *)video - (uint32 *)_screen.dst_ptr) + this->anim_buf;
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
Colour *dst = (Colour *)video;
|
Colour *dst = (Colour *)video;
|
||||||
|
@ -357,8 +354,7 @@ void Blitter_32bppAnim::CopyFromBuffer(void *video, const void *src, int width,
|
||||||
assert(video >= _screen.dst_ptr && video <= (uint32 *)_screen.dst_ptr + _screen.width + _screen.height * _screen.pitch);
|
assert(video >= _screen.dst_ptr && video <= (uint32 *)_screen.dst_ptr + _screen.width + _screen.height * _screen.pitch);
|
||||||
Colour *dst = (Colour *)video;
|
Colour *dst = (Colour *)video;
|
||||||
const uint32 *usrc = (const uint32 *)src;
|
const uint32 *usrc = (const uint32 *)src;
|
||||||
assert(_screen.pitch == this->anim_buf_pitch); // precondition for translating 'video' into an 'anim_buf' offset below.
|
uint16 *anim_line = this->ScreenToAnimOffset((uint32 *)video) + this->anim_buf;
|
||||||
uint16 *anim_line = ((uint32 *)video - (uint32 *)_screen.dst_ptr) + this->anim_buf;
|
|
||||||
|
|
||||||
for (; height > 0; height--) {
|
for (; height > 0; height--) {
|
||||||
/* We need to keep those for palette animation. */
|
/* We need to keep those for palette animation. */
|
||||||
|
@ -401,8 +397,7 @@ void Blitter_32bppAnim::CopyToBuffer(const void *video, void *dst, int width, in
|
||||||
|
|
||||||
if (this->anim_buf == NULL) return;
|
if (this->anim_buf == NULL) return;
|
||||||
|
|
||||||
assert(_screen.pitch == this->anim_buf_pitch); // precondition for translating 'video' into an 'anim_buf' offset below.
|
const uint16 *anim_line = this->ScreenToAnimOffset((const uint32 *)video) + this->anim_buf;
|
||||||
const uint16 *anim_line = ((const uint32 *)video - (uint32 *)_screen.dst_ptr) + this->anim_buf;
|
|
||||||
|
|
||||||
for (; height > 0; height--) {
|
for (; height > 0; height--) {
|
||||||
memcpy(udst, src, width * sizeof(uint32));
|
memcpy(udst, src, width * sizeof(uint32));
|
||||||
|
@ -485,18 +480,22 @@ void Blitter_32bppAnim::PaletteAnimate(const Palette &palette)
|
||||||
Colour *dst = (Colour *)_screen.dst_ptr;
|
Colour *dst = (Colour *)_screen.dst_ptr;
|
||||||
|
|
||||||
/* Let's walk the anim buffer and try to find the pixels */
|
/* Let's walk the anim buffer and try to find the pixels */
|
||||||
|
const int width = this->anim_buf_width;
|
||||||
|
const int pitch_offset = _screen.pitch - width;
|
||||||
|
const int anim_pitch_offset = this->anim_buf_pitch - width;
|
||||||
for (int y = this->anim_buf_height; y != 0 ; y--) {
|
for (int y = this->anim_buf_height; y != 0 ; y--) {
|
||||||
for (int x = this->anim_buf_width; x != 0 ; x--) {
|
for (int x = width; x != 0 ; x--) {
|
||||||
uint colour = GB(*anim, 0, 8);
|
uint16 value = *anim;
|
||||||
|
uint8 colour = GB(value, 0, 8);
|
||||||
if (colour >= PALETTE_ANIM_START) {
|
if (colour >= PALETTE_ANIM_START) {
|
||||||
/* Update this pixel */
|
/* Update this pixel */
|
||||||
*dst = this->AdjustBrightness(LookupColourInPalette(colour), GB(*anim, 8, 8));
|
*dst = this->AdjustBrightness(LookupColourInPalette(colour), GB(value, 8, 8));
|
||||||
}
|
}
|
||||||
dst++;
|
dst++;
|
||||||
anim++;
|
anim++;
|
||||||
}
|
}
|
||||||
dst += _screen.pitch - this->anim_buf_width;
|
dst += pitch_offset;
|
||||||
anim += this->anim_buf_pitch - this->anim_buf_width;
|
anim += anim_pitch_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Make sure the backend redraws the whole screen */
|
/* Make sure the backend redraws the whole screen */
|
||||||
|
@ -513,10 +512,13 @@ void Blitter_32bppAnim::PostResize()
|
||||||
if (_screen.width != this->anim_buf_width || _screen.height != this->anim_buf_height ||
|
if (_screen.width != this->anim_buf_width || _screen.height != this->anim_buf_height ||
|
||||||
_screen.pitch != this->anim_buf_pitch) {
|
_screen.pitch != this->anim_buf_pitch) {
|
||||||
/* The size of the screen changed; we can assume we can wipe all data from our buffer */
|
/* The size of the screen changed; we can assume we can wipe all data from our buffer */
|
||||||
free(this->anim_buf);
|
free(this->anim_alloc);
|
||||||
this->anim_buf_width = _screen.width;
|
this->anim_buf_width = _screen.width;
|
||||||
this->anim_buf_height = _screen.height;
|
this->anim_buf_height = _screen.height;
|
||||||
this->anim_buf_pitch = _screen.pitch;
|
this->anim_buf_pitch = (_screen.width + 7) & ~7;
|
||||||
this->anim_buf = CallocT<uint16>(this->anim_buf_height * this->anim_buf_pitch);
|
this->anim_alloc = CallocT<uint16>(this->anim_buf_pitch * this->anim_buf_height + 8);
|
||||||
|
|
||||||
|
/* align buffer to next 16 byte boundary */
|
||||||
|
this->anim_buf = reinterpret_cast<uint16 *>((reinterpret_cast<uintptr_t>(this->anim_alloc) + 0xF) & (~0xF));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,14 +18,16 @@
|
||||||
class Blitter_32bppAnim : public Blitter_32bppOptimized {
|
class Blitter_32bppAnim : public Blitter_32bppOptimized {
|
||||||
protected:
|
protected:
|
||||||
uint16 *anim_buf; ///< In this buffer we keep track of the 8bpp indexes so we can do palette animation
|
uint16 *anim_buf; ///< In this buffer we keep track of the 8bpp indexes so we can do palette animation
|
||||||
|
void *anim_alloc; ///< The raw allocated buffer, not necessarily aligned correctly
|
||||||
int anim_buf_width; ///< The width of the animation buffer.
|
int anim_buf_width; ///< The width of the animation buffer.
|
||||||
int anim_buf_height; ///< The height of the animation buffer.
|
int anim_buf_height; ///< The height of the animation buffer.
|
||||||
int anim_buf_pitch; ///< The pitch of the animation buffer.
|
int anim_buf_pitch; ///< The pitch of the animation buffer (width rounded up to 16 byte boundary).
|
||||||
Palette palette; ///< The current palette.
|
Palette palette; ///< The current palette.
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Blitter_32bppAnim() :
|
Blitter_32bppAnim() :
|
||||||
anim_buf(NULL),
|
anim_buf(NULL),
|
||||||
|
anim_alloc(NULL),
|
||||||
anim_buf_width(0),
|
anim_buf_width(0),
|
||||||
anim_buf_height(0),
|
anim_buf_height(0),
|
||||||
anim_buf_pitch(0)
|
anim_buf_pitch(0)
|
||||||
|
@ -58,6 +60,15 @@ public:
|
||||||
return this->palette.palette[index];
|
return this->palette.palette[index];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline int ScreenToAnimOffset(const uint32 *video)
|
||||||
|
{
|
||||||
|
int raw_offset = video - (const uint32 *)_screen.dst_ptr;
|
||||||
|
if (_screen.pitch == this->anim_buf_pitch) return raw_offset;
|
||||||
|
int lines = raw_offset / _screen.pitch;
|
||||||
|
int across = raw_offset % _screen.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, ZoomLevel zoom);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,100 @@
|
||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of OpenTTD.
|
||||||
|
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||||
|
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @file 32bpp_anim.cpp Implementation of a partially SSSE2 32bpp blitter with animation support. */
|
||||||
|
|
||||||
|
#ifdef WITH_SSE
|
||||||
|
|
||||||
|
#include "../stdafx.h"
|
||||||
|
#include "../video/video_driver.hpp"
|
||||||
|
#include "32bpp_anim_sse2.hpp"
|
||||||
|
#include "32bpp_sse_func.hpp"
|
||||||
|
|
||||||
|
#include "../safeguards.h"
|
||||||
|
|
||||||
|
/** Instantiation of the partially SSSE2 32bpp with animation blitter factory. */
|
||||||
|
static FBlitter_32bppSSE2_Anim iFBlitter_32bppSSE2_Anim;
|
||||||
|
|
||||||
|
void Blitter_32bppSSE2_Anim::PaletteAnimate(const Palette &palette)
|
||||||
|
{
|
||||||
|
assert(!_screen_disable_anim);
|
||||||
|
|
||||||
|
this->palette = palette;
|
||||||
|
/* If first_dirty is 0, it is for 8bpp indication to send the new
|
||||||
|
* palette. However, only the animation colours might possibly change.
|
||||||
|
* Especially when going between toyland and non-toyland. */
|
||||||
|
assert(this->palette.first_dirty == PALETTE_ANIM_START || this->palette.first_dirty == 0);
|
||||||
|
|
||||||
|
const uint16 *anim = this->anim_buf;
|
||||||
|
Colour *dst = (Colour *)_screen.dst_ptr;
|
||||||
|
|
||||||
|
bool screen_dirty = false;
|
||||||
|
|
||||||
|
/* Let's walk the anim buffer and try to find the pixels */
|
||||||
|
const int width = this->anim_buf_width;
|
||||||
|
const int screen_pitch = _screen.pitch;
|
||||||
|
const int anim_pitch = this->anim_buf_pitch;
|
||||||
|
__m128i anim_cmp = _mm_set1_epi16(PALETTE_ANIM_START - 1);
|
||||||
|
__m128i brightness_cmp = _mm_set1_epi16(Blitter_32bppBase::DEFAULT_BRIGHTNESS);
|
||||||
|
__m128i colour_mask = _mm_set1_epi16(0xFF);
|
||||||
|
for (int y = this->anim_buf_height; y != 0 ; y--) {
|
||||||
|
Colour *next_dst_ln = dst + screen_pitch;
|
||||||
|
const uint16 *next_anim_ln = anim + anim_pitch;
|
||||||
|
int x = width;
|
||||||
|
while (x > 0) {
|
||||||
|
__m128i data = _mm_load_si128((const __m128i *) anim);
|
||||||
|
|
||||||
|
/* low bytes only, shifted into high positions */
|
||||||
|
__m128i colour_data = _mm_and_si128(data, colour_mask);
|
||||||
|
|
||||||
|
/* test if any colour >= PALETTE_ANIM_START */
|
||||||
|
int colour_cmp_result = _mm_movemask_epi8(_mm_cmpgt_epi16(colour_data, anim_cmp));
|
||||||
|
if (colour_cmp_result) {
|
||||||
|
/* test if any brightness is unexpected */
|
||||||
|
if (x < 8 || colour_cmp_result != 0xFFFF ||
|
||||||
|
_mm_movemask_epi8(_mm_cmpeq_epi16(_mm_srli_epi16(data, 8), brightness_cmp)) != 0xFFFF) {
|
||||||
|
/* slow path: < 8 pixels left or unexpected brightnesses */
|
||||||
|
for (int z = min<int>(x, 8); z != 0 ; z--) {
|
||||||
|
int value = _mm_extract_epi16(data, 0);
|
||||||
|
uint8 colour = GB(value, 0, 8);
|
||||||
|
if (colour >= PALETTE_ANIM_START) {
|
||||||
|
/* Update this pixel */
|
||||||
|
*dst = AdjustBrightneSSE(LookupColourInPalette(colour), GB(value, 8, 8));
|
||||||
|
screen_dirty = true;
|
||||||
|
}
|
||||||
|
data = _mm_srli_si128(data, 2);
|
||||||
|
dst++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* medium path: 8 pixels to animate all of expected brightnesses */
|
||||||
|
for (int z = 0; z < 8; z++) {
|
||||||
|
*dst = LookupColourInPalette(_mm_extract_epi16(colour_data, 0));
|
||||||
|
colour_data = _mm_srli_si128(colour_data, 2);
|
||||||
|
dst++;
|
||||||
|
}
|
||||||
|
screen_dirty = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
/* fast path, no animation */
|
||||||
|
dst += 8;
|
||||||
|
}
|
||||||
|
anim += 8;
|
||||||
|
x -= 8;
|
||||||
|
}
|
||||||
|
dst = next_dst_ln;
|
||||||
|
anim = next_anim_ln;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (screen_dirty) {
|
||||||
|
/* Make sure the backend redraws the whole screen */
|
||||||
|
VideoDriver::GetInstance()->MakeDirty(0, 0, _screen.width, _screen.height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* WITH_SSE */
|
|
@ -0,0 +1,43 @@
|
||||||
|
/* $Id$ */
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of OpenTTD.
|
||||||
|
* OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
|
||||||
|
* OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||||
|
* See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @file 32bpp_anim.hpp A partially SSE2 32 bpp blitter with animation support. */
|
||||||
|
|
||||||
|
#ifndef BLITTER_32BPP_SSE2_ANIM_HPP
|
||||||
|
#define BLITTER_32BPP_SSE2_ANIM_HPP
|
||||||
|
|
||||||
|
#ifdef WITH_SSE
|
||||||
|
|
||||||
|
#ifndef SSE_VERSION
|
||||||
|
#define SSE_VERSION 2
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef FULL_ANIMATION
|
||||||
|
#define FULL_ANIMATION 1
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "32bpp_anim.hpp"
|
||||||
|
#include "32bpp_sse2.hpp"
|
||||||
|
|
||||||
|
/** A partially 32 bpp blitter with palette animation. */
|
||||||
|
class Blitter_32bppSSE2_Anim : public Blitter_32bppAnim {
|
||||||
|
public:
|
||||||
|
/* virtual */ void PaletteAnimate(const Palette &palette);
|
||||||
|
/* virtual */ const char *GetName() { return "32bpp-sse2-anim"; }
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Factory for the partially 32bpp blitter with animation. */
|
||||||
|
class FBlitter_32bppSSE2_Anim : public BlitterFactory {
|
||||||
|
public:
|
||||||
|
FBlitter_32bppSSE2_Anim() : BlitterFactory("32bpp-sse2-anim", "32bpp partially SSE2 Animation Blitter (palette animation)", HasCPUIDFlag(1, 3, 26)) {}
|
||||||
|
/* virtual */ Blitter *CreateInstance() { return new Blitter_32bppSSE2_Anim(); }
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* WITH_SSE */
|
||||||
|
#endif /* BLITTER_32BPP_ANIM_HPP */
|
|
@ -35,8 +35,7 @@ inline void Blitter_32bppSSE4_Anim::Draw(const Blitter::BlitterParams *bp, ZoomL
|
||||||
{
|
{
|
||||||
const byte * const remap = bp->remap;
|
const byte * 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;
|
||||||
assert(_screen.pitch == this->anim_buf_pitch); // precondition for translating 'bp->dst' into an 'anim_buf' offset below.
|
uint16 *anim_line = this->anim_buf + this->ScreenToAnimOffset((uint32 *)bp->dst) + bp->top * this->anim_buf_pitch + bp->left;
|
||||||
uint16 *anim_line = this->anim_buf + ((uint32 *)bp->dst - (uint32 *)_screen.dst_ptr) + bp->top * this->anim_buf_pitch + bp->left;
|
|
||||||
int effective_width = bp->width;
|
int effective_width = bp->width;
|
||||||
|
|
||||||
/* Find where to start reading in the source sprite. */
|
/* Find where to start reading in the source sprite. */
|
||||||
|
|
|
@ -23,13 +23,14 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "32bpp_anim.hpp"
|
#include "32bpp_anim.hpp"
|
||||||
|
#include "32bpp_anim_sse2.hpp"
|
||||||
#include "32bpp_sse4.hpp"
|
#include "32bpp_sse4.hpp"
|
||||||
|
|
||||||
#undef MARGIN_NORMAL_THRESHOLD
|
#undef MARGIN_NORMAL_THRESHOLD
|
||||||
#define MARGIN_NORMAL_THRESHOLD 4
|
#define MARGIN_NORMAL_THRESHOLD 4
|
||||||
|
|
||||||
/** The SSE4 32 bpp blitter with palette animation. */
|
/** The SSE4 32 bpp blitter with palette animation. */
|
||||||
class Blitter_32bppSSE4_Anim FINAL : public Blitter_32bppAnim, public Blitter_32bppSSE_Base {
|
class Blitter_32bppSSE4_Anim FINAL : public Blitter_32bppSSE2_Anim, public Blitter_32bppSSE_Base {
|
||||||
private:
|
private:
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -143,6 +143,36 @@ void Blitter_32bppBase::PaletteAnimate(const Palette &palette)
|
||||||
/* By default, 32bpp doesn't have palette animation */
|
/* By default, 32bpp doesn't have palette animation */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Colour Blitter_32bppBase::ReallyAdjustBrightness(Colour colour, uint8 brightness)
|
||||||
|
{
|
||||||
|
assert(DEFAULT_BRIGHTNESS == 1 << 7);
|
||||||
|
|
||||||
|
uint64 combined = (((uint64) colour.r) << 32) | (((uint64) colour.g) << 16) | ((uint64) colour.b);
|
||||||
|
combined *= brightness;
|
||||||
|
|
||||||
|
uint16 r = GB(combined, 39, 9);
|
||||||
|
uint16 g = GB(combined, 23, 9);
|
||||||
|
uint16 b = GB(combined, 7, 9);
|
||||||
|
|
||||||
|
if ((combined & 0x800080008000L) == 0L) {
|
||||||
|
return Colour(r, g, b, colour.a);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16 ob = 0;
|
||||||
|
/* Sum overbright */
|
||||||
|
if (r > 255) ob += r - 255;
|
||||||
|
if (g > 255) ob += g - 255;
|
||||||
|
if (b > 255) ob += b - 255;
|
||||||
|
|
||||||
|
/* Reduce overbright strength */
|
||||||
|
ob /= 2;
|
||||||
|
return Colour(
|
||||||
|
r >= 255 ? 255 : min(r + ob * (255 - r) / 256, 255),
|
||||||
|
g >= 255 ? 255 : min(g + ob * (255 - g) / 256, 255),
|
||||||
|
b >= 255 ? 255 : min(b + ob * (255 - b) / 256, 255),
|
||||||
|
colour.a);
|
||||||
|
}
|
||||||
|
|
||||||
Blitter::PaletteAnimation Blitter_32bppBase::UsePaletteAnimation()
|
Blitter::PaletteAnimation Blitter_32bppBase::UsePaletteAnimation()
|
||||||
{
|
{
|
||||||
return Blitter::PALETTE_ANIMATION_NONE;
|
return Blitter::PALETTE_ANIMATION_NONE;
|
||||||
|
|
|
@ -146,30 +146,14 @@ public:
|
||||||
|
|
||||||
static const int DEFAULT_BRIGHTNESS = 128;
|
static const int DEFAULT_BRIGHTNESS = 128;
|
||||||
|
|
||||||
|
static Colour ReallyAdjustBrightness(Colour colour, uint8 brightness);
|
||||||
|
|
||||||
static inline Colour AdjustBrightness(Colour colour, uint8 brightness)
|
static inline Colour AdjustBrightness(Colour colour, uint8 brightness)
|
||||||
{
|
{
|
||||||
/* Shortcut for normal brightness */
|
/* Shortcut for normal brightness */
|
||||||
if (brightness == DEFAULT_BRIGHTNESS) return colour;
|
if (brightness == DEFAULT_BRIGHTNESS) return colour;
|
||||||
|
|
||||||
uint16 ob = 0;
|
return ReallyAdjustBrightness(colour, brightness);
|
||||||
uint16 r = colour.r * brightness / DEFAULT_BRIGHTNESS;
|
|
||||||
uint16 g = colour.g * brightness / DEFAULT_BRIGHTNESS;
|
|
||||||
uint16 b = colour.b * brightness / DEFAULT_BRIGHTNESS;
|
|
||||||
|
|
||||||
/* Sum overbright */
|
|
||||||
if (r > 255) ob += r - 255;
|
|
||||||
if (g > 255) ob += g - 255;
|
|
||||||
if (b > 255) ob += b - 255;
|
|
||||||
|
|
||||||
if (ob == 0) return Colour(r, g, b, colour.a);
|
|
||||||
|
|
||||||
/* Reduce overbright strength */
|
|
||||||
ob /= 2;
|
|
||||||
return Colour(
|
|
||||||
r >= 255 ? 255 : min(r + ob * (255 - r) / 256, 255),
|
|
||||||
g >= 255 ? 255 : min(g + ob * (255 - g) / 256, 255),
|
|
||||||
b >= 255 ? 255 : min(b + ob * (255 - b) / 256, 255),
|
|
||||||
colour.a);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -284,6 +284,9 @@ static bool SwitchNewGRFBlitter()
|
||||||
#endif
|
#endif
|
||||||
{ "8bpp-optimized", 2, 8, 8, 8, 8 },
|
{ "8bpp-optimized", 2, 8, 8, 8, 8 },
|
||||||
{ "32bpp-optimized", 0, 8, 32, 8, 32 },
|
{ "32bpp-optimized", 0, 8, 32, 8, 32 },
|
||||||
|
#ifdef WITH_SSE
|
||||||
|
{ "32bpp-sse2-anim", 1, 8, 32, 8, 32 },
|
||||||
|
#endif
|
||||||
{ "32bpp-anim", 1, 8, 32, 8, 32 },
|
{ "32bpp-anim", 1, 8, 32, 8, 32 },
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue