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*targetWidth); 158 int minScissorH = deCeilFloatToInt32(minScissorSize*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*targetWidth); 231 int minH = deCeilFloatToInt32(minSize*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 269