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