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