Merge "Check only what's needed and use threshold"
[platform/upstream/VK-GL-CTS.git] / modules / glshared / glsInteractionTestUtil.cpp
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL (ES) 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 Interaction test utilities.
22  *//*--------------------------------------------------------------------*/
23
24 #include "glsInteractionTestUtil.hpp"
25
26 #include "tcuVector.hpp"
27
28 #include "deRandom.hpp"
29 #include "deMath.h"
30
31 #include "glwEnums.hpp"
32
33 namespace deqp
34 {
35 namespace gls
36 {
37 namespace InteractionTestUtil
38 {
39
40 using tcu::Vec4;
41 using tcu::IVec2;
42 using std::vector;
43
44 static Vec4 getRandomColor (de::Random& rnd)
45 {
46         static const float components[] = { 0.0f, 0.2f, 0.4f, 0.5f, 0.6f, 0.8f, 1.0f };
47         float r = rnd.choose<float>(DE_ARRAY_BEGIN(components), DE_ARRAY_END(components));
48         float g = rnd.choose<float>(DE_ARRAY_BEGIN(components), DE_ARRAY_END(components));
49         float b = rnd.choose<float>(DE_ARRAY_BEGIN(components), DE_ARRAY_END(components));
50         float a = rnd.choose<float>(DE_ARRAY_BEGIN(components), DE_ARRAY_END(components));
51         return Vec4(r, g, b, a);
52 }
53
54 void computeRandomRenderState (de::Random& rnd, RenderState& state, glu::ApiType apiType, int targetWidth, int targetHeight)
55 {
56         // Constants governing randomization.
57         const float             scissorTestProbability          = 0.2f;
58         const float             stencilTestProbability          = 0.4f;
59         const float             depthTestProbability            = 0.6f;
60         const float             blendProbability                        = 0.4f;
61         const float             ditherProbability                       = 0.5f;
62
63         const float             depthWriteProbability           = 0.7f;
64         const float             colorWriteProbability           = 0.7f;
65
66         const int               minStencilVal                           = -3;
67         const int               maxStencilVal                           = 260;
68
69         const int               maxScissorOutOfBounds           = 10;
70         const float             minScissorSize                          = 0.7f;
71
72         static const deUint32 compareFuncs[] =
73         {
74                 GL_NEVER,
75                 GL_ALWAYS,
76                 GL_LESS,
77                 GL_LEQUAL,
78                 GL_EQUAL,
79                 GL_GEQUAL,
80                 GL_GREATER,
81                 GL_NOTEQUAL
82         };
83
84         static const deUint32 stencilOps[] =
85         {
86                 GL_KEEP,
87                 GL_ZERO,
88                 GL_REPLACE,
89                 GL_INCR,
90                 GL_DECR,
91                 GL_INVERT,
92                 GL_INCR_WRAP,
93                 GL_DECR_WRAP
94         };
95
96         static const deUint32 blendEquations[] =
97         {
98                 GL_FUNC_ADD,
99                 GL_FUNC_SUBTRACT,
100                 GL_FUNC_REVERSE_SUBTRACT,
101                 GL_MIN,
102                 GL_MAX
103         };
104
105         static const deUint32 blendFuncs[] =
106         {
107                 GL_ZERO,
108                 GL_ONE,
109                 GL_SRC_COLOR,
110                 GL_ONE_MINUS_SRC_COLOR,
111                 GL_DST_COLOR,
112                 GL_ONE_MINUS_DST_COLOR,
113                 GL_SRC_ALPHA,
114                 GL_ONE_MINUS_SRC_ALPHA,
115                 GL_DST_ALPHA,
116                 GL_ONE_MINUS_DST_ALPHA,
117                 GL_CONSTANT_COLOR,
118                 GL_ONE_MINUS_CONSTANT_COLOR,
119                 GL_CONSTANT_ALPHA,
120                 GL_ONE_MINUS_CONSTANT_ALPHA,
121                 GL_SRC_ALPHA_SATURATE
122         };
123
124         static const deUint32 blendEquationsES2[] =
125         {
126                 GL_FUNC_ADD,
127                 GL_FUNC_SUBTRACT,
128                 GL_FUNC_REVERSE_SUBTRACT
129         };
130
131         static const deUint32 blendFuncsDstES2[] =
132         {
133                 GL_ZERO,
134                 GL_ONE,
135                 GL_SRC_COLOR,
136                 GL_ONE_MINUS_SRC_COLOR,
137                 GL_DST_COLOR,
138                 GL_ONE_MINUS_DST_COLOR,
139                 GL_SRC_ALPHA,
140                 GL_ONE_MINUS_SRC_ALPHA,
141                 GL_DST_ALPHA,
142                 GL_ONE_MINUS_DST_ALPHA,
143                 GL_CONSTANT_COLOR,
144                 GL_ONE_MINUS_CONSTANT_COLOR,
145                 GL_CONSTANT_ALPHA,
146                 GL_ONE_MINUS_CONSTANT_ALPHA
147         };
148
149         state.scissorTestEnabled        = rnd.getFloat() < scissorTestProbability;
150         state.stencilTestEnabled        = rnd.getFloat() < stencilTestProbability;
151         state.depthTestEnabled          = rnd.getFloat() < depthTestProbability;
152         state.blendEnabled                      = rnd.getFloat() < blendProbability;
153         state.ditherEnabled                     = rnd.getFloat() < ditherProbability;
154
155         if (state.scissorTestEnabled)
156         {
157                 int minScissorW         = deCeilFloatToInt32(minScissorSize * (float)targetWidth);
158                 int minScissorH         = deCeilFloatToInt32(minScissorSize * (float)targetHeight);
159                 int maxScissorW         = targetWidth + 2*maxScissorOutOfBounds;
160                 int maxScissorH         = targetHeight + 2*maxScissorOutOfBounds;
161
162                 int scissorW            = rnd.getInt(minScissorW, maxScissorW);
163                 int     scissorH                = rnd.getInt(minScissorH, maxScissorH);
164                 int scissorX            = rnd.getInt(-maxScissorOutOfBounds, targetWidth+maxScissorOutOfBounds-scissorW);
165                 int scissorY            = rnd.getInt(-maxScissorOutOfBounds, targetHeight+maxScissorOutOfBounds-scissorH);
166
167                 state.scissorRectangle = rr::WindowRectangle(scissorX, scissorY, scissorW, scissorH);
168         }
169
170         if (state.stencilTestEnabled)
171         {
172                 for (int ndx = 0; ndx < 2; ndx++)
173                 {
174                         state.stencil[ndx].function                     = rnd.choose<deUint32>(DE_ARRAY_BEGIN(compareFuncs), DE_ARRAY_END(compareFuncs));
175                         state.stencil[ndx].reference            = rnd.getInt(minStencilVal, maxStencilVal);
176                         state.stencil[ndx].compareMask          = rnd.getUint32();
177                         state.stencil[ndx].stencilFailOp        = rnd.choose<deUint32>(DE_ARRAY_BEGIN(stencilOps), DE_ARRAY_END(stencilOps));
178                         state.stencil[ndx].depthFailOp          = rnd.choose<deUint32>(DE_ARRAY_BEGIN(stencilOps), DE_ARRAY_END(stencilOps));
179                         state.stencil[ndx].depthPassOp          = rnd.choose<deUint32>(DE_ARRAY_BEGIN(stencilOps), DE_ARRAY_END(stencilOps));
180                         state.stencil[ndx].writeMask            = rnd.getUint32();
181                 }
182         }
183
184         if (state.depthTestEnabled)
185         {
186                 state.depthFunc                 = rnd.choose<deUint32>(DE_ARRAY_BEGIN(compareFuncs), DE_ARRAY_END(compareFuncs));
187                 state.depthWriteMask    = rnd.getFloat() < depthWriteProbability;
188         }
189
190         if (state.blendEnabled)
191         {
192                 if (apiType == glu::ApiType::es(2,0))
193                 {
194                         state.blendRGBState.equation    = rnd.choose<deUint32>(DE_ARRAY_BEGIN(blendEquationsES2), DE_ARRAY_END(blendEquationsES2));
195                         state.blendRGBState.srcFunc             = rnd.choose<deUint32>(DE_ARRAY_BEGIN(blendFuncs), DE_ARRAY_END(blendFuncs));
196                         state.blendRGBState.dstFunc             = rnd.choose<deUint32>(DE_ARRAY_BEGIN(blendFuncsDstES2), DE_ARRAY_END(blendFuncsDstES2));
197
198                         state.blendAState.equation              = rnd.choose<deUint32>(DE_ARRAY_BEGIN(blendEquationsES2), DE_ARRAY_END(blendEquationsES2));
199                         state.blendAState.srcFunc               = rnd.choose<deUint32>(DE_ARRAY_BEGIN(blendFuncs), DE_ARRAY_END(blendFuncs));
200                         state.blendAState.dstFunc               = rnd.choose<deUint32>(DE_ARRAY_BEGIN(blendFuncsDstES2), DE_ARRAY_END(blendFuncsDstES2));
201                 }
202                 else
203                 {
204                         state.blendRGBState.equation    = rnd.choose<deUint32>(DE_ARRAY_BEGIN(blendEquations), DE_ARRAY_END(blendEquations));
205                         state.blendRGBState.srcFunc             = rnd.choose<deUint32>(DE_ARRAY_BEGIN(blendFuncs), DE_ARRAY_END(blendFuncs));
206                         state.blendRGBState.dstFunc             = rnd.choose<deUint32>(DE_ARRAY_BEGIN(blendFuncs), DE_ARRAY_END(blendFuncs));
207
208                         state.blendAState.equation              = rnd.choose<deUint32>(DE_ARRAY_BEGIN(blendEquations), DE_ARRAY_END(blendEquations));
209                         state.blendAState.srcFunc               = rnd.choose<deUint32>(DE_ARRAY_BEGIN(blendFuncs), DE_ARRAY_END(blendFuncs));
210                         state.blendAState.dstFunc               = rnd.choose<deUint32>(DE_ARRAY_BEGIN(blendFuncs), DE_ARRAY_END(blendFuncs));
211                 }
212
213                 state.blendColor                                = getRandomColor(rnd);
214         }
215
216         for (int ndx = 0; ndx < 4; ndx++)
217                 state.colorMask[ndx] = rnd.getFloat() < colorWriteProbability;
218 }
219
220 void computeRandomQuad (de::Random& rnd, gls::FragmentOpUtil::IntegerQuad& quad, int targetWidth, int targetHeight)
221 {
222         // \note In viewport coordinates.
223         // \todo [2012-12-18 pyry] Out-of-bounds values.
224         // \note Not using depth 1.0 since clearing with 1.0 and rendering with 1.0 may not be same value.
225         static const float depthValues[] = { 0.0f, 0.2f, 0.4f, 0.5f, 0.51f, 0.6f, 0.8f, 0.95f };
226
227         const int               maxOutOfBounds          = 0;
228         const float             minSize                         = 0.5f;
229
230         int minW                = deCeilFloatToInt32(minSize * (float)targetWidth);
231         int minH                = deCeilFloatToInt32(minSize * (float)targetHeight);
232         int maxW                = targetWidth + 2*maxOutOfBounds;
233         int maxH                = targetHeight + 2*maxOutOfBounds;
234
235         int width               = rnd.getInt(minW, maxW);
236         int     height          = rnd.getInt(minH, maxH);
237         int x                   = rnd.getInt(-maxOutOfBounds, targetWidth+maxOutOfBounds-width);
238         int y                   = rnd.getInt(-maxOutOfBounds, targetHeight+maxOutOfBounds-height);
239
240         bool flipX              = rnd.getBool();
241         bool flipY              = rnd.getBool();
242
243         float depth             = rnd.choose<float>(DE_ARRAY_BEGIN(depthValues), DE_ARRAY_END(depthValues));
244
245         quad.posA       = IVec2(flipX ? (x+width-1) : x, flipY ? (y+height-1) : y);
246         quad.posB       = IVec2(flipX ? x : (x+width-1), flipY ? y : (y+height-1));
247
248         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(quad.color); ndx++)
249                 quad.color[ndx] = getRandomColor(rnd);
250
251         std::fill(DE_ARRAY_BEGIN(quad.depth), DE_ARRAY_END(quad.depth), depth);
252 }
253
254 void computeRandomRenderCommands (de::Random& rnd, glu::ApiType apiType, int numCommands, int targetW, int targetH, vector<RenderCommand>& dst)
255 {
256         DE_ASSERT(dst.empty());
257
258         dst.resize(numCommands);
259         for (vector<RenderCommand>::iterator cmd = dst.begin(); cmd != dst.end(); cmd++)
260         {
261                 computeRandomRenderState(rnd, cmd->state, apiType, targetW, targetH);
262                 computeRandomQuad(rnd, cmd->quad, targetW, targetH);
263         }
264 }
265
266 } // InteractionTestUtil
267 } // gls
268 } // deqp