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
getRandomColor(de::Random & rnd)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
computeRandomRenderState(de::Random & rnd,RenderState & state,glu::ApiType apiType,int targetWidth,int targetHeight)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
computeRandomQuad(de::Random & rnd,gls::FragmentOpUtil::IntegerQuad & quad,int targetWidth,int targetHeight)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
computeRandomRenderCommands(de::Random & rnd,glu::ApiType apiType,int numCommands,int targetW,int targetH,vector<RenderCommand> & dst)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
269