14 #include "../stdafx.h" 15 #include "../video/video_driver.hpp" 16 #include "../table/sprites.h" 17 #include "32bpp_anim_sse4.hpp" 20 #include "../safeguards.h" 23 static FBlitter_32bppSSE4_Anim iFBlitter_32bppSSE4_Anim;
32 IGNORE_UNINITIALIZED_WARNING_START
33 template <BlitterMode mode, Blitter_32bppSSE2::ReadMode read_mode, Blitter_32bppSSE2::BlockType bt_last,
bool translucent,
bool animated>
36 const byte *
const remap = bp->
remap;
38 assert(_screen.pitch == this->anim_buf_pitch);
39 uint16 *anim_line = this->anim_buf + ((uint32 *)bp->
dst - (uint32 *)_screen.dst_ptr) + bp->
top * this->anim_buf_pitch + bp->
left;
40 int effective_width = bp->
width;
43 const Blitter_32bppSSE_Base::SpriteData *
const sd = (
const Blitter_32bppSSE_Base::SpriteData *) bp->
sprite;
44 const SpriteInfo *
const si = &sd->infos[zoom];
45 const MapValue *src_mv_line = (
const MapValue *) &sd->data[si->mv_offset] + bp->
skip_top * si->sprite_width;
46 const Colour *src_rgba_line = (
const Colour *) ((
const byte *) &sd->data[si->sprite_offset] + bp->
skip_top * si->sprite_line_size);
48 if (read_mode != RM_WITH_MARGIN) {
52 const MapValue *src_mv = src_mv_line;
55 const __m128i a_cm = ALPHA_CONTROL_MASK;
56 const __m128i pack_low_cm = PACK_LOW_CONTROL_MASK;
57 const __m128i tr_nom_base = TRANSPARENT_NOM_BASE;
59 for (
int y = bp->
height; y != 0; y--) {
61 const Colour *src = src_rgba_line + META_LENGTH;
63 uint16 *anim = anim_line;
65 if (read_mode == RM_WITH_MARGIN) {
66 assert(bt_last == BT_NONE);
67 anim += src_rgba_line[0].data;
68 src += src_rgba_line[0].
data;
69 dst += src_rgba_line[0].
data;
71 const int width_diff = si->sprite_width - bp->
width;
72 effective_width = bp->
width - (int) src_rgba_line[0].data;
73 const int delta_diff = (int) src_rgba_line[1].data - width_diff;
74 const int new_width = effective_width - delta_diff;
75 effective_width = delta_diff > 0 ? new_width : effective_width;
76 if (effective_width <= 0)
goto next_line;
82 for (uint x = (uint) effective_width; x > 0; x--) {
85 *anim = *(
const uint16*) src_mv;
86 *dst = (src_mv->m >=
PALETTE_ANIM_START) ? AdjustBrightneSSE(this->LookupColourInPalette(src_mv->m), src_mv->v) : src->
data;
92 if (animated) src_mv++;
100 for (uint x = (uint) effective_width/2; x != 0; x--) {
101 uint32 mvX2 = *((uint32 *) const_cast<MapValue *>(src_mv));
102 __m128i srcABCD = _mm_loadl_epi64((
const __m128i*) src);
103 __m128i dstABCD = _mm_loadl_epi64((__m128i*) dst);
107 const byte m0 = mvX2;
109 const Colour c0 = (this->LookupColourInPalette(m0).data & 0x00FFFFFF) | (src[0].data & 0xFF000000);
110 InsertFirstUint32(AdjustBrightneSSE(c0, (byte) (mvX2 >> 8)).data, srcABCD);
112 const byte m1 = mvX2 >> 16;
114 const Colour c1 = (this->LookupColourInPalette(m1).data & 0x00FFFFFF) | (src[1].data & 0xFF000000);
115 InsertSecondUint32(AdjustBrightneSSE(c1, (byte) (mvX2 >> 24)).data, srcABCD);
119 const byte a0 = src[0].
a;
120 const byte a1 = src[1].
a;
124 *(uint32*) anim = mvX2;
125 goto bmno_full_opacity;
127 anim01 = (uint16) mvX2;
128 }
else if (a0 == 0) {
130 goto bmno_full_transparency;
132 if (a1 == 255) anim[1] = (uint16) (mvX2 >> 16);
133 goto bmno_alpha_blend;
137 if (a1 == 255) anim01 |= mvX2 & 0xFFFF0000;
138 *(uint32*) anim = anim01;
140 anim[0] = (uint16) anim01;
143 if (src[0].a) anim[0] = 0;
144 if (src[1].a) anim[1] = 0;
149 srcABCD = AlphaBlendTwoPixels(srcABCD, dstABCD, a_cm, pack_low_cm);
151 _mm_storel_epi64((__m128i *) dst, srcABCD);
152 bmno_full_transparency:
159 if ((bt_last == BT_NONE && effective_width & 1) || bt_last == BT_ODD) {
161 }
else if (src->
a == 255) {
162 *anim = *(
const uint16*) src_mv;
163 *dst = (src_mv->m >=
PALETTE_ANIM_START) ? AdjustBrightneSSE(LookupColourInPalette(src_mv->m), src_mv->v) : *src;
167 __m128i dstABCD = _mm_cvtsi32_si128(dst->
data);
169 Colour colour = AdjustBrightneSSE(LookupColourInPalette(src_mv->m), src_mv->v);
171 srcABCD = _mm_cvtsi32_si128(colour.
data);
173 srcABCD = _mm_cvtsi32_si128(src->
data);
175 dst->
data = _mm_cvtsi128_si32(AlphaBlendTwoPixels(srcABCD, dstABCD, a_cm, pack_low_cm));
181 for (uint x = (uint) effective_width / 2; x != 0; x--) {
182 uint32 mvX2 = *((uint32 *) const_cast<MapValue *>(src_mv));
183 __m128i srcABCD = _mm_loadl_epi64((
const __m128i*) src);
184 __m128i dstABCD = _mm_loadl_epi64((__m128i*) dst);
187 const uint m0 = (byte) mvX2;
188 const uint r0 = remap[m0];
189 const uint m1 = (byte) (mvX2 >> 16);
190 const uint r1 = remap[m1];
191 if (mvX2 & 0x00FF00FF) {
192 #define CMOV_REMAP(m_colour, m_colour_init, m_src, m_m) \ 194 Colour m_colour = m_colour_init; \ 196 const Colour srcm = (Colour) (m_src); \ 197 const uint m = (byte) (m_m); \ 198 const uint r = remap[m]; \ 199 const Colour cmap = (this->LookupColourInPalette(r).data & 0x00FFFFFF) | (srcm.data & 0xFF000000); \ 200 m_colour = r == 0 ? m_colour : cmap; \ 201 m_colour = m != 0 ? m_colour : srcm; \ 204 uint64 srcs = _mm_cvtsi128_si64(srcABCD);
206 if (animated) dsts = _mm_cvtsi128_si64(dstABCD);
207 uint64 remapped_src = 0;
208 CMOV_REMAP(c0, animated ? dsts : 0, srcs, mvX2);
209 remapped_src = c0.
data;
210 CMOV_REMAP(c1, animated ? dsts >> 32 : 0, srcs >> 32, mvX2 >> 16);
211 remapped_src |= (uint64) c1.
data << 32;
212 srcABCD = _mm_cvtsi64_si128(remapped_src);
215 CMOV_REMAP(c0, animated ? _mm_cvtsi128_si32(dstABCD) : 0, _mm_cvtsi128_si32(srcABCD), mvX2);
216 remapped_src[0] = c0.
data;
217 CMOV_REMAP(c1, animated ? dst[1] : 0, src[1], mvX2 >> 16);
218 remapped_src[1] = c1.
data;
219 srcABCD = _mm_loadl_epi64((__m128i*) &remapped_src);
222 if ((mvX2 & 0xFF00FF00) != 0x80008000) srcABCD = AdjustBrightnessOfTwoPixels(srcABCD, mvX2);
227 const byte a0 = src[0].
a;
228 const byte a1 = src[1].
a;
229 uint32 anim01 = mvX2 & 0xFF00FF00;
233 *(uint32*) anim = anim01 | (r1 << 16);
234 goto bmcr_full_opacity;
236 }
else if (a0 == 0) {
238 goto bmcr_full_transparency;
241 anim[1] = r1 | (anim01 >> 16);
243 goto bmcr_alpha_blend;
247 if (a1 == 255) anim01 |= r1 << 16;
248 *(uint32*) anim = anim01;
250 anim[0] = (uint16) anim01;
253 if (src[0].a) anim[0] = 0;
254 if (src[1].a) anim[1] = 0;
259 srcABCD = AlphaBlendTwoPixels(srcABCD, dstABCD, a_cm, pack_low_cm);
261 _mm_storel_epi64((__m128i *) dst, srcABCD);
262 bmcr_full_transparency:
269 if ((bt_last == BT_NONE && effective_width & 1) || bt_last == BT_ODD) {
272 if (src->
a == 0)
break;
274 const uint r = remap[src_mv->m];
275 *anim = (animated && src->
a == 255) ? r | ((uint16) src_mv->v << 8 ) : 0;
277 Colour remapped_colour = AdjustBrightneSSE(this->LookupColourInPalette(r), src_mv->v);
279 *dst = remapped_colour;
281 remapped_colour.
a = src->
a;
282 srcABCD = _mm_cvtsi32_si128(remapped_colour.
data);
283 goto bmcr_alpha_blend_single;
288 srcABCD = _mm_cvtsi32_si128(src->
data);
290 bmcr_alpha_blend_single:
291 __m128i dstABCD = _mm_cvtsi32_si128(dst->
data);
292 srcABCD = AlphaBlendTwoPixels(srcABCD, dstABCD, a_cm, pack_low_cm);
294 dst->
data = _mm_cvtsi128_si32(srcABCD);
301 for (uint x = (uint) bp->
width / 2; x > 0; x--) {
302 __m128i srcABCD = _mm_loadl_epi64((
const __m128i*) src);
303 __m128i dstABCD = _mm_loadl_epi64((__m128i*) dst);
304 _mm_storel_epi64((__m128i *) dst, DarkenTwoPixels(srcABCD, dstABCD, a_cm, tr_nom_base));
308 if (src[-2].a) anim[-2] = 0;
309 if (src[-1].a) anim[-1] = 0;
312 if ((bt_last == BT_NONE && bp->
width & 1) || bt_last == BT_ODD) {
313 __m128i srcABCD = _mm_cvtsi32_si128(src->
data);
314 __m128i dstABCD = _mm_cvtsi32_si128(dst->data);
315 dst->data = _mm_cvtsi128_si32(DarkenTwoPixels(srcABCD, dstABCD, a_cm, tr_nom_base));
316 if (src[0].a) anim[0] = 0;
321 for (uint x = (uint) bp->
width; x > 0; x--) {
322 if (src_mv->m == 0) {
324 uint8 g = MakeDark(src->r, src->g, src->b);
325 *dst = ComposeColourRGBA(g, g, g, src->
a, *dst);
329 uint r = remap[src_mv->m];
330 if (r != 0) *dst = ComposeColourPANoCheck(this->AdjustBrightness(this->LookupColourInPalette(r), src_mv->v), src->
a, *dst);
340 for (uint x = (uint) bp->
width; x > 0; x--) {
355 src_rgba_line = (
const Colour*) ((
const byte*) src_rgba_line + si->sprite_line_size);
356 dst_line += bp->
pitch;
357 anim_line += this->anim_buf_pitch;
360 IGNORE_UNINITIALIZED_WARNING_STOP
371 const Blitter_32bppSSE_Base::SpriteFlags sprite_flags = ((
const Blitter_32bppSSE_Base::SpriteData *) bp->
sprite)->flags;
376 const BlockType bt_last = (BlockType) (bp->
width & 1);
377 if (bt_last == BT_EVEN) {
378 if (sprite_flags & SF_NO_ANIM) Draw<BM_NORMAL, RM_WITH_SKIP, BT_EVEN, true, false>(bp, zoom);
379 else Draw<BM_NORMAL, RM_WITH_SKIP, BT_EVEN, true, true>(bp, zoom);
381 if (sprite_flags & SF_NO_ANIM) Draw<BM_NORMAL, RM_WITH_SKIP, BT_ODD, true, false>(bp, zoom);
382 else Draw<BM_NORMAL, RM_WITH_SKIP, BT_ODD, true, true>(bp, zoom);
386 if (sprite_flags & SF_TRANSLUCENT) {
387 if (sprite_flags & SF_NO_ANIM) Draw<BM_NORMAL, RM_WITH_MARGIN, BT_NONE, true, false>(bp, zoom);
388 else Draw<BM_NORMAL, RM_WITH_MARGIN, BT_NONE, true, true>(bp, zoom);
390 if (sprite_flags & SF_NO_ANIM) Draw<BM_NORMAL, RM_WITH_MARGIN, BT_NONE, false, false>(bp, zoom);
391 else Draw<BM_NORMAL, RM_WITH_MARGIN, BT_NONE, false, true>(bp, zoom);
394 if (sprite_flags & SF_NO_ANIM) Draw<BM_NORMAL, RM_WITH_MARGIN, BT_NONE, true, false>(bp, zoom);
395 else Draw<BM_NORMAL, RM_WITH_MARGIN, BT_NONE, true, true>(bp, zoom);
401 if (sprite_flags & SF_NO_REMAP)
goto bm_normal;
403 if (sprite_flags & SF_NO_ANIM) Draw<BM_COLOUR_REMAP, RM_WITH_SKIP, BT_NONE, true, false>(bp, zoom);
404 else Draw<BM_COLOUR_REMAP, RM_WITH_SKIP, BT_NONE, true, true>(bp, zoom);
406 if (sprite_flags & SF_NO_ANIM) Draw<BM_COLOUR_REMAP, RM_WITH_MARGIN, BT_NONE, true, false>(bp, zoom);
407 else Draw<BM_COLOUR_REMAP, RM_WITH_MARGIN, BT_NONE, true, true>(bp, zoom);
410 case BM_TRANSPARENT: Draw<BM_TRANSPARENT, RM_NONE, BT_NONE, true, true>(bp, zoom);
return;
411 case BM_CRASH_REMAP: Draw<BM_CRASH_REMAP, RM_NONE, BT_NONE, true, true>(bp, zoom);
return;
412 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)
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.
ZoomLevel
All zoom levels we know.
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.
Index in the _palettes array from which all animations are taking places (table/palettes.h)