/*------------------------------------------------------------------------- * drawElements Quality Program OpenGL (ES) Module * ----------------------------------------------- * * Copyright 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *//*! * \file * \brief Interaction test utilities. *//*--------------------------------------------------------------------*/ #include "glsInteractionTestUtil.hpp" #include "tcuVector.hpp" #include "deRandom.hpp" #include "deMath.h" #include "glwEnums.hpp" namespace deqp { namespace gls { namespace InteractionTestUtil { using tcu::Vec4; using tcu::IVec2; using std::vector; static Vec4 getRandomColor (de::Random& rnd) { static const float components[] = { 0.0f, 0.2f, 0.4f, 0.5f, 0.6f, 0.8f, 1.0f }; float r = rnd.choose<float>(DE_ARRAY_BEGIN(components), DE_ARRAY_END(components)); float g = rnd.choose<float>(DE_ARRAY_BEGIN(components), DE_ARRAY_END(components)); float b = rnd.choose<float>(DE_ARRAY_BEGIN(components), DE_ARRAY_END(components)); float a = rnd.choose<float>(DE_ARRAY_BEGIN(components), DE_ARRAY_END(components)); return Vec4(r, g, b, a); } void computeRandomRenderState (de::Random& rnd, RenderState& state, glu::ApiType apiType, int targetWidth, int targetHeight) { // Constants governing randomization. const float scissorTestProbability = 0.2f; const float stencilTestProbability = 0.4f; const float depthTestProbability = 0.6f; const float blendProbability = 0.4f; const float ditherProbability = 0.5f; const float depthWriteProbability = 0.7f; const float colorWriteProbability = 0.7f; const int minStencilVal = -3; const int maxStencilVal = 260; const int maxScissorOutOfBounds = 10; const float minScissorSize = 0.7f; static const deUint32 compareFuncs[] = { GL_NEVER, GL_ALWAYS, GL_LESS, GL_LEQUAL, GL_EQUAL, GL_GEQUAL, GL_GREATER, GL_NOTEQUAL }; static const deUint32 stencilOps[] = { GL_KEEP, GL_ZERO, GL_REPLACE, GL_INCR, GL_DECR, GL_INVERT, GL_INCR_WRAP, GL_DECR_WRAP }; static const deUint32 blendEquations[] = { GL_FUNC_ADD, GL_FUNC_SUBTRACT, GL_FUNC_REVERSE_SUBTRACT, GL_MIN, GL_MAX }; static const deUint32 blendFuncs[] = { GL_ZERO, GL_ONE, GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_DST_COLOR, GL_ONE_MINUS_DST_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_CONSTANT_COLOR, GL_ONE_MINUS_CONSTANT_COLOR, GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA, GL_SRC_ALPHA_SATURATE }; static const deUint32 blendEquationsES2[] = { GL_FUNC_ADD, GL_FUNC_SUBTRACT, GL_FUNC_REVERSE_SUBTRACT }; static const deUint32 blendFuncsDstES2[] = { GL_ZERO, GL_ONE, GL_SRC_COLOR, GL_ONE_MINUS_SRC_COLOR, GL_DST_COLOR, GL_ONE_MINUS_DST_COLOR, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_DST_ALPHA, GL_ONE_MINUS_DST_ALPHA, GL_CONSTANT_COLOR, GL_ONE_MINUS_CONSTANT_COLOR, GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA }; state.scissorTestEnabled = rnd.getFloat() < scissorTestProbability; state.stencilTestEnabled = rnd.getFloat() < stencilTestProbability; state.depthTestEnabled = rnd.getFloat() < depthTestProbability; state.blendEnabled = rnd.getFloat() < blendProbability; state.ditherEnabled = rnd.getFloat() < ditherProbability; if (state.scissorTestEnabled) { int minScissorW = deCeilFloatToInt32(minScissorSize*targetWidth); int minScissorH = deCeilFloatToInt32(minScissorSize*targetHeight); int maxScissorW = targetWidth + 2*maxScissorOutOfBounds; int maxScissorH = targetHeight + 2*maxScissorOutOfBounds; int scissorW = rnd.getInt(minScissorW, maxScissorW); int scissorH = rnd.getInt(minScissorH, maxScissorH); int scissorX = rnd.getInt(-maxScissorOutOfBounds, targetWidth+maxScissorOutOfBounds-scissorW); int scissorY = rnd.getInt(-maxScissorOutOfBounds, targetHeight+maxScissorOutOfBounds-scissorH); state.scissorRectangle = rr::WindowRectangle(scissorX, scissorY, scissorW, scissorH); } if (state.stencilTestEnabled) { for (int ndx = 0; ndx < 2; ndx++) { state.stencil[ndx].function = rnd.choose<deUint32>(DE_ARRAY_BEGIN(compareFuncs), DE_ARRAY_END(compareFuncs)); state.stencil[ndx].reference = rnd.getInt(minStencilVal, maxStencilVal); state.stencil[ndx].compareMask = rnd.getUint32(); state.stencil[ndx].stencilFailOp = rnd.choose<deUint32>(DE_ARRAY_BEGIN(stencilOps), DE_ARRAY_END(stencilOps)); state.stencil[ndx].depthFailOp = rnd.choose<deUint32>(DE_ARRAY_BEGIN(stencilOps), DE_ARRAY_END(stencilOps)); state.stencil[ndx].depthPassOp = rnd.choose<deUint32>(DE_ARRAY_BEGIN(stencilOps), DE_ARRAY_END(stencilOps)); state.stencil[ndx].writeMask = rnd.getUint32(); } } if (state.depthTestEnabled) { state.depthFunc = rnd.choose<deUint32>(DE_ARRAY_BEGIN(compareFuncs), DE_ARRAY_END(compareFuncs)); state.depthWriteMask = rnd.getFloat() < depthWriteProbability; } if (state.blendEnabled) { if (apiType == glu::ApiType::es(2,0)) { state.blendRGBState.equation = rnd.choose<deUint32>(DE_ARRAY_BEGIN(blendEquationsES2), DE_ARRAY_END(blendEquationsES2)); state.blendRGBState.srcFunc = rnd.choose<deUint32>(DE_ARRAY_BEGIN(blendFuncs), DE_ARRAY_END(blendFuncs)); state.blendRGBState.dstFunc = rnd.choose<deUint32>(DE_ARRAY_BEGIN(blendFuncsDstES2), DE_ARRAY_END(blendFuncsDstES2)); state.blendAState.equation = rnd.choose<deUint32>(DE_ARRAY_BEGIN(blendEquationsES2), DE_ARRAY_END(blendEquationsES2)); state.blendAState.srcFunc = rnd.choose<deUint32>(DE_ARRAY_BEGIN(blendFuncs), DE_ARRAY_END(blendFuncs)); state.blendAState.dstFunc = rnd.choose<deUint32>(DE_ARRAY_BEGIN(blendFuncsDstES2), DE_ARRAY_END(blendFuncsDstES2)); } else { state.blendRGBState.equation = rnd.choose<deUint32>(DE_ARRAY_BEGIN(blendEquations), DE_ARRAY_END(blendEquations)); state.blendRGBState.srcFunc = rnd.choose<deUint32>(DE_ARRAY_BEGIN(blendFuncs), DE_ARRAY_END(blendFuncs)); state.blendRGBState.dstFunc = rnd.choose<deUint32>(DE_ARRAY_BEGIN(blendFuncs), DE_ARRAY_END(blendFuncs)); state.blendAState.equation = rnd.choose<deUint32>(DE_ARRAY_BEGIN(blendEquations), DE_ARRAY_END(blendEquations)); state.blendAState.srcFunc = rnd.choose<deUint32>(DE_ARRAY_BEGIN(blendFuncs), DE_ARRAY_END(blendFuncs)); state.blendAState.dstFunc = rnd.choose<deUint32>(DE_ARRAY_BEGIN(blendFuncs), DE_ARRAY_END(blendFuncs)); } state.blendColor = getRandomColor(rnd); } for (int ndx = 0; ndx < 4; ndx++) state.colorMask[ndx] = rnd.getFloat() < colorWriteProbability; } void computeRandomQuad (de::Random& rnd, gls::FragmentOpUtil::IntegerQuad& quad, int targetWidth, int targetHeight) { // \note In viewport coordinates. // \todo [2012-12-18 pyry] Out-of-bounds values. // \note Not using depth 1.0 since clearing with 1.0 and rendering with 1.0 may not be same value. static const float depthValues[] = { 0.0f, 0.2f, 0.4f, 0.5f, 0.51f, 0.6f, 0.8f, 0.95f }; const int maxOutOfBounds = 0; const float minSize = 0.5f; int minW = deCeilFloatToInt32(minSize*targetWidth); int minH = deCeilFloatToInt32(minSize*targetHeight); int maxW = targetWidth + 2*maxOutOfBounds; int maxH = targetHeight + 2*maxOutOfBounds; int width = rnd.getInt(minW, maxW); int height = rnd.getInt(minH, maxH); int x = rnd.getInt(-maxOutOfBounds, targetWidth+maxOutOfBounds-width); int y = rnd.getInt(-maxOutOfBounds, targetHeight+maxOutOfBounds-height); bool flipX = rnd.getBool(); bool flipY = rnd.getBool(); float depth = rnd.choose<float>(DE_ARRAY_BEGIN(depthValues), DE_ARRAY_END(depthValues)); quad.posA = IVec2(flipX ? (x+width-1) : x, flipY ? (y+height-1) : y); quad.posB = IVec2(flipX ? x : (x+width-1), flipY ? y : (y+height-1)); for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(quad.color); ndx++) quad.color[ndx] = getRandomColor(rnd); std::fill(DE_ARRAY_BEGIN(quad.depth), DE_ARRAY_END(quad.depth), depth); } void computeRandomRenderCommands (de::Random& rnd, glu::ApiType apiType, int numCommands, int targetW, int targetH, vector<RenderCommand>& dst) { DE_ASSERT(dst.empty()); dst.resize(numCommands); for (vector<RenderCommand>::iterator cmd = dst.begin(); cmd != dst.end(); cmd++) { computeRandomRenderState(rnd, cmd->state, apiType, targetW, targetH); computeRandomQuad(rnd, cmd->quad, targetW, targetH); } } } // InteractionTestUtil } // gls } // deqp