xref: /aosp_15_r20/external/deqp/modules/glshared/glsFragOpInteractionCase.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1*35238bceSAndroid Build Coastguard Worker /*-------------------------------------------------------------------------
2*35238bceSAndroid Build Coastguard Worker  * drawElements Quality Program OpenGL (ES) Module
3*35238bceSAndroid Build Coastguard Worker  * -----------------------------------------------
4*35238bceSAndroid Build Coastguard Worker  *
5*35238bceSAndroid Build Coastguard Worker  * Copyright 2014 The Android Open Source Project
6*35238bceSAndroid Build Coastguard Worker  *
7*35238bceSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
8*35238bceSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
9*35238bceSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
10*35238bceSAndroid Build Coastguard Worker  *
11*35238bceSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
12*35238bceSAndroid Build Coastguard Worker  *
13*35238bceSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
14*35238bceSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
15*35238bceSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16*35238bceSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
17*35238bceSAndroid Build Coastguard Worker  * limitations under the License.
18*35238bceSAndroid Build Coastguard Worker  *
19*35238bceSAndroid Build Coastguard Worker  *//*!
20*35238bceSAndroid Build Coastguard Worker  * \file
21*35238bceSAndroid Build Coastguard Worker  * \brief Shader - render state interaction case.
22*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
23*35238bceSAndroid Build Coastguard Worker 
24*35238bceSAndroid Build Coastguard Worker #include "glsFragOpInteractionCase.hpp"
25*35238bceSAndroid Build Coastguard Worker 
26*35238bceSAndroid Build Coastguard Worker #include "glsRandomShaderProgram.hpp"
27*35238bceSAndroid Build Coastguard Worker #include "glsFragmentOpUtil.hpp"
28*35238bceSAndroid Build Coastguard Worker #include "glsInteractionTestUtil.hpp"
29*35238bceSAndroid Build Coastguard Worker 
30*35238bceSAndroid Build Coastguard Worker #include "gluRenderContext.hpp"
31*35238bceSAndroid Build Coastguard Worker #include "gluContextInfo.hpp"
32*35238bceSAndroid Build Coastguard Worker 
33*35238bceSAndroid Build Coastguard Worker #include "rsgShader.hpp"
34*35238bceSAndroid Build Coastguard Worker #include "rsgProgramGenerator.hpp"
35*35238bceSAndroid Build Coastguard Worker #include "rsgUtils.hpp"
36*35238bceSAndroid Build Coastguard Worker 
37*35238bceSAndroid Build Coastguard Worker #include "sglrContext.hpp"
38*35238bceSAndroid Build Coastguard Worker #include "sglrReferenceContext.hpp"
39*35238bceSAndroid Build Coastguard Worker #include "sglrGLContext.hpp"
40*35238bceSAndroid Build Coastguard Worker #include "sglrContextUtil.hpp"
41*35238bceSAndroid Build Coastguard Worker 
42*35238bceSAndroid Build Coastguard Worker #include "tcuRenderTarget.hpp"
43*35238bceSAndroid Build Coastguard Worker #include "tcuImageCompare.hpp"
44*35238bceSAndroid Build Coastguard Worker 
45*35238bceSAndroid Build Coastguard Worker #include "deRandom.hpp"
46*35238bceSAndroid Build Coastguard Worker #include "deString.h"
47*35238bceSAndroid Build Coastguard Worker #include "deStringUtil.hpp"
48*35238bceSAndroid Build Coastguard Worker 
49*35238bceSAndroid Build Coastguard Worker #include "glwEnums.hpp"
50*35238bceSAndroid Build Coastguard Worker 
51*35238bceSAndroid Build Coastguard Worker #include "gluDrawUtil.hpp"
52*35238bceSAndroid Build Coastguard Worker 
53*35238bceSAndroid Build Coastguard Worker namespace deqp
54*35238bceSAndroid Build Coastguard Worker {
55*35238bceSAndroid Build Coastguard Worker namespace gls
56*35238bceSAndroid Build Coastguard Worker {
57*35238bceSAndroid Build Coastguard Worker 
58*35238bceSAndroid Build Coastguard Worker using std::string;
59*35238bceSAndroid Build Coastguard Worker using std::vector;
60*35238bceSAndroid Build Coastguard Worker using tcu::IVec2;
61*35238bceSAndroid Build Coastguard Worker using tcu::IVec4;
62*35238bceSAndroid Build Coastguard Worker using tcu::Vec2;
63*35238bceSAndroid Build Coastguard Worker using tcu::Vec4;
64*35238bceSAndroid Build Coastguard Worker 
65*35238bceSAndroid Build Coastguard Worker using gls::InteractionTestUtil::RenderState;
66*35238bceSAndroid Build Coastguard Worker using gls::InteractionTestUtil::StencilState;
67*35238bceSAndroid Build Coastguard Worker 
68*35238bceSAndroid Build Coastguard Worker enum
69*35238bceSAndroid Build Coastguard Worker {
70*35238bceSAndroid Build Coastguard Worker     NUM_ITERATIONS             = 5,
71*35238bceSAndroid Build Coastguard Worker     NUM_COMMANDS_PER_ITERATION = 5,
72*35238bceSAndroid Build Coastguard Worker     VIEWPORT_WIDTH             = 64,
73*35238bceSAndroid Build Coastguard Worker     VIEWPORT_HEIGHT            = 64
74*35238bceSAndroid Build Coastguard Worker };
75*35238bceSAndroid Build Coastguard Worker 
76*35238bceSAndroid Build Coastguard Worker namespace
77*35238bceSAndroid Build Coastguard Worker {
78*35238bceSAndroid Build Coastguard Worker 
computeVertexLayout(const vector<rsg::ShaderInput * > & attributes,int numVertices,vector<glu::VertexArrayBinding> * layout,int * stride)79*35238bceSAndroid Build Coastguard Worker static void computeVertexLayout(const vector<rsg::ShaderInput *> &attributes, int numVertices,
80*35238bceSAndroid Build Coastguard Worker                                 vector<glu::VertexArrayBinding> *layout, int *stride)
81*35238bceSAndroid Build Coastguard Worker {
82*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(layout->empty());
83*35238bceSAndroid Build Coastguard Worker 
84*35238bceSAndroid Build Coastguard Worker     int curOffset = 0;
85*35238bceSAndroid Build Coastguard Worker 
86*35238bceSAndroid Build Coastguard Worker     for (vector<rsg::ShaderInput *>::const_iterator iter = attributes.begin(); iter != attributes.end(); ++iter)
87*35238bceSAndroid Build Coastguard Worker     {
88*35238bceSAndroid Build Coastguard Worker         const rsg::ShaderInput *attrib = *iter;
89*35238bceSAndroid Build Coastguard Worker         const rsg::Variable *var       = attrib->getVariable();
90*35238bceSAndroid Build Coastguard Worker         const rsg::VariableType &type  = var->getType();
91*35238bceSAndroid Build Coastguard Worker         const int numComps             = type.getNumElements();
92*35238bceSAndroid Build Coastguard Worker 
93*35238bceSAndroid Build Coastguard Worker         TCU_CHECK_INTERNAL(type.getBaseType() == rsg::VariableType::TYPE_FLOAT &&
94*35238bceSAndroid Build Coastguard Worker                            de::inRange(type.getNumElements(), 1, 4));
95*35238bceSAndroid Build Coastguard Worker 
96*35238bceSAndroid Build Coastguard Worker         layout->push_back(glu::va::Float(var->getName(), numComps, numVertices, 0 /* computed later */,
97*35238bceSAndroid Build Coastguard Worker                                          (const float *)(uintptr_t)curOffset));
98*35238bceSAndroid Build Coastguard Worker 
99*35238bceSAndroid Build Coastguard Worker         curOffset += numComps * (int)sizeof(float);
100*35238bceSAndroid Build Coastguard Worker     }
101*35238bceSAndroid Build Coastguard Worker 
102*35238bceSAndroid Build Coastguard Worker     for (vector<glu::VertexArrayBinding>::iterator vaIter = layout->begin(); vaIter != layout->end(); ++vaIter)
103*35238bceSAndroid Build Coastguard Worker         vaIter->pointer.stride = curOffset;
104*35238bceSAndroid Build Coastguard Worker 
105*35238bceSAndroid Build Coastguard Worker     *stride = curOffset;
106*35238bceSAndroid Build Coastguard Worker }
107*35238bceSAndroid Build Coastguard Worker 
108*35238bceSAndroid Build Coastguard Worker class VertexDataStorage
109*35238bceSAndroid Build Coastguard Worker {
110*35238bceSAndroid Build Coastguard Worker public:
111*35238bceSAndroid Build Coastguard Worker     VertexDataStorage(const vector<rsg::ShaderInput *> &attributes, int numVertices);
112*35238bceSAndroid Build Coastguard Worker 
getDataSize(void) const113*35238bceSAndroid Build Coastguard Worker     int getDataSize(void) const
114*35238bceSAndroid Build Coastguard Worker     {
115*35238bceSAndroid Build Coastguard Worker         return (int)m_data.size();
116*35238bceSAndroid Build Coastguard Worker     }
getBasePtr(void)117*35238bceSAndroid Build Coastguard Worker     void *getBasePtr(void)
118*35238bceSAndroid Build Coastguard Worker     {
119*35238bceSAndroid Build Coastguard Worker         return m_data.empty() ? DE_NULL : &m_data[0];
120*35238bceSAndroid Build Coastguard Worker     }
getBasePtr(void) const121*35238bceSAndroid Build Coastguard Worker     const void *getBasePtr(void) const
122*35238bceSAndroid Build Coastguard Worker     {
123*35238bceSAndroid Build Coastguard Worker         return m_data.empty() ? DE_NULL : &m_data[0];
124*35238bceSAndroid Build Coastguard Worker     }
125*35238bceSAndroid Build Coastguard Worker 
getLayout(void) const126*35238bceSAndroid Build Coastguard Worker     const std::vector<glu::VertexArrayBinding> &getLayout(void) const
127*35238bceSAndroid Build Coastguard Worker     {
128*35238bceSAndroid Build Coastguard Worker         return m_layout;
129*35238bceSAndroid Build Coastguard Worker     }
130*35238bceSAndroid Build Coastguard Worker 
getNumEntries(void) const131*35238bceSAndroid Build Coastguard Worker     int getNumEntries(void) const
132*35238bceSAndroid Build Coastguard Worker     {
133*35238bceSAndroid Build Coastguard Worker         return (int)m_layout.size();
134*35238bceSAndroid Build Coastguard Worker     }
getLayoutEntry(int ndx) const135*35238bceSAndroid Build Coastguard Worker     const glu::VertexArrayBinding &getLayoutEntry(int ndx) const
136*35238bceSAndroid Build Coastguard Worker     {
137*35238bceSAndroid Build Coastguard Worker         return m_layout[ndx];
138*35238bceSAndroid Build Coastguard Worker     }
139*35238bceSAndroid Build Coastguard Worker 
140*35238bceSAndroid Build Coastguard Worker private:
141*35238bceSAndroid Build Coastguard Worker     std::vector<uint8_t> m_data;
142*35238bceSAndroid Build Coastguard Worker     std::vector<glu::VertexArrayBinding> m_layout;
143*35238bceSAndroid Build Coastguard Worker };
144*35238bceSAndroid Build Coastguard Worker 
VertexDataStorage(const vector<rsg::ShaderInput * > & attributes,int numVertices)145*35238bceSAndroid Build Coastguard Worker VertexDataStorage::VertexDataStorage(const vector<rsg::ShaderInput *> &attributes, int numVertices)
146*35238bceSAndroid Build Coastguard Worker {
147*35238bceSAndroid Build Coastguard Worker     int stride = 0;
148*35238bceSAndroid Build Coastguard Worker     computeVertexLayout(attributes, numVertices, &m_layout, &stride);
149*35238bceSAndroid Build Coastguard Worker     m_data.resize(stride * numVertices);
150*35238bceSAndroid Build Coastguard Worker }
151*35238bceSAndroid Build Coastguard Worker 
getEntryWithPointer(const VertexDataStorage & data,int ndx)152*35238bceSAndroid Build Coastguard Worker static inline glu::VertexArrayBinding getEntryWithPointer(const VertexDataStorage &data, int ndx)
153*35238bceSAndroid Build Coastguard Worker {
154*35238bceSAndroid Build Coastguard Worker     const glu::VertexArrayBinding &entry = data.getLayoutEntry(ndx);
155*35238bceSAndroid Build Coastguard Worker     return glu::VertexArrayBinding(
156*35238bceSAndroid Build Coastguard Worker         entry.binding,
157*35238bceSAndroid Build Coastguard Worker         glu::VertexArrayPointer(entry.pointer.componentType, entry.pointer.convert, entry.pointer.numComponents,
158*35238bceSAndroid Build Coastguard Worker                                 entry.pointer.numElements, entry.pointer.stride,
159*35238bceSAndroid Build Coastguard Worker                                 (const void *)((uintptr_t)entry.pointer.data + (uintptr_t)data.getBasePtr())));
160*35238bceSAndroid Build Coastguard Worker }
161*35238bceSAndroid Build Coastguard Worker 
162*35238bceSAndroid Build Coastguard Worker template <int Size>
setVertex(const glu::VertexArrayPointer & pointer,int vertexNdx,const tcu::Vector<float,Size> & value)163*35238bceSAndroid Build Coastguard Worker static void setVertex(const glu::VertexArrayPointer &pointer, int vertexNdx, const tcu::Vector<float, Size> &value)
164*35238bceSAndroid Build Coastguard Worker {
165*35238bceSAndroid Build Coastguard Worker     // \todo [2013-12-14 pyry] Implement other modes.
166*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(pointer.componentType == glu::VTX_COMP_FLOAT && pointer.convert == glu::VTX_COMP_CONVERT_NONE);
167*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(pointer.numComponents == Size);
168*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(de::inBounds(vertexNdx, 0, pointer.numElements));
169*35238bceSAndroid Build Coastguard Worker 
170*35238bceSAndroid Build Coastguard Worker     float *dst = (float *)((uint8_t *)pointer.data + pointer.stride * vertexNdx);
171*35238bceSAndroid Build Coastguard Worker 
172*35238bceSAndroid Build Coastguard Worker     for (int ndx = 0; ndx < Size; ndx++)
173*35238bceSAndroid Build Coastguard Worker         dst[ndx] = value[ndx];
174*35238bceSAndroid Build Coastguard Worker }
175*35238bceSAndroid Build Coastguard Worker 
176*35238bceSAndroid Build Coastguard Worker template <int Size>
interpolateRange(const rsg::ConstValueRangeAccess & range,const tcu::Vector<float,Size> & t)177*35238bceSAndroid Build Coastguard Worker static tcu::Vector<float, Size> interpolateRange(const rsg::ConstValueRangeAccess &range,
178*35238bceSAndroid Build Coastguard Worker                                                  const tcu::Vector<float, Size> &t)
179*35238bceSAndroid Build Coastguard Worker {
180*35238bceSAndroid Build Coastguard Worker     tcu::Vector<float, Size> result;
181*35238bceSAndroid Build Coastguard Worker 
182*35238bceSAndroid Build Coastguard Worker     for (int ndx = 0; ndx < Size; ndx++)
183*35238bceSAndroid Build Coastguard Worker         result[ndx] = range.getMin().component(ndx).asFloat() * (1.0f - t[ndx]) +
184*35238bceSAndroid Build Coastguard Worker                       range.getMax().component(ndx).asFloat() * t[ndx];
185*35238bceSAndroid Build Coastguard Worker 
186*35238bceSAndroid Build Coastguard Worker     return result;
187*35238bceSAndroid Build Coastguard Worker }
188*35238bceSAndroid Build Coastguard Worker 
189*35238bceSAndroid Build Coastguard Worker struct Quad
190*35238bceSAndroid Build Coastguard Worker {
191*35238bceSAndroid Build Coastguard Worker     tcu::IVec2 posA;
192*35238bceSAndroid Build Coastguard Worker     tcu::IVec2 posB;
193*35238bceSAndroid Build Coastguard Worker };
194*35238bceSAndroid Build Coastguard Worker 
195*35238bceSAndroid Build Coastguard Worker struct RenderCommand
196*35238bceSAndroid Build Coastguard Worker {
197*35238bceSAndroid Build Coastguard Worker     Quad quad;
198*35238bceSAndroid Build Coastguard Worker     float depth;
199*35238bceSAndroid Build Coastguard Worker     RenderState state;
200*35238bceSAndroid Build Coastguard Worker 
RenderCommanddeqp::gls::__anon7fa661730211::RenderCommand201*35238bceSAndroid Build Coastguard Worker     RenderCommand(void) : depth(0.0f)
202*35238bceSAndroid Build Coastguard Worker     {
203*35238bceSAndroid Build Coastguard Worker     }
204*35238bceSAndroid Build Coastguard Worker };
205*35238bceSAndroid Build Coastguard Worker 
getRandomQuad(de::Random & rnd,int targetW,int targetH)206*35238bceSAndroid Build Coastguard Worker static Quad getRandomQuad(de::Random &rnd, int targetW, int targetH)
207*35238bceSAndroid Build Coastguard Worker {
208*35238bceSAndroid Build Coastguard Worker     // \note In viewport coordinates.
209*35238bceSAndroid Build Coastguard Worker     // \todo [2012-12-18 pyry] Out-of-bounds values.
210*35238bceSAndroid Build Coastguard Worker     const int maxOutOfBounds = 0;
211*35238bceSAndroid Build Coastguard Worker     const float minSize      = 0.5f;
212*35238bceSAndroid Build Coastguard Worker 
213*35238bceSAndroid Build Coastguard Worker     const int minW = deCeilFloatToInt32(minSize * (float)targetW);
214*35238bceSAndroid Build Coastguard Worker     const int minH = deCeilFloatToInt32(minSize * (float)targetH);
215*35238bceSAndroid Build Coastguard Worker     const int maxW = targetW + 2 * maxOutOfBounds;
216*35238bceSAndroid Build Coastguard Worker     const int maxH = targetH + 2 * maxOutOfBounds;
217*35238bceSAndroid Build Coastguard Worker 
218*35238bceSAndroid Build Coastguard Worker     const int width  = rnd.getInt(minW, maxW);
219*35238bceSAndroid Build Coastguard Worker     const int height = rnd.getInt(minH, maxH);
220*35238bceSAndroid Build Coastguard Worker     const int x      = rnd.getInt(-maxOutOfBounds, targetW + maxOutOfBounds - width);
221*35238bceSAndroid Build Coastguard Worker     const int y      = rnd.getInt(-maxOutOfBounds, targetH + maxOutOfBounds - height);
222*35238bceSAndroid Build Coastguard Worker 
223*35238bceSAndroid Build Coastguard Worker     const bool flipX = rnd.getBool();
224*35238bceSAndroid Build Coastguard Worker     const bool flipY = rnd.getBool();
225*35238bceSAndroid Build Coastguard Worker 
226*35238bceSAndroid Build Coastguard Worker     Quad quad;
227*35238bceSAndroid Build Coastguard Worker 
228*35238bceSAndroid Build Coastguard Worker     quad.posA = tcu::IVec2(flipX ? (x + width - 1) : x, flipY ? (y + height - 1) : y);
229*35238bceSAndroid Build Coastguard Worker     quad.posB = tcu::IVec2(flipX ? x : (x + width - 1), flipY ? y : (y + height - 1));
230*35238bceSAndroid Build Coastguard Worker 
231*35238bceSAndroid Build Coastguard Worker     return quad;
232*35238bceSAndroid Build Coastguard Worker }
233*35238bceSAndroid Build Coastguard Worker 
getRandomDepth(de::Random & rnd)234*35238bceSAndroid Build Coastguard Worker static float getRandomDepth(de::Random &rnd)
235*35238bceSAndroid Build Coastguard Worker {
236*35238bceSAndroid Build Coastguard Worker     // \note Not using depth 1.0 since clearing with 1.0 and rendering with 1.0 may not be same value.
237*35238bceSAndroid Build Coastguard Worker     static const float depthValues[] = {0.0f, 0.2f, 0.4f, 0.5f, 0.51f, 0.6f, 0.8f, 0.95f};
238*35238bceSAndroid Build Coastguard Worker     return rnd.choose<float>(DE_ARRAY_BEGIN(depthValues), DE_ARRAY_END(depthValues));
239*35238bceSAndroid Build Coastguard Worker }
240*35238bceSAndroid Build Coastguard Worker 
computeRandomRenderCommand(de::Random & rnd,RenderCommand & command,glu::ApiType apiType,int targetW,int targetH)241*35238bceSAndroid Build Coastguard Worker static void computeRandomRenderCommand(de::Random &rnd, RenderCommand &command, glu::ApiType apiType, int targetW,
242*35238bceSAndroid Build Coastguard Worker                                        int targetH)
243*35238bceSAndroid Build Coastguard Worker {
244*35238bceSAndroid Build Coastguard Worker     command.quad  = getRandomQuad(rnd, targetW, targetH);
245*35238bceSAndroid Build Coastguard Worker     command.depth = getRandomDepth(rnd);
246*35238bceSAndroid Build Coastguard Worker     gls::InteractionTestUtil::computeRandomRenderState(rnd, command.state, apiType, targetW, targetH);
247*35238bceSAndroid Build Coastguard Worker }
248*35238bceSAndroid Build Coastguard Worker 
setRenderState(sglr::Context & ctx,const RenderState & state)249*35238bceSAndroid Build Coastguard Worker static void setRenderState(sglr::Context &ctx, const RenderState &state)
250*35238bceSAndroid Build Coastguard Worker {
251*35238bceSAndroid Build Coastguard Worker     if (state.scissorTestEnabled)
252*35238bceSAndroid Build Coastguard Worker     {
253*35238bceSAndroid Build Coastguard Worker         ctx.enable(GL_SCISSOR_TEST);
254*35238bceSAndroid Build Coastguard Worker         ctx.scissor(state.scissorRectangle.left, state.scissorRectangle.bottom, state.scissorRectangle.width,
255*35238bceSAndroid Build Coastguard Worker                     state.scissorRectangle.height);
256*35238bceSAndroid Build Coastguard Worker     }
257*35238bceSAndroid Build Coastguard Worker     else
258*35238bceSAndroid Build Coastguard Worker         ctx.disable(GL_SCISSOR_TEST);
259*35238bceSAndroid Build Coastguard Worker 
260*35238bceSAndroid Build Coastguard Worker     if (state.stencilTestEnabled)
261*35238bceSAndroid Build Coastguard Worker     {
262*35238bceSAndroid Build Coastguard Worker         ctx.enable(GL_STENCIL_TEST);
263*35238bceSAndroid Build Coastguard Worker 
264*35238bceSAndroid Build Coastguard Worker         for (int face = 0; face < rr::FACETYPE_LAST; face++)
265*35238bceSAndroid Build Coastguard Worker         {
266*35238bceSAndroid Build Coastguard Worker             uint32_t glFace             = face == rr::FACETYPE_BACK ? GL_BACK : GL_FRONT;
267*35238bceSAndroid Build Coastguard Worker             const StencilState &sParams = state.stencil[face];
268*35238bceSAndroid Build Coastguard Worker 
269*35238bceSAndroid Build Coastguard Worker             ctx.stencilFuncSeparate(glFace, sParams.function, sParams.reference, sParams.compareMask);
270*35238bceSAndroid Build Coastguard Worker             ctx.stencilOpSeparate(glFace, sParams.stencilFailOp, sParams.depthFailOp, sParams.depthPassOp);
271*35238bceSAndroid Build Coastguard Worker             ctx.stencilMaskSeparate(glFace, sParams.writeMask);
272*35238bceSAndroid Build Coastguard Worker         }
273*35238bceSAndroid Build Coastguard Worker     }
274*35238bceSAndroid Build Coastguard Worker     else
275*35238bceSAndroid Build Coastguard Worker         ctx.disable(GL_STENCIL_TEST);
276*35238bceSAndroid Build Coastguard Worker 
277*35238bceSAndroid Build Coastguard Worker     if (state.depthTestEnabled)
278*35238bceSAndroid Build Coastguard Worker     {
279*35238bceSAndroid Build Coastguard Worker         ctx.enable(GL_DEPTH_TEST);
280*35238bceSAndroid Build Coastguard Worker         ctx.depthFunc(state.depthFunc);
281*35238bceSAndroid Build Coastguard Worker         ctx.depthMask(state.depthWriteMask ? GL_TRUE : GL_FALSE);
282*35238bceSAndroid Build Coastguard Worker     }
283*35238bceSAndroid Build Coastguard Worker     else
284*35238bceSAndroid Build Coastguard Worker         ctx.disable(GL_DEPTH_TEST);
285*35238bceSAndroid Build Coastguard Worker 
286*35238bceSAndroid Build Coastguard Worker     if (state.blendEnabled)
287*35238bceSAndroid Build Coastguard Worker     {
288*35238bceSAndroid Build Coastguard Worker         ctx.enable(GL_BLEND);
289*35238bceSAndroid Build Coastguard Worker         ctx.blendEquationSeparate(state.blendRGBState.equation, state.blendAState.equation);
290*35238bceSAndroid Build Coastguard Worker         ctx.blendFuncSeparate(state.blendRGBState.srcFunc, state.blendRGBState.dstFunc, state.blendAState.srcFunc,
291*35238bceSAndroid Build Coastguard Worker                               state.blendAState.dstFunc);
292*35238bceSAndroid Build Coastguard Worker         ctx.blendColor(state.blendColor.x(), state.blendColor.y(), state.blendColor.z(), state.blendColor.w());
293*35238bceSAndroid Build Coastguard Worker     }
294*35238bceSAndroid Build Coastguard Worker     else
295*35238bceSAndroid Build Coastguard Worker         ctx.disable(GL_BLEND);
296*35238bceSAndroid Build Coastguard Worker 
297*35238bceSAndroid Build Coastguard Worker     if (state.ditherEnabled)
298*35238bceSAndroid Build Coastguard Worker         ctx.enable(GL_DITHER);
299*35238bceSAndroid Build Coastguard Worker     else
300*35238bceSAndroid Build Coastguard Worker         ctx.disable(GL_DITHER);
301*35238bceSAndroid Build Coastguard Worker 
302*35238bceSAndroid Build Coastguard Worker     ctx.colorMask(state.colorMask[0] ? GL_TRUE : GL_FALSE, state.colorMask[1] ? GL_TRUE : GL_FALSE,
303*35238bceSAndroid Build Coastguard Worker                   state.colorMask[2] ? GL_TRUE : GL_FALSE, state.colorMask[3] ? GL_TRUE : GL_FALSE);
304*35238bceSAndroid Build Coastguard Worker }
305*35238bceSAndroid Build Coastguard Worker 
renderQuad(sglr::Context & ctx,const glu::VertexArrayPointer & posPtr,const Quad & quad,const float depth)306*35238bceSAndroid Build Coastguard Worker static void renderQuad(sglr::Context &ctx, const glu::VertexArrayPointer &posPtr, const Quad &quad, const float depth)
307*35238bceSAndroid Build Coastguard Worker {
308*35238bceSAndroid Build Coastguard Worker     const uint16_t indices[] = {0, 1, 2, 2, 1, 3};
309*35238bceSAndroid Build Coastguard Worker 
310*35238bceSAndroid Build Coastguard Worker     const bool flipX    = quad.posB.x() < quad.posA.x();
311*35238bceSAndroid Build Coastguard Worker     const bool flipY    = quad.posB.y() < quad.posA.y();
312*35238bceSAndroid Build Coastguard Worker     const int viewportX = de::min(quad.posA.x(), quad.posB.x());
313*35238bceSAndroid Build Coastguard Worker     const int viewportY = de::min(quad.posA.y(), quad.posB.y());
314*35238bceSAndroid Build Coastguard Worker     const int viewportW = de::abs(quad.posA.x() - quad.posB.x()) + 1;
315*35238bceSAndroid Build Coastguard Worker     const int viewportH = de::abs(quad.posA.y() - quad.posB.y()) + 1;
316*35238bceSAndroid Build Coastguard Worker 
317*35238bceSAndroid Build Coastguard Worker     const Vec2 pA(flipX ? 1.0f : -1.0f, flipY ? 1.0f : -1.0f);
318*35238bceSAndroid Build Coastguard Worker     const Vec2 pB(flipX ? -1.0f : 1.0f, flipY ? -1.0f : 1.0f);
319*35238bceSAndroid Build Coastguard Worker 
320*35238bceSAndroid Build Coastguard Worker     setVertex(posPtr, 0, Vec4(pA.x(), pA.y(), depth, 1.0f));
321*35238bceSAndroid Build Coastguard Worker     setVertex(posPtr, 1, Vec4(pB.x(), pA.y(), depth, 1.0f));
322*35238bceSAndroid Build Coastguard Worker     setVertex(posPtr, 2, Vec4(pA.x(), pB.y(), depth, 1.0f));
323*35238bceSAndroid Build Coastguard Worker     setVertex(posPtr, 3, Vec4(pB.x(), pB.y(), depth, 1.0f));
324*35238bceSAndroid Build Coastguard Worker 
325*35238bceSAndroid Build Coastguard Worker     ctx.viewport(viewportX, viewportY, viewportW, viewportH);
326*35238bceSAndroid Build Coastguard Worker     ctx.drawElements(GL_TRIANGLES, DE_LENGTH_OF_ARRAY(indices), GL_UNSIGNED_SHORT, &indices[0]);
327*35238bceSAndroid Build Coastguard Worker }
328*35238bceSAndroid Build Coastguard Worker 
render(sglr::Context & ctx,const glu::VertexArrayPointer & posPtr,const RenderCommand & cmd)329*35238bceSAndroid Build Coastguard Worker static void render(sglr::Context &ctx, const glu::VertexArrayPointer &posPtr, const RenderCommand &cmd)
330*35238bceSAndroid Build Coastguard Worker {
331*35238bceSAndroid Build Coastguard Worker     setRenderState(ctx, cmd.state);
332*35238bceSAndroid Build Coastguard Worker     renderQuad(ctx, posPtr, cmd.quad, cmd.depth);
333*35238bceSAndroid Build Coastguard Worker }
334*35238bceSAndroid Build Coastguard Worker 
setupAttributes(sglr::Context & ctx,const VertexDataStorage & vertexData,uint32_t program)335*35238bceSAndroid Build Coastguard Worker static void setupAttributes(sglr::Context &ctx, const VertexDataStorage &vertexData, uint32_t program)
336*35238bceSAndroid Build Coastguard Worker {
337*35238bceSAndroid Build Coastguard Worker     for (int attribNdx = 0; attribNdx < vertexData.getNumEntries(); ++attribNdx)
338*35238bceSAndroid Build Coastguard Worker     {
339*35238bceSAndroid Build Coastguard Worker         const glu::VertexArrayBinding bindingPtr = getEntryWithPointer(vertexData, attribNdx);
340*35238bceSAndroid Build Coastguard Worker         const int attribLoc                      = bindingPtr.binding.type == glu::BindingPoint::BPTYPE_NAME ?
341*35238bceSAndroid Build Coastguard Worker                                                        ctx.getAttribLocation(program, bindingPtr.binding.name.c_str()) :
342*35238bceSAndroid Build Coastguard Worker                                                        bindingPtr.binding.location;
343*35238bceSAndroid Build Coastguard Worker 
344*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(bindingPtr.pointer.componentType == glu::VTX_COMP_FLOAT);
345*35238bceSAndroid Build Coastguard Worker 
346*35238bceSAndroid Build Coastguard Worker         if (attribLoc >= 0)
347*35238bceSAndroid Build Coastguard Worker         {
348*35238bceSAndroid Build Coastguard Worker             ctx.enableVertexAttribArray(attribLoc);
349*35238bceSAndroid Build Coastguard Worker             ctx.vertexAttribPointer(attribLoc, bindingPtr.pointer.numComponents, GL_FLOAT, GL_FALSE,
350*35238bceSAndroid Build Coastguard Worker                                     bindingPtr.pointer.stride, bindingPtr.pointer.data);
351*35238bceSAndroid Build Coastguard Worker         }
352*35238bceSAndroid Build Coastguard Worker     }
353*35238bceSAndroid Build Coastguard Worker }
354*35238bceSAndroid Build Coastguard Worker 
setUniformValue(sglr::Context & ctx,int location,rsg::ConstValueAccess value)355*35238bceSAndroid Build Coastguard Worker void setUniformValue(sglr::Context &ctx, int location, rsg::ConstValueAccess value)
356*35238bceSAndroid Build Coastguard Worker {
357*35238bceSAndroid Build Coastguard Worker     DE_STATIC_ASSERT(sizeof(rsg::Scalar) == sizeof(float));
358*35238bceSAndroid Build Coastguard Worker     DE_STATIC_ASSERT(sizeof(rsg::Scalar) == sizeof(int));
359*35238bceSAndroid Build Coastguard Worker 
360*35238bceSAndroid Build Coastguard Worker     switch (value.getType().getBaseType())
361*35238bceSAndroid Build Coastguard Worker     {
362*35238bceSAndroid Build Coastguard Worker     case rsg::VariableType::TYPE_FLOAT:
363*35238bceSAndroid Build Coastguard Worker         switch (value.getType().getNumElements())
364*35238bceSAndroid Build Coastguard Worker         {
365*35238bceSAndroid Build Coastguard Worker         case 1:
366*35238bceSAndroid Build Coastguard Worker             ctx.uniform1fv(location, 1, (float *)value.value().getValuePtr());
367*35238bceSAndroid Build Coastguard Worker             break;
368*35238bceSAndroid Build Coastguard Worker         case 2:
369*35238bceSAndroid Build Coastguard Worker             ctx.uniform2fv(location, 1, (float *)value.value().getValuePtr());
370*35238bceSAndroid Build Coastguard Worker             break;
371*35238bceSAndroid Build Coastguard Worker         case 3:
372*35238bceSAndroid Build Coastguard Worker             ctx.uniform3fv(location, 1, (float *)value.value().getValuePtr());
373*35238bceSAndroid Build Coastguard Worker             break;
374*35238bceSAndroid Build Coastguard Worker         case 4:
375*35238bceSAndroid Build Coastguard Worker             ctx.uniform4fv(location, 1, (float *)value.value().getValuePtr());
376*35238bceSAndroid Build Coastguard Worker             break;
377*35238bceSAndroid Build Coastguard Worker         default:
378*35238bceSAndroid Build Coastguard Worker             TCU_FAIL("Unsupported type");
379*35238bceSAndroid Build Coastguard Worker         }
380*35238bceSAndroid Build Coastguard Worker         break;
381*35238bceSAndroid Build Coastguard Worker 
382*35238bceSAndroid Build Coastguard Worker     case rsg::VariableType::TYPE_INT:
383*35238bceSAndroid Build Coastguard Worker     case rsg::VariableType::TYPE_BOOL:
384*35238bceSAndroid Build Coastguard Worker     case rsg::VariableType::TYPE_SAMPLER_2D:
385*35238bceSAndroid Build Coastguard Worker     case rsg::VariableType::TYPE_SAMPLER_CUBE:
386*35238bceSAndroid Build Coastguard Worker         switch (value.getType().getNumElements())
387*35238bceSAndroid Build Coastguard Worker         {
388*35238bceSAndroid Build Coastguard Worker         case 1:
389*35238bceSAndroid Build Coastguard Worker             ctx.uniform1iv(location, 1, (int *)value.value().getValuePtr());
390*35238bceSAndroid Build Coastguard Worker             break;
391*35238bceSAndroid Build Coastguard Worker         case 2:
392*35238bceSAndroid Build Coastguard Worker             ctx.uniform2iv(location, 1, (int *)value.value().getValuePtr());
393*35238bceSAndroid Build Coastguard Worker             break;
394*35238bceSAndroid Build Coastguard Worker         case 3:
395*35238bceSAndroid Build Coastguard Worker             ctx.uniform3iv(location, 1, (int *)value.value().getValuePtr());
396*35238bceSAndroid Build Coastguard Worker             break;
397*35238bceSAndroid Build Coastguard Worker         case 4:
398*35238bceSAndroid Build Coastguard Worker             ctx.uniform4iv(location, 1, (int *)value.value().getValuePtr());
399*35238bceSAndroid Build Coastguard Worker             break;
400*35238bceSAndroid Build Coastguard Worker         default:
401*35238bceSAndroid Build Coastguard Worker             TCU_FAIL("Unsupported type");
402*35238bceSAndroid Build Coastguard Worker         }
403*35238bceSAndroid Build Coastguard Worker         break;
404*35238bceSAndroid Build Coastguard Worker 
405*35238bceSAndroid Build Coastguard Worker     default:
406*35238bceSAndroid Build Coastguard Worker         throw tcu::InternalError("Unsupported type", "", __FILE__, __LINE__);
407*35238bceSAndroid Build Coastguard Worker     }
408*35238bceSAndroid Build Coastguard Worker }
409*35238bceSAndroid Build Coastguard Worker 
findShaderInputIndex(const vector<rsg::ShaderInput * > & vars,const char * name)410*35238bceSAndroid Build Coastguard Worker static int findShaderInputIndex(const vector<rsg::ShaderInput *> &vars, const char *name)
411*35238bceSAndroid Build Coastguard Worker {
412*35238bceSAndroid Build Coastguard Worker     for (int ndx = 0; ndx < (int)vars.size(); ++ndx)
413*35238bceSAndroid Build Coastguard Worker     {
414*35238bceSAndroid Build Coastguard Worker         if (deStringEqual(vars[ndx]->getVariable()->getName(), name))
415*35238bceSAndroid Build Coastguard Worker             return ndx;
416*35238bceSAndroid Build Coastguard Worker     }
417*35238bceSAndroid Build Coastguard Worker 
418*35238bceSAndroid Build Coastguard Worker     throw tcu::InternalError(string(name) + " not found in shader inputs");
419*35238bceSAndroid Build Coastguard Worker }
420*35238bceSAndroid Build Coastguard Worker 
getWellBehavingChannelColor(float v,int numBits)421*35238bceSAndroid Build Coastguard Worker static float getWellBehavingChannelColor(float v, int numBits)
422*35238bceSAndroid Build Coastguard Worker {
423*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(de::inRange(numBits, 0, 32));
424*35238bceSAndroid Build Coastguard Worker 
425*35238bceSAndroid Build Coastguard Worker     // clear color may not be accurately representable in the target format. If the clear color is
426*35238bceSAndroid Build Coastguard Worker     // on a representable value mapping range border, it could be rounded differently by the GL and in
427*35238bceSAndroid Build Coastguard Worker     // SGLR adding an unexpected error source. However, selecting an accurately representable background
428*35238bceSAndroid Build Coastguard Worker     // color would effectively disable dithering. To allow dithering and to prevent undefined rounding
429*35238bceSAndroid Build Coastguard Worker     // direction from affecting results, round accurate color to target color format with 8 sub-units
430*35238bceSAndroid Build Coastguard Worker     // (3 bits). If the selected sub-unit value is 3 or 4 (bordering 0.5), replace it with 2 and 5,
431*35238bceSAndroid Build Coastguard Worker     // respectively.
432*35238bceSAndroid Build Coastguard Worker 
433*35238bceSAndroid Build Coastguard Worker     if (numBits == 0 || v <= 0.0f || v >= 1.0f)
434*35238bceSAndroid Build Coastguard Worker     {
435*35238bceSAndroid Build Coastguard Worker         // already accurately representable
436*35238bceSAndroid Build Coastguard Worker         return v;
437*35238bceSAndroid Build Coastguard Worker     }
438*35238bceSAndroid Build Coastguard Worker     else
439*35238bceSAndroid Build Coastguard Worker     {
440*35238bceSAndroid Build Coastguard Worker         const uint64_t numSubBits      = 3;
441*35238bceSAndroid Build Coastguard Worker         const uint64_t subUnitBorderLo = (1u << (numSubBits - 1u)) - 1u;
442*35238bceSAndroid Build Coastguard Worker         const uint64_t subUnitBorderHi = 1u << (numSubBits - 1u);
443*35238bceSAndroid Build Coastguard Worker         const uint64_t maxFixedValue   = (1u << (numBits + numSubBits)) - 1u;
444*35238bceSAndroid Build Coastguard Worker         const uint64_t fixedValue      = deRoundFloatToInt64(v * (float)maxFixedValue);
445*35238bceSAndroid Build Coastguard Worker 
446*35238bceSAndroid Build Coastguard Worker         const uint64_t units    = fixedValue >> numSubBits;
447*35238bceSAndroid Build Coastguard Worker         const uint64_t subUnits = fixedValue & ((1u << numSubBits) - 1u);
448*35238bceSAndroid Build Coastguard Worker 
449*35238bceSAndroid Build Coastguard Worker         const uint64_t tweakedSubUnits = (subUnits == subUnitBorderLo) ? (subUnitBorderLo - 1) :
450*35238bceSAndroid Build Coastguard Worker                                          (subUnits == subUnitBorderHi) ? (subUnitBorderHi + 1) :
451*35238bceSAndroid Build Coastguard Worker                                                                          (subUnits);
452*35238bceSAndroid Build Coastguard Worker         const uint64_t tweakedValue    = (units << numSubBits) | (tweakedSubUnits);
453*35238bceSAndroid Build Coastguard Worker 
454*35238bceSAndroid Build Coastguard Worker         return float(tweakedValue) / float(maxFixedValue);
455*35238bceSAndroid Build Coastguard Worker     }
456*35238bceSAndroid Build Coastguard Worker }
457*35238bceSAndroid Build Coastguard Worker 
getWellBehavingColor(const tcu::Vec4 & accurateColor,const tcu::PixelFormat & format)458*35238bceSAndroid Build Coastguard Worker static tcu::Vec4 getWellBehavingColor(const tcu::Vec4 &accurateColor, const tcu::PixelFormat &format)
459*35238bceSAndroid Build Coastguard Worker {
460*35238bceSAndroid Build Coastguard Worker     return tcu::Vec4(getWellBehavingChannelColor(accurateColor[0], format.redBits),
461*35238bceSAndroid Build Coastguard Worker                      getWellBehavingChannelColor(accurateColor[1], format.greenBits),
462*35238bceSAndroid Build Coastguard Worker                      getWellBehavingChannelColor(accurateColor[2], format.blueBits),
463*35238bceSAndroid Build Coastguard Worker                      getWellBehavingChannelColor(accurateColor[3], format.alphaBits));
464*35238bceSAndroid Build Coastguard Worker }
465*35238bceSAndroid Build Coastguard Worker 
466*35238bceSAndroid Build Coastguard Worker } // namespace
467*35238bceSAndroid Build Coastguard Worker 
468*35238bceSAndroid Build Coastguard Worker struct FragOpInteractionCase::ReferenceContext
469*35238bceSAndroid Build Coastguard Worker {
470*35238bceSAndroid Build Coastguard Worker     const sglr::ReferenceContextLimits limits;
471*35238bceSAndroid Build Coastguard Worker     sglr::ReferenceContextBuffers buffers;
472*35238bceSAndroid Build Coastguard Worker     sglr::ReferenceContext context;
473*35238bceSAndroid Build Coastguard Worker 
ReferenceContextdeqp::gls::FragOpInteractionCase::ReferenceContext474*35238bceSAndroid Build Coastguard Worker     ReferenceContext(glu::RenderContext &renderCtx, int width, int height)
475*35238bceSAndroid Build Coastguard Worker         : limits(renderCtx)
476*35238bceSAndroid Build Coastguard Worker         , buffers(renderCtx.getRenderTarget().getPixelFormat(), renderCtx.getRenderTarget().getDepthBits(),
477*35238bceSAndroid Build Coastguard Worker                   renderCtx.getRenderTarget().getStencilBits(), width, height)
478*35238bceSAndroid Build Coastguard Worker         , context(limits, buffers.getColorbuffer(), buffers.getDepthbuffer(), buffers.getStencilbuffer())
479*35238bceSAndroid Build Coastguard Worker     {
480*35238bceSAndroid Build Coastguard Worker     }
481*35238bceSAndroid Build Coastguard Worker };
482*35238bceSAndroid Build Coastguard Worker 
FragOpInteractionCase(tcu::TestContext & testCtx,glu::RenderContext & renderCtx,const glu::ContextInfo & ctxInfo,const char * name,const rsg::ProgramParameters & params)483*35238bceSAndroid Build Coastguard Worker FragOpInteractionCase::FragOpInteractionCase(tcu::TestContext &testCtx, glu::RenderContext &renderCtx,
484*35238bceSAndroid Build Coastguard Worker                                              const glu::ContextInfo &ctxInfo, const char *name,
485*35238bceSAndroid Build Coastguard Worker                                              const rsg::ProgramParameters &params)
486*35238bceSAndroid Build Coastguard Worker     : TestCase(testCtx, name, "")
487*35238bceSAndroid Build Coastguard Worker     , m_renderCtx(renderCtx)
488*35238bceSAndroid Build Coastguard Worker     , m_ctxInfo(ctxInfo)
489*35238bceSAndroid Build Coastguard Worker     , m_params(params)
490*35238bceSAndroid Build Coastguard Worker     , m_vertexShader(rsg::Shader::TYPE_VERTEX)
491*35238bceSAndroid Build Coastguard Worker     , m_fragmentShader(rsg::Shader::TYPE_FRAGMENT)
492*35238bceSAndroid Build Coastguard Worker     , m_program(DE_NULL)
493*35238bceSAndroid Build Coastguard Worker     , m_glCtx(DE_NULL)
494*35238bceSAndroid Build Coastguard Worker     , m_referenceCtx(DE_NULL)
495*35238bceSAndroid Build Coastguard Worker     , m_glProgram(0)
496*35238bceSAndroid Build Coastguard Worker     , m_refProgram(0)
497*35238bceSAndroid Build Coastguard Worker     , m_iterNdx(0)
498*35238bceSAndroid Build Coastguard Worker {
499*35238bceSAndroid Build Coastguard Worker }
500*35238bceSAndroid Build Coastguard Worker 
~FragOpInteractionCase(void)501*35238bceSAndroid Build Coastguard Worker FragOpInteractionCase::~FragOpInteractionCase(void)
502*35238bceSAndroid Build Coastguard Worker {
503*35238bceSAndroid Build Coastguard Worker     FragOpInteractionCase::deinit();
504*35238bceSAndroid Build Coastguard Worker }
505*35238bceSAndroid Build Coastguard Worker 
init(void)506*35238bceSAndroid Build Coastguard Worker void FragOpInteractionCase::init(void)
507*35238bceSAndroid Build Coastguard Worker {
508*35238bceSAndroid Build Coastguard Worker     de::Random rnd(m_params.seed ^ 0x232faac);
509*35238bceSAndroid Build Coastguard Worker     const int viewportW = de::min<int>(m_renderCtx.getRenderTarget().getWidth(), VIEWPORT_WIDTH);
510*35238bceSAndroid Build Coastguard Worker     const int viewportH = de::min<int>(m_renderCtx.getRenderTarget().getHeight(), VIEWPORT_HEIGHT);
511*35238bceSAndroid Build Coastguard Worker     const int viewportX = rnd.getInt(0, m_renderCtx.getRenderTarget().getWidth() - viewportW);
512*35238bceSAndroid Build Coastguard Worker     const int viewportY = rnd.getInt(0, m_renderCtx.getRenderTarget().getHeight() - viewportH);
513*35238bceSAndroid Build Coastguard Worker 
514*35238bceSAndroid Build Coastguard Worker     rsg::ProgramGenerator generator;
515*35238bceSAndroid Build Coastguard Worker 
516*35238bceSAndroid Build Coastguard Worker     generator.generate(m_params, m_vertexShader, m_fragmentShader);
517*35238bceSAndroid Build Coastguard Worker     rsg::computeUnifiedUniforms(m_vertexShader, m_fragmentShader, m_unifiedUniforms);
518*35238bceSAndroid Build Coastguard Worker 
519*35238bceSAndroid Build Coastguard Worker     try
520*35238bceSAndroid Build Coastguard Worker     {
521*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(!m_program);
522*35238bceSAndroid Build Coastguard Worker         m_program = new gls::RandomShaderProgram(m_vertexShader, m_fragmentShader, (int)m_unifiedUniforms.size(),
523*35238bceSAndroid Build Coastguard Worker                                                  m_unifiedUniforms.empty() ? DE_NULL : &m_unifiedUniforms[0]);
524*35238bceSAndroid Build Coastguard Worker 
525*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(!m_referenceCtx);
526*35238bceSAndroid Build Coastguard Worker         m_referenceCtx = new ReferenceContext(m_renderCtx, viewportW, viewportH);
527*35238bceSAndroid Build Coastguard Worker 
528*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(!m_glCtx);
529*35238bceSAndroid Build Coastguard Worker         m_glCtx = new sglr::GLContext(m_renderCtx, m_testCtx.getLog(),
530*35238bceSAndroid Build Coastguard Worker                                       sglr::GLCONTEXT_LOG_CALLS | sglr::GLCONTEXT_LOG_PROGRAMS,
531*35238bceSAndroid Build Coastguard Worker                                       IVec4(viewportX, viewportY, viewportW, viewportH));
532*35238bceSAndroid Build Coastguard Worker 
533*35238bceSAndroid Build Coastguard Worker         m_refProgram = m_referenceCtx->context.createProgram(m_program);
534*35238bceSAndroid Build Coastguard Worker         m_glProgram  = m_glCtx->createProgram(m_program);
535*35238bceSAndroid Build Coastguard Worker 
536*35238bceSAndroid Build Coastguard Worker         m_viewportSize = tcu::IVec2(viewportW, viewportH);
537*35238bceSAndroid Build Coastguard Worker         m_iterNdx      = 0;
538*35238bceSAndroid Build Coastguard Worker         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
539*35238bceSAndroid Build Coastguard Worker     }
540*35238bceSAndroid Build Coastguard Worker     catch (...)
541*35238bceSAndroid Build Coastguard Worker     {
542*35238bceSAndroid Build Coastguard Worker         // Save some memory by cleaning up stuff.
543*35238bceSAndroid Build Coastguard Worker         FragOpInteractionCase::deinit();
544*35238bceSAndroid Build Coastguard Worker         throw;
545*35238bceSAndroid Build Coastguard Worker     }
546*35238bceSAndroid Build Coastguard Worker }
547*35238bceSAndroid Build Coastguard Worker 
deinit(void)548*35238bceSAndroid Build Coastguard Worker void FragOpInteractionCase::deinit(void)
549*35238bceSAndroid Build Coastguard Worker {
550*35238bceSAndroid Build Coastguard Worker     delete m_referenceCtx;
551*35238bceSAndroid Build Coastguard Worker     m_referenceCtx = DE_NULL;
552*35238bceSAndroid Build Coastguard Worker 
553*35238bceSAndroid Build Coastguard Worker     delete m_glCtx;
554*35238bceSAndroid Build Coastguard Worker     m_glCtx = DE_NULL;
555*35238bceSAndroid Build Coastguard Worker 
556*35238bceSAndroid Build Coastguard Worker     delete m_program;
557*35238bceSAndroid Build Coastguard Worker     m_program = DE_NULL;
558*35238bceSAndroid Build Coastguard Worker }
559*35238bceSAndroid Build Coastguard Worker 
iterate(void)560*35238bceSAndroid Build Coastguard Worker FragOpInteractionCase::IterateResult FragOpInteractionCase::iterate(void)
561*35238bceSAndroid Build Coastguard Worker {
562*35238bceSAndroid Build Coastguard Worker     de::Random rnd(m_params.seed ^ deInt32Hash(m_iterNdx));
563*35238bceSAndroid Build Coastguard Worker     const tcu::ScopedLogSection section(m_testCtx.getLog(), string("Iter") + de::toString(m_iterNdx),
564*35238bceSAndroid Build Coastguard Worker                                         string("Iteration ") + de::toString(m_iterNdx));
565*35238bceSAndroid Build Coastguard Worker 
566*35238bceSAndroid Build Coastguard Worker     const int positionNdx = findShaderInputIndex(m_vertexShader.getInputs(), "dEQP_Position");
567*35238bceSAndroid Build Coastguard Worker 
568*35238bceSAndroid Build Coastguard Worker     const int numVertices = 4;
569*35238bceSAndroid Build Coastguard Worker     VertexDataStorage vertexData(m_vertexShader.getInputs(), numVertices);
570*35238bceSAndroid Build Coastguard Worker     std::vector<rsg::VariableValue> uniformValues;
571*35238bceSAndroid Build Coastguard Worker     std::vector<RenderCommand> renderCmds(NUM_COMMANDS_PER_ITERATION);
572*35238bceSAndroid Build Coastguard Worker 
573*35238bceSAndroid Build Coastguard Worker     tcu::Surface rendered(m_viewportSize.x(), m_viewportSize.y());
574*35238bceSAndroid Build Coastguard Worker     tcu::Surface reference(m_viewportSize.x(), m_viewportSize.y());
575*35238bceSAndroid Build Coastguard Worker 
576*35238bceSAndroid Build Coastguard Worker     const tcu::Vec4 vtxInterpFactors[] = {tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f), tcu::Vec4(1.0f, 0.0f, 0.5f, 0.5f),
577*35238bceSAndroid Build Coastguard Worker                                           tcu::Vec4(0.0f, 1.0f, 0.5f, 0.5f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f)};
578*35238bceSAndroid Build Coastguard Worker 
579*35238bceSAndroid Build Coastguard Worker     rsg::computeUniformValues(rnd, uniformValues, m_unifiedUniforms);
580*35238bceSAndroid Build Coastguard Worker 
581*35238bceSAndroid Build Coastguard Worker     for (int attribNdx = 0; attribNdx < (int)m_vertexShader.getInputs().size(); ++attribNdx)
582*35238bceSAndroid Build Coastguard Worker     {
583*35238bceSAndroid Build Coastguard Worker         if (attribNdx == positionNdx)
584*35238bceSAndroid Build Coastguard Worker             continue;
585*35238bceSAndroid Build Coastguard Worker 
586*35238bceSAndroid Build Coastguard Worker         const rsg::ShaderInput *shaderIn            = m_vertexShader.getInputs()[attribNdx];
587*35238bceSAndroid Build Coastguard Worker         const rsg::VariableType &varType            = shaderIn->getVariable()->getType();
588*35238bceSAndroid Build Coastguard Worker         const rsg::ConstValueRangeAccess valueRange = shaderIn->getValueRange();
589*35238bceSAndroid Build Coastguard Worker         const int numComponents                     = varType.getNumElements();
590*35238bceSAndroid Build Coastguard Worker         const glu::VertexArrayBinding layoutEntry   = getEntryWithPointer(vertexData, attribNdx);
591*35238bceSAndroid Build Coastguard Worker 
592*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(varType.getBaseType() == rsg::VariableType::TYPE_FLOAT);
593*35238bceSAndroid Build Coastguard Worker 
594*35238bceSAndroid Build Coastguard Worker         for (int vtxNdx = 0; vtxNdx < 4; vtxNdx++)
595*35238bceSAndroid Build Coastguard Worker         {
596*35238bceSAndroid Build Coastguard Worker             const int fNdx     = (attribNdx + vtxNdx + m_iterNdx) % DE_LENGTH_OF_ARRAY(vtxInterpFactors);
597*35238bceSAndroid Build Coastguard Worker             const tcu::Vec4 &f = vtxInterpFactors[fNdx];
598*35238bceSAndroid Build Coastguard Worker 
599*35238bceSAndroid Build Coastguard Worker             switch (numComponents)
600*35238bceSAndroid Build Coastguard Worker             {
601*35238bceSAndroid Build Coastguard Worker             case 1:
602*35238bceSAndroid Build Coastguard Worker                 setVertex(layoutEntry.pointer, vtxNdx, interpolateRange(valueRange, f.toWidth<1>()));
603*35238bceSAndroid Build Coastguard Worker                 break;
604*35238bceSAndroid Build Coastguard Worker             case 2:
605*35238bceSAndroid Build Coastguard Worker                 setVertex(layoutEntry.pointer, vtxNdx, interpolateRange(valueRange, f.toWidth<2>()));
606*35238bceSAndroid Build Coastguard Worker                 break;
607*35238bceSAndroid Build Coastguard Worker             case 3:
608*35238bceSAndroid Build Coastguard Worker                 setVertex(layoutEntry.pointer, vtxNdx, interpolateRange(valueRange, f.toWidth<3>()));
609*35238bceSAndroid Build Coastguard Worker                 break;
610*35238bceSAndroid Build Coastguard Worker             case 4:
611*35238bceSAndroid Build Coastguard Worker                 setVertex(layoutEntry.pointer, vtxNdx, interpolateRange(valueRange, f.toWidth<4>()));
612*35238bceSAndroid Build Coastguard Worker                 break;
613*35238bceSAndroid Build Coastguard Worker             default:
614*35238bceSAndroid Build Coastguard Worker                 DE_ASSERT(false);
615*35238bceSAndroid Build Coastguard Worker             }
616*35238bceSAndroid Build Coastguard Worker         }
617*35238bceSAndroid Build Coastguard Worker     }
618*35238bceSAndroid Build Coastguard Worker 
619*35238bceSAndroid Build Coastguard Worker     for (vector<RenderCommand>::iterator cmdIter = renderCmds.begin(); cmdIter != renderCmds.end(); ++cmdIter)
620*35238bceSAndroid Build Coastguard Worker         computeRandomRenderCommand(rnd, *cmdIter, m_renderCtx.getType().getAPI(), m_viewportSize.x(),
621*35238bceSAndroid Build Coastguard Worker                                    m_viewportSize.y());
622*35238bceSAndroid Build Coastguard Worker 
623*35238bceSAndroid Build Coastguard Worker     // Workaround for inaccurate barycentric/depth computation in current reference renderer:
624*35238bceSAndroid Build Coastguard Worker     // Small bias is added to the draw call depths, in increasing order, to avoid accuracy issues in depth comparison.
625*35238bceSAndroid Build Coastguard Worker     for (int cmdNdx = 0; cmdNdx < (int)renderCmds.size(); cmdNdx++)
626*35238bceSAndroid Build Coastguard Worker         renderCmds[cmdNdx].depth += 0.0231725f * float(cmdNdx);
627*35238bceSAndroid Build Coastguard Worker 
628*35238bceSAndroid Build Coastguard Worker     {
629*35238bceSAndroid Build Coastguard Worker         const glu::VertexArrayPointer posPtr = getEntryWithPointer(vertexData, positionNdx).pointer;
630*35238bceSAndroid Build Coastguard Worker 
631*35238bceSAndroid Build Coastguard Worker         sglr::Context *const contexts[]  = {m_glCtx, &m_referenceCtx->context};
632*35238bceSAndroid Build Coastguard Worker         const uint32_t programs[]        = {m_glProgram, m_refProgram};
633*35238bceSAndroid Build Coastguard Worker         tcu::PixelBufferAccess readDst[] = {rendered.getAccess(), reference.getAccess()};
634*35238bceSAndroid Build Coastguard Worker 
635*35238bceSAndroid Build Coastguard Worker         const tcu::Vec4 accurateClearColor = tcu::Vec4(0.0f, 0.25f, 0.5f, 1.0f);
636*35238bceSAndroid Build Coastguard Worker         const tcu::Vec4 clearColor =
637*35238bceSAndroid Build Coastguard Worker             getWellBehavingColor(accurateClearColor, m_renderCtx.getRenderTarget().getPixelFormat());
638*35238bceSAndroid Build Coastguard Worker 
639*35238bceSAndroid Build Coastguard Worker         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(contexts); ndx++)
640*35238bceSAndroid Build Coastguard Worker         {
641*35238bceSAndroid Build Coastguard Worker             sglr::Context &ctx     = *contexts[ndx];
642*35238bceSAndroid Build Coastguard Worker             const uint32_t program = programs[ndx];
643*35238bceSAndroid Build Coastguard Worker 
644*35238bceSAndroid Build Coastguard Worker             setupAttributes(ctx, vertexData, program);
645*35238bceSAndroid Build Coastguard Worker 
646*35238bceSAndroid Build Coastguard Worker             ctx.disable(GL_SCISSOR_TEST);
647*35238bceSAndroid Build Coastguard Worker             ctx.colorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
648*35238bceSAndroid Build Coastguard Worker             ctx.depthMask(GL_TRUE);
649*35238bceSAndroid Build Coastguard Worker             ctx.stencilMask(~0u);
650*35238bceSAndroid Build Coastguard Worker             ctx.clearColor(clearColor.x(), clearColor.y(), clearColor.z(), clearColor.w());
651*35238bceSAndroid Build Coastguard Worker             ctx.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
652*35238bceSAndroid Build Coastguard Worker 
653*35238bceSAndroid Build Coastguard Worker             ctx.useProgram(program);
654*35238bceSAndroid Build Coastguard Worker 
655*35238bceSAndroid Build Coastguard Worker             for (vector<rsg::VariableValue>::const_iterator uniformIter = uniformValues.begin();
656*35238bceSAndroid Build Coastguard Worker                  uniformIter != uniformValues.end(); ++uniformIter)
657*35238bceSAndroid Build Coastguard Worker                 setUniformValue(ctx, ctx.getUniformLocation(program, uniformIter->getVariable()->getName()),
658*35238bceSAndroid Build Coastguard Worker                                 uniformIter->getValue());
659*35238bceSAndroid Build Coastguard Worker 
660*35238bceSAndroid Build Coastguard Worker             for (vector<RenderCommand>::const_iterator cmdIter = renderCmds.begin(); cmdIter != renderCmds.end();
661*35238bceSAndroid Build Coastguard Worker                  ++cmdIter)
662*35238bceSAndroid Build Coastguard Worker                 render(ctx, posPtr, *cmdIter);
663*35238bceSAndroid Build Coastguard Worker 
664*35238bceSAndroid Build Coastguard Worker             GLU_EXPECT_NO_ERROR(ctx.getError(), "Rendering failed");
665*35238bceSAndroid Build Coastguard Worker 
666*35238bceSAndroid Build Coastguard Worker             ctx.readPixels(0, 0, m_viewportSize.x(), m_viewportSize.y(), GL_RGBA, GL_UNSIGNED_BYTE,
667*35238bceSAndroid Build Coastguard Worker                            readDst[ndx].getDataPtr());
668*35238bceSAndroid Build Coastguard Worker         }
669*35238bceSAndroid Build Coastguard Worker     }
670*35238bceSAndroid Build Coastguard Worker 
671*35238bceSAndroid Build Coastguard Worker     {
672*35238bceSAndroid Build Coastguard Worker         const tcu::RGBA threshold =
673*35238bceSAndroid Build Coastguard Worker             m_renderCtx.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(3, 3, 3, 3);
674*35238bceSAndroid Build Coastguard Worker         const bool compareOk =
675*35238bceSAndroid Build Coastguard Worker             tcu::bilinearCompare(m_testCtx.getLog(), "CompareResult", "Image comparison result", reference.getAccess(),
676*35238bceSAndroid Build Coastguard Worker                                  rendered.getAccess(), threshold, tcu::COMPARE_LOG_RESULT);
677*35238bceSAndroid Build Coastguard Worker 
678*35238bceSAndroid Build Coastguard Worker         if (!compareOk)
679*35238bceSAndroid Build Coastguard Worker         {
680*35238bceSAndroid Build Coastguard Worker             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
681*35238bceSAndroid Build Coastguard Worker             return STOP;
682*35238bceSAndroid Build Coastguard Worker         }
683*35238bceSAndroid Build Coastguard Worker     }
684*35238bceSAndroid Build Coastguard Worker 
685*35238bceSAndroid Build Coastguard Worker     m_iterNdx += 1;
686*35238bceSAndroid Build Coastguard Worker     return (m_iterNdx < NUM_ITERATIONS) ? CONTINUE : STOP;
687*35238bceSAndroid Build Coastguard Worker }
688*35238bceSAndroid Build Coastguard Worker 
689*35238bceSAndroid Build Coastguard Worker } // namespace gls
690*35238bceSAndroid Build Coastguard Worker } // namespace deqp
691