diff options
-rw-r--r-- | projects/openttd_vs100.vcxproj | 1 | ||||
-rw-r--r-- | projects/openttd_vs100.vcxproj.filters | 3 | ||||
-rw-r--r-- | projects/openttd_vs80.vcproj | 4 | ||||
-rw-r--r-- | projects/openttd_vs90.vcproj | 4 | ||||
-rw-r--r-- | source.list | 1 | ||||
-rw-r--r-- | src/blitter/32bpp_anim_sse4.cpp | 1 | ||||
-rw-r--r-- | src/blitter/32bpp_anim_sse4.hpp | 5 | ||||
-rw-r--r-- | src/blitter/32bpp_sse2.cpp | 158 | ||||
-rw-r--r-- | src/blitter/32bpp_sse2.hpp | 7 | ||||
-rw-r--r-- | src/blitter/32bpp_sse4.cpp | 201 | ||||
-rw-r--r-- | src/blitter/32bpp_sse4.hpp | 5 | ||||
-rw-r--r-- | src/blitter/32bpp_sse_func.hpp | 281 | ||||
-rw-r--r-- | src/blitter/32bpp_sse_type.h | 56 | ||||
-rw-r--r-- | src/blitter/32bpp_ssse3.cpp | 201 | ||||
-rw-r--r-- | src/blitter/32bpp_ssse3.hpp | 5 |
15 files changed, 333 insertions, 600 deletions
diff --git a/projects/openttd_vs100.vcxproj b/projects/openttd_vs100.vcxproj index ba10f2794..d93f31927 100644 --- a/projects/openttd_vs100.vcxproj +++ b/projects/openttd_vs100.vcxproj @@ -1124,6 +1124,7 @@ <ClCompile Include="..\src\blitter\32bpp_simple.cpp" /> <ClInclude Include="..\src\blitter\32bpp_simple.hpp" /> <ClInclude Include="..\src\blitter\32bpp_sse_func.hpp" /> + <ClInclude Include="..\src\blitter\32bpp_sse_type.h" /> <ClCompile Include="..\src\blitter\32bpp_sse2.cpp" /> <ClInclude Include="..\src\blitter\32bpp_sse2.hpp" /> <ClCompile Include="..\src\blitter\32bpp_sse4.cpp" /> diff --git a/projects/openttd_vs100.vcxproj.filters b/projects/openttd_vs100.vcxproj.filters index 613b1a3e1..8cce80374 100644 --- a/projects/openttd_vs100.vcxproj.filters +++ b/projects/openttd_vs100.vcxproj.filters @@ -2601,6 +2601,9 @@ <ClInclude Include="..\src\blitter\32bpp_sse_func.hpp"> <Filter>Blitters</Filter> </ClInclude> + <ClInclude Include="..\src\blitter\32bpp_sse_type.h"> + <Filter>Blitters</Filter> + </ClInclude> <ClCompile Include="..\src\blitter\32bpp_sse2.cpp"> <Filter>Blitters</Filter> </ClCompile> diff --git a/projects/openttd_vs80.vcproj b/projects/openttd_vs80.vcproj index 7dde340e9..787f3a4e0 100644 --- a/projects/openttd_vs80.vcproj +++ b/projects/openttd_vs80.vcproj @@ -3839,6 +3839,10 @@ > </File> <File + RelativePath=".\..\src\blitter\32bpp_sse_type.h" + > + </File> + <File RelativePath=".\..\src\blitter\32bpp_sse2.cpp" > </File> diff --git a/projects/openttd_vs90.vcproj b/projects/openttd_vs90.vcproj index 3f14faacb..a433653a1 100644 --- a/projects/openttd_vs90.vcproj +++ b/projects/openttd_vs90.vcproj @@ -3836,6 +3836,10 @@ > </File> <File + RelativePath=".\..\src\blitter\32bpp_sse_type.h" + > + </File> + <File RelativePath=".\..\src\blitter\32bpp_sse2.cpp" > </File> diff --git a/source.list b/source.list index 04bc67d55..c8aa11bf3 100644 --- a/source.list +++ b/source.list @@ -913,6 +913,7 @@ blitter/32bpp_simple.cpp blitter/32bpp_simple.hpp #if SSE blitter/32bpp_sse_func.hpp +blitter/32bpp_sse_type.h blitter/32bpp_sse2.cpp blitter/32bpp_sse2.hpp blitter/32bpp_sse4.cpp diff --git a/src/blitter/32bpp_anim_sse4.cpp b/src/blitter/32bpp_anim_sse4.cpp index ae1b34d69..eb74b959f 100644 --- a/src/blitter/32bpp_anim_sse4.cpp +++ b/src/blitter/32bpp_anim_sse4.cpp @@ -15,6 +15,7 @@ #include "../video/video_driver.hpp" #include "../table/sprites.h" #include "32bpp_anim_sse4.hpp" +#include "32bpp_sse_func.hpp" /** Instantiation of the SSE4 32bpp blitter factory. */ static FBlitter_32bppSSE4_Anim iFBlitter_32bppSSE4_Anim; diff --git a/src/blitter/32bpp_anim_sse4.hpp b/src/blitter/32bpp_anim_sse4.hpp index 9a3f93ca8..096ee62e0 100644 --- a/src/blitter/32bpp_anim_sse4.hpp +++ b/src/blitter/32bpp_anim_sse4.hpp @@ -17,6 +17,11 @@ #ifndef SSE_VERSION #define SSE_VERSION 4 #endif + +#ifndef FULL_ANIMATION +#define FULL_ANIMATION 1 +#endif + #include "32bpp_anim.hpp" #include "32bpp_sse4.hpp" diff --git a/src/blitter/32bpp_sse2.cpp b/src/blitter/32bpp_sse2.cpp index 49fb28c35..2f1dc3828 100644 --- a/src/blitter/32bpp_sse2.cpp +++ b/src/blitter/32bpp_sse2.cpp @@ -15,167 +15,11 @@ #include "../zoom_func.h" #include "../settings_type.h" #include "32bpp_sse2.hpp" +#include "32bpp_sse_func.hpp" /** Instantiation of the SSE2 32bpp blitter factory. */ static FBlitter_32bppSSE2 iFBlitter_32bppSSE2; -/** - * Draws a sprite to a (screen) buffer. It is templated to allow faster operation. - * - * @tparam mode blitter mode - * @param bp further blitting parameters - * @param zoom zoom level at which we are drawing - */ -IGNORE_UNINITIALIZED_WARNING_START -template <BlitterMode mode, Blitter_32bppSSE2::ReadMode read_mode, Blitter_32bppSSE2::BlockType bt_last> -inline void Blitter_32bppSSE2::Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom) -{ - const byte *remap = bp->remap; - Colour *dst_line = (Colour *) bp->dst + bp->top * bp->pitch + bp->left; - int effective_width = bp->width; - - /* Find where to start reading in the source sprite */ - const SpriteData * const sd = (const SpriteData *) bp->sprite; - const SpriteInfo * const si = &sd->infos[zoom]; - const MapValue *src_mv_line = (const MapValue *) &sd->data[si->mv_offset] + bp->skip_top * si->sprite_width; - const Colour *src_rgba_line = (const Colour *) ((const byte *) &sd->data[si->sprite_offset] + bp->skip_top * si->sprite_line_size); - - if (read_mode != RM_WITH_MARGIN) { - src_rgba_line += bp->skip_left; - src_mv_line += bp->skip_left; - } - const MapValue *src_mv = src_mv_line; - - /* Load these variables into register before loop. */ - const __m128i clear_hi = CLEAR_HIGH_BYTE_MASK; - const __m128i tr_nom_base = TRANSPARENT_NOM_BASE; - - for (int y = bp->height; y != 0; y--) { - Colour *dst = dst_line; - const Colour *src = src_rgba_line + META_LENGTH; - if (mode == BM_COLOUR_REMAP) src_mv = src_mv_line; - - if (read_mode == RM_WITH_MARGIN) { - assert(bt_last == BT_NONE); // or you must ensure block type is preserved - src += src_rgba_line[0].data; - dst += src_rgba_line[0].data; - if (mode == BM_COLOUR_REMAP) src_mv += src_rgba_line[0].data; - const int width_diff = si->sprite_width - bp->width; - effective_width = bp->width - (int) src_rgba_line[0].data; - const int delta_diff = (int) src_rgba_line[1].data - width_diff; - const int new_width = effective_width - delta_diff; - effective_width = delta_diff > 0 ? new_width : effective_width; - if (effective_width <= 0) goto next_line; - } - - switch (mode) { - default: - for (uint x = (uint) effective_width / 2; x > 0; x--) { - __m128i srcABCD = _mm_loadl_epi64((const __m128i*) src); - __m128i dstABCD = _mm_loadl_epi64((__m128i*) dst); - _mm_storel_epi64((__m128i*) dst, AlphaBlendTwoPixels(srcABCD, dstABCD, clear_hi, clear_hi)); - src += 2; - dst += 2; - } - - if ((bt_last == BT_NONE && effective_width & 1) || bt_last == BT_ODD) { - __m128i srcABCD = _mm_cvtsi32_si128(src->data); - __m128i dstABCD = _mm_cvtsi32_si128(dst->data); - dst->data = _mm_cvtsi128_si32(AlphaBlendTwoPixels(srcABCD, dstABCD, clear_hi, clear_hi)); - } - break; - - case BM_COLOUR_REMAP: - for (uint x = (uint) effective_width; x != 0; x--) { - /* In case the m-channel is zero, do not remap this pixel in any way. */ - __m128i srcABCD; - if (src_mv->m) { - const uint r = remap[src_mv->m]; - if (r != 0) { - Colour remapped_colour = AdjustBrightneSSE(this->LookupColourInPalette(r), src_mv->v); - if (src->a == 255) { - *dst = remapped_colour; - } else { - remapped_colour.a = src->a; - srcABCD = _mm_cvtsi32_si128(remapped_colour.data); - goto bmcr_alpha_blend_single; - } - } - } else { - srcABCD = _mm_cvtsi32_si128(src->data); - if (src->a < 255) { -bmcr_alpha_blend_single: - __m128i dstABCD = _mm_cvtsi32_si128(dst->data); - srcABCD = AlphaBlendTwoPixels(srcABCD, dstABCD, clear_hi, clear_hi); - } - dst->data = _mm_cvtsi128_si32(srcABCD); - } - src_mv++; - dst++; - src++; - } - break; - - case BM_TRANSPARENT: - /* Make the current colour a bit more black, so it looks like this image is transparent. */ - for (uint x = (uint) bp->width / 2; x > 0; x--) { - __m128i srcABCD = _mm_loadl_epi64((const __m128i*) src); - __m128i dstABCD = _mm_loadl_epi64((__m128i*) dst); - _mm_storel_epi64((__m128i *) dst, DarkenTwoPixels(srcABCD, dstABCD, tr_nom_base, tr_nom_base)); - src += 2; - dst += 2; - } - - if ((bt_last == BT_NONE && bp->width & 1) || bt_last == BT_ODD) { - __m128i srcABCD = _mm_cvtsi32_si128(src->data); - __m128i dstABCD = _mm_cvtsi32_si128(dst->data); - dst->data = _mm_cvtsi128_si32(DarkenTwoPixels(srcABCD, dstABCD, tr_nom_base, tr_nom_base)); - } - break; - } - -next_line: - if (mode == BM_COLOUR_REMAP) src_mv_line += si->sprite_width; - src_rgba_line = (const Colour*) ((const byte*) src_rgba_line + si->sprite_line_size); - dst_line += bp->pitch; - } -} -IGNORE_UNINITIALIZED_WARNING_STOP - -/** - * Draws a sprite to a (screen) buffer. Calls adequate templated function. - * - * @param bp further blitting parameters - * @param mode blitter mode - * @param zoom zoom level at which we are drawing - */ -void Blitter_32bppSSE2::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom) -{ - switch (mode) { - case BM_NORMAL: { - if (bp->skip_left != 0 || bp->width <= MARGIN_NORMAL_THRESHOLD) { - const BlockType bt_last = (BlockType) (bp->width & 1); - switch (bt_last) { - case BT_EVEN: Draw<BM_NORMAL, RM_WITH_SKIP, BT_EVEN>(bp, zoom); return; - case BT_ODD: Draw<BM_NORMAL, RM_WITH_SKIP, BT_ODD>(bp, zoom); return; - default: NOT_REACHED(); - } - } else { - Draw<BM_NORMAL, RM_WITH_MARGIN, BT_NONE>(bp, zoom); return; - } - break; - } - case BM_COLOUR_REMAP: - if (bp->skip_left != 0 || bp->width <= MARGIN_REMAP_THRESHOLD) { - Draw<BM_COLOUR_REMAP, RM_WITH_SKIP, BT_NONE>(bp, zoom); return; - } else { - Draw<BM_COLOUR_REMAP, RM_WITH_MARGIN, BT_NONE>(bp, zoom); return; - } - case BM_TRANSPARENT: Draw<BM_TRANSPARENT, RM_NONE, BT_NONE>(bp, zoom); return; - default: NOT_REACHED(); - } -} - Sprite *Blitter_32bppSSE_Base::Encode(const SpriteLoader::Sprite *sprite, AllocatorProc *allocator) { /* First uint32 of a line = the number of transparent pixels from the left. diff --git a/src/blitter/32bpp_sse2.hpp b/src/blitter/32bpp_sse2.hpp index 3bab0d752..3caf7ba76 100644 --- a/src/blitter/32bpp_sse2.hpp +++ b/src/blitter/32bpp_sse2.hpp @@ -17,7 +17,12 @@ #ifndef SSE_VERSION #define SSE_VERSION 2 #endif -#include "32bpp_sse_func.hpp" + +#ifndef FULL_ANIMATION +#define FULL_ANIMATION 0 +#endif + +#include "32bpp_sse_type.h" /** Base methods for 32bpp SSE blitters. */ class Blitter_32bppSSE_Base { diff --git a/src/blitter/32bpp_sse4.cpp b/src/blitter/32bpp_sse4.cpp index 1403d3659..dab0d8f3e 100644 --- a/src/blitter/32bpp_sse4.cpp +++ b/src/blitter/32bpp_sse4.cpp @@ -15,208 +15,9 @@ #include "../zoom_func.h" #include "../settings_type.h" #include "32bpp_sse4.hpp" +#include "32bpp_sse_func.hpp" /** Instantiation of the SSE4 32bpp blitter factory. */ static FBlitter_32bppSSE4 iFBlitter_32bppSSE4; -/** - * Draws a sprite to a (screen) buffer. It is templated to allow faster operation. - * - * @tparam mode blitter mode - * @param bp further blitting parameters - * @param zoom zoom level at which we are drawing - */ -IGNORE_UNINITIALIZED_WARNING_START -template <BlitterMode mode, Blitter_32bppSSE2::ReadMode read_mode, Blitter_32bppSSE2::BlockType bt_last> -inline void Blitter_32bppSSE4::Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom) -{ - const byte * const remap = bp->remap; - Colour *dst_line = (Colour *) bp->dst + bp->top * bp->pitch + bp->left; - int effective_width = bp->width; - - /* Find where to start reading in the source sprite. */ - const SpriteData * const sd = (const SpriteData *) bp->sprite; - const SpriteInfo * const si = &sd->infos[zoom]; - const MapValue *src_mv_line = (const MapValue *) &sd->data[si->mv_offset] + bp->skip_top * si->sprite_width; - const Colour *src_rgba_line = (const Colour *) ((const byte *) &sd->data[si->sprite_offset] + bp->skip_top * si->sprite_line_size); - - if (read_mode != RM_WITH_MARGIN) { - src_rgba_line += bp->skip_left; - src_mv_line += bp->skip_left; - } - const MapValue *src_mv = src_mv_line; - - /* Load these variables into register before loop. */ - const __m128i a_cm = ALPHA_CONTROL_MASK; - const __m128i pack_low_cm = PACK_LOW_CONTROL_MASK; - const __m128i tr_nom_base = TRANSPARENT_NOM_BASE; - - for (int y = bp->height; y != 0; y--) { - Colour *dst = dst_line; - const Colour *src = src_rgba_line + META_LENGTH; - if (mode == BM_COLOUR_REMAP) src_mv = src_mv_line; - - if (read_mode == RM_WITH_MARGIN) { - assert(bt_last == BT_NONE); // or you must ensure block type is preserved - src += src_rgba_line[0].data; - dst += src_rgba_line[0].data; - if (mode == BM_COLOUR_REMAP) src_mv += src_rgba_line[0].data; - const int width_diff = si->sprite_width - bp->width; - effective_width = bp->width - (int) src_rgba_line[0].data; - const int delta_diff = (int) src_rgba_line[1].data - width_diff; - const int new_width = effective_width - delta_diff; - effective_width = delta_diff > 0 ? new_width : effective_width; - if (effective_width <= 0) goto next_line; - } - - switch (mode) { - default: - for (uint x = (uint) effective_width / 2; x > 0; x--) { - __m128i srcABCD = _mm_loadl_epi64((const __m128i*) src); - __m128i dstABCD = _mm_loadl_epi64((__m128i*) dst); - _mm_storel_epi64((__m128i*) dst, AlphaBlendTwoPixels(srcABCD, dstABCD, a_cm, pack_low_cm)); - src += 2; - dst += 2; - } - - if ((bt_last == BT_NONE && effective_width & 1) || bt_last == BT_ODD) { - __m128i srcABCD = _mm_cvtsi32_si128(src->data); - __m128i dstABCD = _mm_cvtsi32_si128(dst->data); - dst->data = _mm_cvtsi128_si32(AlphaBlendTwoPixels(srcABCD, dstABCD, a_cm, pack_low_cm)); - } - break; - - case BM_COLOUR_REMAP: - for (uint x = (uint) effective_width / 2; x > 0; x--) { - __m128i srcABCD = _mm_loadl_epi64((const __m128i*) src); - __m128i dstABCD = _mm_loadl_epi64((__m128i*) dst); - uint32 mvX2 = *((uint32 *) const_cast<MapValue *>(src_mv)); - - /* Remap colours. */ - if (mvX2 & 0x00FF00FF) { - #define CMOV_REMAP(m_colour, m_src, m_m) \ - /* Written so the compiler uses CMOV. */ \ - Colour m_colour = 0; \ - { \ - const Colour srcm = (Colour) (m_src); \ - const uint m = (byte) (m_m); \ - const uint r = remap[m]; \ - const Colour cmap = (this->LookupColourInPalette(r).data & 0x00FFFFFF) | (srcm.data & 0xFF000000); \ - m_colour = r == 0 ? m_colour : cmap; \ - m_colour = m != 0 ? m_colour : srcm; \ - } -#ifdef _SQ64 - uint64 srcs = _mm_cvtsi128_si64(srcABCD); - uint64 remapped_src = 0; - CMOV_REMAP(c0, srcs, mvX2); - remapped_src = c0.data; - CMOV_REMAP(c1, srcs >> 32, mvX2 >> 16); - remapped_src |= (uint64) c1.data << 32; - srcABCD = _mm_cvtsi64_si128(remapped_src); -#else - Colour remapped_src[2]; - CMOV_REMAP(c0, _mm_cvtsi128_si32(srcABCD), mvX2); - remapped_src[0] = c0.data; - CMOV_REMAP(c1, src[1], mvX2 >> 16); - remapped_src[1] = c1.data; - srcABCD = _mm_loadl_epi64((__m128i*) &remapped_src); -#endif - - if ((mvX2 & 0xFF00FF00) != 0x80008000) srcABCD = AdjustBrightnessOfTwoPixels(srcABCD, mvX2); - } - - /* Blend colours. */ - _mm_storel_epi64((__m128i *) dst, AlphaBlendTwoPixels(srcABCD, dstABCD, a_cm, pack_low_cm)); - dst += 2; - src += 2; - src_mv += 2; - } - - if ((bt_last == BT_NONE && effective_width & 1) || bt_last == BT_ODD) { - /* In case the m-channel is zero, do not remap this pixel in any way. */ - __m128i srcABCD; - if (src_mv->m) { - const uint r = remap[src_mv->m]; - if (r != 0) { - Colour remapped_colour = AdjustBrightneSSE(this->LookupColourInPalette(r), src_mv->v); - if (src->a == 255) { - *dst = remapped_colour; - } else { - remapped_colour.a = src->a; - srcABCD = _mm_cvtsi32_si128(remapped_colour.data); - goto bmcr_alpha_blend_single; - } - } - } else { - srcABCD = _mm_cvtsi32_si128(src->data); - if (src->a < 255) { -bmcr_alpha_blend_single: - __m128i dstABCD = _mm_cvtsi32_si128(dst->data); - srcABCD = AlphaBlendTwoPixels(srcABCD, dstABCD, a_cm, pack_low_cm); - } - dst->data = _mm_cvtsi128_si32(srcABCD); - } - } - break; - - case BM_TRANSPARENT: - /* Make the current colour a bit more black, so it looks like this image is transparent. */ - for (uint x = (uint) bp->width / 2; x > 0; x--) { - __m128i srcABCD = _mm_loadl_epi64((const __m128i*) src); - __m128i dstABCD = _mm_loadl_epi64((__m128i*) dst); - _mm_storel_epi64((__m128i *) dst, DarkenTwoPixels(srcABCD, dstABCD, a_cm, tr_nom_base)); - src += 2; - dst += 2; - } - - if ((bt_last == BT_NONE && bp->width & 1) || bt_last == BT_ODD) { - __m128i srcABCD = _mm_cvtsi32_si128(src->data); - __m128i dstABCD = _mm_cvtsi32_si128(dst->data); - dst->data = _mm_cvtsi128_si32(DarkenTwoPixels(srcABCD, dstABCD, a_cm, tr_nom_base)); - } - break; - } - -next_line: - if (mode == BM_COLOUR_REMAP) src_mv_line += si->sprite_width; - src_rgba_line = (const Colour*) ((const byte*) src_rgba_line + si->sprite_line_size); - dst_line += bp->pitch; - } -} -IGNORE_UNINITIALIZED_WARNING_STOP - -/** - * Draws a sprite to a (screen) buffer. Calls adequate templated function. - * - * @param bp further blitting parameters - * @param mode blitter mode - * @param zoom zoom level at which we are drawing - */ -void Blitter_32bppSSE4::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom) -{ - switch (mode) { - case BM_NORMAL: { - if (bp->skip_left != 0 || bp->width <= MARGIN_NORMAL_THRESHOLD) { - const BlockType bt_last = (BlockType) (bp->width & 1); - switch (bt_last) { - case BT_EVEN: Draw<BM_NORMAL, RM_WITH_SKIP, BT_EVEN>(bp, zoom); return; - case BT_ODD: Draw<BM_NORMAL, RM_WITH_SKIP, BT_ODD>(bp, zoom); return; - default: NOT_REACHED(); - } - } else { - Draw<BM_NORMAL, RM_WITH_MARGIN, BT_NONE>(bp, zoom); return; - } - break; - } - case BM_COLOUR_REMAP: - if (bp->skip_left != 0 || bp->width <= MARGIN_REMAP_THRESHOLD) { - Draw<BM_COLOUR_REMAP, RM_WITH_SKIP, BT_NONE>(bp, zoom); return; - } else { - Draw<BM_COLOUR_REMAP, RM_WITH_MARGIN, BT_NONE>(bp, zoom); return; - } - case BM_TRANSPARENT: Draw<BM_TRANSPARENT, RM_NONE, BT_NONE>(bp, zoom); return; - default: NOT_REACHED(); - } -} - #endif /* WITH_SSE */ diff --git a/src/blitter/32bpp_sse4.hpp b/src/blitter/32bpp_sse4.hpp index 7a3332d87..38f00920c 100644 --- a/src/blitter/32bpp_sse4.hpp +++ b/src/blitter/32bpp_sse4.hpp @@ -17,6 +17,11 @@ #ifndef SSE_VERSION #define SSE_VERSION 4 #endif + +#ifndef FULL_ANIMATION +#define FULL_ANIMATION 0 +#endif + #include "32bpp_ssse3.hpp" /** The SSE4 32 bpp blitter (without palette animation). */ diff --git a/src/blitter/32bpp_sse_func.hpp b/src/blitter/32bpp_sse_func.hpp index d6febcf49..b6a61f9c7 100644 --- a/src/blitter/32bpp_sse_func.hpp +++ b/src/blitter/32bpp_sse_func.hpp @@ -7,51 +7,13 @@ * 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_sse_base.hpp Functions related to SSE 32 bpp blitter. */ +/** @file 32bpp_sse_func.hpp Functions related to SSE 32 bpp blitter. */ -#ifndef BLITTER_32BPP_SSE_BASE_HPP -#define BLITTER_32BPP_SSE_BASE_HPP +#ifndef BLITTER_32BPP_SSE_FUNC_HPP +#define BLITTER_32BPP_SSE_FUNC_HPP #ifdef WITH_SSE -#include "32bpp_simple.hpp" -#if (SSE_VERSION == 2) -#include <emmintrin.h> -#elif (SSE_VERSION == 3) -#include <tmmintrin.h> -#elif (SSE_VERSION == 4) -#include <smmintrin.h> -#endif - -#define META_LENGTH 2 ///< Number of uint32 inserted before each line of pixels in a sprite. -#define MARGIN_NORMAL_THRESHOLD (zoom == ZOOM_LVL_OUT_32X ? 8 : 4) ///< Minimum width to use margins with BM_NORMAL. -#define MARGIN_REMAP_THRESHOLD 4 ///< Minimum width to use margins with BM_COLOUR_REMAP. - -#ifdef _MSC_VER - #define ALIGN(n) __declspec(align(n)) -#else - #define ALIGN(n) __attribute__ ((aligned (n))) -#endif - -typedef union ALIGN(16) um128i { - __m128i m128i; - uint8 m128i_u8[16]; - uint16 m128i_u16[8]; - uint32 m128i_u32[4]; - uint64 m128i_u64[2]; -} um128i; - -#define CLEAR_HIGH_BYTE_MASK _mm_setr_epi8(-1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0) -#define ALPHA_CONTROL_MASK _mm_setr_epi8( 6, 7, 6, 7, 6, 7, -1, -1, 14, 15, 14, 15, 14, 15, -1, -1) -#define PACK_LOW_CONTROL_MASK _mm_setr_epi8( 0, 2, 4, -1, 8, 10, 12, -1, -1, -1, -1, -1, -1, -1, -1, -1) -#define PACK_HIGH_CONTROL_MASK _mm_setr_epi8(-1, -1, -1, -1, -1, -1, -1, -1, 0, 2, 4, -1, 8, 10, 12, -1) -#define BRIGHTNESS_LOW_CONTROL_MASK _mm_setr_epi8( 1, 2, 1, 2, 1, 2, 0, 2, 3, 2, 3, 2, 3, 2, 0, 2) -#define BRIGHTNESS_DIV_CLEANER _mm_setr_epi8(-1, 1, -1, 1, -1, 1, -1, 0, -1, 1, -1, 1, -1, 1, -1, 0) -#define OVERBRIGHT_PRESENCE_MASK _mm_setr_epi8( 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0) -#define OVERBRIGHT_VALUE_MASK _mm_setr_epi8(-1, 0, -1, 0, -1, 0, 0, 0, -1, 0, -1, 0, -1, 0, 0, 0) -#define OVERBRIGHT_CONTROL_MASK _mm_setr_epi8( 0, 1, 0, 1, 0, 1, 7, 7, 2, 3, 2, 3, 2, 3, 7, 7) -#define TRANSPARENT_NOM_BASE _mm_setr_epi16(256, 256, 256, 256, 256, 256, 256, 256) - static inline void InsertFirstUint32(const uint32 value, __m128i &into) { #if (SSE_VERSION >= 4) @@ -221,5 +183,240 @@ static inline __m128i AdjustBrightnessOfTwoPixels(__m128i from, uint32 brightnes #endif } +#if FULL_ANIMATION == 0 +/** + * Draws a sprite to a (screen) buffer. It is templated to allow faster operation. + * + * @tparam mode blitter mode + * @param bp further blitting parameters + * @param zoom zoom level at which we are drawing + */ +IGNORE_UNINITIALIZED_WARNING_START +template <BlitterMode mode, Blitter_32bppSSE2::ReadMode read_mode, Blitter_32bppSSE2::BlockType bt_last> +#if (SSE_VERSION == 2) +inline void Blitter_32bppSSE2::Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom) +#elif (SSE_VERSION == 3) +inline void Blitter_32bppSSSE3::Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom) +#elif (SSE_VERSION == 4) +inline void Blitter_32bppSSE4::Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom) +#endif +{ + const byte * const remap = bp->remap; + Colour *dst_line = (Colour *) bp->dst + bp->top * bp->pitch + bp->left; + int effective_width = bp->width; + + /* Find where to start reading in the source sprite. */ + const SpriteData * const sd = (const SpriteData *) bp->sprite; + const SpriteInfo * const si = &sd->infos[zoom]; + const MapValue *src_mv_line = (const MapValue *) &sd->data[si->mv_offset] + bp->skip_top * si->sprite_width; + const Colour *src_rgba_line = (const Colour *) ((const byte *) &sd->data[si->sprite_offset] + bp->skip_top * si->sprite_line_size); + + if (read_mode != RM_WITH_MARGIN) { + src_rgba_line += bp->skip_left; + src_mv_line += bp->skip_left; + } + const MapValue *src_mv = src_mv_line; + + /* Load these variables into register before loop. */ +#if (SSE_VERSION == 2) + const __m128i clear_hi = CLEAR_HIGH_BYTE_MASK; + #define ALPHA_BLEND_PARAM_1 clear_hi + #define ALPHA_BLEND_PARAM_2 clear_hi + #define DARKEN_PARAM_1 tr_nom_base + #define DARKEN_PARAM_2 tr_nom_base +#else + const __m128i a_cm = ALPHA_CONTROL_MASK; + const __m128i pack_low_cm = PACK_LOW_CONTROL_MASK; + #define ALPHA_BLEND_PARAM_1 a_cm + #define ALPHA_BLEND_PARAM_2 pack_low_cm + #define DARKEN_PARAM_1 a_cm + #define DARKEN_PARAM_2 tr_nom_base +#endif + const __m128i tr_nom_base = TRANSPARENT_NOM_BASE; + + for (int y = bp->height; y != 0; y--) { + Colour *dst = dst_line; + const Colour *src = src_rgba_line + META_LENGTH; + if (mode == BM_COLOUR_REMAP) src_mv = src_mv_line; + + if (read_mode == RM_WITH_MARGIN) { + assert(bt_last == BT_NONE); // or you must ensure block type is preserved + src += src_rgba_line[0].data; + dst += src_rgba_line[0].data; + if (mode == BM_COLOUR_REMAP) src_mv += src_rgba_line[0].data; + const int width_diff = si->sprite_width - bp->width; + effective_width = bp->width - (int) src_rgba_line[0].data; + const int delta_diff = (int) src_rgba_line[1].data - width_diff; + const int new_width = effective_width - delta_diff; + effective_width = delta_diff > 0 ? new_width : effective_width; + if (effective_width <= 0) goto next_line; + } + + switch (mode) { + default: + for (uint x = (uint) effective_width / 2; x > 0; x--) { + __m128i srcABCD = _mm_loadl_epi64((const __m128i*) src); + __m128i dstABCD = _mm_loadl_epi64((__m128i*) dst); + _mm_storel_epi64((__m128i*) dst, AlphaBlendTwoPixels(srcABCD, dstABCD, ALPHA_BLEND_PARAM_1, ALPHA_BLEND_PARAM_2)); + src += 2; + dst += 2; + } + + if ((bt_last == BT_NONE && effective_width & 1) || bt_last == BT_ODD) { + __m128i srcABCD = _mm_cvtsi32_si128(src->data); + __m128i dstABCD = _mm_cvtsi32_si128(dst->data); + dst->data = _mm_cvtsi128_si32(AlphaBlendTwoPixels(srcABCD, dstABCD, ALPHA_BLEND_PARAM_1, ALPHA_BLEND_PARAM_2)); + } + break; + + case BM_COLOUR_REMAP: +#if (SSE_VERSION >= 3) + for (uint x = (uint) effective_width / 2; x > 0; x--) { + __m128i srcABCD = _mm_loadl_epi64((const __m128i*) src); + __m128i dstABCD = _mm_loadl_epi64((__m128i*) dst); + uint32 mvX2 = *((uint32 *) const_cast<MapValue *>(src_mv)); + + /* Remap colours. */ + if (mvX2 & 0x00FF00FF) { + #define CMOV_REMAP(m_colour, m_src, m_m) \ + /* Written so the compiler uses CMOV. */ \ + Colour m_colour = 0; \ + { \ + const Colour srcm = (Colour) (m_src); \ + const uint m = (byte) (m_m); \ + const uint r = remap[m]; \ + const Colour cmap = (this->LookupColourInPalette(r).data & 0x00FFFFFF) | (srcm.data & 0xFF000000); \ + m_colour = r == 0 ? m_colour : cmap; \ + m_colour = m != 0 ? m_colour : srcm; \ + } +#ifdef _SQ64 + uint64 srcs = _mm_cvtsi128_si64(srcABCD); + uint64 remapped_src = 0; + CMOV_REMAP(c0, srcs, mvX2); + remapped_src = c0.data; + CMOV_REMAP(c1, srcs >> 32, mvX2 >> 16); + remapped_src |= (uint64) c1.data << 32; + srcABCD = _mm_cvtsi64_si128(remapped_src); +#else + Colour remapped_src[2]; + CMOV_REMAP(c0, _mm_cvtsi128_si32(srcABCD), mvX2); + remapped_src[0] = c0.data; + CMOV_REMAP(c1, src[1], mvX2 >> 16); + remapped_src[1] = c1.data; + srcABCD = _mm_loadl_epi64((__m128i*) &remapped_src); +#endif + + if ((mvX2 & 0xFF00FF00) != 0x80008000) srcABCD = AdjustBrightnessOfTwoPixels(srcABCD, mvX2); + } + + /* Blend colours. */ + _mm_storel_epi64((__m128i *) dst, AlphaBlendTwoPixels(srcABCD, dstABCD, ALPHA_BLEND_PARAM_1, ALPHA_BLEND_PARAM_2)); + dst += 2; + src += 2; + src_mv += 2; + } + + if ((bt_last == BT_NONE && effective_width & 1) || bt_last == BT_ODD) { +#else + for (uint x = (uint) effective_width; x > 0; x--) { +#endif + /* In case the m-channel is zero, do not remap this pixel in any way. */ + __m128i srcABCD; + if (src_mv->m) { + const uint r = remap[src_mv->m]; + if (r != 0) { + Colour remapped_colour = AdjustBrightneSSE(this->LookupColourInPalette(r), src_mv->v); + if (src->a == 255) { + *dst = remapped_colour; + } else { + remapped_colour.a = src->a; + srcABCD = _mm_cvtsi32_si128(remapped_colour.data); + goto bmcr_alpha_blend_single; + } + } + } else { + srcABCD = _mm_cvtsi32_si128(src->data); + if (src->a < 255) { +bmcr_alpha_blend_single: + __m128i dstABCD = _mm_cvtsi32_si128(dst->data); + srcABCD = AlphaBlendTwoPixels(srcABCD, dstABCD, ALPHA_BLEND_PARAM_1, ALPHA_BLEND_PARAM_2); + } + dst->data = _mm_cvtsi128_si32(srcABCD); + } +#if (SSE_VERSION == 2) + src_mv++; + dst++; + src++; +#endif + } + break; + + case BM_TRANSPARENT: + /* Make the current colour a bit more black, so it looks like this image is transparent. */ + for (uint x = (uint) bp->width / 2; x > 0; x--) { + __m128i srcABCD = _mm_loadl_epi64((const __m128i*) src); + __m128i dstABCD = _mm_loadl_epi64((__m128i*) dst); + _mm_storel_epi64((__m128i *) dst, DarkenTwoPixels(srcABCD, dstABCD, DARKEN_PARAM_1, DARKEN_PARAM_2)); + src += 2; + dst += 2; + } + + if ((bt_last == BT_NONE && bp->width & 1) || bt_last == BT_ODD) { + __m128i srcABCD = _mm_cvtsi32_si128(src->data); + __m128i dstABCD = _mm_cvtsi32_si128(dst->data); + dst->data = _mm_cvtsi128_si32(DarkenTwoPixels(srcABCD, dstABCD, DARKEN_PARAM_1, DARKEN_PARAM_2)); + } + break; + } + +next_line: + if (mode == BM_COLOUR_REMAP) src_mv_line += si->sprite_width; + src_rgba_line = (const Colour*) ((const byte*) src_rgba_line + si->sprite_line_size); + dst_line += bp->pitch; + } +} +IGNORE_UNINITIALIZED_WARNING_STOP + +/** + * Draws a sprite to a (screen) buffer. Calls adequate templated function. + * + * @param bp further blitting parameters + * @param mode blitter mode + * @param zoom zoom level at which we are drawing + */ +#if (SSE_VERSION == 2) +void Blitter_32bppSSE2::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom) +#elif (SSE_VERSION == 3) +void Blitter_32bppSSSE3::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom) +#elif (SSE_VERSION == 4) +void Blitter_32bppSSE4::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom) +#endif +{ + switch (mode) { + case BM_NORMAL: { + if (bp->skip_left != 0 || bp->width <= MARGIN_NORMAL_THRESHOLD) { + const BlockType bt_last = (BlockType) (bp->width & 1); + switch (bt_last) { + case BT_EVEN: Draw<BM_NORMAL, RM_WITH_SKIP, BT_EVEN>(bp, zoom); return; + case BT_ODD: Draw<BM_NORMAL, RM_WITH_SKIP, BT_ODD>(bp, zoom); return; + default: NOT_REACHED(); + } + } else { + Draw<BM_NORMAL, RM_WITH_MARGIN, BT_NONE>(bp, zoom); return; + } + break; + } + case BM_COLOUR_REMAP: + if (bp->skip_left != 0 || bp->width <= MARGIN_REMAP_THRESHOLD) { + Draw<BM_COLOUR_REMAP, RM_WITH_SKIP, BT_NONE>(bp, zoom); return; + } else { + Draw<BM_COLOUR_REMAP, RM_WITH_MARGIN, BT_NONE>(bp, zoom); return; + } + case BM_TRANSPARENT: Draw<BM_TRANSPARENT, RM_NONE, BT_NONE>(bp, zoom); return; + default: NOT_REACHED(); + } +} +#endif /* FULL_ANIMATION */ + #endif /* WITH_SSE */ -#endif /* BLITTER_32BPP_SSE_BASE_HPP */ +#endif /* BLITTER_32BPP_SSE_FUNC_HPP */ diff --git a/src/blitter/32bpp_sse_type.h b/src/blitter/32bpp_sse_type.h new file mode 100644 index 000000000..ac8da1be7 --- /dev/null +++ b/src/blitter/32bpp_sse_type.h @@ -0,0 +1,56 @@ +/* $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_sse_type.hpp Types related to SSE 32 bpp blitter. */ + +#ifndef BLITTER_32BPP_SSE_TYPE_HPP +#define BLITTER_32BPP_SSE_TYPE_HPP + +#ifdef WITH_SSE + +#include "32bpp_simple.hpp" +#if (SSE_VERSION == 2) +#include <emmintrin.h> +#elif (SSE_VERSION == 3) +#include <tmmintrin.h> +#elif (SSE_VERSION == 4) +#include <smmintrin.h> +#endif + +#define META_LENGTH 2 ///< Number of uint32 inserted before each line of pixels in a sprite. +#define MARGIN_NORMAL_THRESHOLD (zoom == ZOOM_LVL_OUT_32X ? 8 : 4) ///< Minimum width to use margins with BM_NORMAL. +#define MARGIN_REMAP_THRESHOLD 4 ///< Minimum width to use margins with BM_COLOUR_REMAP. + +#ifdef _MSC_VER + #define ALIGN(n) __declspec(align(n)) +#else + #define ALIGN(n) __attribute__ ((aligned (n))) +#endif + +typedef union ALIGN(16) um128i { + __m128i m128i; + uint8 m128i_u8[16]; + uint16 m128i_u16[8]; + uint32 m128i_u32[4]; + uint64 m128i_u64[2]; +} um128i; + +#define CLEAR_HIGH_BYTE_MASK _mm_setr_epi8(-1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0) +#define ALPHA_CONTROL_MASK _mm_setr_epi8( 6, 7, 6, 7, 6, 7, -1, -1, 14, 15, 14, 15, 14, 15, -1, -1) +#define PACK_LOW_CONTROL_MASK _mm_setr_epi8( 0, 2, 4, -1, 8, 10, 12, -1, -1, -1, -1, -1, -1, -1, -1, -1) +#define PACK_HIGH_CONTROL_MASK _mm_setr_epi8(-1, -1, -1, -1, -1, -1, -1, -1, 0, 2, 4, -1, 8, 10, 12, -1) +#define BRIGHTNESS_LOW_CONTROL_MASK _mm_setr_epi8( 1, 2, 1, 2, 1, 2, 0, 2, 3, 2, 3, 2, 3, 2, 0, 2) +#define BRIGHTNESS_DIV_CLEANER _mm_setr_epi8(-1, 1, -1, 1, -1, 1, -1, 0, -1, 1, -1, 1, -1, 1, -1, 0) +#define OVERBRIGHT_PRESENCE_MASK _mm_setr_epi8( 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0) +#define OVERBRIGHT_VALUE_MASK _mm_setr_epi8(-1, 0, -1, 0, -1, 0, 0, 0, -1, 0, -1, 0, -1, 0, 0, 0) +#define OVERBRIGHT_CONTROL_MASK _mm_setr_epi8( 0, 1, 0, 1, 0, 1, 7, 7, 2, 3, 2, 3, 2, 3, 7, 7) +#define TRANSPARENT_NOM_BASE _mm_setr_epi16(256, 256, 256, 256, 256, 256, 256, 256) + +#endif /* WITH_SSE */ +#endif /* BLITTER_32BPP_SSE_TYPE_HPP */ diff --git a/src/blitter/32bpp_ssse3.cpp b/src/blitter/32bpp_ssse3.cpp index 3c42d359c..33d49648e 100644 --- a/src/blitter/32bpp_ssse3.cpp +++ b/src/blitter/32bpp_ssse3.cpp @@ -15,208 +15,9 @@ #include "../zoom_func.h" #include "../settings_type.h" #include "32bpp_ssse3.hpp" +#include "32bpp_sse_func.hpp" /** Instantiation of the SSSE3 32bpp blitter factory. */ static FBlitter_32bppSSSE3 iFBlitter_32bppSSSE3; -/** - * Draws a sprite to a (screen) buffer. It is templated to allow faster operation. - * - * @tparam mode blitter mode - * @param bp further blitting parameters - * @param zoom zoom level at which we are drawing - */ -IGNORE_UNINITIALIZED_WARNING_START -template <BlitterMode mode, Blitter_32bppSSE2::ReadMode read_mode, Blitter_32bppSSE2::BlockType bt_last> -inline void Blitter_32bppSSSE3::Draw(const Blitter::BlitterParams *bp, ZoomLevel zoom) -{ - const byte * const remap = bp->remap; - Colour *dst_line = (Colour *) bp->dst + bp->top * bp->pitch + bp->left; - int effective_width = bp->width; - - /* Find where to start reading in the source sprite. */ - const SpriteData * const sd = (const SpriteData *) bp->sprite; - const SpriteInfo * const si = &sd->infos[zoom]; - const MapValue *src_mv_line = (const MapValue *) &sd->data[si->mv_offset] + bp->skip_top * si->sprite_width; - const Colour *src_rgba_line = (const Colour *) ((const byte *) &sd->data[si->sprite_offset] + bp->skip_top * si->sprite_line_size); - - if (read_mode != RM_WITH_MARGIN) { - src_rgba_line += bp->skip_left; - src_mv_line += bp->skip_left; - } - const MapValue *src_mv = src_mv_line; - - /* Load these variables into register before loop. */ - const __m128i a_cm = ALPHA_CONTROL_MASK; - const __m128i pack_low_cm = PACK_LOW_CONTROL_MASK; - const __m128i tr_nom_base = TRANSPARENT_NOM_BASE; - - for (int y = bp->height; y != 0; y--) { - Colour *dst = dst_line; - const Colour *src = src_rgba_line + META_LENGTH; - if (mode == BM_COLOUR_REMAP) src_mv = src_mv_line; - - if (read_mode == RM_WITH_MARGIN) { - assert(bt_last == BT_NONE); // or you must ensure block type is preserved - src += src_rgba_line[0].data; - dst += src_rgba_line[0].data; - if (mode == BM_COLOUR_REMAP) src_mv += src_rgba_line[0].data; - const int width_diff = si->sprite_width - bp->width; - effective_width = bp->width - (int) src_rgba_line[0].data; - const int delta_diff = (int) src_rgba_line[1].data - width_diff; - const int new_width = effective_width - delta_diff; - effective_width = delta_diff > 0 ? new_width : effective_width; - if (effective_width <= 0) goto next_line; - } - - switch (mode) { - default: - for (uint x = (uint) effective_width / 2; x > 0; x--) { - __m128i srcABCD = _mm_loadl_epi64((const __m128i*) src); - __m128i dstABCD = _mm_loadl_epi64((__m128i*) dst); - _mm_storel_epi64((__m128i*) dst, AlphaBlendTwoPixels(srcABCD, dstABCD, a_cm, pack_low_cm)); - src += 2; - dst += 2; - } - - if ((bt_last == BT_NONE && effective_width & 1) || bt_last == BT_ODD) { - __m128i srcABCD = _mm_cvtsi32_si128(src->data); - __m128i dstABCD = _mm_cvtsi32_si128(dst->data); - dst->data = _mm_cvtsi128_si32(AlphaBlendTwoPixels(srcABCD, dstABCD, a_cm, pack_low_cm)); - } - break; - - case BM_COLOUR_REMAP: - for (uint x = (uint) effective_width / 2; x > 0; x--) { - __m128i srcABCD = _mm_loadl_epi64((const __m128i*) src); - __m128i dstABCD = _mm_loadl_epi64((__m128i*) dst); - uint32 mvX2 = *((uint32 *) const_cast<MapValue *>(src_mv)); - - /* Remap colours. */ - if (mvX2 & 0x00FF00FF) { - #define CMOV_REMAP(m_colour, m_src, m_m) \ - /* Written so the compiler uses CMOV. */ \ - Colour m_colour = 0; \ - { \ - const Colour srcm = (Colour) (m_src); \ - const uint m = (byte) (m_m); \ - const uint r = remap[m]; \ - const Colour cmap = (this->LookupColourInPalette(r).data & 0x00FFFFFF) | (srcm.data & 0xFF000000); \ - m_colour = r == 0 ? m_colour : cmap; \ - m_colour = m != 0 ? m_colour : srcm; \ - } -#ifdef _SQ64 - uint64 srcs = _mm_cvtsi128_si64(srcABCD); - uint64 remapped_src = 0; - CMOV_REMAP(c0, srcs, mvX2); - remapped_src = c0.data; - CMOV_REMAP(c1, srcs >> 32, mvX2 >> 16); - remapped_src |= (uint64) c1.data << 32; - srcABCD = _mm_cvtsi64_si128(remapped_src); -#else - Colour remapped_src[2]; - CMOV_REMAP(c0, _mm_cvtsi128_si32(srcABCD), mvX2); - remapped_src[0] = c0.data; - CMOV_REMAP(c1, src[1], mvX2 >> 16); - remapped_src[1] = c1.data; - srcABCD = _mm_loadl_epi64((__m128i*) &remapped_src); -#endif - - if ((mvX2 & 0xFF00FF00) != 0x80008000) srcABCD = AdjustBrightnessOfTwoPixels(srcABCD, mvX2); - } - - /* Blend colours. */ - _mm_storel_epi64((__m128i *) dst, AlphaBlendTwoPixels(srcABCD, dstABCD, a_cm, pack_low_cm)); - dst += 2; - src += 2; - src_mv += 2; - } - - if ((bt_last == BT_NONE && effective_width & 1) || bt_last == BT_ODD) { - /* In case the m-channel is zero, do not remap this pixel in any way. */ - __m128i srcABCD; - if (src_mv->m) { - const uint r = remap[src_mv->m]; - if (r != 0) { - Colour remapped_colour = AdjustBrightneSSE(this->LookupColourInPalette(r), src_mv->v); - if (src->a == 255) { - *dst = remapped_colour; - } else { - remapped_colour.a = src->a; - srcABCD = _mm_cvtsi32_si128(remapped_colour.data); - goto bmcr_alpha_blend_single; - } - } - } else { - srcABCD = _mm_cvtsi32_si128(src->data); - if (src->a < 255) { -bmcr_alpha_blend_single: - __m128i dstABCD = _mm_cvtsi32_si128(dst->data); - srcABCD = AlphaBlendTwoPixels(srcABCD, dstABCD, a_cm, pack_low_cm); - } - dst->data = _mm_cvtsi128_si32(srcABCD); - } - } - break; - - case BM_TRANSPARENT: - /* Make the current colour a bit more black, so it looks like this image is transparent. */ - for (uint x = (uint) bp->width / 2; x > 0; x--) { - __m128i srcABCD = _mm_loadl_epi64((const __m128i*) src); - __m128i dstABCD = _mm_loadl_epi64((__m128i*) dst); - _mm_storel_epi64((__m128i *) dst, DarkenTwoPixels(srcABCD, dstABCD, a_cm, tr_nom_base)); - src += 2; - dst += 2; - } - - if ((bt_last == BT_NONE && bp->width & 1) || bt_last == BT_ODD) { - __m128i srcABCD = _mm_cvtsi32_si128(src->data); - __m128i dstABCD = _mm_cvtsi32_si128(dst->data); - dst->data = _mm_cvtsi128_si32(DarkenTwoPixels(srcABCD, dstABCD, a_cm, tr_nom_base)); - } - break; - } - -next_line: - if (mode == BM_COLOUR_REMAP) src_mv_line += si->sprite_width; - src_rgba_line = (const Colour*) ((const byte*) src_rgba_line + si->sprite_line_size); - dst_line += bp->pitch; - } -} -IGNORE_UNINITIALIZED_WARNING_STOP - -/** - * Draws a sprite to a (screen) buffer. Calls adequate templated function. - * - * @param bp further blitting parameters - * @param mode blitter mode - * @param zoom zoom level at which we are drawing - */ -void Blitter_32bppSSSE3::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom) -{ - switch (mode) { - case BM_NORMAL: { - if (bp->skip_left != 0 || bp->width <= MARGIN_NORMAL_THRESHOLD) { - const BlockType bt_last = (BlockType) (bp->width & 1); - switch (bt_last) { - case BT_EVEN: Draw<BM_NORMAL, RM_WITH_SKIP, BT_EVEN>(bp, zoom); return; - case BT_ODD: Draw<BM_NORMAL, RM_WITH_SKIP, BT_ODD>(bp, zoom); return; - default: NOT_REACHED(); - } - } else { - Draw<BM_NORMAL, RM_WITH_MARGIN, BT_NONE>(bp, zoom); return; - } - break; - } - case BM_COLOUR_REMAP: - if (bp->skip_left != 0 || bp->width <= MARGIN_REMAP_THRESHOLD) { - Draw<BM_COLOUR_REMAP, RM_WITH_SKIP, BT_NONE>(bp, zoom); return; - } else { - Draw<BM_COLOUR_REMAP, RM_WITH_MARGIN, BT_NONE>(bp, zoom); return; - } - case BM_TRANSPARENT: Draw<BM_TRANSPARENT, RM_NONE, BT_NONE>(bp, zoom); return; - default: NOT_REACHED(); - } -} - #endif /* WITH_SSE */ diff --git a/src/blitter/32bpp_ssse3.hpp b/src/blitter/32bpp_ssse3.hpp index 090dd5c42..c666408e7 100644 --- a/src/blitter/32bpp_ssse3.hpp +++ b/src/blitter/32bpp_ssse3.hpp @@ -17,6 +17,11 @@ #ifndef SSE_VERSION #define SSE_VERSION 3 #endif + +#ifndef FULL_ANIMATION +#define FULL_ANIMATION 0 +#endif + #include "32bpp_sse2.hpp" /** The SSSE3 32 bpp blitter (without palette animation). */ |