xref: /aosp_15_r20/external/deqp/modules/egl/teglRenderTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1*35238bceSAndroid Build Coastguard Worker /*-------------------------------------------------------------------------
2*35238bceSAndroid Build Coastguard Worker  * drawElements Quality Program EGL 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 Rendering tests for different config and api combinations.
22*35238bceSAndroid Build Coastguard Worker  * \todo [2013-03-19 pyry] GLES1 and VG support.
23*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
24*35238bceSAndroid Build Coastguard Worker 
25*35238bceSAndroid Build Coastguard Worker #include "teglRenderTests.hpp"
26*35238bceSAndroid Build Coastguard Worker #include "teglRenderCase.hpp"
27*35238bceSAndroid Build Coastguard Worker 
28*35238bceSAndroid Build Coastguard Worker #include "tcuRenderTarget.hpp"
29*35238bceSAndroid Build Coastguard Worker #include "tcuTestLog.hpp"
30*35238bceSAndroid Build Coastguard Worker #include "tcuImageCompare.hpp"
31*35238bceSAndroid Build Coastguard Worker #include "tcuTextureUtil.hpp"
32*35238bceSAndroid Build Coastguard Worker #include "tcuSurface.hpp"
33*35238bceSAndroid Build Coastguard Worker 
34*35238bceSAndroid Build Coastguard Worker #include "egluDefs.hpp"
35*35238bceSAndroid Build Coastguard Worker #include "egluUtil.hpp"
36*35238bceSAndroid Build Coastguard Worker 
37*35238bceSAndroid Build Coastguard Worker #include "eglwLibrary.hpp"
38*35238bceSAndroid Build Coastguard Worker #include "eglwEnums.hpp"
39*35238bceSAndroid Build Coastguard Worker 
40*35238bceSAndroid Build Coastguard Worker #include "gluShaderProgram.hpp"
41*35238bceSAndroid Build Coastguard Worker 
42*35238bceSAndroid Build Coastguard Worker #include "glwFunctions.hpp"
43*35238bceSAndroid Build Coastguard Worker #include "glwEnums.hpp"
44*35238bceSAndroid Build Coastguard Worker 
45*35238bceSAndroid Build Coastguard Worker #include "deRandom.hpp"
46*35238bceSAndroid Build Coastguard Worker #include "deSharedPtr.hpp"
47*35238bceSAndroid Build Coastguard Worker #include "deSemaphore.hpp"
48*35238bceSAndroid Build Coastguard Worker #include "deThread.hpp"
49*35238bceSAndroid Build Coastguard Worker #include "deString.h"
50*35238bceSAndroid Build Coastguard Worker 
51*35238bceSAndroid Build Coastguard Worker #include "rrRenderer.hpp"
52*35238bceSAndroid Build Coastguard Worker #include "rrFragmentOperations.hpp"
53*35238bceSAndroid Build Coastguard Worker 
54*35238bceSAndroid Build Coastguard Worker #include <algorithm>
55*35238bceSAndroid Build Coastguard Worker #include <iterator>
56*35238bceSAndroid Build Coastguard Worker #include <memory>
57*35238bceSAndroid Build Coastguard Worker #include <set>
58*35238bceSAndroid Build Coastguard Worker 
59*35238bceSAndroid Build Coastguard Worker namespace deqp
60*35238bceSAndroid Build Coastguard Worker {
61*35238bceSAndroid Build Coastguard Worker namespace egl
62*35238bceSAndroid Build Coastguard Worker {
63*35238bceSAndroid Build Coastguard Worker 
64*35238bceSAndroid Build Coastguard Worker using std::set;
65*35238bceSAndroid Build Coastguard Worker using std::string;
66*35238bceSAndroid Build Coastguard Worker using std::vector;
67*35238bceSAndroid Build Coastguard Worker 
68*35238bceSAndroid Build Coastguard Worker using tcu::Vec4;
69*35238bceSAndroid Build Coastguard Worker 
70*35238bceSAndroid Build Coastguard Worker using tcu::TestLog;
71*35238bceSAndroid Build Coastguard Worker 
72*35238bceSAndroid Build Coastguard Worker using namespace glw;
73*35238bceSAndroid Build Coastguard Worker using namespace eglw;
74*35238bceSAndroid Build Coastguard Worker 
75*35238bceSAndroid Build Coastguard Worker static const tcu::Vec4 CLEAR_COLOR = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
76*35238bceSAndroid Build Coastguard Worker static const float CLEAR_DEPTH     = 1.0f;
77*35238bceSAndroid Build Coastguard Worker static const int CLEAR_STENCIL     = 0;
78*35238bceSAndroid Build Coastguard Worker 
79*35238bceSAndroid Build Coastguard Worker namespace
80*35238bceSAndroid Build Coastguard Worker {
81*35238bceSAndroid Build Coastguard Worker 
82*35238bceSAndroid Build Coastguard Worker enum PrimitiveType
83*35238bceSAndroid Build Coastguard Worker {
84*35238bceSAndroid Build Coastguard Worker     PRIMITIVETYPE_TRIANGLE = 0, //!< Triangles, requires 3 coordinates per primitive
85*35238bceSAndroid Build Coastguard Worker     //    PRIMITIVETYPE_POINT, //!< Points, requires 1 coordinate per primitive (w is used as size)
86*35238bceSAndroid Build Coastguard Worker     //    PRIMITIVETYPE_LINE, //!< Lines, requires 2 coordinates per primitive
87*35238bceSAndroid Build Coastguard Worker 
88*35238bceSAndroid Build Coastguard Worker     PRIMITIVETYPE_LAST
89*35238bceSAndroid Build Coastguard Worker };
90*35238bceSAndroid Build Coastguard Worker 
91*35238bceSAndroid Build Coastguard Worker enum BlendMode
92*35238bceSAndroid Build Coastguard Worker {
93*35238bceSAndroid Build Coastguard Worker     BLENDMODE_NONE = 0, //!< No blending
94*35238bceSAndroid Build Coastguard Worker     BLENDMODE_ADDITIVE, //!< Blending with ONE, ONE
95*35238bceSAndroid Build Coastguard Worker     BLENDMODE_SRC_OVER, //!< Blending with SRC_ALPHA, ONE_MINUS_SRC_ALPHA
96*35238bceSAndroid Build Coastguard Worker 
97*35238bceSAndroid Build Coastguard Worker     BLENDMODE_LAST
98*35238bceSAndroid Build Coastguard Worker };
99*35238bceSAndroid Build Coastguard Worker 
100*35238bceSAndroid Build Coastguard Worker enum DepthMode
101*35238bceSAndroid Build Coastguard Worker {
102*35238bceSAndroid Build Coastguard Worker     DEPTHMODE_NONE = 0, //!< No depth test or depth writes
103*35238bceSAndroid Build Coastguard Worker     DEPTHMODE_LESS,     //!< Depth test with less & depth write
104*35238bceSAndroid Build Coastguard Worker 
105*35238bceSAndroid Build Coastguard Worker     DEPTHMODE_LAST
106*35238bceSAndroid Build Coastguard Worker };
107*35238bceSAndroid Build Coastguard Worker 
108*35238bceSAndroid Build Coastguard Worker enum StencilMode
109*35238bceSAndroid Build Coastguard Worker {
110*35238bceSAndroid Build Coastguard Worker     STENCILMODE_NONE = 0,   //!< No stencil test or write
111*35238bceSAndroid Build Coastguard Worker     STENCILMODE_LEQUAL_INC, //!< Stencil test with LEQUAL, increment on pass
112*35238bceSAndroid Build Coastguard Worker 
113*35238bceSAndroid Build Coastguard Worker     STENCILMODE_LAST
114*35238bceSAndroid Build Coastguard Worker };
115*35238bceSAndroid Build Coastguard Worker 
116*35238bceSAndroid Build Coastguard Worker struct DrawPrimitiveOp
117*35238bceSAndroid Build Coastguard Worker {
118*35238bceSAndroid Build Coastguard Worker     PrimitiveType type;
119*35238bceSAndroid Build Coastguard Worker     int count;
120*35238bceSAndroid Build Coastguard Worker     vector<Vec4> positions;
121*35238bceSAndroid Build Coastguard Worker     vector<Vec4> colors;
122*35238bceSAndroid Build Coastguard Worker     BlendMode blend;
123*35238bceSAndroid Build Coastguard Worker     DepthMode depth;
124*35238bceSAndroid Build Coastguard Worker     StencilMode stencil;
125*35238bceSAndroid Build Coastguard Worker     int stencilRef;
126*35238bceSAndroid Build Coastguard Worker };
127*35238bceSAndroid Build Coastguard Worker 
isANarrowScreenSpaceTriangle(const tcu::Vec4 & p0,const tcu::Vec4 & p1,const tcu::Vec4 & p2)128*35238bceSAndroid Build Coastguard Worker static bool isANarrowScreenSpaceTriangle(const tcu::Vec4 &p0, const tcu::Vec4 &p1, const tcu::Vec4 &p2)
129*35238bceSAndroid Build Coastguard Worker {
130*35238bceSAndroid Build Coastguard Worker     // to clip space
131*35238bceSAndroid Build Coastguard Worker     const tcu::Vec2 csp0 = p0.swizzle(0, 1) / p0.w();
132*35238bceSAndroid Build Coastguard Worker     const tcu::Vec2 csp1 = p1.swizzle(0, 1) / p1.w();
133*35238bceSAndroid Build Coastguard Worker     const tcu::Vec2 csp2 = p2.swizzle(0, 1) / p2.w();
134*35238bceSAndroid Build Coastguard Worker 
135*35238bceSAndroid Build Coastguard Worker     const tcu::Vec2 e01 = (csp1 - csp0);
136*35238bceSAndroid Build Coastguard Worker     const tcu::Vec2 e02 = (csp2 - csp0);
137*35238bceSAndroid Build Coastguard Worker 
138*35238bceSAndroid Build Coastguard Worker     const float minimumVisibleArea = 0.4f; // must cover at least 10% of the surface
139*35238bceSAndroid Build Coastguard Worker     const float visibleArea        = de::abs(e01.x() * e02.y() - e02.x() * e01.y()) * 0.5f;
140*35238bceSAndroid Build Coastguard Worker 
141*35238bceSAndroid Build Coastguard Worker     return visibleArea < minimumVisibleArea;
142*35238bceSAndroid Build Coastguard Worker }
143*35238bceSAndroid Build Coastguard Worker 
randomizeDrawOp(de::Random & rnd,DrawPrimitiveOp & drawOp,const bool alphaZeroOrOne)144*35238bceSAndroid Build Coastguard Worker void randomizeDrawOp(de::Random &rnd, DrawPrimitiveOp &drawOp, const bool alphaZeroOrOne)
145*35238bceSAndroid Build Coastguard Worker {
146*35238bceSAndroid Build Coastguard Worker     const int minStencilRef = 0;
147*35238bceSAndroid Build Coastguard Worker     const int maxStencilRef = 8;
148*35238bceSAndroid Build Coastguard Worker     const int minPrimitives = 2;
149*35238bceSAndroid Build Coastguard Worker     const int maxPrimitives = 4;
150*35238bceSAndroid Build Coastguard Worker 
151*35238bceSAndroid Build Coastguard Worker     const float maxTriOffset = 1.0f;
152*35238bceSAndroid Build Coastguard Worker     const float minDepth     = -1.0f; // \todo [pyry] Reference doesn't support Z clipping yet
153*35238bceSAndroid Build Coastguard Worker     const float maxDepth     = 1.0f;
154*35238bceSAndroid Build Coastguard Worker 
155*35238bceSAndroid Build Coastguard Worker     const float minRGB   = 0.2f;
156*35238bceSAndroid Build Coastguard Worker     const float maxRGB   = 0.9f;
157*35238bceSAndroid Build Coastguard Worker     const float minAlpha = 0.3f;
158*35238bceSAndroid Build Coastguard Worker     const float maxAlpha = 1.0f;
159*35238bceSAndroid Build Coastguard Worker 
160*35238bceSAndroid Build Coastguard Worker     drawOp.type       = (PrimitiveType)rnd.getInt(0, PRIMITIVETYPE_LAST - 1);
161*35238bceSAndroid Build Coastguard Worker     drawOp.count      = rnd.getInt(minPrimitives, maxPrimitives);
162*35238bceSAndroid Build Coastguard Worker     drawOp.blend      = (BlendMode)rnd.getInt(0, BLENDMODE_LAST - 1);
163*35238bceSAndroid Build Coastguard Worker     drawOp.depth      = (DepthMode)rnd.getInt(0, DEPTHMODE_LAST - 1);
164*35238bceSAndroid Build Coastguard Worker     drawOp.stencil    = (StencilMode)rnd.getInt(0, STENCILMODE_LAST - 1);
165*35238bceSAndroid Build Coastguard Worker     drawOp.stencilRef = rnd.getInt(minStencilRef, maxStencilRef);
166*35238bceSAndroid Build Coastguard Worker 
167*35238bceSAndroid Build Coastguard Worker     if (drawOp.type == PRIMITIVETYPE_TRIANGLE)
168*35238bceSAndroid Build Coastguard Worker     {
169*35238bceSAndroid Build Coastguard Worker         drawOp.positions.resize(drawOp.count * 3);
170*35238bceSAndroid Build Coastguard Worker         drawOp.colors.resize(drawOp.count * 3);
171*35238bceSAndroid Build Coastguard Worker 
172*35238bceSAndroid Build Coastguard Worker         for (int triNdx = 0; triNdx < drawOp.count; triNdx++)
173*35238bceSAndroid Build Coastguard Worker         {
174*35238bceSAndroid Build Coastguard Worker             const float cx        = rnd.getFloat(-1.0f, 1.0f);
175*35238bceSAndroid Build Coastguard Worker             const float cy        = rnd.getFloat(-1.0f, 1.0f);
176*35238bceSAndroid Build Coastguard Worker             const float flatAlpha = (rnd.getFloat(minAlpha, maxAlpha) > 0.5f) ? 1.0f : 0.0f;
177*35238bceSAndroid Build Coastguard Worker 
178*35238bceSAndroid Build Coastguard Worker             for (int coordNdx = 0; coordNdx < 3; coordNdx++)
179*35238bceSAndroid Build Coastguard Worker             {
180*35238bceSAndroid Build Coastguard Worker                 tcu::Vec4 &position = drawOp.positions[triNdx * 3 + coordNdx];
181*35238bceSAndroid Build Coastguard Worker                 tcu::Vec4 &color    = drawOp.colors[triNdx * 3 + coordNdx];
182*35238bceSAndroid Build Coastguard Worker 
183*35238bceSAndroid Build Coastguard Worker                 position.x() = cx + rnd.getFloat(-maxTriOffset, maxTriOffset);
184*35238bceSAndroid Build Coastguard Worker                 position.y() = cy + rnd.getFloat(-maxTriOffset, maxTriOffset);
185*35238bceSAndroid Build Coastguard Worker                 position.z() = rnd.getFloat(minDepth, maxDepth);
186*35238bceSAndroid Build Coastguard Worker                 position.w() = 1.0f;
187*35238bceSAndroid Build Coastguard Worker 
188*35238bceSAndroid Build Coastguard Worker                 color.x() = rnd.getFloat(minRGB, maxRGB);
189*35238bceSAndroid Build Coastguard Worker                 color.y() = rnd.getFloat(minRGB, maxRGB);
190*35238bceSAndroid Build Coastguard Worker                 color.z() = rnd.getFloat(minRGB, maxRGB);
191*35238bceSAndroid Build Coastguard Worker                 color.w() = rnd.getFloat(minAlpha, maxAlpha);
192*35238bceSAndroid Build Coastguard Worker 
193*35238bceSAndroid Build Coastguard Worker                 if (alphaZeroOrOne)
194*35238bceSAndroid Build Coastguard Worker                 {
195*35238bceSAndroid Build Coastguard Worker                     color.w() = flatAlpha;
196*35238bceSAndroid Build Coastguard Worker                 }
197*35238bceSAndroid Build Coastguard Worker             }
198*35238bceSAndroid Build Coastguard Worker 
199*35238bceSAndroid Build Coastguard Worker             // avoid generating narrow triangles
200*35238bceSAndroid Build Coastguard Worker             {
201*35238bceSAndroid Build Coastguard Worker                 const int maxAttempts = 100;
202*35238bceSAndroid Build Coastguard Worker                 int numAttempts       = 0;
203*35238bceSAndroid Build Coastguard Worker                 tcu::Vec4 &p0         = drawOp.positions[triNdx * 3 + 0];
204*35238bceSAndroid Build Coastguard Worker                 tcu::Vec4 &p1         = drawOp.positions[triNdx * 3 + 1];
205*35238bceSAndroid Build Coastguard Worker                 tcu::Vec4 &p2         = drawOp.positions[triNdx * 3 + 2];
206*35238bceSAndroid Build Coastguard Worker 
207*35238bceSAndroid Build Coastguard Worker                 while (isANarrowScreenSpaceTriangle(p0, p1, p2))
208*35238bceSAndroid Build Coastguard Worker                 {
209*35238bceSAndroid Build Coastguard Worker                     p1.x() = cx + rnd.getFloat(-maxTriOffset, maxTriOffset);
210*35238bceSAndroid Build Coastguard Worker                     p1.y() = cy + rnd.getFloat(-maxTriOffset, maxTriOffset);
211*35238bceSAndroid Build Coastguard Worker                     p1.z() = rnd.getFloat(minDepth, maxDepth);
212*35238bceSAndroid Build Coastguard Worker                     p1.w() = 1.0f;
213*35238bceSAndroid Build Coastguard Worker 
214*35238bceSAndroid Build Coastguard Worker                     p2.x() = cx + rnd.getFloat(-maxTriOffset, maxTriOffset);
215*35238bceSAndroid Build Coastguard Worker                     p2.y() = cy + rnd.getFloat(-maxTriOffset, maxTriOffset);
216*35238bceSAndroid Build Coastguard Worker                     p2.z() = rnd.getFloat(minDepth, maxDepth);
217*35238bceSAndroid Build Coastguard Worker                     p2.w() = 1.0f;
218*35238bceSAndroid Build Coastguard Worker 
219*35238bceSAndroid Build Coastguard Worker                     if (++numAttempts > maxAttempts)
220*35238bceSAndroid Build Coastguard Worker                     {
221*35238bceSAndroid Build Coastguard Worker                         DE_ASSERT(false);
222*35238bceSAndroid Build Coastguard Worker                         break;
223*35238bceSAndroid Build Coastguard Worker                     }
224*35238bceSAndroid Build Coastguard Worker                 }
225*35238bceSAndroid Build Coastguard Worker             }
226*35238bceSAndroid Build Coastguard Worker         }
227*35238bceSAndroid Build Coastguard Worker     }
228*35238bceSAndroid Build Coastguard Worker     else
229*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
230*35238bceSAndroid Build Coastguard Worker }
231*35238bceSAndroid Build Coastguard Worker 
232*35238bceSAndroid Build Coastguard Worker // Reference rendering code
233*35238bceSAndroid Build Coastguard Worker 
234*35238bceSAndroid Build Coastguard Worker class ReferenceShader : public rr::VertexShader, public rr::FragmentShader
235*35238bceSAndroid Build Coastguard Worker {
236*35238bceSAndroid Build Coastguard Worker public:
237*35238bceSAndroid Build Coastguard Worker     enum
238*35238bceSAndroid Build Coastguard Worker     {
239*35238bceSAndroid Build Coastguard Worker         VaryingLoc_Color = 0
240*35238bceSAndroid Build Coastguard Worker     };
241*35238bceSAndroid Build Coastguard Worker 
ReferenceShader()242*35238bceSAndroid Build Coastguard Worker     ReferenceShader()
243*35238bceSAndroid Build Coastguard Worker         : rr::VertexShader(2, 1)   // color and pos in => color out
244*35238bceSAndroid Build Coastguard Worker         , rr::FragmentShader(1, 1) // color in => color out
245*35238bceSAndroid Build Coastguard Worker     {
246*35238bceSAndroid Build Coastguard Worker         this->rr::VertexShader::m_inputs[0].type = rr::GENERICVECTYPE_FLOAT;
247*35238bceSAndroid Build Coastguard Worker         this->rr::VertexShader::m_inputs[1].type = rr::GENERICVECTYPE_FLOAT;
248*35238bceSAndroid Build Coastguard Worker 
249*35238bceSAndroid Build Coastguard Worker         this->rr::VertexShader::m_outputs[0].type      = rr::GENERICVECTYPE_FLOAT;
250*35238bceSAndroid Build Coastguard Worker         this->rr::VertexShader::m_outputs[0].flatshade = false;
251*35238bceSAndroid Build Coastguard Worker 
252*35238bceSAndroid Build Coastguard Worker         this->rr::FragmentShader::m_inputs[0].type      = rr::GENERICVECTYPE_FLOAT;
253*35238bceSAndroid Build Coastguard Worker         this->rr::FragmentShader::m_inputs[0].flatshade = false;
254*35238bceSAndroid Build Coastguard Worker 
255*35238bceSAndroid Build Coastguard Worker         this->rr::FragmentShader::m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
256*35238bceSAndroid Build Coastguard Worker     }
257*35238bceSAndroid Build Coastguard Worker 
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const258*35238bceSAndroid Build Coastguard Worker     void shadeVertices(const rr::VertexAttrib *inputs, rr::VertexPacket *const *packets, const int numPackets) const
259*35238bceSAndroid Build Coastguard Worker     {
260*35238bceSAndroid Build Coastguard Worker         for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
261*35238bceSAndroid Build Coastguard Worker         {
262*35238bceSAndroid Build Coastguard Worker             const int positionAttrLoc = 0;
263*35238bceSAndroid Build Coastguard Worker             const int colorAttrLoc    = 1;
264*35238bceSAndroid Build Coastguard Worker 
265*35238bceSAndroid Build Coastguard Worker             rr::VertexPacket &packet = *packets[packetNdx];
266*35238bceSAndroid Build Coastguard Worker 
267*35238bceSAndroid Build Coastguard Worker             // Transform to position
268*35238bceSAndroid Build Coastguard Worker             packet.position = rr::readVertexAttribFloat(inputs[positionAttrLoc], packet.instanceNdx, packet.vertexNdx);
269*35238bceSAndroid Build Coastguard Worker 
270*35238bceSAndroid Build Coastguard Worker             // Pass color to FS
271*35238bceSAndroid Build Coastguard Worker             packet.outputs[VaryingLoc_Color] =
272*35238bceSAndroid Build Coastguard Worker                 rr::readVertexAttribFloat(inputs[colorAttrLoc], packet.instanceNdx, packet.vertexNdx);
273*35238bceSAndroid Build Coastguard Worker         }
274*35238bceSAndroid Build Coastguard Worker     }
275*35238bceSAndroid Build Coastguard Worker 
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const276*35238bceSAndroid Build Coastguard Worker     void shadeFragments(rr::FragmentPacket *packets, const int numPackets,
277*35238bceSAndroid Build Coastguard Worker                         const rr::FragmentShadingContext &context) const
278*35238bceSAndroid Build Coastguard Worker     {
279*35238bceSAndroid Build Coastguard Worker         for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
280*35238bceSAndroid Build Coastguard Worker         {
281*35238bceSAndroid Build Coastguard Worker             rr::FragmentPacket &packet = packets[packetNdx];
282*35238bceSAndroid Build Coastguard Worker 
283*35238bceSAndroid Build Coastguard Worker             for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
284*35238bceSAndroid Build Coastguard Worker                 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0,
285*35238bceSAndroid Build Coastguard Worker                                         rr::readVarying<float>(packet, context, VaryingLoc_Color, fragNdx));
286*35238bceSAndroid Build Coastguard Worker         }
287*35238bceSAndroid Build Coastguard Worker     }
288*35238bceSAndroid Build Coastguard Worker };
289*35238bceSAndroid Build Coastguard Worker 
toReferenceRenderState(rr::RenderState & state,const DrawPrimitiveOp & drawOp)290*35238bceSAndroid Build Coastguard Worker void toReferenceRenderState(rr::RenderState &state, const DrawPrimitiveOp &drawOp)
291*35238bceSAndroid Build Coastguard Worker {
292*35238bceSAndroid Build Coastguard Worker     state.cullMode = rr::CULLMODE_NONE;
293*35238bceSAndroid Build Coastguard Worker 
294*35238bceSAndroid Build Coastguard Worker     if (drawOp.blend != BLENDMODE_NONE)
295*35238bceSAndroid Build Coastguard Worker     {
296*35238bceSAndroid Build Coastguard Worker         state.fragOps.blendMode = rr::BLENDMODE_STANDARD;
297*35238bceSAndroid Build Coastguard Worker 
298*35238bceSAndroid Build Coastguard Worker         switch (drawOp.blend)
299*35238bceSAndroid Build Coastguard Worker         {
300*35238bceSAndroid Build Coastguard Worker         case BLENDMODE_ADDITIVE:
301*35238bceSAndroid Build Coastguard Worker             state.fragOps.blendRGBState.srcFunc  = rr::BLENDFUNC_ONE;
302*35238bceSAndroid Build Coastguard Worker             state.fragOps.blendRGBState.dstFunc  = rr::BLENDFUNC_ONE;
303*35238bceSAndroid Build Coastguard Worker             state.fragOps.blendRGBState.equation = rr::BLENDEQUATION_ADD;
304*35238bceSAndroid Build Coastguard Worker             state.fragOps.blendAState            = state.fragOps.blendRGBState;
305*35238bceSAndroid Build Coastguard Worker             break;
306*35238bceSAndroid Build Coastguard Worker 
307*35238bceSAndroid Build Coastguard Worker         case BLENDMODE_SRC_OVER:
308*35238bceSAndroid Build Coastguard Worker             state.fragOps.blendRGBState.srcFunc  = rr::BLENDFUNC_SRC_ALPHA;
309*35238bceSAndroid Build Coastguard Worker             state.fragOps.blendRGBState.dstFunc  = rr::BLENDFUNC_ONE_MINUS_SRC_ALPHA;
310*35238bceSAndroid Build Coastguard Worker             state.fragOps.blendRGBState.equation = rr::BLENDEQUATION_ADD;
311*35238bceSAndroid Build Coastguard Worker             state.fragOps.blendAState            = state.fragOps.blendRGBState;
312*35238bceSAndroid Build Coastguard Worker             break;
313*35238bceSAndroid Build Coastguard Worker 
314*35238bceSAndroid Build Coastguard Worker         default:
315*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(false);
316*35238bceSAndroid Build Coastguard Worker         }
317*35238bceSAndroid Build Coastguard Worker     }
318*35238bceSAndroid Build Coastguard Worker 
319*35238bceSAndroid Build Coastguard Worker     if (drawOp.depth != DEPTHMODE_NONE)
320*35238bceSAndroid Build Coastguard Worker     {
321*35238bceSAndroid Build Coastguard Worker         state.fragOps.depthTestEnabled = true;
322*35238bceSAndroid Build Coastguard Worker 
323*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(drawOp.depth == DEPTHMODE_LESS);
324*35238bceSAndroid Build Coastguard Worker         state.fragOps.depthFunc = rr::TESTFUNC_LESS;
325*35238bceSAndroid Build Coastguard Worker     }
326*35238bceSAndroid Build Coastguard Worker 
327*35238bceSAndroid Build Coastguard Worker     if (drawOp.stencil != STENCILMODE_NONE)
328*35238bceSAndroid Build Coastguard Worker     {
329*35238bceSAndroid Build Coastguard Worker         state.fragOps.stencilTestEnabled = true;
330*35238bceSAndroid Build Coastguard Worker 
331*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(drawOp.stencil == STENCILMODE_LEQUAL_INC);
332*35238bceSAndroid Build Coastguard Worker         state.fragOps.stencilStates[0].func   = rr::TESTFUNC_LEQUAL;
333*35238bceSAndroid Build Coastguard Worker         state.fragOps.stencilStates[0].sFail  = rr::STENCILOP_KEEP;
334*35238bceSAndroid Build Coastguard Worker         state.fragOps.stencilStates[0].dpFail = rr::STENCILOP_INCR;
335*35238bceSAndroid Build Coastguard Worker         state.fragOps.stencilStates[0].dpPass = rr::STENCILOP_INCR;
336*35238bceSAndroid Build Coastguard Worker         state.fragOps.stencilStates[0].ref    = drawOp.stencilRef;
337*35238bceSAndroid Build Coastguard Worker         state.fragOps.stencilStates[1]        = state.fragOps.stencilStates[0];
338*35238bceSAndroid Build Coastguard Worker     }
339*35238bceSAndroid Build Coastguard Worker }
340*35238bceSAndroid Build Coastguard Worker 
getColorFormat(const tcu::PixelFormat & colorBits)341*35238bceSAndroid Build Coastguard Worker tcu::TextureFormat getColorFormat(const tcu::PixelFormat &colorBits)
342*35238bceSAndroid Build Coastguard Worker {
343*35238bceSAndroid Build Coastguard Worker     using tcu::TextureFormat;
344*35238bceSAndroid Build Coastguard Worker 
345*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(de::inBounds(colorBits.redBits, 0, 0xff) && de::inBounds(colorBits.greenBits, 0, 0xff) &&
346*35238bceSAndroid Build Coastguard Worker               de::inBounds(colorBits.blueBits, 0, 0xff) && de::inBounds(colorBits.alphaBits, 0, 0xff));
347*35238bceSAndroid Build Coastguard Worker 
348*35238bceSAndroid Build Coastguard Worker #define PACK_FMT(R, G, B, A) (((R) << 24) | ((G) << 16) | ((B) << 8) | (A))
349*35238bceSAndroid Build Coastguard Worker 
350*35238bceSAndroid Build Coastguard Worker     // \note [pyry] This may not hold true on some implementations - best effort guess only.
351*35238bceSAndroid Build Coastguard Worker     switch (PACK_FMT(colorBits.redBits, colorBits.greenBits, colorBits.blueBits, colorBits.alphaBits))
352*35238bceSAndroid Build Coastguard Worker     {
353*35238bceSAndroid Build Coastguard Worker     case PACK_FMT(8, 8, 8, 8):
354*35238bceSAndroid Build Coastguard Worker         return TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8);
355*35238bceSAndroid Build Coastguard Worker     case PACK_FMT(8, 8, 8, 0):
356*35238bceSAndroid Build Coastguard Worker         return TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT8);
357*35238bceSAndroid Build Coastguard Worker     case PACK_FMT(4, 4, 4, 4):
358*35238bceSAndroid Build Coastguard Worker         return TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_SHORT_4444);
359*35238bceSAndroid Build Coastguard Worker     case PACK_FMT(5, 5, 5, 1):
360*35238bceSAndroid Build Coastguard Worker         return TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_SHORT_5551);
361*35238bceSAndroid Build Coastguard Worker     case PACK_FMT(5, 6, 5, 0):
362*35238bceSAndroid Build Coastguard Worker         return TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_SHORT_565);
363*35238bceSAndroid Build Coastguard Worker     case PACK_FMT(10, 10, 10, 2):
364*35238bceSAndroid Build Coastguard Worker         return TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT_1010102_REV);
365*35238bceSAndroid Build Coastguard Worker     case PACK_FMT(10, 10, 10, 0):
366*35238bceSAndroid Build Coastguard Worker         return TextureFormat(TextureFormat::RGB, TextureFormat::UNORM_INT_101010);
367*35238bceSAndroid Build Coastguard Worker     // \note Defaults to RGBA8
368*35238bceSAndroid Build Coastguard Worker     default:
369*35238bceSAndroid Build Coastguard Worker         return TextureFormat(TextureFormat::RGBA, TextureFormat::UNORM_INT8);
370*35238bceSAndroid Build Coastguard Worker     }
371*35238bceSAndroid Build Coastguard Worker 
372*35238bceSAndroid Build Coastguard Worker #undef PACK_FMT
373*35238bceSAndroid Build Coastguard Worker }
374*35238bceSAndroid Build Coastguard Worker 
375*35238bceSAndroid Build Coastguard Worker /*
376*35238bceSAndroid Build Coastguard Worker The getColorThreshold function is used to obtain a
377*35238bceSAndroid Build Coastguard Worker threshold usable for the fuzzyCompare function.
378*35238bceSAndroid Build Coastguard Worker 
379*35238bceSAndroid Build Coastguard Worker For 8bit color depths a value of 0.02 should provide
380*35238bceSAndroid Build Coastguard Worker a good metric for rejecting images above this level.
381*35238bceSAndroid Build Coastguard Worker For other bit depths other thresholds should be selected.
382*35238bceSAndroid Build Coastguard Worker Ideally this function would take advantage of the
383*35238bceSAndroid Build Coastguard Worker getColorThreshold function provided by the PixelFormat class
384*35238bceSAndroid Build Coastguard Worker as this would also allow setting per channel thresholds.
385*35238bceSAndroid Build Coastguard Worker However using the PixelFormat provided function can result
386*35238bceSAndroid Build Coastguard Worker in too strict thresholds for 8bit bit depths (compared to
387*35238bceSAndroid Build Coastguard Worker the current default of 0.02) or too relaxed for lower bit
388*35238bceSAndroid Build Coastguard Worker depths if scaled proportionally to the 8bit default.
389*35238bceSAndroid Build Coastguard Worker */
390*35238bceSAndroid Build Coastguard Worker 
getColorThreshold(const tcu::PixelFormat & colorBits)391*35238bceSAndroid Build Coastguard Worker float getColorThreshold(const tcu::PixelFormat &colorBits)
392*35238bceSAndroid Build Coastguard Worker {
393*35238bceSAndroid Build Coastguard Worker     if ((colorBits.redBits > 0 && colorBits.redBits < 8) || (colorBits.greenBits > 0 && colorBits.greenBits < 8) ||
394*35238bceSAndroid Build Coastguard Worker         (colorBits.blueBits > 0 && colorBits.blueBits < 8) || (colorBits.alphaBits > 0 && colorBits.alphaBits < 8))
395*35238bceSAndroid Build Coastguard Worker     {
396*35238bceSAndroid Build Coastguard Worker         return 0.05f;
397*35238bceSAndroid Build Coastguard Worker     }
398*35238bceSAndroid Build Coastguard Worker     else
399*35238bceSAndroid Build Coastguard Worker     {
400*35238bceSAndroid Build Coastguard Worker         return 0.02f;
401*35238bceSAndroid Build Coastguard Worker     }
402*35238bceSAndroid Build Coastguard Worker }
403*35238bceSAndroid Build Coastguard Worker 
getDepthFormat(const int depthBits)404*35238bceSAndroid Build Coastguard Worker tcu::TextureFormat getDepthFormat(const int depthBits)
405*35238bceSAndroid Build Coastguard Worker {
406*35238bceSAndroid Build Coastguard Worker     switch (depthBits)
407*35238bceSAndroid Build Coastguard Worker     {
408*35238bceSAndroid Build Coastguard Worker     case 0:
409*35238bceSAndroid Build Coastguard Worker         return tcu::TextureFormat();
410*35238bceSAndroid Build Coastguard Worker     case 8:
411*35238bceSAndroid Build Coastguard Worker         return tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNORM_INT8);
412*35238bceSAndroid Build Coastguard Worker     case 16:
413*35238bceSAndroid Build Coastguard Worker         return tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNORM_INT16);
414*35238bceSAndroid Build Coastguard Worker     case 24:
415*35238bceSAndroid Build Coastguard Worker         return tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNORM_INT24);
416*35238bceSAndroid Build Coastguard Worker     case 32:
417*35238bceSAndroid Build Coastguard Worker     default:
418*35238bceSAndroid Build Coastguard Worker         return tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::FLOAT);
419*35238bceSAndroid Build Coastguard Worker     }
420*35238bceSAndroid Build Coastguard Worker }
421*35238bceSAndroid Build Coastguard Worker 
getStencilFormat(int stencilBits)422*35238bceSAndroid Build Coastguard Worker tcu::TextureFormat getStencilFormat(int stencilBits)
423*35238bceSAndroid Build Coastguard Worker {
424*35238bceSAndroid Build Coastguard Worker     switch (stencilBits)
425*35238bceSAndroid Build Coastguard Worker     {
426*35238bceSAndroid Build Coastguard Worker     case 0:
427*35238bceSAndroid Build Coastguard Worker         return tcu::TextureFormat();
428*35238bceSAndroid Build Coastguard Worker     case 8:
429*35238bceSAndroid Build Coastguard Worker     default:
430*35238bceSAndroid Build Coastguard Worker         return tcu::TextureFormat(tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT8);
431*35238bceSAndroid Build Coastguard Worker     }
432*35238bceSAndroid Build Coastguard Worker }
433*35238bceSAndroid Build Coastguard Worker 
renderReference(const tcu::PixelBufferAccess & dst,const vector<DrawPrimitiveOp> & drawOps,const tcu::PixelFormat & colorBits,const int depthBits,const int stencilBits,const int numSamples,const int subpixelBits)434*35238bceSAndroid Build Coastguard Worker void renderReference(const tcu::PixelBufferAccess &dst, const vector<DrawPrimitiveOp> &drawOps,
435*35238bceSAndroid Build Coastguard Worker                      const tcu::PixelFormat &colorBits, const int depthBits, const int stencilBits,
436*35238bceSAndroid Build Coastguard Worker                      const int numSamples, const int subpixelBits)
437*35238bceSAndroid Build Coastguard Worker {
438*35238bceSAndroid Build Coastguard Worker     const int width  = dst.getWidth();
439*35238bceSAndroid Build Coastguard Worker     const int height = dst.getHeight();
440*35238bceSAndroid Build Coastguard Worker 
441*35238bceSAndroid Build Coastguard Worker     tcu::TextureLevel colorBuffer;
442*35238bceSAndroid Build Coastguard Worker     tcu::TextureLevel depthBuffer;
443*35238bceSAndroid Build Coastguard Worker     tcu::TextureLevel stencilBuffer;
444*35238bceSAndroid Build Coastguard Worker 
445*35238bceSAndroid Build Coastguard Worker     rr::Renderer referenceRenderer;
446*35238bceSAndroid Build Coastguard Worker     rr::VertexAttrib attributes[2];
447*35238bceSAndroid Build Coastguard Worker     const ReferenceShader shader;
448*35238bceSAndroid Build Coastguard Worker 
449*35238bceSAndroid Build Coastguard Worker     attributes[0].type            = rr::VERTEXATTRIBTYPE_FLOAT;
450*35238bceSAndroid Build Coastguard Worker     attributes[0].size            = 4;
451*35238bceSAndroid Build Coastguard Worker     attributes[0].stride          = 0;
452*35238bceSAndroid Build Coastguard Worker     attributes[0].instanceDivisor = 0;
453*35238bceSAndroid Build Coastguard Worker 
454*35238bceSAndroid Build Coastguard Worker     attributes[1].type            = rr::VERTEXATTRIBTYPE_FLOAT;
455*35238bceSAndroid Build Coastguard Worker     attributes[1].size            = 4;
456*35238bceSAndroid Build Coastguard Worker     attributes[1].stride          = 0;
457*35238bceSAndroid Build Coastguard Worker     attributes[1].instanceDivisor = 0;
458*35238bceSAndroid Build Coastguard Worker 
459*35238bceSAndroid Build Coastguard Worker     // Initialize buffers.
460*35238bceSAndroid Build Coastguard Worker     colorBuffer.setStorage(getColorFormat(colorBits), numSamples, width, height);
461*35238bceSAndroid Build Coastguard Worker     rr::clearMultisampleColorBuffer(colorBuffer, CLEAR_COLOR, rr::WindowRectangle(0, 0, width, height));
462*35238bceSAndroid Build Coastguard Worker 
463*35238bceSAndroid Build Coastguard Worker     if (depthBits > 0)
464*35238bceSAndroid Build Coastguard Worker     {
465*35238bceSAndroid Build Coastguard Worker         depthBuffer.setStorage(getDepthFormat(depthBits), numSamples, width, height);
466*35238bceSAndroid Build Coastguard Worker         rr::clearMultisampleDepthBuffer(depthBuffer, CLEAR_DEPTH, rr::WindowRectangle(0, 0, width, height));
467*35238bceSAndroid Build Coastguard Worker     }
468*35238bceSAndroid Build Coastguard Worker 
469*35238bceSAndroid Build Coastguard Worker     if (stencilBits > 0)
470*35238bceSAndroid Build Coastguard Worker     {
471*35238bceSAndroid Build Coastguard Worker         stencilBuffer.setStorage(getStencilFormat(stencilBits), numSamples, width, height);
472*35238bceSAndroid Build Coastguard Worker         rr::clearMultisampleStencilBuffer(stencilBuffer, CLEAR_STENCIL, rr::WindowRectangle(0, 0, width, height));
473*35238bceSAndroid Build Coastguard Worker     }
474*35238bceSAndroid Build Coastguard Worker 
475*35238bceSAndroid Build Coastguard Worker     const rr::RenderTarget renderTarget(
476*35238bceSAndroid Build Coastguard Worker         rr::MultisamplePixelBufferAccess::fromMultisampleAccess(colorBuffer.getAccess()),
477*35238bceSAndroid Build Coastguard Worker         rr::MultisamplePixelBufferAccess::fromMultisampleAccess(depthBuffer.getAccess()),
478*35238bceSAndroid Build Coastguard Worker         rr::MultisamplePixelBufferAccess::fromMultisampleAccess(stencilBuffer.getAccess()));
479*35238bceSAndroid Build Coastguard Worker 
480*35238bceSAndroid Build Coastguard Worker     for (vector<DrawPrimitiveOp>::const_iterator drawOp = drawOps.begin(); drawOp != drawOps.end(); drawOp++)
481*35238bceSAndroid Build Coastguard Worker     {
482*35238bceSAndroid Build Coastguard Worker         // Translate state
483*35238bceSAndroid Build Coastguard Worker         rr::RenderState renderState(
484*35238bceSAndroid Build Coastguard Worker             (rr::ViewportState)(rr::MultisamplePixelBufferAccess::fromMultisampleAccess(colorBuffer.getAccess())),
485*35238bceSAndroid Build Coastguard Worker             subpixelBits);
486*35238bceSAndroid Build Coastguard Worker         toReferenceRenderState(renderState, *drawOp);
487*35238bceSAndroid Build Coastguard Worker 
488*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(drawOp->type == PRIMITIVETYPE_TRIANGLE);
489*35238bceSAndroid Build Coastguard Worker 
490*35238bceSAndroid Build Coastguard Worker         attributes[0].pointer = &drawOp->positions[0];
491*35238bceSAndroid Build Coastguard Worker         attributes[1].pointer = &drawOp->colors[0];
492*35238bceSAndroid Build Coastguard Worker 
493*35238bceSAndroid Build Coastguard Worker         referenceRenderer.draw(rr::DrawCommand(renderState, renderTarget,
494*35238bceSAndroid Build Coastguard Worker                                                rr::Program(static_cast<const rr::VertexShader *>(&shader),
495*35238bceSAndroid Build Coastguard Worker                                                            static_cast<const rr::FragmentShader *>(&shader)),
496*35238bceSAndroid Build Coastguard Worker                                                2, attributes,
497*35238bceSAndroid Build Coastguard Worker                                                rr::PrimitiveList(rr::PRIMITIVETYPE_TRIANGLES, drawOp->count * 3, 0)));
498*35238bceSAndroid Build Coastguard Worker     }
499*35238bceSAndroid Build Coastguard Worker 
500*35238bceSAndroid Build Coastguard Worker     rr::resolveMultisampleColorBuffer(dst,
501*35238bceSAndroid Build Coastguard Worker                                       rr::MultisamplePixelBufferAccess::fromMultisampleAccess(colorBuffer.getAccess()));
502*35238bceSAndroid Build Coastguard Worker }
503*35238bceSAndroid Build Coastguard Worker 
504*35238bceSAndroid Build Coastguard Worker // API rendering code
505*35238bceSAndroid Build Coastguard Worker 
506*35238bceSAndroid Build Coastguard Worker class Program
507*35238bceSAndroid Build Coastguard Worker {
508*35238bceSAndroid Build Coastguard Worker public:
Program(void)509*35238bceSAndroid Build Coastguard Worker     Program(void)
510*35238bceSAndroid Build Coastguard Worker     {
511*35238bceSAndroid Build Coastguard Worker     }
~Program(void)512*35238bceSAndroid Build Coastguard Worker     virtual ~Program(void)
513*35238bceSAndroid Build Coastguard Worker     {
514*35238bceSAndroid Build Coastguard Worker     }
515*35238bceSAndroid Build Coastguard Worker 
516*35238bceSAndroid Build Coastguard Worker     virtual void setup(void) const = DE_NULL;
517*35238bceSAndroid Build Coastguard Worker };
518*35238bceSAndroid Build Coastguard Worker 
519*35238bceSAndroid Build Coastguard Worker typedef de::SharedPtr<Program> ProgramSp;
520*35238bceSAndroid Build Coastguard Worker 
getProgramSourcesES2(void)521*35238bceSAndroid Build Coastguard Worker static glu::ProgramSources getProgramSourcesES2(void)
522*35238bceSAndroid Build Coastguard Worker {
523*35238bceSAndroid Build Coastguard Worker     static const char *s_vertexSrc = "attribute highp vec4 a_position;\n"
524*35238bceSAndroid Build Coastguard Worker                                      "attribute mediump vec4 a_color;\n"
525*35238bceSAndroid Build Coastguard Worker                                      "varying mediump vec4 v_color;\n"
526*35238bceSAndroid Build Coastguard Worker                                      "void main (void)\n"
527*35238bceSAndroid Build Coastguard Worker                                      "{\n"
528*35238bceSAndroid Build Coastguard Worker                                      "    gl_Position = a_position;\n"
529*35238bceSAndroid Build Coastguard Worker                                      "    v_color = a_color;\n"
530*35238bceSAndroid Build Coastguard Worker                                      "}\n";
531*35238bceSAndroid Build Coastguard Worker 
532*35238bceSAndroid Build Coastguard Worker     static const char *s_fragmentSrc = "varying mediump vec4 v_color;\n"
533*35238bceSAndroid Build Coastguard Worker                                        "void main (void)\n"
534*35238bceSAndroid Build Coastguard Worker                                        "{\n"
535*35238bceSAndroid Build Coastguard Worker                                        "    gl_FragColor = v_color;\n"
536*35238bceSAndroid Build Coastguard Worker                                        "}\n";
537*35238bceSAndroid Build Coastguard Worker 
538*35238bceSAndroid Build Coastguard Worker     return glu::ProgramSources() << glu::VertexSource(s_vertexSrc) << glu::FragmentSource(s_fragmentSrc);
539*35238bceSAndroid Build Coastguard Worker }
540*35238bceSAndroid Build Coastguard Worker 
541*35238bceSAndroid Build Coastguard Worker class GLES2Program : public Program
542*35238bceSAndroid Build Coastguard Worker {
543*35238bceSAndroid Build Coastguard Worker public:
GLES2Program(const glw::Functions & gl)544*35238bceSAndroid Build Coastguard Worker     GLES2Program(const glw::Functions &gl)
545*35238bceSAndroid Build Coastguard Worker         : m_gl(gl)
546*35238bceSAndroid Build Coastguard Worker         , m_program(gl, getProgramSourcesES2())
547*35238bceSAndroid Build Coastguard Worker         , m_positionLoc(0)
548*35238bceSAndroid Build Coastguard Worker         , m_colorLoc(0)
549*35238bceSAndroid Build Coastguard Worker     {
550*35238bceSAndroid Build Coastguard Worker 
551*35238bceSAndroid Build Coastguard Worker         m_positionLoc = m_gl.getAttribLocation(m_program.getProgram(), "a_position");
552*35238bceSAndroid Build Coastguard Worker         m_colorLoc    = m_gl.getAttribLocation(m_program.getProgram(), "a_color");
553*35238bceSAndroid Build Coastguard Worker     }
554*35238bceSAndroid Build Coastguard Worker 
~GLES2Program(void)555*35238bceSAndroid Build Coastguard Worker     ~GLES2Program(void)
556*35238bceSAndroid Build Coastguard Worker     {
557*35238bceSAndroid Build Coastguard Worker     }
558*35238bceSAndroid Build Coastguard Worker 
setup(void) const559*35238bceSAndroid Build Coastguard Worker     void setup(void) const
560*35238bceSAndroid Build Coastguard Worker     {
561*35238bceSAndroid Build Coastguard Worker         m_gl.useProgram(m_program.getProgram());
562*35238bceSAndroid Build Coastguard Worker         m_gl.enableVertexAttribArray(m_positionLoc);
563*35238bceSAndroid Build Coastguard Worker         m_gl.enableVertexAttribArray(m_colorLoc);
564*35238bceSAndroid Build Coastguard Worker         GLU_CHECK_GLW_MSG(m_gl, "Program setup failed");
565*35238bceSAndroid Build Coastguard Worker     }
566*35238bceSAndroid Build Coastguard Worker 
getPositionLoc(void) const567*35238bceSAndroid Build Coastguard Worker     int getPositionLoc(void) const
568*35238bceSAndroid Build Coastguard Worker     {
569*35238bceSAndroid Build Coastguard Worker         return m_positionLoc;
570*35238bceSAndroid Build Coastguard Worker     }
getColorLoc(void) const571*35238bceSAndroid Build Coastguard Worker     int getColorLoc(void) const
572*35238bceSAndroid Build Coastguard Worker     {
573*35238bceSAndroid Build Coastguard Worker         return m_colorLoc;
574*35238bceSAndroid Build Coastguard Worker     }
575*35238bceSAndroid Build Coastguard Worker 
576*35238bceSAndroid Build Coastguard Worker private:
577*35238bceSAndroid Build Coastguard Worker     const glw::Functions &m_gl;
578*35238bceSAndroid Build Coastguard Worker     glu::ShaderProgram m_program;
579*35238bceSAndroid Build Coastguard Worker     int m_positionLoc;
580*35238bceSAndroid Build Coastguard Worker     int m_colorLoc;
581*35238bceSAndroid Build Coastguard Worker };
582*35238bceSAndroid Build Coastguard Worker 
clearGLES2(const glw::Functions & gl,const tcu::Vec4 & color,const float depth,const int stencil)583*35238bceSAndroid Build Coastguard Worker void clearGLES2(const glw::Functions &gl, const tcu::Vec4 &color, const float depth, const int stencil)
584*35238bceSAndroid Build Coastguard Worker {
585*35238bceSAndroid Build Coastguard Worker     gl.clearColor(color.x(), color.y(), color.z(), color.w());
586*35238bceSAndroid Build Coastguard Worker     gl.clearDepthf(depth);
587*35238bceSAndroid Build Coastguard Worker     gl.clearStencil(stencil);
588*35238bceSAndroid Build Coastguard Worker     gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
589*35238bceSAndroid Build Coastguard Worker }
590*35238bceSAndroid Build Coastguard Worker 
drawGLES2(const glw::Functions & gl,const Program & program,const DrawPrimitiveOp & drawOp)591*35238bceSAndroid Build Coastguard Worker void drawGLES2(const glw::Functions &gl, const Program &program, const DrawPrimitiveOp &drawOp)
592*35238bceSAndroid Build Coastguard Worker {
593*35238bceSAndroid Build Coastguard Worker     const GLES2Program &gles2Program = dynamic_cast<const GLES2Program &>(program);
594*35238bceSAndroid Build Coastguard Worker 
595*35238bceSAndroid Build Coastguard Worker     switch (drawOp.blend)
596*35238bceSAndroid Build Coastguard Worker     {
597*35238bceSAndroid Build Coastguard Worker     case BLENDMODE_NONE:
598*35238bceSAndroid Build Coastguard Worker         gl.disable(GL_BLEND);
599*35238bceSAndroid Build Coastguard Worker         break;
600*35238bceSAndroid Build Coastguard Worker 
601*35238bceSAndroid Build Coastguard Worker     case BLENDMODE_ADDITIVE:
602*35238bceSAndroid Build Coastguard Worker         gl.enable(GL_BLEND);
603*35238bceSAndroid Build Coastguard Worker         gl.blendFunc(GL_ONE, GL_ONE);
604*35238bceSAndroid Build Coastguard Worker         break;
605*35238bceSAndroid Build Coastguard Worker 
606*35238bceSAndroid Build Coastguard Worker     case BLENDMODE_SRC_OVER:
607*35238bceSAndroid Build Coastguard Worker         gl.enable(GL_BLEND);
608*35238bceSAndroid Build Coastguard Worker         gl.blendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
609*35238bceSAndroid Build Coastguard Worker         break;
610*35238bceSAndroid Build Coastguard Worker 
611*35238bceSAndroid Build Coastguard Worker     default:
612*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
613*35238bceSAndroid Build Coastguard Worker     }
614*35238bceSAndroid Build Coastguard Worker 
615*35238bceSAndroid Build Coastguard Worker     switch (drawOp.depth)
616*35238bceSAndroid Build Coastguard Worker     {
617*35238bceSAndroid Build Coastguard Worker     case DEPTHMODE_NONE:
618*35238bceSAndroid Build Coastguard Worker         gl.disable(GL_DEPTH_TEST);
619*35238bceSAndroid Build Coastguard Worker         break;
620*35238bceSAndroid Build Coastguard Worker 
621*35238bceSAndroid Build Coastguard Worker     case DEPTHMODE_LESS:
622*35238bceSAndroid Build Coastguard Worker         gl.enable(GL_DEPTH_TEST);
623*35238bceSAndroid Build Coastguard Worker         break;
624*35238bceSAndroid Build Coastguard Worker 
625*35238bceSAndroid Build Coastguard Worker     default:
626*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
627*35238bceSAndroid Build Coastguard Worker     }
628*35238bceSAndroid Build Coastguard Worker 
629*35238bceSAndroid Build Coastguard Worker     switch (drawOp.stencil)
630*35238bceSAndroid Build Coastguard Worker     {
631*35238bceSAndroid Build Coastguard Worker     case STENCILMODE_NONE:
632*35238bceSAndroid Build Coastguard Worker         gl.disable(GL_STENCIL_TEST);
633*35238bceSAndroid Build Coastguard Worker         break;
634*35238bceSAndroid Build Coastguard Worker 
635*35238bceSAndroid Build Coastguard Worker     case STENCILMODE_LEQUAL_INC:
636*35238bceSAndroid Build Coastguard Worker         gl.enable(GL_STENCIL_TEST);
637*35238bceSAndroid Build Coastguard Worker         gl.stencilFunc(GL_LEQUAL, drawOp.stencilRef, ~0u);
638*35238bceSAndroid Build Coastguard Worker         gl.stencilOp(GL_KEEP, GL_INCR, GL_INCR);
639*35238bceSAndroid Build Coastguard Worker         break;
640*35238bceSAndroid Build Coastguard Worker 
641*35238bceSAndroid Build Coastguard Worker     default:
642*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
643*35238bceSAndroid Build Coastguard Worker     }
644*35238bceSAndroid Build Coastguard Worker 
645*35238bceSAndroid Build Coastguard Worker     gl.disable(GL_DITHER);
646*35238bceSAndroid Build Coastguard Worker 
647*35238bceSAndroid Build Coastguard Worker     gl.vertexAttribPointer(gles2Program.getPositionLoc(), 4, GL_FLOAT, GL_FALSE, 0, &drawOp.positions[0]);
648*35238bceSAndroid Build Coastguard Worker     gl.vertexAttribPointer(gles2Program.getColorLoc(), 4, GL_FLOAT, GL_FALSE, 0, &drawOp.colors[0]);
649*35238bceSAndroid Build Coastguard Worker 
650*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(drawOp.type == PRIMITIVETYPE_TRIANGLE);
651*35238bceSAndroid Build Coastguard Worker     gl.drawArrays(GL_TRIANGLES, 0, drawOp.count * 3);
652*35238bceSAndroid Build Coastguard Worker }
653*35238bceSAndroid Build Coastguard Worker 
readPixelsGLES2(const glw::Functions & gl,tcu::Surface & dst)654*35238bceSAndroid Build Coastguard Worker static void readPixelsGLES2(const glw::Functions &gl, tcu::Surface &dst)
655*35238bceSAndroid Build Coastguard Worker {
656*35238bceSAndroid Build Coastguard Worker     gl.readPixels(0, 0, dst.getWidth(), dst.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, dst.getAccess().getDataPtr());
657*35238bceSAndroid Build Coastguard Worker }
658*35238bceSAndroid Build Coastguard Worker 
createProgram(const glw::Functions & gl,EGLint api)659*35238bceSAndroid Build Coastguard Worker Program *createProgram(const glw::Functions &gl, EGLint api)
660*35238bceSAndroid Build Coastguard Worker {
661*35238bceSAndroid Build Coastguard Worker     switch (api)
662*35238bceSAndroid Build Coastguard Worker     {
663*35238bceSAndroid Build Coastguard Worker     case EGL_OPENGL_ES2_BIT:
664*35238bceSAndroid Build Coastguard Worker         return new GLES2Program(gl);
665*35238bceSAndroid Build Coastguard Worker     case EGL_OPENGL_ES3_BIT_KHR:
666*35238bceSAndroid Build Coastguard Worker         return new GLES2Program(gl);
667*35238bceSAndroid Build Coastguard Worker     default:
668*35238bceSAndroid Build Coastguard Worker         throw tcu::NotSupportedError("Unsupported API");
669*35238bceSAndroid Build Coastguard Worker     }
670*35238bceSAndroid Build Coastguard Worker }
671*35238bceSAndroid Build Coastguard Worker 
draw(const glw::Functions & gl,EGLint api,const Program & program,const DrawPrimitiveOp & drawOp)672*35238bceSAndroid Build Coastguard Worker void draw(const glw::Functions &gl, EGLint api, const Program &program, const DrawPrimitiveOp &drawOp)
673*35238bceSAndroid Build Coastguard Worker {
674*35238bceSAndroid Build Coastguard Worker     switch (api)
675*35238bceSAndroid Build Coastguard Worker     {
676*35238bceSAndroid Build Coastguard Worker     case EGL_OPENGL_ES2_BIT:
677*35238bceSAndroid Build Coastguard Worker         drawGLES2(gl, program, drawOp);
678*35238bceSAndroid Build Coastguard Worker         break;
679*35238bceSAndroid Build Coastguard Worker     case EGL_OPENGL_ES3_BIT_KHR:
680*35238bceSAndroid Build Coastguard Worker         drawGLES2(gl, program, drawOp);
681*35238bceSAndroid Build Coastguard Worker         break;
682*35238bceSAndroid Build Coastguard Worker     default:
683*35238bceSAndroid Build Coastguard Worker         throw tcu::NotSupportedError("Unsupported API");
684*35238bceSAndroid Build Coastguard Worker     }
685*35238bceSAndroid Build Coastguard Worker }
686*35238bceSAndroid Build Coastguard Worker 
clear(const glw::Functions & gl,EGLint api,const tcu::Vec4 & color,const float depth,const int stencil)687*35238bceSAndroid Build Coastguard Worker void clear(const glw::Functions &gl, EGLint api, const tcu::Vec4 &color, const float depth, const int stencil)
688*35238bceSAndroid Build Coastguard Worker {
689*35238bceSAndroid Build Coastguard Worker     switch (api)
690*35238bceSAndroid Build Coastguard Worker     {
691*35238bceSAndroid Build Coastguard Worker     case EGL_OPENGL_ES2_BIT:
692*35238bceSAndroid Build Coastguard Worker         clearGLES2(gl, color, depth, stencil);
693*35238bceSAndroid Build Coastguard Worker         break;
694*35238bceSAndroid Build Coastguard Worker     case EGL_OPENGL_ES3_BIT_KHR:
695*35238bceSAndroid Build Coastguard Worker         clearGLES2(gl, color, depth, stencil);
696*35238bceSAndroid Build Coastguard Worker         break;
697*35238bceSAndroid Build Coastguard Worker     default:
698*35238bceSAndroid Build Coastguard Worker         throw tcu::NotSupportedError("Unsupported API");
699*35238bceSAndroid Build Coastguard Worker     }
700*35238bceSAndroid Build Coastguard Worker }
701*35238bceSAndroid Build Coastguard Worker 
readPixels(const glw::Functions & gl,EGLint api,tcu::Surface & dst)702*35238bceSAndroid Build Coastguard Worker static void readPixels(const glw::Functions &gl, EGLint api, tcu::Surface &dst)
703*35238bceSAndroid Build Coastguard Worker {
704*35238bceSAndroid Build Coastguard Worker     switch (api)
705*35238bceSAndroid Build Coastguard Worker     {
706*35238bceSAndroid Build Coastguard Worker     case EGL_OPENGL_ES2_BIT:
707*35238bceSAndroid Build Coastguard Worker         readPixelsGLES2(gl, dst);
708*35238bceSAndroid Build Coastguard Worker         break;
709*35238bceSAndroid Build Coastguard Worker     case EGL_OPENGL_ES3_BIT_KHR:
710*35238bceSAndroid Build Coastguard Worker         readPixelsGLES2(gl, dst);
711*35238bceSAndroid Build Coastguard Worker         break;
712*35238bceSAndroid Build Coastguard Worker     default:
713*35238bceSAndroid Build Coastguard Worker         throw tcu::NotSupportedError("Unsupported API");
714*35238bceSAndroid Build Coastguard Worker     }
715*35238bceSAndroid Build Coastguard Worker }
716*35238bceSAndroid Build Coastguard Worker 
finish(const glw::Functions & gl,EGLint api)717*35238bceSAndroid Build Coastguard Worker static void finish(const glw::Functions &gl, EGLint api)
718*35238bceSAndroid Build Coastguard Worker {
719*35238bceSAndroid Build Coastguard Worker     switch (api)
720*35238bceSAndroid Build Coastguard Worker     {
721*35238bceSAndroid Build Coastguard Worker     case EGL_OPENGL_ES2_BIT:
722*35238bceSAndroid Build Coastguard Worker     case EGL_OPENGL_ES3_BIT_KHR:
723*35238bceSAndroid Build Coastguard Worker         gl.finish();
724*35238bceSAndroid Build Coastguard Worker         break;
725*35238bceSAndroid Build Coastguard Worker 
726*35238bceSAndroid Build Coastguard Worker     default:
727*35238bceSAndroid Build Coastguard Worker         throw tcu::NotSupportedError("Unsupported API");
728*35238bceSAndroid Build Coastguard Worker     }
729*35238bceSAndroid Build Coastguard Worker }
730*35238bceSAndroid Build Coastguard Worker 
getPixelFormat(const Library & egl,EGLDisplay display,EGLConfig config)731*35238bceSAndroid Build Coastguard Worker tcu::PixelFormat getPixelFormat(const Library &egl, EGLDisplay display, EGLConfig config)
732*35238bceSAndroid Build Coastguard Worker {
733*35238bceSAndroid Build Coastguard Worker     tcu::PixelFormat fmt;
734*35238bceSAndroid Build Coastguard Worker     fmt.redBits   = eglu::getConfigAttribInt(egl, display, config, EGL_RED_SIZE);
735*35238bceSAndroid Build Coastguard Worker     fmt.greenBits = eglu::getConfigAttribInt(egl, display, config, EGL_GREEN_SIZE);
736*35238bceSAndroid Build Coastguard Worker     fmt.blueBits  = eglu::getConfigAttribInt(egl, display, config, EGL_BLUE_SIZE);
737*35238bceSAndroid Build Coastguard Worker     fmt.alphaBits = eglu::getConfigAttribInt(egl, display, config, EGL_ALPHA_SIZE);
738*35238bceSAndroid Build Coastguard Worker     return fmt;
739*35238bceSAndroid Build Coastguard Worker }
740*35238bceSAndroid Build Coastguard Worker 
741*35238bceSAndroid Build Coastguard Worker } // namespace
742*35238bceSAndroid Build Coastguard Worker 
743*35238bceSAndroid Build Coastguard Worker // SingleThreadRenderCase
744*35238bceSAndroid Build Coastguard Worker 
745*35238bceSAndroid Build Coastguard Worker class SingleThreadRenderCase : public MultiContextRenderCase
746*35238bceSAndroid Build Coastguard Worker {
747*35238bceSAndroid Build Coastguard Worker public:
748*35238bceSAndroid Build Coastguard Worker     SingleThreadRenderCase(EglTestContext &eglTestCtx, const char *name, const char *description, EGLint api,
749*35238bceSAndroid Build Coastguard Worker                            EGLint surfaceType, const eglu::FilterList &filters, int numContextsPerApi);
750*35238bceSAndroid Build Coastguard Worker 
751*35238bceSAndroid Build Coastguard Worker     void init(void);
752*35238bceSAndroid Build Coastguard Worker 
753*35238bceSAndroid Build Coastguard Worker private:
754*35238bceSAndroid Build Coastguard Worker     virtual void executeForContexts(EGLDisplay display, EGLSurface surface, const Config &config,
755*35238bceSAndroid Build Coastguard Worker                                     const std::vector<std::pair<EGLint, EGLContext>> &contexts);
756*35238bceSAndroid Build Coastguard Worker 
757*35238bceSAndroid Build Coastguard Worker     glw::Functions m_gl;
758*35238bceSAndroid Build Coastguard Worker };
759*35238bceSAndroid Build Coastguard Worker 
760*35238bceSAndroid Build Coastguard Worker // SingleThreadColorClearCase
761*35238bceSAndroid Build Coastguard Worker 
SingleThreadRenderCase(EglTestContext & eglTestCtx,const char * name,const char * description,EGLint api,EGLint surfaceType,const eglu::FilterList & filters,int numContextsPerApi)762*35238bceSAndroid Build Coastguard Worker SingleThreadRenderCase::SingleThreadRenderCase(EglTestContext &eglTestCtx, const char *name, const char *description,
763*35238bceSAndroid Build Coastguard Worker                                                EGLint api, EGLint surfaceType, const eglu::FilterList &filters,
764*35238bceSAndroid Build Coastguard Worker                                                int numContextsPerApi)
765*35238bceSAndroid Build Coastguard Worker     : MultiContextRenderCase(eglTestCtx, name, description, api, surfaceType, filters, numContextsPerApi)
766*35238bceSAndroid Build Coastguard Worker {
767*35238bceSAndroid Build Coastguard Worker }
768*35238bceSAndroid Build Coastguard Worker 
init(void)769*35238bceSAndroid Build Coastguard Worker void SingleThreadRenderCase::init(void)
770*35238bceSAndroid Build Coastguard Worker {
771*35238bceSAndroid Build Coastguard Worker     MultiContextRenderCase::init();
772*35238bceSAndroid Build Coastguard Worker     m_eglTestCtx.initGLFunctions(&m_gl, glu::ApiType::es(2, 0));
773*35238bceSAndroid Build Coastguard Worker }
774*35238bceSAndroid Build Coastguard Worker 
executeForContexts(EGLDisplay display,EGLSurface surface,const Config & config,const std::vector<std::pair<EGLint,EGLContext>> & contexts)775*35238bceSAndroid Build Coastguard Worker void SingleThreadRenderCase::executeForContexts(EGLDisplay display, EGLSurface surface, const Config &config,
776*35238bceSAndroid Build Coastguard Worker                                                 const std::vector<std::pair<EGLint, EGLContext>> &contexts)
777*35238bceSAndroid Build Coastguard Worker {
778*35238bceSAndroid Build Coastguard Worker     const Library &egl              = m_eglTestCtx.getLibrary();
779*35238bceSAndroid Build Coastguard Worker     const int width                 = eglu::querySurfaceInt(egl, display, surface, EGL_WIDTH);
780*35238bceSAndroid Build Coastguard Worker     const int height                = eglu::querySurfaceInt(egl, display, surface, EGL_HEIGHT);
781*35238bceSAndroid Build Coastguard Worker     const int numContexts           = (int)contexts.size();
782*35238bceSAndroid Build Coastguard Worker     const int drawsPerCtx           = 2;
783*35238bceSAndroid Build Coastguard Worker     const int numIters              = 2;
784*35238bceSAndroid Build Coastguard Worker     const tcu::PixelFormat pixelFmt = getPixelFormat(egl, display, config.config);
785*35238bceSAndroid Build Coastguard Worker     const float threshold           = getColorThreshold(pixelFmt);
786*35238bceSAndroid Build Coastguard Worker 
787*35238bceSAndroid Build Coastguard Worker     const int depthBits   = eglu::getConfigAttribInt(egl, display, config.config, EGL_DEPTH_SIZE);
788*35238bceSAndroid Build Coastguard Worker     const int stencilBits = eglu::getConfigAttribInt(egl, display, config.config, EGL_STENCIL_SIZE);
789*35238bceSAndroid Build Coastguard Worker     const int numSamples  = eglu::getConfigAttribInt(egl, display, config.config, EGL_SAMPLES);
790*35238bceSAndroid Build Coastguard Worker 
791*35238bceSAndroid Build Coastguard Worker     TestLog &log = m_testCtx.getLog();
792*35238bceSAndroid Build Coastguard Worker 
793*35238bceSAndroid Build Coastguard Worker     tcu::Surface refFrame(width, height);
794*35238bceSAndroid Build Coastguard Worker     tcu::Surface frame(width, height);
795*35238bceSAndroid Build Coastguard Worker 
796*35238bceSAndroid Build Coastguard Worker     de::Random rnd(deStringHash(getName()) ^ deInt32Hash(numContexts));
797*35238bceSAndroid Build Coastguard Worker     vector<ProgramSp> programs(contexts.size());
798*35238bceSAndroid Build Coastguard Worker     vector<DrawPrimitiveOp> drawOps;
799*35238bceSAndroid Build Coastguard Worker 
800*35238bceSAndroid Build Coastguard Worker     // Log basic information about config.
801*35238bceSAndroid Build Coastguard Worker     log << TestLog::Message << "EGL_RED_SIZE = " << pixelFmt.redBits << TestLog::EndMessage;
802*35238bceSAndroid Build Coastguard Worker     log << TestLog::Message << "EGL_GREEN_SIZE = " << pixelFmt.greenBits << TestLog::EndMessage;
803*35238bceSAndroid Build Coastguard Worker     log << TestLog::Message << "EGL_BLUE_SIZE = " << pixelFmt.blueBits << TestLog::EndMessage;
804*35238bceSAndroid Build Coastguard Worker     log << TestLog::Message << "EGL_ALPHA_SIZE = " << pixelFmt.alphaBits << TestLog::EndMessage;
805*35238bceSAndroid Build Coastguard Worker     log << TestLog::Message << "EGL_DEPTH_SIZE = " << depthBits << TestLog::EndMessage;
806*35238bceSAndroid Build Coastguard Worker     log << TestLog::Message << "EGL_STENCIL_SIZE = " << stencilBits << TestLog::EndMessage;
807*35238bceSAndroid Build Coastguard Worker     log << TestLog::Message << "EGL_SAMPLES = " << numSamples << TestLog::EndMessage;
808*35238bceSAndroid Build Coastguard Worker 
809*35238bceSAndroid Build Coastguard Worker     // Generate draw ops.
810*35238bceSAndroid Build Coastguard Worker     drawOps.resize(numContexts * drawsPerCtx * numIters);
811*35238bceSAndroid Build Coastguard Worker     for (vector<DrawPrimitiveOp>::iterator drawOp = drawOps.begin(); drawOp != drawOps.end(); ++drawOp)
812*35238bceSAndroid Build Coastguard Worker     {
813*35238bceSAndroid Build Coastguard Worker         // The randomized draws force us to use the fuzzyCompare algorithm to check for possible rasterization differences between
814*35238bceSAndroid Build Coastguard Worker         // our rasterizer and the one used by the implementation. However, fuzzyCompare only takes a single float as the error
815*35238bceSAndroid Build Coastguard Worker         // threshold. As per the comments in the code, that threshold doesn't have a direct equivalent to a difference in color
816*35238bceSAndroid Build Coastguard Worker         // values. Instead, it's related to an accumulated quadratic error. Also according to these comments, this works well for
817*35238bceSAndroid Build Coastguard Worker         // rgba8 (the only case it was originally designed for), and it can also be made to work for other formats in which all
818*35238bceSAndroid Build Coastguard Worker         // used channels have a roughly similar number of bits.
819*35238bceSAndroid Build Coastguard Worker         //
820*35238bceSAndroid Build Coastguard Worker         // However, in some of these tests we will run this code using formats such as rgb10a2, in which the alpha can only have
821*35238bceSAndroid Build Coastguard Worker         // values of 0, 0.33, 0.66 and 1.0 while other channels have much more precission. Any small difference in the rounding
822*35238bceSAndroid Build Coastguard Worker         // applied by CTS and the implementation could result in wildly different alpha values that make using the single floating
823*35238bceSAndroid Build Coastguard Worker         // point threshold risky, because we can't separate the alpha errors from the rgb errors. If we increase the threshold to
824*35238bceSAndroid Build Coastguard Worker         // a point which is acceptable for alpha errors, the kind of errors we allow in the colors would be huge.
825*35238bceSAndroid Build Coastguard Worker         //
826*35238bceSAndroid Build Coastguard Worker         // For this reason, with 2 bits for alpha we restrict ourselves to alpha values of 1.0 and 0.0, as if alphabits was 1.
827*35238bceSAndroid Build Coastguard Worker         randomizeDrawOp(rnd, *drawOp, (pixelFmt.alphaBits <= 2));
828*35238bceSAndroid Build Coastguard Worker     }
829*35238bceSAndroid Build Coastguard Worker 
830*35238bceSAndroid Build Coastguard Worker     // Create and setup programs per context
831*35238bceSAndroid Build Coastguard Worker     for (int ctxNdx = 0; ctxNdx < numContexts; ctxNdx++)
832*35238bceSAndroid Build Coastguard Worker     {
833*35238bceSAndroid Build Coastguard Worker         EGLint api         = contexts[ctxNdx].first;
834*35238bceSAndroid Build Coastguard Worker         EGLContext context = contexts[ctxNdx].second;
835*35238bceSAndroid Build Coastguard Worker 
836*35238bceSAndroid Build Coastguard Worker         EGLU_CHECK_CALL(egl, makeCurrent(display, surface, surface, context));
837*35238bceSAndroid Build Coastguard Worker 
838*35238bceSAndroid Build Coastguard Worker         programs[ctxNdx] = ProgramSp(createProgram(m_gl, api));
839*35238bceSAndroid Build Coastguard Worker         programs[ctxNdx]->setup();
840*35238bceSAndroid Build Coastguard Worker     }
841*35238bceSAndroid Build Coastguard Worker 
842*35238bceSAndroid Build Coastguard Worker     // Clear to black using first context.
843*35238bceSAndroid Build Coastguard Worker     {
844*35238bceSAndroid Build Coastguard Worker         EGLint api         = contexts[0].first;
845*35238bceSAndroid Build Coastguard Worker         EGLContext context = contexts[0].second;
846*35238bceSAndroid Build Coastguard Worker 
847*35238bceSAndroid Build Coastguard Worker         EGLU_CHECK_CALL(egl, makeCurrent(display, surface, surface, context));
848*35238bceSAndroid Build Coastguard Worker 
849*35238bceSAndroid Build Coastguard Worker         clear(m_gl, api, CLEAR_COLOR, CLEAR_DEPTH, CLEAR_STENCIL);
850*35238bceSAndroid Build Coastguard Worker         finish(m_gl, api);
851*35238bceSAndroid Build Coastguard Worker     }
852*35238bceSAndroid Build Coastguard Worker 
853*35238bceSAndroid Build Coastguard Worker     // Render.
854*35238bceSAndroid Build Coastguard Worker     for (int iterNdx = 0; iterNdx < numIters; iterNdx++)
855*35238bceSAndroid Build Coastguard Worker     {
856*35238bceSAndroid Build Coastguard Worker         for (int ctxNdx = 0; ctxNdx < numContexts; ctxNdx++)
857*35238bceSAndroid Build Coastguard Worker         {
858*35238bceSAndroid Build Coastguard Worker             EGLint api         = contexts[ctxNdx].first;
859*35238bceSAndroid Build Coastguard Worker             EGLContext context = contexts[ctxNdx].second;
860*35238bceSAndroid Build Coastguard Worker 
861*35238bceSAndroid Build Coastguard Worker             EGLU_CHECK_CALL(egl, makeCurrent(display, surface, surface, context));
862*35238bceSAndroid Build Coastguard Worker 
863*35238bceSAndroid Build Coastguard Worker             for (int drawNdx = 0; drawNdx < drawsPerCtx; drawNdx++)
864*35238bceSAndroid Build Coastguard Worker             {
865*35238bceSAndroid Build Coastguard Worker                 const DrawPrimitiveOp &drawOp =
866*35238bceSAndroid Build Coastguard Worker                     drawOps[iterNdx * numContexts * drawsPerCtx + ctxNdx * drawsPerCtx + drawNdx];
867*35238bceSAndroid Build Coastguard Worker                 draw(m_gl, api, *programs[ctxNdx], drawOp);
868*35238bceSAndroid Build Coastguard Worker             }
869*35238bceSAndroid Build Coastguard Worker 
870*35238bceSAndroid Build Coastguard Worker             finish(m_gl, api);
871*35238bceSAndroid Build Coastguard Worker         }
872*35238bceSAndroid Build Coastguard Worker     }
873*35238bceSAndroid Build Coastguard Worker 
874*35238bceSAndroid Build Coastguard Worker     // Read pixels using first context. \todo [pyry] Randomize?
875*35238bceSAndroid Build Coastguard Worker     {
876*35238bceSAndroid Build Coastguard Worker         EGLint api         = contexts[0].first;
877*35238bceSAndroid Build Coastguard Worker         EGLContext context = contexts[0].second;
878*35238bceSAndroid Build Coastguard Worker 
879*35238bceSAndroid Build Coastguard Worker         EGLU_CHECK_CALL(egl, makeCurrent(display, surface, surface, context));
880*35238bceSAndroid Build Coastguard Worker 
881*35238bceSAndroid Build Coastguard Worker         readPixels(m_gl, api, frame);
882*35238bceSAndroid Build Coastguard Worker     }
883*35238bceSAndroid Build Coastguard Worker 
884*35238bceSAndroid Build Coastguard Worker     int subpixelBits = 0;
885*35238bceSAndroid Build Coastguard Worker     m_gl.getIntegerv(GL_SUBPIXEL_BITS, &subpixelBits);
886*35238bceSAndroid Build Coastguard Worker 
887*35238bceSAndroid Build Coastguard Worker     EGLU_CHECK_CALL(egl, makeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
888*35238bceSAndroid Build Coastguard Worker 
889*35238bceSAndroid Build Coastguard Worker     // Render reference.
890*35238bceSAndroid Build Coastguard Worker     // \note Reference image is always generated using single-sampling.
891*35238bceSAndroid Build Coastguard Worker     renderReference(refFrame.getAccess(), drawOps, pixelFmt, depthBits, stencilBits, 1, subpixelBits);
892*35238bceSAndroid Build Coastguard Worker 
893*35238bceSAndroid Build Coastguard Worker     // Compare images
894*35238bceSAndroid Build Coastguard Worker     {
895*35238bceSAndroid Build Coastguard Worker         bool imagesOk = tcu::fuzzyCompare(log, "ComparisonResult", "Image comparison result", refFrame, frame,
896*35238bceSAndroid Build Coastguard Worker                                           threshold, tcu::COMPARE_LOG_RESULT);
897*35238bceSAndroid Build Coastguard Worker 
898*35238bceSAndroid Build Coastguard Worker         if (!imagesOk)
899*35238bceSAndroid Build Coastguard Worker             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
900*35238bceSAndroid Build Coastguard Worker     }
901*35238bceSAndroid Build Coastguard Worker }
902*35238bceSAndroid Build Coastguard Worker 
903*35238bceSAndroid Build Coastguard Worker // MultiThreadRenderCase
904*35238bceSAndroid Build Coastguard Worker 
905*35238bceSAndroid Build Coastguard Worker class MultiThreadRenderCase : public MultiContextRenderCase
906*35238bceSAndroid Build Coastguard Worker {
907*35238bceSAndroid Build Coastguard Worker public:
908*35238bceSAndroid Build Coastguard Worker     MultiThreadRenderCase(EglTestContext &eglTestCtx, const char *name, const char *description, EGLint api,
909*35238bceSAndroid Build Coastguard Worker                           EGLint surfaceType, const eglu::FilterList &filters, int numContextsPerApi);
910*35238bceSAndroid Build Coastguard Worker 
911*35238bceSAndroid Build Coastguard Worker     void init(void);
912*35238bceSAndroid Build Coastguard Worker 
913*35238bceSAndroid Build Coastguard Worker private:
914*35238bceSAndroid Build Coastguard Worker     virtual void executeForContexts(EGLDisplay display, EGLSurface surface, const Config &config,
915*35238bceSAndroid Build Coastguard Worker                                     const std::vector<std::pair<EGLint, EGLContext>> &contexts);
916*35238bceSAndroid Build Coastguard Worker 
917*35238bceSAndroid Build Coastguard Worker     glw::Functions m_gl;
918*35238bceSAndroid Build Coastguard Worker };
919*35238bceSAndroid Build Coastguard Worker 
920*35238bceSAndroid Build Coastguard Worker class RenderTestThread;
921*35238bceSAndroid Build Coastguard Worker 
922*35238bceSAndroid Build Coastguard Worker typedef de::SharedPtr<RenderTestThread> RenderTestThreadSp;
923*35238bceSAndroid Build Coastguard Worker typedef de::SharedPtr<de::Semaphore> SemaphoreSp;
924*35238bceSAndroid Build Coastguard Worker 
925*35238bceSAndroid Build Coastguard Worker struct DrawOpPacket
926*35238bceSAndroid Build Coastguard Worker {
DrawOpPacketdeqp::egl::DrawOpPacket927*35238bceSAndroid Build Coastguard Worker     DrawOpPacket(void) : drawOps(DE_NULL), numOps(0)
928*35238bceSAndroid Build Coastguard Worker     {
929*35238bceSAndroid Build Coastguard Worker     }
930*35238bceSAndroid Build Coastguard Worker 
931*35238bceSAndroid Build Coastguard Worker     const DrawPrimitiveOp *drawOps;
932*35238bceSAndroid Build Coastguard Worker     int numOps;
933*35238bceSAndroid Build Coastguard Worker     SemaphoreSp wait;
934*35238bceSAndroid Build Coastguard Worker     SemaphoreSp signal;
935*35238bceSAndroid Build Coastguard Worker };
936*35238bceSAndroid Build Coastguard Worker 
937*35238bceSAndroid Build Coastguard Worker class RenderTestThread : public de::Thread
938*35238bceSAndroid Build Coastguard Worker {
939*35238bceSAndroid Build Coastguard Worker public:
RenderTestThread(const Library & egl,EGLDisplay display,EGLSurface surface,EGLContext context,EGLint api,const glw::Functions & gl,const Program & program,const std::vector<DrawOpPacket> & packets)940*35238bceSAndroid Build Coastguard Worker     RenderTestThread(const Library &egl, EGLDisplay display, EGLSurface surface, EGLContext context, EGLint api,
941*35238bceSAndroid Build Coastguard Worker                      const glw::Functions &gl, const Program &program, const std::vector<DrawOpPacket> &packets)
942*35238bceSAndroid Build Coastguard Worker         : m_egl(egl)
943*35238bceSAndroid Build Coastguard Worker         , m_display(display)
944*35238bceSAndroid Build Coastguard Worker         , m_surface(surface)
945*35238bceSAndroid Build Coastguard Worker         , m_context(context)
946*35238bceSAndroid Build Coastguard Worker         , m_api(api)
947*35238bceSAndroid Build Coastguard Worker         , m_gl(gl)
948*35238bceSAndroid Build Coastguard Worker         , m_program(program)
949*35238bceSAndroid Build Coastguard Worker         , m_packets(packets)
950*35238bceSAndroid Build Coastguard Worker     {
951*35238bceSAndroid Build Coastguard Worker     }
952*35238bceSAndroid Build Coastguard Worker 
run(void)953*35238bceSAndroid Build Coastguard Worker     void run(void)
954*35238bceSAndroid Build Coastguard Worker     {
955*35238bceSAndroid Build Coastguard Worker         for (std::vector<DrawOpPacket>::const_iterator packetIter = m_packets.begin(); packetIter != m_packets.end();
956*35238bceSAndroid Build Coastguard Worker              packetIter++)
957*35238bceSAndroid Build Coastguard Worker         {
958*35238bceSAndroid Build Coastguard Worker             // Wait until it is our turn.
959*35238bceSAndroid Build Coastguard Worker             packetIter->wait->decrement();
960*35238bceSAndroid Build Coastguard Worker 
961*35238bceSAndroid Build Coastguard Worker             // Acquire context.
962*35238bceSAndroid Build Coastguard Worker             EGLU_CHECK_CALL(m_egl, makeCurrent(m_display, m_surface, m_surface, m_context));
963*35238bceSAndroid Build Coastguard Worker 
964*35238bceSAndroid Build Coastguard Worker             // Execute rendering.
965*35238bceSAndroid Build Coastguard Worker             for (int ndx = 0; ndx < packetIter->numOps; ndx++)
966*35238bceSAndroid Build Coastguard Worker                 draw(m_gl, m_api, m_program, packetIter->drawOps[ndx]);
967*35238bceSAndroid Build Coastguard Worker 
968*35238bceSAndroid Build Coastguard Worker             finish(m_gl, m_api);
969*35238bceSAndroid Build Coastguard Worker 
970*35238bceSAndroid Build Coastguard Worker             // Release context.
971*35238bceSAndroid Build Coastguard Worker             EGLU_CHECK_CALL(m_egl, makeCurrent(m_display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
972*35238bceSAndroid Build Coastguard Worker 
973*35238bceSAndroid Build Coastguard Worker             // Signal completion.
974*35238bceSAndroid Build Coastguard Worker             packetIter->signal->increment();
975*35238bceSAndroid Build Coastguard Worker         }
976*35238bceSAndroid Build Coastguard Worker         m_egl.releaseThread();
977*35238bceSAndroid Build Coastguard Worker     }
978*35238bceSAndroid Build Coastguard Worker 
979*35238bceSAndroid Build Coastguard Worker private:
980*35238bceSAndroid Build Coastguard Worker     const Library &m_egl;
981*35238bceSAndroid Build Coastguard Worker     EGLDisplay m_display;
982*35238bceSAndroid Build Coastguard Worker     EGLSurface m_surface;
983*35238bceSAndroid Build Coastguard Worker     EGLContext m_context;
984*35238bceSAndroid Build Coastguard Worker     EGLint m_api;
985*35238bceSAndroid Build Coastguard Worker     const glw::Functions &m_gl;
986*35238bceSAndroid Build Coastguard Worker     const Program &m_program;
987*35238bceSAndroid Build Coastguard Worker     const std::vector<DrawOpPacket> &m_packets;
988*35238bceSAndroid Build Coastguard Worker };
989*35238bceSAndroid Build Coastguard Worker 
MultiThreadRenderCase(EglTestContext & eglTestCtx,const char * name,const char * description,EGLint api,EGLint surfaceType,const eglu::FilterList & filters,int numContextsPerApi)990*35238bceSAndroid Build Coastguard Worker MultiThreadRenderCase::MultiThreadRenderCase(EglTestContext &eglTestCtx, const char *name, const char *description,
991*35238bceSAndroid Build Coastguard Worker                                              EGLint api, EGLint surfaceType, const eglu::FilterList &filters,
992*35238bceSAndroid Build Coastguard Worker                                              int numContextsPerApi)
993*35238bceSAndroid Build Coastguard Worker     : MultiContextRenderCase(eglTestCtx, name, description, api, surfaceType, filters, numContextsPerApi)
994*35238bceSAndroid Build Coastguard Worker {
995*35238bceSAndroid Build Coastguard Worker }
996*35238bceSAndroid Build Coastguard Worker 
init(void)997*35238bceSAndroid Build Coastguard Worker void MultiThreadRenderCase::init(void)
998*35238bceSAndroid Build Coastguard Worker {
999*35238bceSAndroid Build Coastguard Worker     MultiContextRenderCase::init();
1000*35238bceSAndroid Build Coastguard Worker     m_eglTestCtx.initGLFunctions(&m_gl, glu::ApiType::es(2, 0));
1001*35238bceSAndroid Build Coastguard Worker }
1002*35238bceSAndroid Build Coastguard Worker 
executeForContexts(EGLDisplay display,EGLSurface surface,const Config & config,const std::vector<std::pair<EGLint,EGLContext>> & contexts)1003*35238bceSAndroid Build Coastguard Worker void MultiThreadRenderCase::executeForContexts(EGLDisplay display, EGLSurface surface, const Config &config,
1004*35238bceSAndroid Build Coastguard Worker                                                const std::vector<std::pair<EGLint, EGLContext>> &contexts)
1005*35238bceSAndroid Build Coastguard Worker {
1006*35238bceSAndroid Build Coastguard Worker     const Library &egl              = m_eglTestCtx.getLibrary();
1007*35238bceSAndroid Build Coastguard Worker     const int width                 = eglu::querySurfaceInt(egl, display, surface, EGL_WIDTH);
1008*35238bceSAndroid Build Coastguard Worker     const int height                = eglu::querySurfaceInt(egl, display, surface, EGL_HEIGHT);
1009*35238bceSAndroid Build Coastguard Worker     const int numContexts           = (int)contexts.size();
1010*35238bceSAndroid Build Coastguard Worker     const int opsPerPacket          = 2;
1011*35238bceSAndroid Build Coastguard Worker     const int packetsPerThread      = 2;
1012*35238bceSAndroid Build Coastguard Worker     const int numThreads            = numContexts;
1013*35238bceSAndroid Build Coastguard Worker     const int numPackets            = numThreads * packetsPerThread;
1014*35238bceSAndroid Build Coastguard Worker     const tcu::PixelFormat pixelFmt = getPixelFormat(egl, display, config.config);
1015*35238bceSAndroid Build Coastguard Worker     const float threshold           = getColorThreshold(pixelFmt);
1016*35238bceSAndroid Build Coastguard Worker 
1017*35238bceSAndroid Build Coastguard Worker     const int depthBits   = eglu::getConfigAttribInt(egl, display, config.config, EGL_DEPTH_SIZE);
1018*35238bceSAndroid Build Coastguard Worker     const int stencilBits = eglu::getConfigAttribInt(egl, display, config.config, EGL_STENCIL_SIZE);
1019*35238bceSAndroid Build Coastguard Worker     const int numSamples  = eglu::getConfigAttribInt(egl, display, config.config, EGL_SAMPLES);
1020*35238bceSAndroid Build Coastguard Worker 
1021*35238bceSAndroid Build Coastguard Worker     TestLog &log = m_testCtx.getLog();
1022*35238bceSAndroid Build Coastguard Worker 
1023*35238bceSAndroid Build Coastguard Worker     tcu::Surface refFrame(width, height);
1024*35238bceSAndroid Build Coastguard Worker     tcu::Surface frame(width, height);
1025*35238bceSAndroid Build Coastguard Worker 
1026*35238bceSAndroid Build Coastguard Worker     de::Random rnd(deStringHash(getName()) ^ deInt32Hash(numContexts));
1027*35238bceSAndroid Build Coastguard Worker 
1028*35238bceSAndroid Build Coastguard Worker     // Resources that need cleanup
1029*35238bceSAndroid Build Coastguard Worker     vector<ProgramSp> programs(numContexts);
1030*35238bceSAndroid Build Coastguard Worker     vector<SemaphoreSp> semaphores(numPackets + 1);
1031*35238bceSAndroid Build Coastguard Worker     vector<DrawPrimitiveOp> drawOps(numPackets * opsPerPacket);
1032*35238bceSAndroid Build Coastguard Worker     vector<vector<DrawOpPacket>> packets(numThreads);
1033*35238bceSAndroid Build Coastguard Worker     vector<RenderTestThreadSp> threads(numThreads);
1034*35238bceSAndroid Build Coastguard Worker 
1035*35238bceSAndroid Build Coastguard Worker     // Log basic information about config.
1036*35238bceSAndroid Build Coastguard Worker     log << TestLog::Message << "EGL_RED_SIZE = " << pixelFmt.redBits << TestLog::EndMessage;
1037*35238bceSAndroid Build Coastguard Worker     log << TestLog::Message << "EGL_GREEN_SIZE = " << pixelFmt.greenBits << TestLog::EndMessage;
1038*35238bceSAndroid Build Coastguard Worker     log << TestLog::Message << "EGL_BLUE_SIZE = " << pixelFmt.blueBits << TestLog::EndMessage;
1039*35238bceSAndroid Build Coastguard Worker     log << TestLog::Message << "EGL_ALPHA_SIZE = " << pixelFmt.alphaBits << TestLog::EndMessage;
1040*35238bceSAndroid Build Coastguard Worker     log << TestLog::Message << "EGL_DEPTH_SIZE = " << depthBits << TestLog::EndMessage;
1041*35238bceSAndroid Build Coastguard Worker     log << TestLog::Message << "EGL_STENCIL_SIZE = " << stencilBits << TestLog::EndMessage;
1042*35238bceSAndroid Build Coastguard Worker     log << TestLog::Message << "EGL_SAMPLES = " << numSamples << TestLog::EndMessage;
1043*35238bceSAndroid Build Coastguard Worker 
1044*35238bceSAndroid Build Coastguard Worker     // Initialize semaphores.
1045*35238bceSAndroid Build Coastguard Worker     for (vector<SemaphoreSp>::iterator sem = semaphores.begin(); sem != semaphores.end(); ++sem)
1046*35238bceSAndroid Build Coastguard Worker         *sem = SemaphoreSp(new de::Semaphore(0));
1047*35238bceSAndroid Build Coastguard Worker 
1048*35238bceSAndroid Build Coastguard Worker     // Create draw ops.
1049*35238bceSAndroid Build Coastguard Worker     for (vector<DrawPrimitiveOp>::iterator drawOp = drawOps.begin(); drawOp != drawOps.end(); ++drawOp)
1050*35238bceSAndroid Build Coastguard Worker     {
1051*35238bceSAndroid Build Coastguard Worker         // The randomized draws force us to use the fuzzyCompare algorithm to check for possible rasterization differences between
1052*35238bceSAndroid Build Coastguard Worker         // our rasterizer and the one used by the implementation. However, fuzzyCompare only takes a single float as the error
1053*35238bceSAndroid Build Coastguard Worker         // threshold. As per the comments in the code, that threshold doesn't have a direct equivalent to a difference in color
1054*35238bceSAndroid Build Coastguard Worker         // values. Instead, it's related to an accumulated quadratic error. Also according to these comments, this works well for
1055*35238bceSAndroid Build Coastguard Worker         // rgba8 (the only case it was originally designed for), and it can also be made to work for other formats in which all
1056*35238bceSAndroid Build Coastguard Worker         // used channels have a roughly similar number of bits.
1057*35238bceSAndroid Build Coastguard Worker         //
1058*35238bceSAndroid Build Coastguard Worker         // However, in some of these tests we will run this code using formats such as rgb10a2, in which the alpha can only have
1059*35238bceSAndroid Build Coastguard Worker         // values of 0, 0.33, 0.66 and 1.0 while other channels have much more precission. Any small difference in the rounding
1060*35238bceSAndroid Build Coastguard Worker         // applied by CTS and the implementation could result in wildly different alpha values that make using the single floating
1061*35238bceSAndroid Build Coastguard Worker         // point threshold risky, because we can't separate the alpha errors from the rgb errors. If we increase the threshold to
1062*35238bceSAndroid Build Coastguard Worker         // a point which is acceptable for alpha errors, the kind of errors we allow in the colors would be huge.
1063*35238bceSAndroid Build Coastguard Worker         //
1064*35238bceSAndroid Build Coastguard Worker         // For this reason, with 2 bits for alpha we restrict ourselves to alpha values of 1.0 and 0.0, as if alphabits was 1.
1065*35238bceSAndroid Build Coastguard Worker         randomizeDrawOp(rnd, *drawOp, (pixelFmt.alphaBits <= 2));
1066*35238bceSAndroid Build Coastguard Worker     }
1067*35238bceSAndroid Build Coastguard Worker 
1068*35238bceSAndroid Build Coastguard Worker     // Create packets.
1069*35238bceSAndroid Build Coastguard Worker     for (int threadNdx = 0; threadNdx < numThreads; threadNdx++)
1070*35238bceSAndroid Build Coastguard Worker     {
1071*35238bceSAndroid Build Coastguard Worker         packets[threadNdx].resize(packetsPerThread);
1072*35238bceSAndroid Build Coastguard Worker 
1073*35238bceSAndroid Build Coastguard Worker         for (int packetNdx = 0; packetNdx < packetsPerThread; packetNdx++)
1074*35238bceSAndroid Build Coastguard Worker         {
1075*35238bceSAndroid Build Coastguard Worker             DrawOpPacket &packet = packets[threadNdx][packetNdx];
1076*35238bceSAndroid Build Coastguard Worker 
1077*35238bceSAndroid Build Coastguard Worker             // Threads take turns with packets.
1078*35238bceSAndroid Build Coastguard Worker             packet.wait    = semaphores[packetNdx * numThreads + threadNdx];
1079*35238bceSAndroid Build Coastguard Worker             packet.signal  = semaphores[packetNdx * numThreads + threadNdx + 1];
1080*35238bceSAndroid Build Coastguard Worker             packet.numOps  = opsPerPacket;
1081*35238bceSAndroid Build Coastguard Worker             packet.drawOps = &drawOps[(packetNdx * numThreads + threadNdx) * opsPerPacket];
1082*35238bceSAndroid Build Coastguard Worker         }
1083*35238bceSAndroid Build Coastguard Worker     }
1084*35238bceSAndroid Build Coastguard Worker 
1085*35238bceSAndroid Build Coastguard Worker     // Create and setup programs per context
1086*35238bceSAndroid Build Coastguard Worker     for (int ctxNdx = 0; ctxNdx < numContexts; ctxNdx++)
1087*35238bceSAndroid Build Coastguard Worker     {
1088*35238bceSAndroid Build Coastguard Worker         EGLint api         = contexts[ctxNdx].first;
1089*35238bceSAndroid Build Coastguard Worker         EGLContext context = contexts[ctxNdx].second;
1090*35238bceSAndroid Build Coastguard Worker 
1091*35238bceSAndroid Build Coastguard Worker         EGLU_CHECK_CALL(egl, makeCurrent(display, surface, surface, context));
1092*35238bceSAndroid Build Coastguard Worker 
1093*35238bceSAndroid Build Coastguard Worker         programs[ctxNdx] = ProgramSp(createProgram(m_gl, api));
1094*35238bceSAndroid Build Coastguard Worker         programs[ctxNdx]->setup();
1095*35238bceSAndroid Build Coastguard Worker 
1096*35238bceSAndroid Build Coastguard Worker         // Release context
1097*35238bceSAndroid Build Coastguard Worker         EGLU_CHECK_CALL(egl, makeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
1098*35238bceSAndroid Build Coastguard Worker     }
1099*35238bceSAndroid Build Coastguard Worker 
1100*35238bceSAndroid Build Coastguard Worker     // Clear to black using first context.
1101*35238bceSAndroid Build Coastguard Worker     {
1102*35238bceSAndroid Build Coastguard Worker         EGLint api         = contexts[0].first;
1103*35238bceSAndroid Build Coastguard Worker         EGLContext context = contexts[0].second;
1104*35238bceSAndroid Build Coastguard Worker 
1105*35238bceSAndroid Build Coastguard Worker         EGLU_CHECK_CALL(egl, makeCurrent(display, surface, surface, context));
1106*35238bceSAndroid Build Coastguard Worker 
1107*35238bceSAndroid Build Coastguard Worker         clear(m_gl, api, CLEAR_COLOR, CLEAR_DEPTH, CLEAR_STENCIL);
1108*35238bceSAndroid Build Coastguard Worker         finish(m_gl, api);
1109*35238bceSAndroid Build Coastguard Worker 
1110*35238bceSAndroid Build Coastguard Worker         // Release context
1111*35238bceSAndroid Build Coastguard Worker         EGLU_CHECK_CALL(egl, makeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
1112*35238bceSAndroid Build Coastguard Worker     }
1113*35238bceSAndroid Build Coastguard Worker 
1114*35238bceSAndroid Build Coastguard Worker     // Create and launch threads (actual rendering starts once first semaphore is signaled).
1115*35238bceSAndroid Build Coastguard Worker     for (int threadNdx = 0; threadNdx < numThreads; threadNdx++)
1116*35238bceSAndroid Build Coastguard Worker     {
1117*35238bceSAndroid Build Coastguard Worker         threads[threadNdx] = RenderTestThreadSp(new RenderTestThread(egl, display, surface, contexts[threadNdx].second,
1118*35238bceSAndroid Build Coastguard Worker                                                                      contexts[threadNdx].first, m_gl,
1119*35238bceSAndroid Build Coastguard Worker                                                                      *programs[threadNdx], packets[threadNdx]));
1120*35238bceSAndroid Build Coastguard Worker         threads[threadNdx]->start();
1121*35238bceSAndroid Build Coastguard Worker     }
1122*35238bceSAndroid Build Coastguard Worker 
1123*35238bceSAndroid Build Coastguard Worker     // Signal start and wait until complete.
1124*35238bceSAndroid Build Coastguard Worker     semaphores.front()->increment();
1125*35238bceSAndroid Build Coastguard Worker     semaphores.back()->decrement();
1126*35238bceSAndroid Build Coastguard Worker 
1127*35238bceSAndroid Build Coastguard Worker     // Read pixels using first context. \todo [pyry] Randomize?
1128*35238bceSAndroid Build Coastguard Worker     {
1129*35238bceSAndroid Build Coastguard Worker         EGLint api         = contexts[0].first;
1130*35238bceSAndroid Build Coastguard Worker         EGLContext context = contexts[0].second;
1131*35238bceSAndroid Build Coastguard Worker 
1132*35238bceSAndroid Build Coastguard Worker         EGLU_CHECK_CALL(egl, makeCurrent(display, surface, surface, context));
1133*35238bceSAndroid Build Coastguard Worker 
1134*35238bceSAndroid Build Coastguard Worker         readPixels(m_gl, api, frame);
1135*35238bceSAndroid Build Coastguard Worker     }
1136*35238bceSAndroid Build Coastguard Worker 
1137*35238bceSAndroid Build Coastguard Worker     int subpixelBits = 0;
1138*35238bceSAndroid Build Coastguard Worker     m_gl.getIntegerv(GL_SUBPIXEL_BITS, &subpixelBits);
1139*35238bceSAndroid Build Coastguard Worker 
1140*35238bceSAndroid Build Coastguard Worker     EGLU_CHECK_CALL(egl, makeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
1141*35238bceSAndroid Build Coastguard Worker 
1142*35238bceSAndroid Build Coastguard Worker     // Join threads.
1143*35238bceSAndroid Build Coastguard Worker     for (int threadNdx = 0; threadNdx < numThreads; threadNdx++)
1144*35238bceSAndroid Build Coastguard Worker         threads[threadNdx]->join();
1145*35238bceSAndroid Build Coastguard Worker 
1146*35238bceSAndroid Build Coastguard Worker     // Render reference.
1147*35238bceSAndroid Build Coastguard Worker     renderReference(refFrame.getAccess(), drawOps, pixelFmt, depthBits, stencilBits, 1, subpixelBits);
1148*35238bceSAndroid Build Coastguard Worker 
1149*35238bceSAndroid Build Coastguard Worker     // Compare images
1150*35238bceSAndroid Build Coastguard Worker     {
1151*35238bceSAndroid Build Coastguard Worker         bool imagesOk = tcu::fuzzyCompare(log, "ComparisonResult", "Image comparison result", refFrame, frame,
1152*35238bceSAndroid Build Coastguard Worker                                           threshold, tcu::COMPARE_LOG_RESULT);
1153*35238bceSAndroid Build Coastguard Worker 
1154*35238bceSAndroid Build Coastguard Worker         if (!imagesOk)
1155*35238bceSAndroid Build Coastguard Worker             m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
1156*35238bceSAndroid Build Coastguard Worker     }
1157*35238bceSAndroid Build Coastguard Worker }
1158*35238bceSAndroid Build Coastguard Worker 
RenderTests(EglTestContext & eglTestCtx)1159*35238bceSAndroid Build Coastguard Worker RenderTests::RenderTests(EglTestContext &eglTestCtx)
1160*35238bceSAndroid Build Coastguard Worker     : TestCaseGroup(eglTestCtx, "render", "Basic rendering with different client APIs")
1161*35238bceSAndroid Build Coastguard Worker {
1162*35238bceSAndroid Build Coastguard Worker }
1163*35238bceSAndroid Build Coastguard Worker 
~RenderTests(void)1164*35238bceSAndroid Build Coastguard Worker RenderTests::~RenderTests(void)
1165*35238bceSAndroid Build Coastguard Worker {
1166*35238bceSAndroid Build Coastguard Worker }
1167*35238bceSAndroid Build Coastguard Worker 
1168*35238bceSAndroid Build Coastguard Worker struct RenderGroupSpec
1169*35238bceSAndroid Build Coastguard Worker {
1170*35238bceSAndroid Build Coastguard Worker     const char *name;
1171*35238bceSAndroid Build Coastguard Worker     const char *desc;
1172*35238bceSAndroid Build Coastguard Worker     EGLint apiBits;
1173*35238bceSAndroid Build Coastguard Worker     eglu::ConfigFilter baseFilter;
1174*35238bceSAndroid Build Coastguard Worker     int numContextsPerApi;
1175*35238bceSAndroid Build Coastguard Worker };
1176*35238bceSAndroid Build Coastguard Worker 
1177*35238bceSAndroid Build Coastguard Worker template <uint32_t Bits>
renderable(const eglu::CandidateConfig & c)1178*35238bceSAndroid Build Coastguard Worker static bool renderable(const eglu::CandidateConfig &c)
1179*35238bceSAndroid Build Coastguard Worker {
1180*35238bceSAndroid Build Coastguard Worker     return (c.renderableType() & Bits) == Bits;
1181*35238bceSAndroid Build Coastguard Worker }
1182*35238bceSAndroid Build Coastguard Worker 
1183*35238bceSAndroid Build Coastguard Worker template <class RenderClass>
createRenderGroups(EglTestContext & eglTestCtx,tcu::TestCaseGroup * group,const RenderGroupSpec * first,const RenderGroupSpec * last)1184*35238bceSAndroid Build Coastguard Worker static void createRenderGroups(EglTestContext &eglTestCtx, tcu::TestCaseGroup *group, const RenderGroupSpec *first,
1185*35238bceSAndroid Build Coastguard Worker                                const RenderGroupSpec *last)
1186*35238bceSAndroid Build Coastguard Worker {
1187*35238bceSAndroid Build Coastguard Worker     for (const RenderGroupSpec *groupIter = first; groupIter != last; groupIter++)
1188*35238bceSAndroid Build Coastguard Worker     {
1189*35238bceSAndroid Build Coastguard Worker         tcu::TestCaseGroup *configGroup =
1190*35238bceSAndroid Build Coastguard Worker             new tcu::TestCaseGroup(eglTestCtx.getTestContext(), groupIter->name, groupIter->desc);
1191*35238bceSAndroid Build Coastguard Worker         group->addChild(configGroup);
1192*35238bceSAndroid Build Coastguard Worker 
1193*35238bceSAndroid Build Coastguard Worker         vector<RenderFilterList> filterLists;
1194*35238bceSAndroid Build Coastguard Worker         eglu::FilterList baseFilters;
1195*35238bceSAndroid Build Coastguard Worker         baseFilters << groupIter->baseFilter;
1196*35238bceSAndroid Build Coastguard Worker         getDefaultRenderFilterLists(filterLists, baseFilters);
1197*35238bceSAndroid Build Coastguard Worker 
1198*35238bceSAndroid Build Coastguard Worker         for (vector<RenderFilterList>::const_iterator listIter = filterLists.begin(); listIter != filterLists.end();
1199*35238bceSAndroid Build Coastguard Worker              listIter++)
1200*35238bceSAndroid Build Coastguard Worker             configGroup->addChild(new RenderClass(eglTestCtx, listIter->getName(), "", groupIter->apiBits,
1201*35238bceSAndroid Build Coastguard Worker                                                   listIter->getSurfaceTypeMask(), *listIter,
1202*35238bceSAndroid Build Coastguard Worker                                                   groupIter->numContextsPerApi));
1203*35238bceSAndroid Build Coastguard Worker     }
1204*35238bceSAndroid Build Coastguard Worker }
1205*35238bceSAndroid Build Coastguard Worker 
init(void)1206*35238bceSAndroid Build Coastguard Worker void RenderTests::init(void)
1207*35238bceSAndroid Build Coastguard Worker {
1208*35238bceSAndroid Build Coastguard Worker     static const RenderGroupSpec singleContextCases[] = {
1209*35238bceSAndroid Build Coastguard Worker         {"gles2", "Primitive rendering using GLES2", EGL_OPENGL_ES2_BIT, renderable<EGL_OPENGL_ES2_BIT>, 1},
1210*35238bceSAndroid Build Coastguard Worker         {"gles3", "Primitive rendering using GLES3", EGL_OPENGL_ES3_BIT, renderable<EGL_OPENGL_ES3_BIT>, 1},
1211*35238bceSAndroid Build Coastguard Worker     };
1212*35238bceSAndroid Build Coastguard Worker 
1213*35238bceSAndroid Build Coastguard Worker     static const RenderGroupSpec multiContextCases[] = {
1214*35238bceSAndroid Build Coastguard Worker         {"gles2", "Primitive rendering using multiple GLES2 contexts to shared surface", EGL_OPENGL_ES2_BIT,
1215*35238bceSAndroid Build Coastguard Worker          renderable<EGL_OPENGL_ES2_BIT>, 3},
1216*35238bceSAndroid Build Coastguard Worker         {"gles3", "Primitive rendering using multiple GLES3 contexts to shared surface", EGL_OPENGL_ES3_BIT,
1217*35238bceSAndroid Build Coastguard Worker          renderable<EGL_OPENGL_ES3_BIT>, 3},
1218*35238bceSAndroid Build Coastguard Worker         {"gles2_gles3", "Primitive rendering using multiple APIs to shared surface",
1219*35238bceSAndroid Build Coastguard Worker          EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT, renderable<EGL_OPENGL_ES2_BIT | EGL_OPENGL_ES3_BIT>, 1},
1220*35238bceSAndroid Build Coastguard Worker     };
1221*35238bceSAndroid Build Coastguard Worker 
1222*35238bceSAndroid Build Coastguard Worker     tcu::TestCaseGroup *singleContextGroup =
1223*35238bceSAndroid Build Coastguard Worker         new tcu::TestCaseGroup(m_testCtx, "single_context", "Single-context rendering");
1224*35238bceSAndroid Build Coastguard Worker     addChild(singleContextGroup);
1225*35238bceSAndroid Build Coastguard Worker     createRenderGroups<SingleThreadRenderCase>(m_eglTestCtx, singleContextGroup, &singleContextCases[0],
1226*35238bceSAndroid Build Coastguard Worker                                                &singleContextCases[DE_LENGTH_OF_ARRAY(singleContextCases)]);
1227*35238bceSAndroid Build Coastguard Worker 
1228*35238bceSAndroid Build Coastguard Worker     tcu::TestCaseGroup *multiContextGroup =
1229*35238bceSAndroid Build Coastguard Worker         new tcu::TestCaseGroup(m_testCtx, "multi_context", "Multi-context rendering with shared surface");
1230*35238bceSAndroid Build Coastguard Worker     addChild(multiContextGroup);
1231*35238bceSAndroid Build Coastguard Worker     createRenderGroups<SingleThreadRenderCase>(m_eglTestCtx, multiContextGroup, &multiContextCases[0],
1232*35238bceSAndroid Build Coastguard Worker                                                &multiContextCases[DE_LENGTH_OF_ARRAY(multiContextCases)]);
1233*35238bceSAndroid Build Coastguard Worker 
1234*35238bceSAndroid Build Coastguard Worker     tcu::TestCaseGroup *multiThreadGroup =
1235*35238bceSAndroid Build Coastguard Worker         new tcu::TestCaseGroup(m_testCtx, "multi_thread", "Multi-thread rendering with shared surface");
1236*35238bceSAndroid Build Coastguard Worker     addChild(multiThreadGroup);
1237*35238bceSAndroid Build Coastguard Worker     createRenderGroups<MultiThreadRenderCase>(m_eglTestCtx, multiThreadGroup, &multiContextCases[0],
1238*35238bceSAndroid Build Coastguard Worker                                               &multiContextCases[DE_LENGTH_OF_ARRAY(multiContextCases)]);
1239*35238bceSAndroid Build Coastguard Worker }
1240*35238bceSAndroid Build Coastguard Worker 
1241*35238bceSAndroid Build Coastguard Worker } // namespace egl
1242*35238bceSAndroid Build Coastguard Worker } // namespace deqp
1243