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 57 RGBA (void) { m_value = 0; } 58 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 68 explicit RGBA (deUint32 val) 69 { 70 m_value = val; 71 } 72 73 explicit RGBA (const Vec4& v); 74 75 void setRed (int v) { DE_ASSERT(deInRange32(v, 0, 255)); m_value = (m_value & ~((deUint32)0xFFu << RED_SHIFT)) | ((deUint32)v << RED_SHIFT); } 76 void setGreen (int v) { DE_ASSERT(deInRange32(v, 0, 255)); m_value = (m_value & ~((deUint32)0xFFu << GREEN_SHIFT)) | ((deUint32)v << GREEN_SHIFT); } 77 void setBlue (int v) { DE_ASSERT(deInRange32(v, 0, 255)); m_value = (m_value & ~((deUint32)0xFFu << BLUE_SHIFT)) | ((deUint32)v << BLUE_SHIFT); } 78 void setAlpha (int v) { DE_ASSERT(deInRange32(v, 0, 255)); m_value = (m_value & ~((deUint32)0xFFu << ALPHA_SHIFT)) | ((deUint32)v << ALPHA_SHIFT); } 79 int getRed (void) const { return (int)((m_value >> (deUint32)RED_SHIFT) & 0xFFu); } 80 int getGreen (void) const { return (int)((m_value >> (deUint32)GREEN_SHIFT) & 0xFFu); } 81 int getBlue (void) const { return (int)((m_value >> (deUint32)BLUE_SHIFT) & 0xFFu); } 82 int getAlpha (void) const { return (int)((m_value >> (deUint32)ALPHA_SHIFT) & 0xFFu); } 83 deUint32 getPacked (void) const { return m_value; } 84 85 bool isBelowThreshold (RGBA thr) const { return (getRed() <= thr.getRed()) && (getGreen() <= thr.getGreen()) && (getBlue() <= thr.getBlue()) && (getAlpha() <= thr.getAlpha()); } 86 87 static RGBA fromBytes (const deUint8* bytes) { return RGBA(bytes[0], bytes[1], bytes[2], bytes[3]); } 88 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 92 bool operator== (const RGBA& v) const { return (m_value == v.m_value); } 93 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. 96 static inline const RGBA red (void) { return RGBA(0xFF, 0x0, 0x0, 0xFF); } 97 static inline const RGBA green (void) { return RGBA(0x0, 0xFF, 0x0, 0xFF); } 98 static inline const RGBA blue (void) { return RGBA(0x0, 0x0, 0xFF, 0xFF); } 99 static inline const RGBA gray (void) { return RGBA(0x80, 0x80, 0x80, 0xFF); } 100 static inline const RGBA white (void) { return RGBA(0xFF, 0xFF, 0xFF, 0xFF); } 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 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 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 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 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 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 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 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 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 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