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