Add new framebuffer fetch extension tests am: 2a609fb223
[platform/upstream/VK-GL-CTS.git] / modules / gles2 / functional / es2fBlendTests.cpp
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 Blend tests.
22  *//*--------------------------------------------------------------------*/
23
24 #include "es2fBlendTests.hpp"
25 #include "glsFragmentOpUtil.hpp"
26 #include "gluPixelTransfer.hpp"
27 #include "gluStrUtil.hpp"
28 #include "tcuSurface.hpp"
29 #include "tcuImageCompare.hpp"
30 #include "tcuRenderTarget.hpp"
31 #include "tcuTestLog.hpp"
32 #include "tcuTextureUtil.hpp"
33 #include "deRandom.hpp"
34 #include "rrFragmentOperations.hpp"
35 #include "sglrReferenceUtils.hpp"
36
37 #include "glw.h"
38
39 #include <string>
40 #include <vector>
41
42 namespace deqp
43 {
44
45 using gls::FragmentOpUtil::Quad;
46 using gls::FragmentOpUtil::IntegerQuad;
47 using gls::FragmentOpUtil::QuadRenderer;
48 using gls::FragmentOpUtil::ReferenceQuadRenderer;
49 using glu::getBlendEquationName;
50 using glu::getBlendFactorName;
51 using tcu::Vec4;
52 using tcu::UVec4;
53 using tcu::TestLog;
54 using tcu::Surface;
55 using tcu::TextureFormat;
56 using tcu::TextureLevel;
57 using std::string;
58 using std::vector;
59
60 namespace gles2
61 {
62 namespace Functional
63 {
64
65 static const int MAX_VIEWPORT_WIDTH             = 64;
66 static const int MAX_VIEWPORT_HEIGHT    = 64;
67
68 struct BlendParams
69 {
70         GLenum  equationRGB;
71         GLenum  srcFuncRGB;
72         GLenum  dstFuncRGB;
73         GLenum  equationAlpha;
74         GLenum  srcFuncAlpha;
75         GLenum  dstFuncAlpha;
76         Vec4    blendColor;
77
78         BlendParams (GLenum             equationRGB_,
79                                  GLenum         srcFuncRGB_,
80                                  GLenum         dstFuncRGB_,
81                                  GLenum         equationAlpha_,
82                                  GLenum         srcFuncAlpha_,
83                                  GLenum         dstFuncAlpha_,
84                                  Vec4           blendColor_)
85         : equationRGB   (equationRGB_)
86         , srcFuncRGB    (srcFuncRGB_)
87         , dstFuncRGB    (dstFuncRGB_)
88         , equationAlpha (equationAlpha_)
89         , srcFuncAlpha  (srcFuncAlpha_)
90         , dstFuncAlpha  (dstFuncAlpha_)
91         , blendColor    (blendColor_)
92         {
93         }
94 };
95
96 class BlendCase : public TestCase
97 {
98 public:
99                                                         BlendCase       (Context&                                               context,
100                                                                                  const char*                                    name,
101                                                                                  const char*                                    desc,
102                                                                                  const vector<BlendParams>&             paramSets);
103
104                                                         ~BlendCase      (void);
105
106         void                                    init            (void);
107         void                                    deinit          (void);
108
109         IterateResult                   iterate         (void);
110
111 private:
112                                                         BlendCase       (const BlendCase& other);
113         BlendCase&                              operator=       (const BlendCase& other);
114
115         vector<BlendParams>             m_paramSets;
116         int                                             m_curParamSetNdx;
117
118         QuadRenderer*                   m_renderer;
119         ReferenceQuadRenderer*  m_referenceRenderer;
120         TextureLevel*                   m_refColorBuffer;
121         Quad                                    m_firstQuad;
122         Quad                                    m_secondQuad;
123         IntegerQuad                             m_firstQuadInt;
124         IntegerQuad                             m_secondQuadInt;
125
126         int                                             m_viewportW;
127         int                                             m_viewportH;
128 };
129
130 BlendCase::BlendCase (Context&                                          context,
131                                           const char*                                   name,
132                                           const char*                                   desc,
133                                           const vector<BlendParams>&    paramSets)
134         : TestCase                              (context, name, desc)
135         , m_paramSets                   (paramSets)
136         , m_curParamSetNdx              (0)
137         , m_renderer                    (DE_NULL)
138         , m_referenceRenderer   (DE_NULL)
139         , m_refColorBuffer              (DE_NULL)
140         , m_viewportW                   (0)
141         , m_viewportH                   (0)
142 {
143         DE_ASSERT(!m_paramSets.empty());
144         for (int i = 0; i < (int)m_paramSets.size(); i++)
145                 DE_ASSERT(m_paramSets[i].dstFuncRGB != GL_SRC_ALPHA_SATURATE && m_paramSets[i].dstFuncAlpha != GL_SRC_ALPHA_SATURATE);
146 }
147
148 void BlendCase::init (void)
149 {
150         bool useRGB = m_context.getRenderTarget().getPixelFormat().alphaBits == 0;
151
152         static const Vec4 baseGradientColors[4] =
153         {
154                 Vec4(0.0f, 0.5f, 1.0f, 0.5f),
155                 Vec4(0.5f, 0.0f, 0.5f, 1.0f),
156                 Vec4(0.5f, 1.0f, 0.5f, 0.0f),
157                 Vec4(1.0f, 0.5f, 0.0f, 0.5f)
158         };
159
160         DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(m_firstQuad.color) == DE_LENGTH_OF_ARRAY(m_firstQuadInt.color));
161         for (int i = 0; i < DE_LENGTH_OF_ARRAY(m_firstQuad.color); i++)
162         {
163                 m_firstQuad.color[i]            = (baseGradientColors[i] - 0.5f) * 0.2f + 0.5f;
164                 m_firstQuadInt.color[i]         = m_firstQuad.color[i];
165
166                 m_secondQuad.color[i]           = (Vec4(1.0f) - baseGradientColors[i] - 0.5f) * 1.0f + 0.5f;
167                 m_secondQuadInt.color[i]        = m_secondQuad.color[i];
168         }
169
170         m_viewportW = de::min<int>(m_context.getRenderTarget().getWidth(),      MAX_VIEWPORT_WIDTH);
171         m_viewportH = de::min<int>(m_context.getRenderTarget().getHeight(),     MAX_VIEWPORT_HEIGHT);
172
173         m_firstQuadInt.posA             = tcu::IVec2(0,                                 0);
174         m_secondQuadInt.posA    = tcu::IVec2(0,                                 0);
175         m_firstQuadInt.posB             = tcu::IVec2(m_viewportW-1,             m_viewportH-1);
176         m_secondQuadInt.posB    = tcu::IVec2(m_viewportW-1,             m_viewportH-1);
177
178         DE_ASSERT(!m_renderer);
179         DE_ASSERT(!m_referenceRenderer);
180         DE_ASSERT(!m_refColorBuffer);
181
182         m_renderer                              = new QuadRenderer(m_context.getRenderContext(), glu::GLSL_VERSION_100_ES);
183         m_referenceRenderer             = new ReferenceQuadRenderer;
184         m_refColorBuffer                = new TextureLevel(TextureFormat(useRGB ? TextureFormat::RGB : TextureFormat::RGBA, TextureFormat::UNORM_INT8),
185                                                                                            m_viewportW, m_viewportH);
186
187         m_curParamSetNdx = 0;
188 }
189
190 BlendCase::~BlendCase (void)
191 {
192         delete m_renderer;
193         delete m_referenceRenderer;
194         delete m_refColorBuffer;
195 }
196
197 void BlendCase::deinit (void)
198 {
199         delete m_renderer;
200         delete m_referenceRenderer;
201         delete m_refColorBuffer;
202
203         m_renderer                      = DE_NULL;
204         m_referenceRenderer     = DE_NULL;
205         m_refColorBuffer        = DE_NULL;
206 }
207
208 BlendCase::IterateResult BlendCase::iterate (void)
209 {
210         de::Random                                              rnd                             (deStringHash(getName()) ^ deInt32Hash(m_curParamSetNdx));
211         int                                                             viewportX               = rnd.getInt(0, m_context.getRenderTarget().getWidth() - m_viewportW);
212         int                                                             viewportY               = rnd.getInt(0, m_context.getRenderTarget().getHeight() - m_viewportH);
213         tcu::Surface                                    renderedImg             (m_viewportW, m_viewportH);
214         tcu::Surface                                    referenceImg    (m_viewportH, m_viewportH);
215         TestLog&                                                log                             (m_testCtx.getLog());
216         const BlendParams&                              paramSet                = m_paramSets[m_curParamSetNdx];
217         rr::FragmentOperationState              referenceState;
218
219         // Log the blend parameters.
220
221         log << TestLog::Message << "RGB equation = " << getBlendEquationName(paramSet.equationRGB) << TestLog::EndMessage;
222         log << TestLog::Message << "RGB src func = " << getBlendFactorName(paramSet.srcFuncRGB) << TestLog::EndMessage;
223         log << TestLog::Message << "RGB dst func = " << getBlendFactorName(paramSet.dstFuncRGB) << TestLog::EndMessage;
224         log << TestLog::Message << "Alpha equation = " << getBlendEquationName(paramSet.equationAlpha) << TestLog::EndMessage;
225         log << TestLog::Message << "Alpha src func = " << getBlendFactorName(paramSet.srcFuncAlpha) << TestLog::EndMessage;
226         log << TestLog::Message << "Alpha dst func = " << getBlendFactorName(paramSet.dstFuncAlpha) << TestLog::EndMessage;
227         log << TestLog::Message << "Blend color = (" << paramSet.blendColor.x() << ", " << paramSet.blendColor.y() << ", " << paramSet.blendColor.z() << ", " << paramSet.blendColor.w() << ")" << TestLog::EndMessage;
228
229         // Set GL state.
230
231         GLU_CHECK_CALL(glBlendEquationSeparate(paramSet.equationRGB, paramSet.equationAlpha));
232         GLU_CHECK_CALL(glBlendFuncSeparate(paramSet.srcFuncRGB, paramSet.dstFuncRGB, paramSet.srcFuncAlpha, paramSet.dstFuncAlpha));
233         GLU_CHECK_CALL(glBlendColor(paramSet.blendColor.x(), paramSet.blendColor.y(), paramSet.blendColor.z(), paramSet.blendColor.w()));
234
235         // Set reference state.
236
237         referenceState.blendRGBState.equation   = sglr::rr_util::mapGLBlendEquation(paramSet.equationRGB);
238         referenceState.blendRGBState.srcFunc    = sglr::rr_util::mapGLBlendFunc(paramSet.srcFuncRGB);
239         referenceState.blendRGBState.dstFunc    = sglr::rr_util::mapGLBlendFunc(paramSet.dstFuncRGB);
240         referenceState.blendAState.equation             = sglr::rr_util::mapGLBlendEquation(paramSet.equationAlpha);
241         referenceState.blendAState.srcFunc              = sglr::rr_util::mapGLBlendFunc(paramSet.srcFuncAlpha);
242         referenceState.blendAState.dstFunc              = sglr::rr_util::mapGLBlendFunc(paramSet.dstFuncAlpha);
243         referenceState.blendColor                               = paramSet.blendColor;
244
245         // Render with GL.
246
247         glDisable(GL_BLEND);
248         glViewport(viewportX, viewportY, m_viewportW, m_viewportH);
249         m_renderer->render(m_firstQuad);
250         glEnable(GL_BLEND);
251         m_renderer->render(m_secondQuad);
252         glFlush();
253
254         // Render reference.
255
256         const tcu::PixelBufferAccess nullAccess = tcu::PixelBufferAccess();
257
258         referenceState.blendMode = rr::BLENDMODE_NONE;
259         m_referenceRenderer->render(gls::FragmentOpUtil::getMultisampleAccess(m_refColorBuffer->getAccess()), nullAccess /* no depth */, nullAccess /* no stencil */, m_firstQuadInt, referenceState);
260         referenceState.blendMode = rr::BLENDMODE_STANDARD;
261         m_referenceRenderer->render(gls::FragmentOpUtil::getMultisampleAccess(m_refColorBuffer->getAccess()), nullAccess /* no depth */, nullAccess /* no stencil */, m_secondQuadInt, referenceState);
262
263         // Expand reference color buffer to RGBA8
264         copy(referenceImg.getAccess(), m_refColorBuffer->getAccess());
265
266         // Read GL image.
267
268         glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, renderedImg.getAccess());
269
270         // Compare images.
271
272         UVec4 compareThreshold = m_context.getRenderTarget().getPixelFormat().getColorThreshold().toIVec().asUint()
273                                                          * UVec4(5) / UVec4(2) + UVec4(3); // \note Non-scientific ad hoc formula. Need big threshold when few color bits; blending brings extra inaccuracy.
274
275         bool comparePass = tcu::intThresholdCompare(m_testCtx.getLog(), "CompareResult", "Image Comparison Result", referenceImg.getAccess(), renderedImg.getAccess(), compareThreshold, tcu::COMPARE_LOG_RESULT);
276
277         // Fail now if images don't match.
278
279         if (!comparePass)
280         {
281                 m_context.getTestContext().setTestResult(QP_TEST_RESULT_FAIL, "Image compare failed");
282                 return STOP;
283         }
284
285         // Continue if param sets still remain in m_paramSets; otherwise stop.
286
287         m_curParamSetNdx++;
288
289         if (m_curParamSetNdx < (int)m_paramSets.size())
290                 return CONTINUE;
291         else
292         {
293                 m_context.getTestContext().setTestResult(QP_TEST_RESULT_PASS, "Passed");
294                 return STOP;
295         }
296 }
297
298 BlendTests::BlendTests (Context& context)
299         : TestCaseGroup(context, "blend", "Blend tests")
300 {
301 }
302
303 BlendTests::~BlendTests (void)
304 {
305 }
306
307 void BlendTests::init (void)
308 {
309         struct EnumGL
310         {
311                 GLenum                  glValue;
312                 const char*             nameStr;
313         };
314
315         static const EnumGL blendEquations[] =
316         {
317                 { GL_FUNC_ADD,                                  "add"                                   },
318                 { GL_FUNC_SUBTRACT,                             "subtract"                              },
319                 { GL_FUNC_REVERSE_SUBTRACT,             "reverse_subtract"              }
320         };
321
322         static const EnumGL blendFunctions[] =
323         {
324                 { GL_ZERO,                                                      "zero"                                          },
325                 { GL_ONE,                                                       "one"                                           },
326                 { GL_SRC_COLOR,                                         "src_color"                                     },
327                 { GL_ONE_MINUS_SRC_COLOR,                       "one_minus_src_color"           },
328                 { GL_DST_COLOR,                                         "dst_color"                                     },
329                 { GL_ONE_MINUS_DST_COLOR,                       "one_minus_dst_color"           },
330                 { GL_SRC_ALPHA,                                         "src_alpha"                                     },
331                 { GL_ONE_MINUS_SRC_ALPHA,                       "one_minus_src_alpha"           },
332                 { GL_DST_ALPHA,                                         "dst_alpha"                                     },
333                 { GL_ONE_MINUS_DST_ALPHA,                       "one_minus_dst_alpha"           },
334                 { GL_CONSTANT_COLOR,                            "constant_color"                        },
335                 { GL_ONE_MINUS_CONSTANT_COLOR,          "one_minus_constant_color"      },
336                 { GL_CONSTANT_ALPHA,                            "constant_alpha"                        },
337                 { GL_ONE_MINUS_CONSTANT_ALPHA,          "one_minus_constant_alpha"      },
338                 { GL_SRC_ALPHA_SATURATE,                        "src_alpha_saturate"            }
339         };
340
341         const Vec4 defaultBlendColor(0.2f, 0.4f, 0.6f, 0.8f);
342
343         // Test all blend equation, src blend function, dst blend function combinations. RGB and alpha modes are the same.
344
345         {
346                 TestCaseGroup* group = new TestCaseGroup(m_context, "equation_src_func_dst_func", "Combinations of Blend Equations and Functions");
347                 addChild(group);
348
349                 for (int equationNdx = 0;       equationNdx < DE_LENGTH_OF_ARRAY(blendEquations);       equationNdx++)
350                 for (int srcFuncNdx = 0;        srcFuncNdx < DE_LENGTH_OF_ARRAY(blendFunctions);        srcFuncNdx++)
351                 for (int dstFuncNdx = 0;        dstFuncNdx < DE_LENGTH_OF_ARRAY(blendFunctions);        dstFuncNdx++)
352                 {
353                         const EnumGL& eq        = blendEquations[equationNdx];
354                         const EnumGL& src       = blendFunctions[srcFuncNdx];
355                         const EnumGL& dst       = blendFunctions[dstFuncNdx];
356
357                         if (dst.glValue == GL_SRC_ALPHA_SATURATE) // SRC_ALPHA_SATURATE is only valid for src func.
358                                 continue;
359
360                         string name                     = string("") + eq.nameStr + "_" + src.nameStr + "_" + dst.nameStr;
361                         string description      = string("") +
362                                                                   "Equations "          + getBlendEquationName(eq.glValue) +
363                                                                   ", src funcs "        + getBlendFactorName(src.glValue) +
364                                                                   ", dst funcs "        + getBlendFactorName(dst.glValue);
365
366                         vector<BlendParams> paramSets;
367                         paramSets.push_back(BlendParams(eq.glValue, src.glValue, dst.glValue, eq.glValue, src.glValue, dst.glValue, defaultBlendColor));
368
369                         group->addChild(new BlendCase(m_context, name.c_str(), description.c_str(), paramSets));
370                 }
371         }
372
373         // Test all RGB src, alpha src and RGB dst, alpha dst combinations. Equations are ADD.
374         // \note For all RGB src, alpha src combinations, also test a couple of different RGBA dst functions, and vice versa.
375
376         {
377                 TestCaseGroup* mainGroup = new TestCaseGroup(m_context, "rgb_func_alpha_func", "Combinations of RGB and Alpha Functions");
378                 addChild(mainGroup);
379                 TestCaseGroup* srcGroup = new TestCaseGroup(m_context, "src", "Source functions");
380                 TestCaseGroup* dstGroup = new TestCaseGroup(m_context, "dst", "Destination functions");
381                 mainGroup->addChild(srcGroup);
382                 mainGroup->addChild(dstGroup);
383
384                 for (int isDstI = 0;            isDstI <= 1;                                                                            isDstI++)
385                 for (int rgbFuncNdx = 0;        rgbFuncNdx < DE_LENGTH_OF_ARRAY(blendFunctions);        rgbFuncNdx++)
386                 for (int alphaFuncNdx = 0;      alphaFuncNdx < DE_LENGTH_OF_ARRAY(blendFunctions);      alphaFuncNdx++)
387                 {
388                         bool                    isSrc                   = isDstI == 0;
389                         TestCaseGroup*  curGroup                = isSrc ? srcGroup : dstGroup;
390                         const EnumGL&   funcRGB                 = blendFunctions[rgbFuncNdx];
391                         const EnumGL&   funcAlpha               = blendFunctions[alphaFuncNdx];
392                         const char*             dstOrSrcStr             = isSrc ? "src" : "dst";
393
394                         if (!isSrc && (funcRGB.glValue == GL_SRC_ALPHA_SATURATE || funcAlpha.glValue == GL_SRC_ALPHA_SATURATE)) // SRC_ALPHA_SATURATE is only valid for src func.
395                                 continue;
396
397                         string name                     = string("") + funcRGB.nameStr + "_" + funcAlpha.nameStr;
398                         string description      = string("") +
399                                                                   "RGB "                + dstOrSrcStr + " func " + getBlendFactorName(funcRGB.glValue) +
400                                                                   ", alpha "    + dstOrSrcStr + " func " + getBlendFactorName(funcAlpha.glValue);
401
402                         // First, make param sets as if this was a src case.
403
404                         vector<BlendParams> paramSets;
405                         paramSets.push_back(BlendParams(GL_FUNC_ADD, funcRGB.glValue, GL_ONE,                   GL_FUNC_ADD, funcAlpha.glValue, GL_ONE,                 defaultBlendColor));
406                         paramSets.push_back(BlendParams(GL_FUNC_ADD, funcRGB.glValue, GL_ZERO,                  GL_FUNC_ADD, funcAlpha.glValue, GL_ZERO,                defaultBlendColor));
407                         paramSets.push_back(BlendParams(GL_FUNC_ADD, funcRGB.glValue, GL_SRC_COLOR,             GL_FUNC_ADD, funcAlpha.glValue, GL_SRC_COLOR,   defaultBlendColor));
408                         paramSets.push_back(BlendParams(GL_FUNC_ADD, funcRGB.glValue, GL_DST_COLOR,             GL_FUNC_ADD, funcAlpha.glValue, GL_DST_COLOR,   defaultBlendColor));
409
410                         // Swap src and dst params if this is a dst case.
411
412                         if (!isSrc)
413                         {
414                                 for (int i = 0; i < (int)paramSets.size(); i++)
415                                 {
416                                         std::swap(paramSets[i].srcFuncRGB,              paramSets[i].dstFuncRGB);
417                                         std::swap(paramSets[i].srcFuncAlpha,    paramSets[i].dstFuncAlpha);
418                                 }
419                         }
420
421                         curGroup->addChild(new BlendCase(m_context, name.c_str(), description.c_str(), paramSets));
422                 }
423         }
424
425         // Test all RGB and alpha equation combinations. Src and dst funcs are ONE for both.
426
427         {
428                 TestCaseGroup* group = new TestCaseGroup(m_context, "rgb_equation_alpha_equation", "Combinations of RGB and Alpha Equation Combinations");
429                 addChild(group);
430
431                 for (int equationRGBNdx = 0;    equationRGBNdx < DE_LENGTH_OF_ARRAY(blendEquations);    equationRGBNdx++)
432                 for (int equationAlphaNdx = 0;  equationAlphaNdx < DE_LENGTH_OF_ARRAY(blendEquations);  equationAlphaNdx++)
433                 {
434                         const EnumGL& eqRGB                     = blendEquations[equationRGBNdx];
435                         const EnumGL& eqAlpha           = blendEquations[equationAlphaNdx];
436
437                         string name                     = string("") + eqRGB.nameStr + "_" + eqAlpha.nameStr;
438                         string description      = string("") +
439                                                                   "RGB equation "               + getBlendEquationName(eqRGB.glValue) +
440                                                                   ", alpha equation "   + getBlendEquationName(eqAlpha.glValue);
441
442                         vector<BlendParams> paramSets;
443                         paramSets.push_back(BlendParams(eqRGB.glValue, GL_ONE, GL_ONE, eqAlpha.glValue, GL_ONE, GL_ONE, defaultBlendColor));
444
445                         group->addChild(new BlendCase(m_context, name.c_str(), description.c_str(), paramSets));
446                 }
447         }
448 }
449
450 } // Functional
451 } // gles2
452 } // deqp