12 #include "../stdafx.h" 13 #include "../video/video_driver.hpp" 14 #include "../table/sprites.h" 18 #include "../safeguards.h" 21 static FBlitter_32bppSSE4_Anim iFBlitter_32bppSSE4_Anim;
30 IGNORE_UNINITIALIZED_WARNING_START
31 template <BlitterMode mode, Blitter_32bppSSE2::ReadMode read_mode, Blitter_32bppSSE2::BlockType bt_last,
bool translucent,
bool animated>
34 const byte *
const remap = bp->
remap;
36 uint16 *anim_line = this->anim_buf + this->ScreenToAnimOffset((uint32 *)bp->
dst) + bp->
top * this->anim_buf_pitch + bp->
left;
37 int effective_width = bp->
width;
40 const Blitter_32bppSSE_Base::SpriteData *
const sd = (
const Blitter_32bppSSE_Base::SpriteData *) bp->
sprite;
41 const SpriteInfo *
const si = &sd->infos[zoom];
42 const MapValue *src_mv_line = (
const MapValue *) &sd->data[si->mv_offset] + bp->
skip_top * si->sprite_width;
43 const Colour *src_rgba_line = (
const Colour *) ((
const byte *) &sd->data[si->sprite_offset] + bp->
skip_top * si->sprite_line_size);
45 if (read_mode != RM_WITH_MARGIN) {
49 const MapValue *src_mv = src_mv_line;
52 const __m128i a_cm = ALPHA_CONTROL_MASK;
53 const __m128i pack_low_cm = PACK_LOW_CONTROL_MASK;
54 const __m128i tr_nom_base = TRANSPARENT_NOM_BASE;
56 for (
int y = bp->
height; y != 0; y--) {
58 const Colour *src = src_rgba_line + META_LENGTH;
60 uint16 *anim = anim_line;
62 if (read_mode == RM_WITH_MARGIN) {
63 assert(bt_last == BT_NONE);
64 anim += src_rgba_line[0].
data;
65 src += src_rgba_line[0].
data;
66 dst += src_rgba_line[0].
data;
68 const int width_diff = si->sprite_width - bp->
width;
69 effective_width = bp->
width - (int) src_rgba_line[0].data;
70 const int delta_diff = (int) src_rgba_line[1].data - width_diff;
71 const int new_width = effective_width - delta_diff;
72 effective_width = delta_diff > 0 ? new_width : effective_width;
73 if (effective_width <= 0)
goto next_line;
79 for (uint x = (uint) effective_width; x > 0; x--) {
82 *anim = *(
const uint16*) src_mv;
83 *dst = (src_mv->m >=
PALETTE_ANIM_START) ? AdjustBrightneSSE(this->LookupColourInPalette(src_mv->m), src_mv->v) : src->
data;
89 if (animated) src_mv++;
97 for (uint x = (uint) effective_width/2; x != 0; x--) {
98 uint32 mvX2 = *((uint32 *) const_cast<MapValue *>(src_mv));
99 __m128i srcABCD = _mm_loadl_epi64((
const __m128i*) src);
100 __m128i dstABCD = _mm_loadl_epi64((__m128i*) dst);
104 const byte m0 = mvX2;
106 const Colour c0 = (this->LookupColourInPalette(m0).data & 0x00FFFFFF) | (src[0].data & 0xFF000000);
107 InsertFirstUint32(AdjustBrightneSSE(c0, (byte) (mvX2 >> 8)).data, srcABCD);
109 const byte m1 = mvX2 >> 16;
111 const Colour c1 = (this->LookupColourInPalette(m1).data & 0x00FFFFFF) | (src[1].data & 0xFF000000);
112 InsertSecondUint32(AdjustBrightneSSE(c1, (byte) (mvX2 >> 24)).data, srcABCD);
116 const byte a0 = src[0].
a;
117 const byte a1 = src[1].
a;
121 *(uint32*) anim = mvX2;
122 goto bmno_full_opacity;
124 anim01 = (uint16) mvX2;
125 }
else if (a0 == 0) {
127 goto bmno_full_transparency;
129 if (a1 == 255) anim[1] = (uint16) (mvX2 >> 16);
130 goto bmno_alpha_blend;
134 if (a1 == 255) anim01 |= mvX2 & 0xFFFF0000;
135 *(uint32*) anim = anim01;
137 anim[0] = (uint16) anim01;
140 if (src[0].a) anim[0] = 0;
141 if (src[1].a) anim[1] = 0;
146 srcABCD = AlphaBlendTwoPixels(srcABCD, dstABCD, a_cm, pack_low_cm);
148 _mm_storel_epi64((__m128i *) dst, srcABCD);
149 bmno_full_transparency:
156 if ((bt_last == BT_NONE && effective_width & 1) || bt_last == BT_ODD) {
158 }
else if (src->
a == 255) {
159 *anim = *(
const uint16*) src_mv;
160 *dst = (src_mv->m >=
PALETTE_ANIM_START) ? AdjustBrightneSSE(LookupColourInPalette(src_mv->m), src_mv->v) : *src;
164 __m128i dstABCD = _mm_cvtsi32_si128(dst->
data);
166 Colour colour = AdjustBrightneSSE(LookupColourInPalette(src_mv->m), src_mv->v);
168 srcABCD = _mm_cvtsi32_si128(colour.
data);
170 srcABCD = _mm_cvtsi32_si128(src->
data);
172 dst->
data = _mm_cvtsi128_si32(AlphaBlendTwoPixels(srcABCD, dstABCD, a_cm, pack_low_cm));
178 for (uint x = (uint) effective_width / 2; x != 0; x--) {
179 uint32 mvX2 = *((uint32 *) const_cast<MapValue *>(src_mv));
180 __m128i srcABCD = _mm_loadl_epi64((
const __m128i*) src);
181 __m128i dstABCD = _mm_loadl_epi64((__m128i*) dst);
184 const uint m0 = (byte) mvX2;
185 const uint r0 = remap[m0];
186 const uint m1 = (byte) (mvX2 >> 16);
187 const uint r1 = remap[m1];
188 if (mvX2 & 0x00FF00FF) {
189 #define CMOV_REMAP(m_colour, m_colour_init, m_src, m_m) \ 191 Colour m_colour = m_colour_init; \ 193 const Colour srcm = (Colour) (m_src); \ 194 const uint m = (byte) (m_m); \ 195 const uint r = remap[m]; \ 196 const Colour cmap = (this->LookupColourInPalette(r).data & 0x00FFFFFF) | (srcm.data & 0xFF000000); \ 197 m_colour = r == 0 ? m_colour : cmap; \ 198 m_colour = m != 0 ? m_colour : srcm; \ 201 uint64 srcs = _mm_cvtsi128_si64(srcABCD);
203 if (animated) dsts = _mm_cvtsi128_si64(dstABCD);
204 uint64 remapped_src = 0;
205 CMOV_REMAP(c0, animated ? dsts : 0, srcs, mvX2);
206 remapped_src = c0.
data;
207 CMOV_REMAP(c1, animated ? dsts >> 32 : 0, srcs >> 32, mvX2 >> 16);
208 remapped_src |= (uint64) c1.
data << 32;
209 srcABCD = _mm_cvtsi64_si128(remapped_src);
212 CMOV_REMAP(c0, animated ? _mm_cvtsi128_si32(dstABCD) : 0, _mm_cvtsi128_si32(srcABCD), mvX2);
213 remapped_src[0] = c0.
data;
214 CMOV_REMAP(c1, animated ? dst[1] : 0, src[1], mvX2 >> 16);
215 remapped_src[1] = c1.
data;
216 srcABCD = _mm_loadl_epi64((__m128i*) &remapped_src);
219 if ((mvX2 & 0xFF00FF00) != 0x80008000) srcABCD = AdjustBrightnessOfTwoPixels(srcABCD, mvX2);
224 const byte a0 = src[0].
a;
225 const byte a1 = src[1].
a;
226 uint32 anim01 = mvX2 & 0xFF00FF00;
230 *(uint32*) anim = anim01 | (r1 << 16);
231 goto bmcr_full_opacity;
233 }
else if (a0 == 0) {
235 goto bmcr_full_transparency;
238 anim[1] = r1 | (anim01 >> 16);
240 goto bmcr_alpha_blend;
244 if (a1 == 255) anim01 |= r1 << 16;
245 *(uint32*) anim = anim01;
247 anim[0] = (uint16) anim01;
250 if (src[0].a) anim[0] = 0;
251 if (src[1].a) anim[1] = 0;
256 srcABCD = AlphaBlendTwoPixels(srcABCD, dstABCD, a_cm, pack_low_cm);
258 _mm_storel_epi64((__m128i *) dst, srcABCD);
259 bmcr_full_transparency:
266 if ((bt_last == BT_NONE && effective_width & 1) || bt_last == BT_ODD) {
269 if (src->
a == 0)
break;
271 const uint r = remap[src_mv->m];
272 *anim = (animated && src->
a == 255) ? r | ((uint16) src_mv->v << 8 ) : 0;
274 Colour remapped_colour = AdjustBrightneSSE(this->LookupColourInPalette(r), src_mv->v);
276 *dst = remapped_colour;
278 remapped_colour.
a = src->
a;
279 srcABCD = _mm_cvtsi32_si128(remapped_colour.
data);
280 goto bmcr_alpha_blend_single;
285 srcABCD = _mm_cvtsi32_si128(src->
data);
287 bmcr_alpha_blend_single:
288 __m128i dstABCD = _mm_cvtsi32_si128(dst->
data);
289 srcABCD = AlphaBlendTwoPixels(srcABCD, dstABCD, a_cm, pack_low_cm);
291 dst->
data = _mm_cvtsi128_si32(srcABCD);
298 for (uint x = (uint) bp->
width / 2; x > 0; x--) {
299 __m128i srcABCD = _mm_loadl_epi64((
const __m128i*) src);
300 __m128i dstABCD = _mm_loadl_epi64((__m128i*) dst);
301 _mm_storel_epi64((__m128i *) dst, DarkenTwoPixels(srcABCD, dstABCD, a_cm, tr_nom_base));
305 if (src[-2].a) anim[-2] = 0;
306 if (src[-1].a) anim[-1] = 0;
309 if ((bt_last == BT_NONE && bp->
width & 1) || bt_last == BT_ODD) {
310 __m128i srcABCD = _mm_cvtsi32_si128(src->
data);
311 __m128i dstABCD = _mm_cvtsi32_si128(dst->data);
312 dst->data = _mm_cvtsi128_si32(DarkenTwoPixels(srcABCD, dstABCD, a_cm, tr_nom_base));
313 if (src[0].a) anim[0] = 0;
318 for (uint x = (uint) bp->
width; x > 0; x--) {
319 if (src_mv->m == 0) {
321 uint8 g = MakeDark(src->r, src->g, src->b);
322 *dst = ComposeColourRGBA(g, g, g, src->
a, *dst);
326 uint r = remap[src_mv->m];
327 if (r != 0) *dst = ComposeColourPANoCheck(this->AdjustBrightness(this->LookupColourInPalette(r), src_mv->v), src->
a, *dst);
337 for (uint x = (uint) bp->
width; x > 0; x--) {
352 src_rgba_line = (
const Colour*) ((
const byte*) src_rgba_line + si->sprite_line_size);
353 dst_line += bp->
pitch;
354 anim_line += this->anim_buf_pitch;
357 IGNORE_UNINITIALIZED_WARNING_STOP
368 const Blitter_32bppSSE_Base::SpriteFlags sprite_flags = ((
const Blitter_32bppSSE_Base::SpriteData *) bp->
sprite)->flags;
373 const BlockType bt_last = (BlockType) (bp->
width & 1);
374 if (bt_last == BT_EVEN) {
375 if (sprite_flags & SF_NO_ANIM) Draw<BM_NORMAL, RM_WITH_SKIP, BT_EVEN, true, false>(bp, zoom);
376 else Draw<BM_NORMAL, RM_WITH_SKIP, BT_EVEN, true, true>(bp, zoom);
378 if (sprite_flags & SF_NO_ANIM) Draw<BM_NORMAL, RM_WITH_SKIP, BT_ODD, true, false>(bp, zoom);
379 else Draw<BM_NORMAL, RM_WITH_SKIP, BT_ODD, true, true>(bp, zoom);
383 if (sprite_flags & SF_TRANSLUCENT) {
384 if (sprite_flags & SF_NO_ANIM) Draw<BM_NORMAL, RM_WITH_MARGIN, BT_NONE, true, false>(bp, zoom);
385 else Draw<BM_NORMAL, RM_WITH_MARGIN, BT_NONE, true, true>(bp, zoom);
387 if (sprite_flags & SF_NO_ANIM) Draw<BM_NORMAL, RM_WITH_MARGIN, BT_NONE, false, false>(bp, zoom);
388 else Draw<BM_NORMAL, RM_WITH_MARGIN, BT_NONE, false, true>(bp, zoom);
391 if (sprite_flags & SF_NO_ANIM) Draw<BM_NORMAL, RM_WITH_MARGIN, BT_NONE, true, false>(bp, zoom);
392 else Draw<BM_NORMAL, RM_WITH_MARGIN, BT_NONE, true, true>(bp, zoom);
398 if (sprite_flags & SF_NO_REMAP)
goto bm_normal;
400 if (sprite_flags & SF_NO_ANIM) Draw<BM_COLOUR_REMAP, RM_WITH_SKIP, BT_NONE, true, false>(bp, zoom);
401 else Draw<BM_COLOUR_REMAP, RM_WITH_SKIP, BT_NONE, true, true>(bp, zoom);
403 if (sprite_flags & SF_NO_ANIM) Draw<BM_COLOUR_REMAP, RM_WITH_MARGIN, BT_NONE, true, false>(bp, zoom);
404 else Draw<BM_COLOUR_REMAP, RM_WITH_MARGIN, BT_NONE, true, true>(bp, zoom);
407 case BM_TRANSPARENT: Draw<BM_TRANSPARENT, RM_NONE, BT_NONE, true, true>(bp, zoom);
return;
408 case BM_CRASH_REMAP: Draw<BM_CRASH_REMAP, RM_NONE, BT_NONE, true, true>(bp, zoom);
return;
409 case BM_BLACK_REMAP: Draw<BM_BLACK_REMAP, RM_NONE, BT_NONE, true, true>(bp, zoom);
return;
int left
The left offset in the 'dst' in pixels to start drawing.
int height
The height in pixels that needs to be drawn to dst.
Perform transparency colour remapping.
int skip_top
How much pixels of the source to skip on the top (based on zoom of dst)
A SSE4 32 bpp blitter with animation support.
uint32 data
Conversion of the channel information to a 32 bit number.
int width
The width in pixels that needs to be drawn to dst.
uint8 a
colour channels in LE order
int skip_left
How much pixels of the source to skip on the left (based on zoom of dst)
Parameters related to blitting.
int pitch
The pitch of the destination buffer.
Perform a crash remapping.
Perform remapping to a completely blackened sprite.
int top
The top offset in the 'dst' in pixels to start drawing.
const byte * remap
XXX – Temporary storage for remap array.
const void * sprite
Pointer to the sprite how ever the encoder stored it.
Perform a colour remapping.
Functions related to SSE 32 bpp blitter.
void * dst
Destination buffer.
Structure to access the alpha, red, green, and blue channels from a 32 bit number.
BlitterMode
The modes of blitting we can do.
ZoomLevel
All zoom levels we know.
Index in the _palettes array from which all animations are taking places (table/palettes.h)