xref: /aosp_15_r20/external/deqp/modules/gles2/functional/es2fShaderAlgorithmTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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,
53                         ShaderEvalFunc evalFunc, const char *vertShaderSource, const char *fragShaderSource);
54     virtual ~ShaderAlgorithmCase(void);
55 
56 private:
57     ShaderAlgorithmCase(const ShaderAlgorithmCase &);            // not allowed!
58     ShaderAlgorithmCase &operator=(const ShaderAlgorithmCase &); // not allowed!
59 };
60 
ShaderAlgorithmCase(Context & context,const char * name,const char * description,bool isVertexCase,ShaderEvalFunc evalFunc,const char * vertShaderSource,const char * fragShaderSource)61 ShaderAlgorithmCase::ShaderAlgorithmCase(Context &context, const char *name, const char *description, bool isVertexCase,
62                                          ShaderEvalFunc evalFunc, const char *vertShaderSource,
63                                          const char *fragShaderSource)
64     : ShaderRenderCase(context.getTestContext(), context.getRenderContext(), context.getContextInfo(), name,
65                        description, isVertexCase, evalFunc)
66 {
67     m_vertShaderSource = vertShaderSource;
68     m_fragShaderSource = fragShaderSource;
69 }
70 
~ShaderAlgorithmCase(void)71 ShaderAlgorithmCase::~ShaderAlgorithmCase(void)
72 {
73 }
74 
75 // Helpers.
76 
createExpressionCase(Context & context,const char * caseName,const char * description,bool isVertexCase,ShaderEvalFunc evalFunc,LineStream & shaderBody)77 static ShaderAlgorithmCase *createExpressionCase(Context &context, const char *caseName, const char *description,
78                                                  bool isVertexCase, ShaderEvalFunc evalFunc, LineStream &shaderBody)
79 {
80     std::ostringstream vtx;
81     std::ostringstream frag;
82     std::ostringstream &op = isVertexCase ? vtx : frag;
83 
84     vtx << "attribute highp vec4 a_position;\n";
85     vtx << "attribute highp vec4 a_unitCoords;\n";
86 
87     if (isVertexCase)
88     {
89         vtx << "varying mediump vec3 v_color;\n";
90         frag << "varying mediump vec3 v_color;\n";
91     }
92     else
93     {
94         vtx << "varying mediump vec4 v_coords;\n";
95         frag << "varying mediump vec4 v_coords;\n";
96     }
97 
98     // op << "uniform mediump sampler2D ut_brick;\n";
99 
100     vtx << "\n";
101     vtx << "void main()\n";
102     vtx << "{\n";
103     vtx << "    gl_Position = a_position;\n";
104 
105     frag << "\n";
106     frag << "void main()\n";
107     frag << "{\n";
108 
109     // Write matrix.
110     if (isVertexCase)
111         op << "    ${PRECISION} vec4 coords = a_unitCoords;\n";
112     else
113         op << "    ${PRECISION} vec4 coords = v_coords;\n";
114 
115     op << "    ${PRECISION} vec3 res = vec3(0.0);\n";
116     op << shaderBody.str();
117 
118     if (isVertexCase)
119     {
120         vtx << "    v_color = res;\n";
121         frag << "    gl_FragColor = vec4(v_color, 1.0);\n";
122     }
123     else
124     {
125         vtx << "    v_coords = a_unitCoords;\n";
126         frag << "    gl_FragColor = vec4(res, 1.0);\n";
127     }
128 
129     vtx << "}\n";
130     frag << "}\n";
131 
132     // Fill in shader templates.
133     map<string, string> params;
134     params.insert(pair<string, string>("PRECISION", "mediump"));
135 
136     StringTemplate vertTemplate(vtx.str().c_str());
137     StringTemplate fragTemplate(frag.str().c_str());
138     string vertexShaderSource   = vertTemplate.specialize(params);
139     string fragmentShaderSource = fragTemplate.specialize(params);
140 
141     return new ShaderAlgorithmCase(context, caseName, description, isVertexCase, evalFunc, vertexShaderSource.c_str(),
142                                    fragmentShaderSource.c_str());
143 }
144 
145 // ShaderAlgorithmTests.
146 
ShaderAlgorithmTests(Context & context)147 ShaderAlgorithmTests::ShaderAlgorithmTests(Context &context)
148     : TestCaseGroup(context, "algorithm", "Miscellaneous algorithm implementations using shaders.")
149 {
150 }
151 
~ShaderAlgorithmTests(void)152 ShaderAlgorithmTests::~ShaderAlgorithmTests(void)
153 {
154 }
155 
init(void)156 void ShaderAlgorithmTests::init(void)
157 {
158     // TestCaseGroup* colorGroup = new TestCaseGroup(m_testCtx, "color", "Miscellaneous color related algorithm tests.");
159     // addChild(colorGroup);
160 
161 #define SHADER_OP_CASE(NAME, DESCRIPTION, SHADER_OP, EVAL_FUNC_BODY)                                                  \
162     do                                                                                                                \
163     {                                                                                                                 \
164         struct Eval_##NAME                                                                                            \
165         {                                                                                                             \
166             static void eval(ShaderEvalContext &c) EVAL_FUNC_BODY                                                     \
167         }; /* NOLINT(EVAL_FUNC_BODY) */                                                                               \
168         addChild(createExpressionCase(m_context, #NAME "_vertex", DESCRIPTION, true, &Eval_##NAME::eval, SHADER_OP)); \
169         addChild(                                                                                                     \
170             createExpressionCase(m_context, #NAME "_fragment", DESCRIPTION, false, &Eval_##NAME::eval, SHADER_OP));   \
171     } while (false)
172 
173     SHADER_OP_CASE(hsl_to_rgb, "Conversion from HSL color space into RGB.",
174                    LineStream(1) << "mediump float H = coords.x, S = coords.y, L = coords.z;"
175                                  << "mediump float v = (L <= 0.5) ? (L * (1.0 + S)) : (L + S - L * S);"
176                                  << "res = vec3(L); // default to gray"
177                                  << "if (v > 0.0)"
178                                  << "{"
179                                  << "    mediump float m = L + L - v;"
180                                  << "    mediump float sv = (v - m) / v;"
181                                  << "    H *= 6.0;"
182                                  << "    mediump int sextant = int(H);"
183                                  << "    mediump float fract = H - float(sextant);"
184                                  << "    mediump float vsf = v * sv * fract;"
185                                  << "    mediump float mid1 = m + vsf;"
186                                  << "    mediump float mid2 = m - vsf;"
187                                  << "    if (sextant == 0)      res = vec3(v, mid1, m);"
188                                  << "    else if (sextant == 1) res = vec3(mid2, v, m);"
189                                  << "    else if (sextant == 2) res = vec3(m, v, mid1);"
190                                  << "    else if (sextant == 3) res = vec3(m, mid2, v);"
191                                  << "    else if (sextant == 4) res = vec3(mid1, m, v);"
192                                  << "    else                   res = vec3(v, m, mid2);"
193                                  << "}",
194                    {
195                        float H  = c.unitCoords.x();
196                        float S  = c.unitCoords.y();
197                        float L  = c.unitCoords.z();
198                        Vec3 rgb = Vec3(L);
199                        float v  = (L <= 0.5f) ? (L * (1.0f + S)) : (L + S - L * S);
200                        if (v > 0.0f)
201                        {
202                            float m  = L + L - v;
203                            float sv = (v - m) / v;
204                            H *= 6.0f;
205                            int sextant = int(H);
206                            float fract = H - float(sextant);
207                            float vsf   = v * sv * fract;
208                            float mid1  = m + vsf;
209                            float mid2  = m - vsf;
210                            if (sextant == 0)
211                                rgb = Vec3(v, mid1, m);
212                            else if (sextant == 1)
213                                rgb = Vec3(mid2, v, m);
214                            else if (sextant == 2)
215                                rgb = Vec3(m, v, mid1);
216                            else if (sextant == 3)
217                                rgb = Vec3(m, mid2, v);
218                            else if (sextant == 4)
219                                rgb = Vec3(mid1, m, v);
220                            else
221                                rgb = Vec3(v, m, mid2);
222                        }
223                        c.color.xyz() = rgb;
224                    });
225 
226     SHADER_OP_CASE(rgb_to_hsl, "Conversion from RGB color space into HSL.",
227                    LineStream(1) << "mediump float r = coords.x, g = coords.y, b = coords.z;"
228                                  << "mediump float minVal = min(min(r, g), b);"
229                                  << "mediump float maxVal = max(max(r, g), b);"
230                                  << "mediump float L = (minVal + maxVal) * 0.5;"
231                                  << "if (minVal == maxVal)"
232                                  << "    res = vec3(0.0, 0.0, L);"
233                                  << "else"
234                                  << "{"
235                                  << "    mediump float H;"
236                                  << "    mediump float S;"
237                                  << "    if (L < 0.5)"
238                                  << "        S = (maxVal - minVal) / (maxVal + minVal);"
239                                  << "    else"
240                                  << "        S = (maxVal - minVal) / (2.0 - maxVal - minVal);"
241                                  << ""
242                                  << "    mediump float ooDiff = 1.0 / (maxVal - minVal);"
243                                  << "    if (r == maxVal)      H = (g - b) * ooDiff;"
244                                  << "    else if (g == maxVal) H = 2.0 + (b - r) * ooDiff;"
245                                  << "    else                  H = 4.0 + (r - g) * ooDiff;"
246                                  << "    H /= 6.0;"
247                                  << ""
248                                  << "    res = vec3(H, S, L);"
249                                  << "}",
250                    {
251                        float r      = c.unitCoords.x();
252                        float g      = c.unitCoords.y();
253                        float b      = c.unitCoords.z();
254                        float minVal = min(min(r, g), b);
255                        float maxVal = max(max(r, g), b);
256                        float L      = (minVal + maxVal) * 0.5f;
257                        Vec3 hsl;
258 
259                        if (minVal == maxVal)
260                            hsl = Vec3(0.0f, 0.0f, L);
261                        else
262                        {
263                            float H;
264                            float S;
265                            if (L < 0.5f)
266                                S = (maxVal - minVal) / (maxVal + minVal);
267                            else
268                                S = (maxVal - minVal) / (2.0f - maxVal - minVal);
269 
270                            float ooDiff = 1.0f / (maxVal - minVal);
271                            if (r == maxVal)
272                                H = (g - b) * ooDiff;
273                            else if (g == maxVal)
274                                H = 2.0f + (b - r) * ooDiff;
275                            else
276                                H = 4.0f + (r - g) * ooDiff;
277                            H /= 6.0f;
278 
279                            hsl = Vec3(H, S, L);
280                        }
281                        c.color.xyz() = hsl;
282                    });
283 
284     /*    SHADER_OP_CASE(image_to_grayscale, "Convert image to grayscale.",
285             LineStream(1)
286             << "res = texture2D(ut_brick, coords.xy).rgb;",
287             {
288                 c.color.xyz() = Vec3(0.5f);
289             });*/
290 }
291 
292 } // namespace Functional
293 } // namespace gles2
294 } // namespace deqp
295