1/*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL ES 2.0 Module 3 * ------------------------------------------------- 4 * 5 * Copyright 2014 The Android Open Source Project 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 *//*! 20 * \file 21 * \brief Algorithm implementation tests. 22 *//*--------------------------------------------------------------------*/ 23 24#include "es2fShaderAlgorithmTests.hpp" 25#include "glsShaderRenderCase.hpp" 26#include "gluShaderUtil.hpp" 27#include "tcuStringTemplate.hpp" 28 29#include "deInt32.h" 30#include "deMemory.h" 31 32#include <map> 33#include <algorithm> 34 35using namespace std; 36using namespace tcu; 37using namespace glu; 38using namespace deqp::gls; 39 40namespace deqp 41{ 42namespace gles2 43{ 44namespace Functional 45{ 46 47// ShaderAlgorithmCase 48 49class ShaderAlgorithmCase : public ShaderRenderCase 50{ 51public: 52 ShaderAlgorithmCase (Context& context, const char* name, const char* description, bool isVertexCase, ShaderEvalFunc evalFunc, const char* vertShaderSource, const char* fragShaderSource); 53 virtual ~ShaderAlgorithmCase (void); 54 55private: 56 ShaderAlgorithmCase (const ShaderAlgorithmCase&); // not allowed! 57 ShaderAlgorithmCase& operator= (const ShaderAlgorithmCase&); // not allowed! 58}; 59 60ShaderAlgorithmCase::ShaderAlgorithmCase (Context& context, const char* name, const char* description, bool isVertexCase, ShaderEvalFunc evalFunc, const char* vertShaderSource, const char* fragShaderSource) 61 : ShaderRenderCase(context.getTestContext(), context.getRenderContext(), context.getContextInfo(), name, description, isVertexCase, evalFunc) 62{ 63 m_vertShaderSource = vertShaderSource; 64 m_fragShaderSource = fragShaderSource; 65} 66 67ShaderAlgorithmCase::~ShaderAlgorithmCase (void) 68{ 69} 70 71// Helpers. 72 73static ShaderAlgorithmCase* createExpressionCase (Context& context, const char* caseName, const char* description, bool isVertexCase, ShaderEvalFunc evalFunc, LineStream& shaderBody) 74{ 75 std::ostringstream vtx; 76 std::ostringstream frag; 77 std::ostringstream& op = isVertexCase ? vtx : frag; 78 79 vtx << "attribute highp vec4 a_position;\n"; 80 vtx << "attribute highp vec4 a_unitCoords;\n"; 81 82 if (isVertexCase) 83 { 84 vtx << "varying mediump vec3 v_color;\n"; 85 frag << "varying mediump vec3 v_color;\n"; 86 } 87 else 88 { 89 vtx << "varying mediump vec4 v_coords;\n"; 90 frag << "varying mediump vec4 v_coords;\n"; 91 } 92 93// op << "uniform mediump sampler2D ut_brick;\n"; 94 95 vtx << "\n"; 96 vtx << "void main()\n"; 97 vtx << "{\n"; 98 vtx << " gl_Position = a_position;\n"; 99 100 frag << "\n"; 101 frag << "void main()\n"; 102 frag << "{\n"; 103 104 // Write matrix. 105 if (isVertexCase) 106 op << " ${PRECISION} vec4 coords = a_unitCoords;\n"; 107 else 108 op << " ${PRECISION} vec4 coords = v_coords;\n"; 109 110 op << " ${PRECISION} vec3 res = vec3(0.0);\n"; 111 op << shaderBody.str(); 112 113 if (isVertexCase) 114 { 115 vtx << " v_color = res;\n"; 116 frag << " gl_FragColor = vec4(v_color, 1.0);\n"; 117 } 118 else 119 { 120 vtx << " v_coords = a_unitCoords;\n"; 121 frag << " gl_FragColor = vec4(res, 1.0);\n"; 122 } 123 124 vtx << "}\n"; 125 frag << "}\n"; 126 127 // Fill in shader templates. 128 map<string, string> params; 129 params.insert(pair<string, string>("PRECISION", "mediump")); 130 131 StringTemplate vertTemplate(vtx.str().c_str()); 132 StringTemplate fragTemplate(frag.str().c_str()); 133 string vertexShaderSource = vertTemplate.specialize(params); 134 string fragmentShaderSource = fragTemplate.specialize(params); 135 136 return new ShaderAlgorithmCase(context, caseName, description, isVertexCase, evalFunc, vertexShaderSource.c_str(), fragmentShaderSource.c_str()); 137} 138 139// ShaderAlgorithmTests. 140 141ShaderAlgorithmTests::ShaderAlgorithmTests(Context& context) 142 : TestCaseGroup(context, "algorithm", "Miscellaneous algorithm implementations using shaders.") 143{ 144} 145 146ShaderAlgorithmTests::~ShaderAlgorithmTests (void) 147{ 148} 149 150void ShaderAlgorithmTests::init (void) 151{ 152// TestCaseGroup* colorGroup = new TestCaseGroup(m_testCtx, "color", "Miscellaneous color related algorithm tests."); 153// addChild(colorGroup); 154 155 #define SHADER_OP_CASE(NAME, DESCRIPTION, SHADER_OP, EVAL_FUNC_BODY) \ 156 do { \ 157 struct Eval_##NAME { static void eval (ShaderEvalContext& c) EVAL_FUNC_BODY }; \ 158 addChild(createExpressionCase(m_context, #NAME "_vertex", DESCRIPTION, true, &Eval_##NAME::eval, SHADER_OP)); \ 159 addChild(createExpressionCase(m_context, #NAME "_fragment", DESCRIPTION, false, &Eval_##NAME::eval, SHADER_OP)); \ 160 } while (deGetFalse()) 161 162 SHADER_OP_CASE(hsl_to_rgb, "Conversion from HSL color space into RGB.", 163 LineStream(1) 164 << "mediump float H = coords.x, S = coords.y, L = coords.z;" 165 << "mediump float v = (L <= 0.5) ? (L * (1.0 + S)) : (L + S - L * S);" 166 << "res = vec3(L); // default to gray" 167 << "if (v > 0.0)" 168 << "{" 169 << " mediump float m = L + L - v;" 170 << " mediump float sv = (v - m) / v;" 171 << " H *= 6.0;" 172 << " mediump int sextant = int(H);" 173 << " mediump float fract = H - float(sextant);" 174 << " mediump float vsf = v * sv * fract;" 175 << " mediump float mid1 = m + vsf;" 176 << " mediump float mid2 = m - vsf;" 177 << " if (sextant == 0) res = vec3(v, mid1, m);" 178 << " else if (sextant == 1) res = vec3(mid2, v, m);" 179 << " else if (sextant == 2) res = vec3(m, v, mid1);" 180 << " else if (sextant == 3) res = vec3(m, mid2, v);" 181 << " else if (sextant == 4) res = vec3(mid1, m, v);" 182 << " else res = vec3(v, m, mid2);" 183 << "}", 184 { 185 float H = c.unitCoords.x(); 186 float S = c.unitCoords.y(); 187 float L = c.unitCoords.z(); 188 Vec3 rgb = Vec3(L); 189 float v = (L <= 0.5f) ? (L * (1.0f + S)) : (L + S - L * S); 190 if (v > 0.0f) 191 { 192 float m = L + L - v; 193 float sv = (v - m) / v; 194 H *= 6.0f; 195 int sextant = int(H); 196 float fract = H - float(sextant); 197 float vsf = v * sv * fract; 198 float mid1 = m + vsf; 199 float mid2 = m - vsf; 200 if (sextant == 0) rgb = Vec3(v, mid1, m); 201 else if (sextant == 1) rgb = Vec3(mid2, v, m); 202 else if (sextant == 2) rgb = Vec3(m, v, mid1); 203 else if (sextant == 3) rgb = Vec3(m, mid2, v); 204 else if (sextant == 4) rgb = Vec3(mid1, m, v); 205 else rgb = Vec3(v, m, mid2); 206 } 207 c.color.xyz() = rgb; 208 }); 209 210 SHADER_OP_CASE(rgb_to_hsl, "Conversion from RGB color space into HSL.", 211 LineStream(1) 212 << "mediump float r = coords.x, g = coords.y, b = coords.z;" 213 << "mediump float minVal = min(min(r, g), b);" 214 << "mediump float maxVal = max(max(r, g), b);" 215 << "mediump float L = (minVal + maxVal) * 0.5;" 216 << "if (minVal == maxVal)" 217 << " res = vec3(0.0, 0.0, L);" 218 << "else" 219 << "{" 220 << " mediump float H;" 221 << " mediump float S;" 222 << " if (L < 0.5)" 223 << " S = (maxVal - minVal) / (maxVal + minVal);" 224 << " else" 225 << " S = (maxVal - minVal) / (2.0 - maxVal - minVal);" 226 << "" 227 << " mediump float ooDiff = 1.0 / (maxVal - minVal);" 228 << " if (r == maxVal) H = (g - b) * ooDiff;" 229 << " else if (g == maxVal) H = 2.0 + (b - r) * ooDiff;" 230 << " else H = 4.0 + (r - g) * ooDiff;" 231 << " H /= 6.0;" 232 << "" 233 << " res = vec3(H, S, L);" 234 << "}", 235 { 236 float r = c.unitCoords.x(); 237 float g = c.unitCoords.y(); 238 float b = c.unitCoords.z(); 239 float minVal = min(min(r, g), b); 240 float maxVal = max(max(r, g), b); 241 float L = (minVal + maxVal) * 0.5f; 242 Vec3 hsl; 243 244 if (minVal == maxVal) 245 hsl = Vec3(0.0f, 0.0f, L); 246 else 247 { 248 float H; 249 float S; 250 if (L < 0.5f) 251 S = (maxVal - minVal) / (maxVal + minVal); 252 else 253 S = (maxVal - minVal) / (2.0f - maxVal - minVal); 254 255 float ooDiff = 1.0f / (maxVal - minVal); 256 if (r == maxVal) H = (g - b) * ooDiff; 257 else if (g == maxVal) H = 2.0f + (b - r) * ooDiff; 258 else H = 4.0f + (r - g) * ooDiff; 259 H /= 6.0f; 260 261 hsl = Vec3(H, S, L); 262 } 263 c.color.xyz() = hsl; 264 }); 265 266/* SHADER_OP_CASE(image_to_grayscale, "Convert image to grayscale.", 267 LineStream(1) 268 << "res = texture2D(ut_brick, coords.xy).rgb;", 269 { 270 c.color.xyz() = Vec3(0.5f); 271 });*/ 272} 273 274} // Functional 275} // gles2 276} // deqp 277