2 * This file is part of OpenTTD.
3 * 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.
4 * 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.
5 * 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/>.
8 /** @file 32bpp_sse_common.h Code common to all SSE 32 bpp blitters. */
10 #ifndef BLITTER_32BPP_SSE_COMMON_H
11 #define BLITTER_32BPP_SSE_COMMON_H
13 #define META_LENGTH 2 ///< Number of uint32 inserted before each line of pixels in a sprite.
14 #define MARGIN_NORMAL_THRESHOLD (zoom == ZOOM_LVL_OUT_32X ? 8 : 4) ///< Minimum width to use margins with BM_NORMAL.
15 #define MARGIN_REMAP_THRESHOLD 4 ///< Minimum width to use margins with BM_COLOUR_REMAP.
17 #define CLEAR_HIGH_BYTE_MASK _mm_setr_epi8(-1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0, -1, 0)
18 #define ALPHA_CONTROL_MASK _mm_setr_epi8( 6, 7, 6, 7, 6, 7, -1, -1, 14, 15, 14, 15, 14, 15, -1, -1)
19 #define PACK_LOW_CONTROL_MASK _mm_setr_epi8( 0, 2, 4, -1, 8, 10, 12, -1, -1, -1, -1, -1, -1, -1, -1, -1)
20 #define PACK_HIGH_CONTROL_MASK _mm_setr_epi8(-1, -1, -1, -1, -1, -1, -1, -1, 0, 2, 4, -1, 8, 10, 12, -1)
21 #define BRIGHTNESS_LOW_CONTROL_MASK _mm_setr_epi8( 1, 2, 1, 2, 1, 2, 0, 2, 3, 2, 3, 2, 3, 2, 0, 2)
22 #define BRIGHTNESS_DIV_CLEANER _mm_setr_epi8(-1, 1, -1, 1, -1, 1, -1, 0, -1, 1, -1, 1, -1, 1, -1, 0)
23 #define OVERBRIGHT_PRESENCE_MASK _mm_setr_epi8( 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0)
24 #define OVERBRIGHT_VALUE_MASK _mm_setr_epi8(-1, 0, -1, 0, -1, 0, 0, 0, -1, 0, -1, 0, -1, 0, 0, 0)
25 #define OVERBRIGHT_CONTROL_MASK _mm_setr_epi8( 0, 1, 0, 1, 0, 1, 7, 7, 2, 3, 2, 3, 2, 3, 7, 7)
26 #define TRANSPARENT_NOM_BASE _mm_setr_epi16(256, 256, 256, 256, 256, 256, 256, 256)
29 static inline __m128i
AlphaBlendTwoPixels(__m128i src
, __m128i dst
, const __m128i
&distribution_mask
, const __m128i
&pack_mask
)
31 __m128i srcAB
= _mm_unpacklo_epi8(src
, _mm_setzero_si128()); // PUNPCKLBW, expand each uint8 into uint16
32 __m128i dstAB
= _mm_unpacklo_epi8(dst
, _mm_setzero_si128());
34 __m128i alphaAB
= _mm_cmpgt_epi16(srcAB
, _mm_setzero_si128()); // PCMPGTW, if (alpha > 0) a++;
35 alphaAB
= _mm_srli_epi16(alphaAB
, 15);
36 alphaAB
= _mm_add_epi16(alphaAB
, srcAB
);
37 alphaAB
= T::distribute_alpha (alphaAB
, distribution_mask
);
39 srcAB
= _mm_sub_epi16(srcAB
, dstAB
); // PSUBW, (r - Cr)
40 srcAB
= _mm_mullo_epi16(srcAB
, alphaAB
); // PMULLW, a*(r - Cr)
41 srcAB
= _mm_srli_epi16(srcAB
, 8); // PSRLW, a*(r - Cr)/256
42 srcAB
= _mm_add_epi16(srcAB
, dstAB
); // PADDW, a*(r - Cr)/256 + Cr
43 return T::pack_unsaturated (srcAB
, pack_mask
);
47 * rgb = rgb * ((256/4) * 4 - (alpha/4)) / ((256/4) * 4)
50 static inline __m128i
DarkenTwoPixels(__m128i src
, __m128i dst
, const __m128i
&distribution_mask
, const __m128i
&tr_nom_base
)
52 __m128i srcAB
= _mm_unpacklo_epi8(src
, _mm_setzero_si128());
53 __m128i dstAB
= _mm_unpacklo_epi8(dst
, _mm_setzero_si128());
54 __m128i alphaAB
= T::distribute_alpha (srcAB
, distribution_mask
);
55 alphaAB
= _mm_srli_epi16(alphaAB
, 2); // Reduce to 64 levels of shades so the max value fits in 16 bits.
56 __m128i nom
= _mm_sub_epi16(tr_nom_base
, alphaAB
);
57 dstAB
= _mm_mullo_epi16(dstAB
, nom
);
58 dstAB
= _mm_srli_epi16(dstAB
, 8);
59 return _mm_packus_epi16(dstAB
, dstAB
);
62 IGNORE_UNINITIALIZED_WARNING_START
64 static Colour
ReallyAdjustBrightness(Colour colour
, uint8 brightness
)
66 uint64 c16
= colour
.b
| (uint64
) colour
.g
<< 16 | (uint64
) colour
.r
<< 32;
68 uint64 c16_ob
= c16
; // Helps out of order execution.
69 c16
/= Blitter_32bppBase::DEFAULT_BRIGHTNESS
;
70 c16
&= 0x01FF01FF01FFULL
;
72 /* Sum overbright (maximum for each rgb is 508, 9 bits, -255 is changed in -256 so we just have to take the 8 lower bits into account). */
73 c16_ob
= (((c16_ob
>> (8 + 7)) & 0x0100010001ULL
) * 0xFF) & c16
;
74 const uint ob
= ((uint16
) c16_ob
+ (uint16
) (c16_ob
>> 16) + (uint16
) (c16_ob
>> 32)) / 2;
76 const uint32 alpha32
= colour
.data
& 0xFF000000;
78 T::load_u64 (c16
, ret
);
80 __m128i ob128
= _mm_cvtsi32_si128(ob
);
81 ob128
= _mm_shufflelo_epi16(ob128
, 0xC0);
82 __m128i white
= OVERBRIGHT_VALUE_MASK
;
84 ret
= _mm_subs_epu16(white
, c128
); // PSUBUSW, (255 - rgb)
85 ret
= _mm_mullo_epi16(ret
, ob128
); // PMULLW, ob*(255 - rgb)
86 ret
= _mm_srli_epi16(ret
, 8); // PSRLW, ob*(255 - rgb)/256
87 ret
= _mm_add_epi16(ret
, c128
); // PADDW, ob*(255 - rgb)/256 + rgb
90 ret
= _mm_packus_epi16(ret
, ret
); // PACKUSWB, saturate and pack.
91 return alpha32
| _mm_cvtsi128_si32(ret
);
93 IGNORE_UNINITIALIZED_WARNING_STOP
95 /** ReallyAdjustBrightness() is not called that often.
96 * Inlining this function implies a far jump, which has a huge latency.
99 static inline Colour
AdjustBrightneSSE(Colour colour
, uint8 brightness
)
101 /* Shortcut for normal brightness. */
102 if (brightness
== Blitter_32bppBase::DEFAULT_BRIGHTNESS
) return colour
;
104 return ReallyAdjustBrightness
<T
> (colour
, brightness
);
108 static inline __m128i
AdjustBrightnessOfTwoPixels(__m128i from
, uint32 brightness
)
110 /* The following dataflow differs from the one of AdjustBrightness() only for alpha.
111 * In order to keep alpha in colAB, insert a 1 in a unused brightness byte (a*1->a).
112 * OK, not a 1 but DEFAULT_BRIGHTNESS to compensate the div.
114 brightness
&= 0xFF00FF00;
115 brightness
+= Blitter_32bppBase::DEFAULT_BRIGHTNESS
;
117 __m128i colAB
= _mm_unpacklo_epi8(from
, _mm_setzero_si128());
118 __m128i briAB
= _mm_cvtsi32_si128(brightness
);
119 briAB
= T::shuffle_epi8 (briAB
, BRIGHTNESS_LOW_CONTROL_MASK
); // DEFAULT_BRIGHTNESS in 0, 0x00 in 2.
120 colAB
= _mm_mullo_epi16(colAB
, briAB
);
121 __m128i colAB_ob
= _mm_srli_epi16(colAB
, 8 + 7);
122 colAB
= _mm_srli_epi16(colAB
, 7);
125 * Maximum for each rgb is 508 => 9 bits. The highest bit tells if there is overbright.
126 * -255 is changed in -256 so we just have to take the 8 lower bits into account.
128 colAB
= _mm_and_si128(colAB
, BRIGHTNESS_DIV_CLEANER
);
129 colAB_ob
= _mm_and_si128(colAB_ob
, OVERBRIGHT_PRESENCE_MASK
);
130 colAB_ob
= _mm_mullo_epi16(colAB_ob
, OVERBRIGHT_VALUE_MASK
);
131 colAB_ob
= _mm_and_si128(colAB_ob
, colAB
);
132 __m128i obAB
= T::hadd_epi16 (T::hadd_epi16 (colAB_ob
, _mm_setzero_si128()), _mm_setzero_si128());
134 obAB
= _mm_srli_epi16(obAB
, 1); // Reduce overbright strength.
135 obAB
= T::shuffle_epi8 (obAB
, OVERBRIGHT_CONTROL_MASK
);
136 __m128i retAB
= OVERBRIGHT_VALUE_MASK
; // ob_mask is equal to white.
137 retAB
= _mm_subs_epu16(retAB
, colAB
); // (255 - rgb)
138 retAB
= _mm_mullo_epi16(retAB
, obAB
); // ob*(255 - rgb)
139 retAB
= _mm_srli_epi16(retAB
, 8); // ob*(255 - rgb)/256
140 retAB
= _mm_add_epi16(retAB
, colAB
); // ob*(255 - rgb)/256 + rgb
142 return _mm_packus_epi16(retAB
, retAB
);
145 #endif /* BLITTER_32BPP_SSE_COMMON_H */