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