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 = ((deUint32)a << ALPHA_SHIFT) | ((deUint32)r << RED_SHIFT) | ((deUint32)g << GREEN_SHIFT) | ((deUint32)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 & ~((deUint32)0xFFu << RED_SHIFT)) | ((deUint32)v << RED_SHIFT); }
setGreen(int v)76 void setGreen (int v) { DE_ASSERT(deInRange32(v, 0, 255)); m_value = (m_value & ~((deUint32)0xFFu << GREEN_SHIFT)) | ((deUint32)v << GREEN_SHIFT); }
setBlue(int v)77 void setBlue (int v) { DE_ASSERT(deInRange32(v, 0, 255)); m_value = (m_value & ~((deUint32)0xFFu << BLUE_SHIFT)) | ((deUint32)v << BLUE_SHIFT); }
setAlpha(int v)78 void setAlpha (int v) { DE_ASSERT(deInRange32(v, 0, 255)); m_value = (m_value & ~((deUint32)0xFFu << ALPHA_SHIFT)) | ((deUint32)v << ALPHA_SHIFT); }
getRed(void) const79 int getRed (void) const { return (int)((m_value >> (deUint32)RED_SHIFT) & 0xFFu); }
getGreen(void) const80 int getGreen (void) const { return (int)((m_value >> (deUint32)GREEN_SHIFT) & 0xFFu); }
getBlue(void) const81 int getBlue (void) const { return (int)((m_value >> (deUint32)BLUE_SHIFT) & 0xFFu); }
getAlpha(void) const82 int getAlpha (void) const { return (int)((m_value >> (deUint32)ALPHA_SHIFT) & 0xFFu); }
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] = (deUint8)getRed(); bytes[1] = (deUint8)getGreen(); bytes[2] = (deUint8)getBlue(); bytes[3] = (deUint8)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. Designed as methods to avoid static-initialization-order fiasco.
red(void)96 static inline const RGBA red (void) { return RGBA(0xFF, 0x0, 0x0, 0xFF); }
green(void)97 static inline const RGBA green (void) { return RGBA(0x0, 0xFF, 0x0, 0xFF); }
blue(void)98 static inline const RGBA blue (void) { return RGBA(0x0, 0x0, 0xFF, 0xFF); }
gray(void)99 static inline const RGBA gray (void) { return RGBA(0x80, 0x80, 0x80, 0xFF); }
white(void)100 static inline const RGBA white (void) { return RGBA(0xFF, 0xFF, 0xFF, 0xFF); }
black(void)101 static inline const RGBA black (void) { return RGBA(0x0, 0x0, 0x0, 0xFF); }
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