1 // license:BSD-3-Clause 2 // copyright-holders:Vas Crabb, Ryan Holtz 3 /*************************************************************************** 4 5 rgbgen.h 6 7 General RGB utilities. 8 9 ***************************************************************************/ 10 11 #ifndef MAME_EMU_VIDEO_RGBGEN_H 12 #define MAME_EMU_VIDEO_RGBGEN_H 13 14 15 /*************************************************************************** 16 TYPE DEFINITIONS 17 ***************************************************************************/ 18 19 class rgbaint_t 20 { 21 public: rgbaint_t()22 rgbaint_t(): m_a(0), m_r(0), m_g(0), m_b(0) { } rgbaint_t(u32 rgba)23 explicit rgbaint_t(u32 rgba) { set(rgba); } rgbaint_t(s32 a,s32 r,s32 g,s32 b)24 rgbaint_t(s32 a, s32 r, s32 g, s32 b) { set(a, r, g, b); } rgbaint_t(const rgb_t & rgba)25 explicit rgbaint_t(const rgb_t& rgba) { set(rgba); } 26 27 rgbaint_t(const rgbaint_t& other) = default; 28 rgbaint_t &operator=(const rgbaint_t& other) = default; 29 set(const rgbaint_t & other)30 void set(const rgbaint_t& other) { set(other.m_a, other.m_r, other.m_g, other.m_b); } set(u32 rgba)31 void set(u32 rgba) { set((rgba >> 24) & 0xff, (rgba >> 16) & 0xff, (rgba >> 8) & 0xff, rgba & 0xff); } set(s32 a,s32 r,s32 g,s32 b)32 void set(s32 a, s32 r, s32 g, s32 b) 33 { 34 m_a = a; 35 m_r = r; 36 m_g = g; 37 m_b = b; 38 } set(const rgb_t & rgba)39 void set(const rgb_t& rgba) { set(rgba.a(), rgba.r(), rgba.g(), rgba.b()); } 40 // This function sets all elements to the same val set_all(const s32 & val)41 void set_all(const s32& val) { set(val, val, val, val); } 42 // This function zeros all elements zero()43 void zero() { set_all(0); } 44 // This function zeros only the alpha element zero_alpha()45 void zero_alpha() { m_a = 0; } 46 to_rgba()47 rgb_t to_rgba() const { return rgb_t(get_a(), get_r(), get_g(), get_b()); } 48 to_rgba_clamp()49 rgb_t to_rgba_clamp() const 50 { 51 const u8 a = (m_a < 0) ? 0 : (m_a > 255) ? 255 : m_a; 52 const u8 r = (m_r < 0) ? 0 : (m_r > 255) ? 255 : m_r; 53 const u8 g = (m_g < 0) ? 0 : (m_g > 255) ? 255 : m_g; 54 const u8 b = (m_b < 0) ? 0 : (m_b > 255) ? 255 : m_b; 55 return rgb_t(a, r, g, b); 56 } 57 set_a16(const s32 value)58 void set_a16(const s32 value) { m_a = value; } set_a(const s32 value)59 void set_a(const s32 value) { m_a = value; } set_r(const s32 value)60 void set_r(const s32 value) { m_r = value; } set_g(const s32 value)61 void set_g(const s32 value) { m_g = value; } set_b(const s32 value)62 void set_b(const s32 value) { m_b = value; } 63 get_a()64 u8 get_a() const { return u8(u32(m_a)); } get_r()65 u8 get_r() const { return u8(u32(m_r)); } get_g()66 u8 get_g() const { return u8(u32(m_g)); } get_b()67 u8 get_b() const { return u8(u32(m_b)); } 68 get_a32()69 s32 get_a32() const { return m_a; } get_r32()70 s32 get_r32() const { return m_r; } get_g32()71 s32 get_g32() const { return m_g; } get_b32()72 s32 get_b32() const { return m_b; } 73 74 // These selects return an rgbaint_t with all fields set to the element choosen (a, r, g, or b) select_alpha32()75 rgbaint_t select_alpha32() const { return rgbaint_t(get_a32(), get_a32(), get_a32(), get_a32()); } select_red32()76 rgbaint_t select_red32() const { return rgbaint_t(get_r32(), get_r32(), get_r32(), get_r32()); } select_green32()77 rgbaint_t select_green32() const { return rgbaint_t(get_g32(), get_g32(), get_g32(), get_g32()); } select_blue32()78 rgbaint_t select_blue32() const { return rgbaint_t(get_b32(), get_b32(), get_b32(), get_b32()); } 79 add(const rgbaint_t & color)80 inline void add(const rgbaint_t& color) 81 { 82 add_imm_rgba(color.m_a, color.m_r, color.m_g, color.m_b); 83 } 84 add_imm(const s32 imm)85 inline void add_imm(const s32 imm) 86 { 87 add_imm_rgba(imm, imm, imm, imm); 88 } 89 add_imm_rgba(const s32 a,const s32 r,const s32 g,const s32 b)90 inline void add_imm_rgba(const s32 a, const s32 r, const s32 g, const s32 b) 91 { 92 m_a += a; 93 m_r += r; 94 m_g += g; 95 m_b += b; 96 } 97 sub(const rgbaint_t & color)98 inline void sub(const rgbaint_t& color) 99 { 100 sub_imm_rgba(color.m_a, color.m_r, color.m_g, color.m_b); 101 } 102 sub_imm(const s32 imm)103 inline void sub_imm(const s32 imm) 104 { 105 sub_imm_rgba(imm, imm, imm, imm); 106 } 107 sub_imm_rgba(const s32 a,const s32 r,const s32 g,const s32 b)108 inline void sub_imm_rgba(const s32 a, const s32 r, const s32 g, const s32 b) 109 { 110 m_a -= a; 111 m_r -= r; 112 m_g -= g; 113 m_b -= b; 114 } 115 subr(const rgbaint_t & color)116 inline void subr(const rgbaint_t& color) 117 { 118 subr_imm_rgba(color.m_a, color.m_r, color.m_g, color.m_b); 119 } 120 subr_imm(const s32 imm)121 inline void subr_imm(const s32 imm) 122 { 123 subr_imm_rgba(imm, imm, imm, imm); 124 } 125 subr_imm_rgba(const s32 a,const s32 r,const s32 g,const s32 b)126 inline void subr_imm_rgba(const s32 a, const s32 r, const s32 g, const s32 b) 127 { 128 m_a = a - m_a; 129 m_r = r - m_r; 130 m_g = g - m_g; 131 m_b = b - m_b; 132 } 133 mul(const rgbaint_t & color)134 inline void mul(const rgbaint_t& color) 135 { 136 mul_imm_rgba(color.m_a, color.m_r, color.m_g, color.m_b); 137 } 138 mul_imm(const s32 imm)139 inline void mul_imm(const s32 imm) 140 { 141 mul_imm_rgba(imm, imm, imm, imm); 142 } 143 mul_imm_rgba(const s32 a,const s32 r,const s32 g,const s32 b)144 inline void mul_imm_rgba(const s32 a, const s32 r, const s32 g, const s32 b) 145 { 146 m_a *= a; 147 m_r *= r; 148 m_g *= g; 149 m_b *= b; 150 } 151 shl(const rgbaint_t & shift)152 inline void shl(const rgbaint_t& shift) 153 { 154 m_a <<= shift.m_a; 155 m_r <<= shift.m_r; 156 m_g <<= shift.m_g; 157 m_b <<= shift.m_b; 158 } 159 shl_imm(const u8 shift)160 inline void shl_imm(const u8 shift) 161 { 162 if (shift == 0) 163 return; 164 165 m_a <<= shift; 166 m_r <<= shift; 167 m_g <<= shift; 168 m_b <<= shift; 169 } 170 shr(const rgbaint_t & shift)171 inline void shr(const rgbaint_t& shift) 172 { 173 m_a = s32(u32(m_a) >> shift.m_a); 174 m_r = s32(u32(m_r) >> shift.m_r); 175 m_g = s32(u32(m_g) >> shift.m_g); 176 m_b = s32(u32(m_b) >> shift.m_b); 177 } 178 shr_imm(const u8 shift)179 inline void shr_imm(const u8 shift) 180 { 181 if (shift == 0) 182 return; 183 184 m_a = s32(u32(m_a) >> shift); 185 m_r = s32(u32(m_r) >> shift); 186 m_g = s32(u32(m_g) >> shift); 187 m_b = s32(u32(m_b) >> shift); 188 } 189 sra(const rgbaint_t & shift)190 inline void sra(const rgbaint_t& shift) 191 { 192 m_a >>= shift.m_a; 193 if (m_a & (1 << (31 - shift.m_a))) 194 m_a |= ~0 << (32 - shift.m_a); 195 196 m_r >>= shift.m_r; 197 if (m_r & (1 << (31 - shift.m_r))) 198 m_r |= ~0 << (32 - shift.m_r); 199 200 m_g >>= shift.m_g; 201 if (m_g & (1 << (31 - shift.m_g))) 202 m_g |= ~0 << (32 - shift.m_g); 203 204 m_b >>= shift.m_b; 205 if (m_b & (1 << (31 - shift.m_b))) 206 m_b |= ~0 << (32 - shift.m_b); 207 } 208 sra_imm(const u8 shift)209 inline void sra_imm(const u8 shift) 210 { 211 const u32 high_bit = 1 << (31 - shift); 212 const u32 high_mask = ~0 << (32 - shift); 213 214 m_a >>= shift; 215 if (m_a & high_bit) 216 m_a |= high_mask; 217 218 m_r >>= shift; 219 if (m_r & high_bit) 220 m_r |= high_mask; 221 222 m_g >>= shift; 223 if (m_g & high_bit) 224 m_g |= high_mask; 225 226 m_b >>= shift; 227 if (m_b & high_bit) 228 m_b |= high_mask; 229 } 230 or_reg(const rgbaint_t & color)231 void or_reg(const rgbaint_t& color) { or_imm_rgba(color.m_a, color.m_r, color.m_g, color.m_b); } and_reg(const rgbaint_t & color)232 void and_reg(const rgbaint_t& color) { and_imm_rgba(color.m_a, color.m_r, color.m_g, color.m_b); } xor_reg(const rgbaint_t & color)233 void xor_reg(const rgbaint_t& color) { xor_imm_rgba(color.m_a, color.m_r, color.m_g, color.m_b); } 234 andnot_reg(const rgbaint_t & color)235 void andnot_reg(const rgbaint_t& color) { and_imm_rgba(~color.m_a, ~color.m_r, ~color.m_g, ~color.m_b); } 236 or_imm(s32 imm)237 void or_imm(s32 imm) { or_imm_rgba(imm, imm, imm, imm); } and_imm(s32 imm)238 void and_imm(s32 imm) { and_imm_rgba(imm, imm, imm, imm); } xor_imm(s32 imm)239 void xor_imm(s32 imm) { xor_imm_rgba(imm, imm, imm, imm); } 240 or_imm_rgba(const s32 a,const s32 r,const s32 g,const s32 b)241 inline void or_imm_rgba(const s32 a, const s32 r, const s32 g, const s32 b) 242 { 243 m_a |= a; 244 m_r |= r; 245 m_g |= g; 246 m_b |= b; 247 } 248 and_imm_rgba(const s32 a,const s32 r,const s32 g,const s32 b)249 inline void and_imm_rgba(const s32 a, const s32 r, const s32 g, const s32 b) 250 { 251 m_a &= a; 252 m_r &= r; 253 m_g &= g; 254 m_b &= b; 255 } 256 xor_imm_rgba(const s32 a,const s32 r,const s32 g,const s32 b)257 inline void xor_imm_rgba(const s32 a, const s32 r, const s32 g, const s32 b) 258 { 259 m_a ^= a; 260 m_r ^= r; 261 m_g ^= g; 262 m_b ^= b; 263 } 264 clamp_and_clear(const u32 sign)265 inline void clamp_and_clear(const u32 sign) 266 { 267 if (m_a & sign) m_a = 0; 268 if (m_r & sign) m_r = 0; 269 if (m_g & sign) m_g = 0; 270 if (m_b & sign) m_b = 0; 271 272 clamp_to_uint8(); 273 } 274 clamp_to_uint8()275 inline void clamp_to_uint8() 276 { 277 m_a = (m_a < 0) ? 0 : (m_a > 255) ? 255 : m_a; 278 m_r = (m_r < 0) ? 0 : (m_r > 255) ? 255 : m_r; 279 m_g = (m_g < 0) ? 0 : (m_g > 255) ? 255 : m_g; 280 m_b = (m_b < 0) ? 0 : (m_b > 255) ? 255 : m_b; 281 } 282 sign_extend(const u32 compare,const u32 sign)283 inline void sign_extend(const u32 compare, const u32 sign) 284 { 285 if ((m_a & compare) == compare) 286 m_a |= sign; 287 288 if ((m_r & compare) == compare) 289 m_r |= sign; 290 291 if ((m_g & compare) == compare) 292 m_g |= sign; 293 294 if ((m_b & compare) == compare) 295 m_b |= sign; 296 } 297 min(const s32 value)298 inline void min(const s32 value) 299 { 300 m_a = (m_a > value) ? value : m_a; 301 m_r = (m_r > value) ? value : m_r; 302 m_g = (m_g > value) ? value : m_g; 303 m_b = (m_b > value) ? value : m_b; 304 } 305 max(const s32 value)306 inline void max(const s32 value) 307 { 308 m_a = (m_a < value) ? value : m_a; 309 m_r = (m_r < value) ? value : m_r; 310 m_g = (m_g < value) ? value : m_g; 311 m_b = (m_b < value) ? value : m_b; 312 } 313 314 void blend(const rgbaint_t& other, u8 factor); 315 316 void scale_and_clamp(const rgbaint_t& scale); 317 void scale_imm_and_clamp(const s32 scale); 318 void scale2_add_and_clamp(const rgbaint_t& scale, const rgbaint_t& other, const rgbaint_t& scale2); 319 void scale_add_and_clamp(const rgbaint_t& scale, const rgbaint_t& other); 320 cmpeq(const rgbaint_t & value)321 void cmpeq(const rgbaint_t& value) { cmpeq_imm_rgba(value.m_a, value.m_r, value.m_g, value.m_b); } cmpgt(const rgbaint_t & value)322 void cmpgt(const rgbaint_t& value) { cmpgt_imm_rgba(value.m_a, value.m_r, value.m_g, value.m_b); } cmplt(const rgbaint_t & value)323 void cmplt(const rgbaint_t& value) { cmplt_imm_rgba(value.m_a, value.m_r, value.m_g, value.m_b); } 324 cmpeq_imm(s32 value)325 void cmpeq_imm(s32 value) { cmpeq_imm_rgba(value, value, value, value); } cmpgt_imm(s32 value)326 void cmpgt_imm(s32 value) { cmpgt_imm_rgba(value, value, value, value); } cmplt_imm(s32 value)327 void cmplt_imm(s32 value) { cmplt_imm_rgba(value, value, value, value); } 328 cmpeq_imm_rgba(s32 a,s32 r,s32 g,s32 b)329 void cmpeq_imm_rgba(s32 a, s32 r, s32 g, s32 b) 330 { 331 m_a = (m_a == a) ? 0xffffffff : 0; 332 m_r = (m_r == r) ? 0xffffffff : 0; 333 m_g = (m_g == g) ? 0xffffffff : 0; 334 m_b = (m_b == b) ? 0xffffffff : 0; 335 } 336 cmpgt_imm_rgba(s32 a,s32 r,s32 g,s32 b)337 void cmpgt_imm_rgba(s32 a, s32 r, s32 g, s32 b) 338 { 339 m_a = (m_a > a) ? 0xffffffff : 0; 340 m_r = (m_r > r) ? 0xffffffff : 0; 341 m_g = (m_g > g) ? 0xffffffff : 0; 342 m_b = (m_b > b) ? 0xffffffff : 0; 343 } 344 cmplt_imm_rgba(s32 a,s32 r,s32 g,s32 b)345 void cmplt_imm_rgba(s32 a, s32 r, s32 g, s32 b) 346 { 347 m_a = (m_a < a) ? 0xffffffff : 0; 348 m_r = (m_r < r) ? 0xffffffff : 0; 349 m_g = (m_g < g) ? 0xffffffff : 0; 350 m_b = (m_b < b) ? 0xffffffff : 0; 351 } 352 merge_alpha16(const rgbaint_t & alpha)353 void merge_alpha16(const rgbaint_t& alpha) 354 { 355 m_a = alpha.m_a; 356 } 357 merge_alpha(const rgbaint_t & alpha)358 void merge_alpha(const rgbaint_t& alpha) 359 { 360 m_a = alpha.m_a; 361 } 362 363 rgbaint_t& operator+=(const rgbaint_t& other) 364 { 365 add_imm_rgba(other.m_a, other.m_r, other.m_g, other.m_b); 366 return *this; 367 } 368 369 rgbaint_t& operator+=(const s32 other) 370 { 371 add_imm_rgba(other, other, other, other); 372 return *this; 373 } 374 375 rgbaint_t &operator-=(const rgbaint_t& other) 376 { 377 sub_imm_rgba(other.m_a, other.m_r, other.m_g, other.m_b); 378 return *this; 379 } 380 381 rgbaint_t& operator*=(const rgbaint_t& other) 382 { 383 mul_imm_rgba(other.m_a, other.m_r, other.m_g, other.m_b); 384 return *this; 385 } 386 387 rgbaint_t& operator*=(const s32 other) 388 { 389 mul_imm_rgba(other, other, other, other); 390 return *this; 391 } 392 393 rgbaint_t& operator>>=(const s32 shift) 394 { 395 sra_imm(shift); 396 return *this; 397 } 398 bilinear_filter(u32 rgb00,u32 rgb01,u32 rgb10,u32 rgb11,u8 u,u8 v)399 static u32 bilinear_filter(u32 rgb00, u32 rgb01, u32 rgb10, u32 rgb11, u8 u, u8 v) 400 { 401 u32 rb0 = (rgb00 & 0x00ff00ff) + ((((rgb01 & 0x00ff00ff) - (rgb00 & 0x00ff00ff)) * u) >> 8); 402 u32 rb1 = (rgb10 & 0x00ff00ff) + ((((rgb11 & 0x00ff00ff) - (rgb10 & 0x00ff00ff)) * u) >> 8); 403 404 rgb00 >>= 8; 405 rgb01 >>= 8; 406 rgb10 >>= 8; 407 rgb11 >>= 8; 408 409 u32 ag0 = (rgb00 & 0x00ff00ff) + ((((rgb01 & 0x00ff00ff) - (rgb00 & 0x00ff00ff)) * u) >> 8); 410 u32 ag1 = (rgb10 & 0x00ff00ff) + ((((rgb11 & 0x00ff00ff) - (rgb10 & 0x00ff00ff)) * u) >> 8); 411 412 rb0 = (rb0 & 0x00ff00ff) + ((((rb1 & 0x00ff00ff) - (rb0 & 0x00ff00ff)) * v) >> 8); 413 ag0 = (ag0 & 0x00ff00ff) + ((((ag1 & 0x00ff00ff) - (ag0 & 0x00ff00ff)) * v) >> 8); 414 415 return ((ag0 << 8) & 0xff00ff00) | (rb0 & 0x00ff00ff); 416 } 417 bilinear_filter_rgbaint(u32 rgb00,u32 rgb01,u32 rgb10,u32 rgb11,u8 u,u8 v)418 void bilinear_filter_rgbaint(u32 rgb00, u32 rgb01, u32 rgb10, u32 rgb11, u8 u, u8 v) 419 { 420 u32 rb0 = (rgb00 & 0x00ff00ff) + ((((rgb01 & 0x00ff00ff) - (rgb00 & 0x00ff00ff)) * u) >> 8); 421 u32 rb1 = (rgb10 & 0x00ff00ff) + ((((rgb11 & 0x00ff00ff) - (rgb10 & 0x00ff00ff)) * u) >> 8); 422 423 rgb00 >>= 8; 424 rgb01 >>= 8; 425 rgb10 >>= 8; 426 rgb11 >>= 8; 427 428 u32 ag0 = (rgb00 & 0x00ff00ff) + ((((rgb01 & 0x00ff00ff) - (rgb00 & 0x00ff00ff)) * u) >> 8); 429 u32 ag1 = (rgb10 & 0x00ff00ff) + ((((rgb11 & 0x00ff00ff) - (rgb10 & 0x00ff00ff)) * u) >> 8); 430 431 rb0 = (rb0 & 0x00ff00ff) + ((((rb1 & 0x00ff00ff) - (rb0 & 0x00ff00ff)) * v) >> 8); 432 ag0 = (ag0 & 0x00ff00ff) + ((((ag1 & 0x00ff00ff) - (ag0 & 0x00ff00ff)) * v) >> 8); 433 434 u32 result = ((ag0 << 8) & 0xff00ff00) | (rb0 & 0x00ff00ff); 435 this->set(result); 436 } 437 438 protected: 439 s32 m_a; 440 s32 m_r; 441 s32 m_g; 442 s32 m_b; 443 }; 444 445 #endif // MAME_EMU_VIDEO_RGBGEN_H 446