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
35 using namespace std;
36 using namespace tcu;
37 using namespace glu;
38 using namespace deqp::gls;
39
40 namespace deqp
41 {
42 namespace gles2
43 {
44 namespace Functional
45 {
46
47 // ShaderAlgorithmCase
48
49 class ShaderAlgorithmCase : public ShaderRenderCase
50 {
51 public:
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
55 private:
56 ShaderAlgorithmCase (const ShaderAlgorithmCase&); // not allowed!
57 ShaderAlgorithmCase& operator= (const ShaderAlgorithmCase&); // not allowed!
58 };
59
ShaderAlgorithmCase(Context & context,const char * name,const char * description,bool isVertexCase,ShaderEvalFunc evalFunc,const char * vertShaderSource,const char * fragShaderSource)60 ShaderAlgorithmCase::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
~ShaderAlgorithmCase(void)67 ShaderAlgorithmCase::~ShaderAlgorithmCase (void)
68 {
69 }
70
71 // Helpers.
72
createExpressionCase(Context & context,const char * caseName,const char * description,bool isVertexCase,ShaderEvalFunc evalFunc,LineStream & shaderBody)73 static 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
ShaderAlgorithmTests(Context & context)141 ShaderAlgorithmTests::ShaderAlgorithmTests(Context& context)
142 : TestCaseGroup(context, "algorithm", "Miscellaneous algorithm implementations using shaders.")
143 {
144 }
145
~ShaderAlgorithmTests(void)146 ShaderAlgorithmTests::~ShaderAlgorithmTests (void)
147 {
148 }
149
init(void)150 void 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