1 #ifndef _TCURGBA_HPP
2 #define _TCURGBA_HPP
3 /*-------------------------------------------------------------------------
4  * drawElements Quality Program Tester Core
5  * ----------------------------------------
6  *
7  * Copyright 2014 The Android Open Source Project
8  *
9  * Licensed under the Apache License, Version 2.0 (the "License");
10  * you may not use this file except in compliance with the License.
11  * You may obtain a copy of the License at
12  *
13  *      http://www.apache.org/licenses/LICENSE-2.0
14  *
15  * Unless required by applicable law or agreed to in writing, software
16  * distributed under the License is distributed on an "AS IS" BASIS,
17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18  * See the License for the specific language governing permissions and
19  * limitations under the License.
20  *
21  *//*!
22  * \file
23  * \brief RGBA8888 color type.
24  *//*--------------------------------------------------------------------*/
25 
26 #include "tcuDefs.hpp"
27 #include "deInt32.h"
28 #include "tcuVectorType.hpp"
29 
30 #include <sstream>
31 
32 namespace tcu
33 {
34 
35 /*--------------------------------------------------------------------*//*!
36  * \brief RGBA8888 color struct
37  *//*--------------------------------------------------------------------*/
38 class RGBA
39 {
40 public:
41 	enum
42 	{
43 		RED_SHIFT	= 0,
44 		GREEN_SHIFT	= 8,
45 		BLUE_SHIFT	= 16,
46 		ALPHA_SHIFT	= 24
47 	};
48 
49 	enum
50 	{
51 		RED_MASK	= (1<<0),
52 		GREEN_MASK	= (1<<1),
53 		BLUE_MASK	= (1<<2),
54 		ALPHA_MASK	= (1<<3)
55 	};
56 
RGBA(void)57 	RGBA (void) { m_value = 0; }
58 
RGBA(int r,int g,int b,int a)59 	RGBA (int r, int g, int b, int a)
60 	{
61 		DE_ASSERT(deInRange32(r, 0, 255));
62 		DE_ASSERT(deInRange32(g, 0, 255));
63 		DE_ASSERT(deInRange32(b, 0, 255));
64 		DE_ASSERT(deInRange32(a, 0, 255));
65 		m_value = (a << ALPHA_SHIFT) | (r << RED_SHIFT) | (g << GREEN_SHIFT) | (b << BLUE_SHIFT);
66 	}
67 
RGBA(deUint32 val)68 	explicit RGBA (deUint32 val)
69 	{
70 		m_value = val;
71 	}
72 
73 	explicit	RGBA					(const Vec4& v);
74 
setRed(int v)75 	void		setRed					(int v) { DE_ASSERT(deInRange32(v, 0, 255)); m_value = (m_value & ~(0xFF << RED_SHIFT)) | (v << RED_SHIFT); }
setGreen(int v)76 	void		setGreen				(int v) { DE_ASSERT(deInRange32(v, 0, 255)); m_value = (m_value & ~(0xFF << GREEN_SHIFT)) | (v << GREEN_SHIFT); }
setBlue(int v)77 	void		setBlue					(int v) { DE_ASSERT(deInRange32(v, 0, 255)); m_value = (m_value & ~(0xFF << BLUE_SHIFT)) | (v << BLUE_SHIFT); }
setAlpha(int v)78 	void		setAlpha				(int v) { DE_ASSERT(deInRange32(v, 0, 255)); m_value = (m_value & ~(0xFF << ALPHA_SHIFT)) | (v << ALPHA_SHIFT); }
getRed(void) const79 	int			getRed					(void) const { return (m_value >> RED_SHIFT) & 0xFF; }
getGreen(void) const80 	int			getGreen				(void) const { return (m_value >> GREEN_SHIFT) & 0xFF; }
getBlue(void) const81 	int			getBlue					(void) const { return (m_value >> BLUE_SHIFT) & 0xFF; }
getAlpha(void) const82 	int			getAlpha				(void) const { return (m_value >> ALPHA_SHIFT) & 0xFF; }
getPacked(void) const83 	deUint32	getPacked				(void) const { return m_value; }
84 
isBelowThreshold(RGBA thr) const85 	bool		isBelowThreshold		(RGBA thr) const	{ return (getRed() <= thr.getRed()) && (getGreen() <= thr.getGreen()) && (getBlue() <= thr.getBlue()) && (getAlpha() <= thr.getAlpha()); }
86 
fromBytes(const deUint8 * bytes)87 	static RGBA	fromBytes				(const deUint8* bytes)	{ return RGBA(bytes[0], bytes[1], bytes[2], bytes[3]); }
toBytes(deUint8 * bytes) const88 	void		toBytes					(deUint8* bytes) const	{ bytes[0] = getRed(); bytes[1] = getGreen(); bytes[2] = getBlue(); bytes[3] = getAlpha(); }
89 	Vec4		toVec					(void) const;
90 	IVec4		toIVec					(void) const;
91 
operator ==(const RGBA & v) const92 	bool		operator==				(const RGBA& v) const { return (m_value == v.m_value); }
operator !=(const RGBA & v) const93 	bool		operator!=				(const RGBA& v) const { return (m_value != v.m_value); }
94 
95 	// Color constants
96 	const static RGBA	red;
97 	const static RGBA	green;
98 	const static RGBA	blue;
99 	const static RGBA	gray;
100 	const static RGBA	white;
101 	const static RGBA	black;
102 
103 private:
104 	deUint32	m_value;
105 } DE_WARN_UNUSED_TYPE;
106 
compareEqualMasked(RGBA a,RGBA b,deUint32 cmpMask)107 inline bool compareEqualMasked (RGBA a, RGBA b, deUint32 cmpMask)
108 {
109 	RGBA		mask((cmpMask&RGBA::RED_MASK)?0xFF:0, (cmpMask&RGBA::GREEN_MASK)?0xFF:0, (cmpMask&RGBA::BLUE_MASK)?0xFF:0, (cmpMask&RGBA::ALPHA_MASK)?0xFF:0);
110 	deUint32	aPacked		= a.getPacked();
111 	deUint32	bPacked		= b.getPacked();
112 	deUint32	maskPacked	= mask.getPacked();
113 	return (aPacked & maskPacked) == (bPacked & maskPacked);
114 }
115 
computeAbsDiff(RGBA a,RGBA b)116 inline RGBA computeAbsDiff (RGBA a, RGBA b)
117 {
118 	return RGBA(
119 		deAbs32(a.getRed()   - b.getRed()),
120 		deAbs32(a.getGreen() - b.getGreen()),
121 		deAbs32(a.getBlue()  - b.getBlue()),
122 		deAbs32(a.getAlpha() - b.getAlpha()));
123 }
124 
blend(RGBA a,RGBA b,float t)125 inline RGBA blend (RGBA a, RGBA b, float t)
126 {
127 	DE_ASSERT(t >= 0.0f && t <= 1.0f);
128 	float it = 1.0f - t;
129 	// \todo [petri] Handling of alpha!
130 	return RGBA(
131 		(int)(it*(float)a.getRed() + t*(float)b.getRed() + 0.5f),
132 		(int)(it*(float)a.getGreen() + t*(float)b.getGreen() + 0.5f),
133 		(int)(it*(float)a.getBlue() + t*(float)b.getBlue() + 0.5f),
134 		(int)(it*(float)a.getAlpha() + t*(float)b.getAlpha() + 0.5f));
135 }
136 
compareThreshold(RGBA a,RGBA b,RGBA threshold)137 inline bool compareThreshold (RGBA a, RGBA b, RGBA threshold)
138 {
139 	if (a == b) return true;	// Quick-accept
140 	return computeAbsDiff(a, b).isBelowThreshold(threshold);
141 }
142 
max(RGBA a,RGBA b)143 inline RGBA max (RGBA a, RGBA b)
144 {
145 	return RGBA(deMax32(a.getRed(),		b.getRed()),
146 				deMax32(a.getGreen(),	b.getGreen()),
147 				deMax32(a.getBlue(),	b.getBlue()),
148 				deMax32(a.getAlpha(),	b.getAlpha()));
149 }
150 
151 RGBA computeAbsDiffMasked	(RGBA a, RGBA b, deUint32 cmpMask);
152 bool compareThresholdMasked	(RGBA a, RGBA b, RGBA threshold, deUint32 cmpMask);
153 
154 // Arithmetic operators (saturating if not stated otherwise).
155 
operator +(const RGBA & a,const RGBA & b)156 inline RGBA operator+ (const RGBA& a, const RGBA& b)
157 {
158 	return RGBA(deClamp32(a.getRed()	+ b.getRed(),	0, 255),
159 				deClamp32(a.getGreen()	+ b.getGreen(),	0, 255),
160 				deClamp32(a.getBlue()	+ b.getBlue(),	0, 255),
161 				deClamp32(a.getAlpha()	+ b.getAlpha(),	0, 255));
162 }
163 
operator -(const RGBA & a,const RGBA & b)164 inline RGBA operator- (const RGBA& a, const RGBA& b)
165 {
166 	return RGBA(deClamp32(a.getRed()	- b.getRed(),	0, 255),
167 				deClamp32(a.getGreen()	- b.getGreen(),	0, 255),
168 				deClamp32(a.getBlue()	- b.getBlue(),	0, 255),
169 				deClamp32(a.getAlpha()	- b.getAlpha(),	0, 255));
170 }
171 
operator *(const RGBA & a,const int b)172 inline RGBA operator* (const RGBA& a, const int b)
173 {
174 	return RGBA(deClamp32(a.getRed()	* b,	0, 255),
175 				deClamp32(a.getGreen()	* b,	0, 255),
176 				deClamp32(a.getBlue()	* b,	0, 255),
177 				deClamp32(a.getAlpha()	* b,	0, 255));
178 }
179 
operator <<(std::ostream & stream,RGBA c)180 inline std::ostream& operator<< (std::ostream& stream, RGBA c)
181 {
182 	return stream << "RGBA(" << c.getRed() << ", " << c.getGreen() << ", " << c.getBlue() << ", " << c.getAlpha() << ")";
183 }
184 
185 } // tcu
186 
187 #endif // _TCURGBA_HPP
188