summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--projects/openttd_vs100.vcxproj1
-rw-r--r--projects/openttd_vs100.vcxproj.filters3
-rw-r--r--projects/openttd_vs80.vcproj4
-rw-r--r--projects/openttd_vs90.vcproj4
-rw-r--r--source.list1
-rw-r--r--src/blitter/32bpp_anim_sse4.cpp1
-rw-r--r--src/blitter/32bpp_anim_sse4.hpp5
-rw-r--r--src/blitter/32bpp_sse2.cpp158
-rw-r--r--src/blitter/32bpp_sse2.hpp7
-rw-r--r--src/blitter/32bpp_sse4.cpp201
-rw-r--r--src/blitter/32bpp_sse4.hpp5
-rw-r--r--src/blitter/32bpp_sse_func.hpp281
-rw-r--r--src/blitter/32bpp_sse_type.h56
-rw-r--r--src/blitter/32bpp_ssse3.cpp201
-rw-r--r--src/blitter/32bpp_ssse3.hpp5
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). */