• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "tcuRenderTarget.hpp"
28 #include "tcuTestLog.hpp"
29 #include "tcuImageCompare.hpp"
30 #include "tcuTextureUtil.hpp"
31 #include "tcuSurface.hpp"
32 
33 #include "deRandom.hpp"
34 #include "deSharedPtr.hpp"
35 #include "deSemaphore.hpp"
36 #include "deThread.hpp"
37 #include "deString.h"
38 
39 #include <algorithm>
40 #include <iterator>
41 #include <memory>
42 #include <set>
43 
44 #include <EGL/eglext.h>
45 
46 #if !defined(EGL_OPENGL_ES3_BIT_KHR)
47 #	define EGL_OPENGL_ES3_BIT_KHR	0x0040
48 #endif
49 #if !defined(EGL_CONTEXT_MAJOR_VERSION_KHR)
50 #	define EGL_CONTEXT_MAJOR_VERSION_KHR EGL_CONTEXT_CLIENT_VERSION
51 #endif
52 
53 #if defined(DEQP_SUPPORT_GLES2)
54 #	include <GLES2/gl2.h>
55 #elif defined(DEQP_SUPPORT_GLES3)
56 #	include <GLES3/gl3.h>
57 #endif
58 
59 #include "rrRenderer.hpp"
60 #include "rrFragmentOperations.hpp"
61 
62 #if defined(DEQP_SUPPORT_GLES2) || defined(DEQP_SUPPORT_GLES3)
63 #      include "gluDefs.hpp"
64 #else
65        // \todo [pyry] Move renderer to common utils
66        // \note [jarkko] gluDefs is required for GLU_CHECK_MSG
67 #      error "Reference renderer requires GLES2 or GLES3 support"
68 #endif
69 
70 namespace deqp
71 {
72 namespace egl
73 {
74 
75 using std::string;
76 using std::vector;
77 using std::set;
78 
79 using tcu::Vec4;
80 
81 using tcu::TestLog;
82 
83 static const tcu::Vec4	CLEAR_COLOR		= tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
84 static const float		CLEAR_DEPTH		= 1.0f;
85 static const int		CLEAR_STENCIL	= 0;
86 
87 namespace
88 {
89 
90 enum PrimitiveType
91 {
92 	PRIMITIVETYPE_TRIANGLE = 0,	//!< Triangles, requires 3 coordinates per primitive
93 //	PRIMITIVETYPE_POINT,		//!< Points, requires 1 coordinate per primitive (w is used as size)
94 //	PRIMITIVETYPE_LINE,			//!< Lines, requires 2 coordinates per primitive
95 
96 	PRIMITIVETYPE_LAST
97 };
98 
99 enum BlendMode
100 {
101 	BLENDMODE_NONE = 0,			//!< No blending
102 	BLENDMODE_ADDITIVE,			//!< Blending with ONE, ONE
103 	BLENDMODE_SRC_OVER,			//!< Blending with SRC_ALPHA, ONE_MINUS_SRC_ALPHA
104 
105 	BLENDMODE_LAST
106 };
107 
108 enum DepthMode
109 {
110 	DEPTHMODE_NONE = 0,			//!< No depth test or depth writes
111 	DEPTHMODE_LESS,				//!< Depth test with less & depth write
112 
113 	DEPTHMODE_LAST
114 };
115 
116 enum StencilMode
117 {
118 	STENCILMODE_NONE = 0,		//!< No stencil test or write
119 	STENCILMODE_LEQUAL_INC,		//!< Stencil test with LEQUAL, increment on pass
120 
121 	STENCILMODE_LAST
122 };
123 
124 struct DrawPrimitiveOp
125 {
126 	PrimitiveType	type;
127 	int				count;
128 	vector<Vec4>	positions;
129 	vector<Vec4>	colors;
130 	BlendMode		blend;
131 	DepthMode		depth;
132 	StencilMode		stencil;
133 	int				stencilRef;
134 };
135 
randomizeDrawOp(de::Random & rnd,DrawPrimitiveOp & drawOp)136 void randomizeDrawOp (de::Random& rnd, DrawPrimitiveOp& drawOp)
137 {
138 	const int	minStencilRef	= 0;
139 	const int	maxStencilRef	= 8;
140 	const int	minPrimitives	= 2;
141 	const int	maxPrimitives	= 4;
142 
143 	const float	maxTriOffset	= 1.0f;
144 	const float	minDepth		= -1.0f; // \todo [pyry] Reference doesn't support Z clipping yet
145 	const float	maxDepth		= 1.0f;
146 
147 	const float	minRGB			= 0.2f;
148 	const float	maxRGB			= 0.9f;
149 	const float	minAlpha		= 0.3f;
150 	const float	maxAlpha		= 1.0f;
151 
152 	drawOp.type			= (PrimitiveType)rnd.getInt(0, PRIMITIVETYPE_LAST-1);
153 	drawOp.count		= rnd.getInt(minPrimitives, maxPrimitives);
154 	drawOp.blend		= (BlendMode)rnd.getInt(0, BLENDMODE_LAST-1);
155 	drawOp.depth		= (DepthMode)rnd.getInt(0, DEPTHMODE_LAST-1);
156 	drawOp.stencil		= (StencilMode)rnd.getInt(0, STENCILMODE_LAST-1);
157 	drawOp.stencilRef	= rnd.getInt(minStencilRef, maxStencilRef);
158 
159 	if (drawOp.type == PRIMITIVETYPE_TRIANGLE)
160 	{
161 		drawOp.positions.resize(drawOp.count*3);
162 		drawOp.colors.resize(drawOp.count*3);
163 
164 		for (int triNdx = 0; triNdx < drawOp.count; triNdx++)
165 		{
166 			const float		cx		= rnd.getFloat(-1.0f, 1.0f);
167 			const float		cy		= rnd.getFloat(-1.0f, 1.0f);
168 
169 			for (int coordNdx = 0; coordNdx < 3; coordNdx++)
170 			{
171 				tcu::Vec4&	position	= drawOp.positions[triNdx*3 + coordNdx];
172 				tcu::Vec4&	color		= drawOp.colors[triNdx*3 + coordNdx];
173 
174 				position.x()	= cx + rnd.getFloat(-maxTriOffset, maxTriOffset);
175 				position.y()	= cy + rnd.getFloat(-maxTriOffset, maxTriOffset);
176 				position.z()	= rnd.getFloat(minDepth, maxDepth);
177 				position.w()	= 1.0f;
178 
179 				color.x()		= rnd.getFloat(minRGB, maxRGB);
180 				color.y()		= rnd.getFloat(minRGB, maxRGB);
181 				color.z()		= rnd.getFloat(minRGB, maxRGB);
182 				color.w()		= rnd.getFloat(minAlpha, maxAlpha);
183 			}
184 		}
185 	}
186 	else
187 		DE_ASSERT(false);
188 }
189 
190 // Reference rendering code
191 
192 class ReferenceShader : public rr::VertexShader, public rr::FragmentShader
193 {
194 public:
195 	enum
196 	{
197 		VaryingLoc_Color = 0
198 	};
199 
ReferenceShader()200 	ReferenceShader ()
201 		: rr::VertexShader	(2, 1)		// color and pos in => color out
202 		, rr::FragmentShader(1, 1)		// color in => color out
203 	{
204 		this->rr::VertexShader::m_inputs[0].type		= rr::GENERICVECTYPE_FLOAT;
205 		this->rr::VertexShader::m_inputs[1].type		= rr::GENERICVECTYPE_FLOAT;
206 
207 		this->rr::VertexShader::m_outputs[0].type		= rr::GENERICVECTYPE_FLOAT;
208 		this->rr::VertexShader::m_outputs[0].flatshade	= false;
209 
210 		this->rr::FragmentShader::m_inputs[0].type		= rr::GENERICVECTYPE_FLOAT;
211 		this->rr::FragmentShader::m_inputs[0].flatshade	= false;
212 
213 		this->rr::FragmentShader::m_outputs[0].type		= rr::GENERICVECTYPE_FLOAT;
214 	}
215 
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const216 	void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const
217 	{
218 		for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
219 		{
220 			const int positionAttrLoc = 0;
221 			const int colorAttrLoc = 1;
222 
223 			rr::VertexPacket& packet = *packets[packetNdx];
224 
225 			// Transform to position
226 			packet.position = rr::readVertexAttribFloat(inputs[positionAttrLoc], packet.instanceNdx, packet.vertexNdx);
227 
228 			// Pass color to FS
229 			packet.outputs[VaryingLoc_Color] = rr::readVertexAttribFloat(inputs[colorAttrLoc], packet.instanceNdx, packet.vertexNdx);
230 		}
231 	}
232 
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const233 	void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const
234 	{
235 		for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
236 		{
237 			rr::FragmentPacket& packet = packets[packetNdx];
238 
239 			for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
240 				rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, rr::readVarying<float>(packet, context, VaryingLoc_Color, fragNdx));
241 		}
242 	}
243 };
244 
toReferenceRenderState(rr::RenderState & state,const DrawPrimitiveOp & drawOp)245 void toReferenceRenderState (rr::RenderState& state, const DrawPrimitiveOp& drawOp)
246 {
247 	state.cullMode	= rr::CULLMODE_NONE;
248 
249 	if (drawOp.blend != BLENDMODE_NONE)
250 	{
251 		state.fragOps.blendMode = rr::BLENDMODE_STANDARD;
252 
253 		switch (drawOp.blend)
254 		{
255 			case BLENDMODE_ADDITIVE:
256 				state.fragOps.blendRGBState.srcFunc		= rr::BLENDFUNC_ONE;
257 				state.fragOps.blendRGBState.dstFunc		= rr::BLENDFUNC_ONE;
258 				state.fragOps.blendRGBState.equation	= rr::BLENDEQUATION_ADD;
259 				state.fragOps.blendAState				= state.fragOps.blendRGBState;
260 				break;
261 
262 			case BLENDMODE_SRC_OVER:
263 				state.fragOps.blendRGBState.srcFunc		= rr::BLENDFUNC_SRC_ALPHA;
264 				state.fragOps.blendRGBState.dstFunc		= rr::BLENDFUNC_ONE_MINUS_SRC_ALPHA;
265 				state.fragOps.blendRGBState.equation	= rr::BLENDEQUATION_ADD;
266 				state.fragOps.blendAState				= state.fragOps.blendRGBState;
267 				break;
268 
269 			default:
270 				DE_ASSERT(false);
271 		}
272 	}
273 
274 	if (drawOp.depth != DEPTHMODE_NONE)
275 	{
276 		state.fragOps.depthTestEnabled = true;
277 
278 		DE_ASSERT(drawOp.depth == DEPTHMODE_LESS);
279 		state.fragOps.depthFunc = rr::TESTFUNC_LESS;
280 	}
281 
282 	if (drawOp.stencil != STENCILMODE_NONE)
283 	{
284 		state.fragOps.stencilTestEnabled = true;
285 
286 		DE_ASSERT(drawOp.stencil == STENCILMODE_LEQUAL_INC);
287 		state.fragOps.stencilStates[0].func		= rr::TESTFUNC_LEQUAL;
288 		state.fragOps.stencilStates[0].sFail	= rr::STENCILOP_KEEP;
289 		state.fragOps.stencilStates[0].dpFail	= rr::STENCILOP_INCR;
290 		state.fragOps.stencilStates[0].dpPass	= rr::STENCILOP_INCR;
291 		state.fragOps.stencilStates[0].ref		= drawOp.stencilRef;
292 		state.fragOps.stencilStates[1]			= state.fragOps.stencilStates[0];
293 	}
294 }
295 
getColorFormat(const tcu::PixelFormat & colorBits)296 tcu::TextureFormat getColorFormat (const tcu::PixelFormat& colorBits)
297 {
298 	using tcu::TextureFormat;
299 
300 	DE_ASSERT(de::inBounds(colorBits.redBits,	0, 0xff) &&
301 			  de::inBounds(colorBits.greenBits,	0, 0xff) &&
302 			  de::inBounds(colorBits.blueBits,	0, 0xff) &&
303 			  de::inBounds(colorBits.alphaBits,	0, 0xff));
304 
305 #define PACK_FMT(R, G, B, A) (((R) << 24) | ((G) << 16) | ((B) << 8) | (A))
306 
307 	// \note [pyry] This may not hold true on some implementations - best effort guess only.
308 	switch (PACK_FMT(colorBits.redBits, colorBits.greenBits, colorBits.blueBits, colorBits.alphaBits))
309 	{
310 		case PACK_FMT(8,8,8,8):		return TextureFormat(TextureFormat::RGBA,	TextureFormat::UNORM_INT8);
311 		case PACK_FMT(8,8,8,0):		return TextureFormat(TextureFormat::RGB,	TextureFormat::UNORM_INT8);
312 		case PACK_FMT(4,4,4,4):		return TextureFormat(TextureFormat::RGBA,	TextureFormat::UNORM_SHORT_4444);
313 		case PACK_FMT(5,5,5,1):		return TextureFormat(TextureFormat::RGBA,	TextureFormat::UNORM_SHORT_5551);
314 		case PACK_FMT(5,6,5,0):		return TextureFormat(TextureFormat::RGB,	TextureFormat::UNORM_SHORT_565);
315 
316 		// \note Defaults to RGBA8
317 		default:					return TextureFormat(TextureFormat::RGBA,	TextureFormat::UNORM_INT8);
318 	}
319 
320 #undef PACK_FMT
321 }
322 
getDepthFormat(const int depthBits)323 tcu::TextureFormat getDepthFormat (const int depthBits)
324 {
325 	switch (depthBits)
326 	{
327 		case 0:		return tcu::TextureFormat();
328 		case 8:		return tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNORM_INT8);
329 		case 16:	return tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNORM_INT16);
330 		case 24:	return tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::UNSIGNED_INT_24_8);
331 		case 32:
332 		default:	return tcu::TextureFormat(tcu::TextureFormat::D, tcu::TextureFormat::FLOAT);
333 	}
334 }
335 
getStencilFormat(int stencilBits)336 tcu::TextureFormat getStencilFormat (int stencilBits)
337 {
338 	switch (stencilBits)
339 	{
340 		case 0:		return tcu::TextureFormat();
341 		case 8:
342 		default:	return tcu::TextureFormat(tcu::TextureFormat::S, tcu::TextureFormat::UNSIGNED_INT8);
343 	}
344 }
345 
renderReference(const tcu::PixelBufferAccess & dst,const vector<DrawPrimitiveOp> & drawOps,const tcu::PixelFormat & colorBits,const int depthBits,const int stencilBits,const int numSamples)346 void renderReference (const tcu::PixelBufferAccess& dst, const vector<DrawPrimitiveOp>& drawOps, const tcu::PixelFormat& colorBits, const int depthBits, const int stencilBits, const int numSamples)
347 {
348 	const int						width			= dst.getWidth();
349 	const int						height			= dst.getHeight();
350 
351 	tcu::TextureLevel				colorBuffer;
352 	tcu::TextureLevel				depthBuffer;
353 	tcu::TextureLevel				stencilBuffer;
354 
355 	rr::Renderer					referenceRenderer;
356 	rr::VertexAttrib				attributes[2];
357 	const ReferenceShader			shader;
358 
359 	attributes[0].type				= rr::VERTEXATTRIBTYPE_FLOAT;
360 	attributes[0].size				= 4;
361 	attributes[0].stride			= 0;
362 	attributes[0].instanceDivisor	= 0;
363 
364 	attributes[1].type				= rr::VERTEXATTRIBTYPE_FLOAT;
365 	attributes[1].size				= 4;
366 	attributes[1].stride			= 0;
367 	attributes[1].instanceDivisor	= 0;
368 
369 	// Initialize buffers.
370 	colorBuffer.setStorage(getColorFormat(colorBits), numSamples, width, height);
371 	rr::clearMultisampleColorBuffer(colorBuffer, CLEAR_COLOR, rr::WindowRectangle(0, 0, width, height));
372 
373 	if (depthBits > 0)
374 	{
375 		depthBuffer.setStorage(getDepthFormat(depthBits), numSamples, width, height);
376 		rr::clearMultisampleDepthBuffer(depthBuffer, CLEAR_DEPTH, rr::WindowRectangle(0, 0, width, height));
377 	}
378 
379 	if (stencilBits > 0)
380 	{
381 		stencilBuffer.setStorage(getStencilFormat(stencilBits), numSamples, width, height);
382 		rr::clearMultisampleStencilBuffer(stencilBuffer, CLEAR_STENCIL, rr::WindowRectangle(0, 0, width, height));
383 	}
384 
385 	const rr::RenderTarget renderTarget(rr::MultisamplePixelBufferAccess::fromMultisampleAccess(colorBuffer.getAccess()),
386 										rr::MultisamplePixelBufferAccess::fromMultisampleAccess(depthBuffer.getAccess()),
387 										rr::MultisamplePixelBufferAccess::fromMultisampleAccess(stencilBuffer.getAccess()));
388 
389 	for (vector<DrawPrimitiveOp>::const_iterator drawOp = drawOps.begin(); drawOp != drawOps.end(); drawOp++)
390 	{
391 		// Translate state
392 		rr::RenderState renderState((rr::ViewportState)(rr::MultisamplePixelBufferAccess::fromMultisampleAccess(colorBuffer.getAccess())));
393 		toReferenceRenderState(renderState, *drawOp);
394 
395 		DE_ASSERT(drawOp->type == PRIMITIVETYPE_TRIANGLE);
396 
397 		attributes[0].pointer = &drawOp->positions[0];
398 		attributes[1].pointer = &drawOp->colors[0];
399 
400 		referenceRenderer.draw(
401 			rr::DrawCommand(
402 				renderState,
403 				renderTarget,
404 				rr::Program(static_cast<const rr::VertexShader*>(&shader), static_cast<const rr::FragmentShader*>(&shader)),
405 				2,
406 				attributes,
407 				rr::PrimitiveList(rr::PRIMITIVETYPE_TRIANGLES, drawOp->count * 3, 0)));
408 	}
409 
410 	rr::resolveMultisampleColorBuffer(dst, rr::MultisamplePixelBufferAccess::fromMultisampleAccess(colorBuffer.getAccess()));
411 }
412 
413 // API rendering code
414 
415 class Program
416 {
417 public:
Program(void)418 					Program				(void) {}
~Program(void)419 	virtual			~Program			(void) {}
420 
421 	virtual void	setup				(void) const = DE_NULL;
422 };
423 
424 typedef de::SharedPtr<Program> ProgramSp;
425 
426 #if defined(DEQP_SUPPORT_GLES2) || defined(DEQP_SUPPORT_GLES3)
427 
428 static const char* s_vertexSrc =
429 	"attribute highp vec4 a_position;\n"
430 	"attribute mediump vec4 a_color;\n"
431 	"varying mediump vec4 v_color;\n"
432 	"void main (void)\n"
433 	"{\n"
434 	"	gl_Position = a_position;\n"
435 	"	v_color = a_color;\n"
436 	"}\n";
437 
438 static const char* s_fragmentSrc =
439 	"varying mediump vec4 v_color;\n"
440 	"void main (void)\n"
441 	"{\n"
442 	"	gl_FragColor = v_color;\n"
443 	"}\n";
444 
createShader(deUint32 shaderType,const char * source)445 static deUint32 createShader (deUint32 shaderType, const char* source)
446 {
447 	deUint32 shader = glCreateShader(shaderType);
448 	glShaderSource(shader, 1, &source, DE_NULL);
449 	glCompileShader(shader);
450 
451 	int compileStatus = 0;
452 	glGetShaderiv(shader, GL_COMPILE_STATUS, &compileStatus);
453 
454 	if (!compileStatus)
455 	{
456 		glDeleteShader(shader);
457 		return 0;
458 	}
459 
460 	return shader;
461 }
462 
createProgram(deUint32 vertexShader,deUint32 fragmentShader)463 static deUint32 createProgram (deUint32 vertexShader, deUint32 fragmentShader)
464 {
465 	deUint32 program = glCreateProgram();
466 	glAttachShader(program, vertexShader);
467 	glAttachShader(program, fragmentShader);
468 	glLinkProgram(program);
469 
470 	int linkStatus = 0;
471 	glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);
472 
473 	if (!linkStatus)
474 	{
475 		glDeleteProgram(program);
476 		return 0;
477 	}
478 
479 	return program;
480 }
481 
482 class GLES2Program : public Program
483 {
484 public:
GLES2Program(void)485 	GLES2Program (void)
486 		: m_program			(0)
487 		, m_vertexShader	(0)
488 		, m_fragmentShader	(0)
489 		, m_positionLoc		(0)
490 		, m_colorLoc		(0)
491 	{
492 		m_vertexShader		= createShader(GL_VERTEX_SHADER, s_vertexSrc);
493 		m_fragmentShader	= createShader(GL_FRAGMENT_SHADER, s_fragmentSrc);
494 
495 		if (!m_vertexShader || !m_fragmentShader)
496 		{
497 			glDeleteShader(m_vertexShader);
498 			glDeleteShader(m_fragmentShader);
499 			throw tcu::TestError("Failed to compile shaders");
500 		}
501 
502 		m_program = createProgram(m_vertexShader, m_fragmentShader);
503 		if (!m_program)
504 		{
505 			glDeleteShader(m_vertexShader);
506 			glDeleteShader(m_fragmentShader);
507 			throw tcu::TestError("Failed to link program");
508 		}
509 
510 		m_positionLoc	= glGetAttribLocation(m_program, "a_position");
511 		m_colorLoc		= glGetAttribLocation(m_program, "a_color");
512 	}
513 
~GLES2Program(void)514 	~GLES2Program (void)
515 	{
516 	}
517 
setup(void) const518 	void setup (void) const
519 	{
520 		glUseProgram(m_program);
521 		glEnableVertexAttribArray(m_positionLoc);
522 		glEnableVertexAttribArray(m_colorLoc);
523 		GLU_CHECK_MSG("Program setup failed");
524 	}
525 
getPositionLoc(void) const526 	int			getPositionLoc		(void) const { return m_positionLoc;	}
getColorLoc(void) const527 	int			getColorLoc			(void) const { return m_colorLoc;		}
528 
529 private:
530 	deUint32	m_program;
531 	deUint32	m_vertexShader;
532 	deUint32	m_fragmentShader;
533 	int			m_positionLoc;
534 	int			m_colorLoc;
535 };
536 
clearGLES2(const tcu::Vec4 & color,const float depth,const int stencil)537 void clearGLES2 (const tcu::Vec4& color, const float depth, const int stencil)
538 {
539 	glClearColor(color.x(), color.y(), color.z(), color.w());
540 	glClearDepthf(depth);
541 	glClearStencil(stencil);
542 	glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT|GL_STENCIL_BUFFER_BIT);
543 }
544 
drawGLES2(const Program & program,const DrawPrimitiveOp & drawOp)545 void drawGLES2 (const Program& program, const DrawPrimitiveOp& drawOp)
546 {
547 	const GLES2Program& gles2Program = dynamic_cast<const GLES2Program&>(program);
548 
549 	switch (drawOp.blend)
550 	{
551 		case BLENDMODE_NONE:
552 			glDisable(GL_BLEND);
553 			break;
554 
555 		case BLENDMODE_ADDITIVE:
556 			glEnable(GL_BLEND);
557 			glBlendFunc(GL_ONE, GL_ONE);
558 			break;
559 
560 		case BLENDMODE_SRC_OVER:
561 			glEnable(GL_BLEND);
562 			glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
563 			break;
564 
565 		default:
566 			DE_ASSERT(false);
567 	}
568 
569 	switch (drawOp.depth)
570 	{
571 		case DEPTHMODE_NONE:
572 			glDisable(GL_DEPTH_TEST);
573 			break;
574 
575 		case DEPTHMODE_LESS:
576 			glEnable(GL_DEPTH_TEST);
577 			break;
578 
579 		default:
580 			DE_ASSERT(false);
581 	}
582 
583 	switch (drawOp.stencil)
584 	{
585 		case STENCILMODE_NONE:
586 			glDisable(GL_STENCIL_TEST);
587 			break;
588 
589 		case STENCILMODE_LEQUAL_INC:
590 			glEnable(GL_STENCIL_TEST);
591 			glStencilFunc(GL_LEQUAL, drawOp.stencilRef, ~0u);
592 			glStencilOp(GL_KEEP, GL_INCR, GL_INCR);
593 			break;
594 
595 		default:
596 			DE_ASSERT(false);
597 	}
598 
599 	glVertexAttribPointer(gles2Program.getPositionLoc(), 4, GL_FLOAT, GL_FALSE, 0, &drawOp.positions[0]);
600 	glVertexAttribPointer(gles2Program.getColorLoc(), 4, GL_FLOAT, GL_FALSE, 0, &drawOp.colors[0]);
601 
602 	DE_ASSERT(drawOp.type == PRIMITIVETYPE_TRIANGLE);
603 	glDrawArrays(GL_TRIANGLES, 0, drawOp.count*3);
604 }
605 
readPixelsGLES2(tcu::Surface & dst)606 static void readPixelsGLES2 (tcu::Surface& dst)
607 {
608 	glReadPixels(0, 0, dst.getWidth(), dst.getHeight(), GL_RGBA, GL_UNSIGNED_BYTE, dst.getAccess().getDataPtr());
609 }
610 
611 #endif
612 
createProgram(EGLint api)613 Program* createProgram (EGLint api)
614 {
615 	switch (api)
616 	{
617 #if defined(DEQP_SUPPORT_GLES2) || defined(DEQP_SUPPORT_GLES3)
618 		case EGL_OPENGL_ES2_BIT:		return new GLES2Program();
619 		case EGL_OPENGL_ES3_BIT_KHR:	return new GLES2Program();
620 #endif
621 		default:
622 			throw tcu::NotSupportedError("Unsupported API");
623 	}
624 }
625 
draw(EGLint api,const Program & program,const DrawPrimitiveOp & drawOp)626 void draw (EGLint api, const Program& program, const DrawPrimitiveOp& drawOp)
627 {
628 	switch (api)
629 	{
630 #if defined(DEQP_SUPPORT_GLES2) || defined(DEQP_SUPPORT_GLES3)
631 		case EGL_OPENGL_ES2_BIT:		drawGLES2(program, drawOp);		break;
632 		case EGL_OPENGL_ES3_BIT_KHR:	drawGLES2(program, drawOp);		break;
633 #endif
634 		default:
635 			throw tcu::NotSupportedError("Unsupported API");
636 	}
637 }
638 
clear(EGLint api,const tcu::Vec4 & color,const float depth,const int stencil)639 void clear (EGLint api, const tcu::Vec4& color, const float depth, const int stencil)
640 {
641 	switch (api)
642 	{
643 #if defined(DEQP_SUPPORT_GLES2) || defined(DEQP_SUPPORT_GLES3)
644 		case EGL_OPENGL_ES2_BIT:		clearGLES2(color, depth, stencil);		break;
645 		case EGL_OPENGL_ES3_BIT_KHR:	clearGLES2(color, depth, stencil);		break;
646 #endif
647 		default:
648 			throw tcu::NotSupportedError("Unsupported API");
649 	}
650 }
651 
readPixels(EGLint api,tcu::Surface & dst)652 static void readPixels (EGLint api, tcu::Surface& dst)
653 {
654 	switch (api)
655 	{
656 #if defined(DEQP_SUPPORT_GLES2) || defined(DEQP_SUPPORT_GLES3)
657 		case EGL_OPENGL_ES2_BIT:		readPixelsGLES2(dst);		break;
658 		case EGL_OPENGL_ES3_BIT_KHR:	readPixelsGLES2(dst);		break;
659 #endif
660 		default:
661 			throw tcu::NotSupportedError("Unsupported API");
662 	}
663 }
664 
getPixelFormat(const tcu::egl::Display & display,EGLConfig config)665 tcu::PixelFormat getPixelFormat (const tcu::egl::Display& display, EGLConfig config)
666 {
667 	tcu::PixelFormat fmt;
668 	display.describeConfig(config, fmt);
669 	return fmt;
670 }
671 
672 } // anonymous
673 
674 // SingleThreadRenderCase
675 
676 class SingleThreadRenderCase : public MultiContextRenderCase
677 {
678 public:
679 						SingleThreadRenderCase		(EglTestContext& eglTestCtx, const char* name, const char* description, EGLint api, EGLint surfaceType, const std::vector<EGLint>& configIds, int numContextsPerApi);
680 
681 private:
682 	virtual void		executeForContexts			(tcu::egl::Display& display, tcu::egl::Surface& surface, EGLConfig config, const std::vector<std::pair<EGLint, tcu::egl::Context*> >& contexts);
683 };
684 
685 // SingleThreadColorClearCase
686 
SingleThreadRenderCase(EglTestContext & eglTestCtx,const char * name,const char * description,EGLint api,EGLint surfaceType,const std::vector<EGLint> & configIds,int numContextsPerApi)687 SingleThreadRenderCase::SingleThreadRenderCase (EglTestContext& eglTestCtx, const char* name, const char* description, EGLint api, EGLint surfaceType, const std::vector<EGLint>& configIds, int numContextsPerApi)
688 	: MultiContextRenderCase(eglTestCtx, name, description, api, surfaceType, configIds, numContextsPerApi)
689 {
690 }
691 
executeForContexts(tcu::egl::Display & display,tcu::egl::Surface & surface,EGLConfig config,const std::vector<std::pair<EGLint,tcu::egl::Context * >> & contexts)692 void SingleThreadRenderCase::executeForContexts (tcu::egl::Display& display, tcu::egl::Surface& surface, EGLConfig config, const std::vector<std::pair<EGLint, tcu::egl::Context*> >& contexts)
693 {
694 	const int				width		= surface.getWidth();
695 	const int				height		= surface.getHeight();
696 	const int				numContexts	= (int)contexts.size();
697 	const int				drawsPerCtx	= 2;
698 	const int				numIters	= 2;
699 	const float				threshold	= 0.02f;
700 
701 	const tcu::PixelFormat	pixelFmt	= getPixelFormat(display, config);
702 	const int				depthBits	= display.getConfigAttrib(config, EGL_DEPTH_SIZE);
703 	const int				stencilBits	= display.getConfigAttrib(config, EGL_STENCIL_SIZE);
704 	const int				numSamples	= display.getConfigAttrib(config, EGL_SAMPLES);
705 
706 	TestLog&				log			= m_testCtx.getLog();
707 
708 	tcu::Surface			refFrame	(width, height);
709 	tcu::Surface			frame		(width, height);
710 
711 	de::Random				rnd			(deStringHash(getName()) ^ deInt32Hash(numContexts));
712 	vector<ProgramSp>		programs	(contexts.size());
713 	vector<DrawPrimitiveOp>	drawOps;
714 
715 	// Log basic information about config.
716 	log << TestLog::Message << "EGL_RED_SIZE = "		<< pixelFmt.redBits << TestLog::EndMessage;
717 	log << TestLog::Message << "EGL_GREEN_SIZE = "		<< pixelFmt.greenBits << TestLog::EndMessage;
718 	log << TestLog::Message << "EGL_BLUE_SIZE = "		<< pixelFmt.blueBits << TestLog::EndMessage;
719 	log << TestLog::Message << "EGL_ALPHA_SIZE = "		<< pixelFmt.alphaBits << TestLog::EndMessage;
720 	log << TestLog::Message << "EGL_DEPTH_SIZE = "		<< depthBits << TestLog::EndMessage;
721 	log << TestLog::Message << "EGL_STENCIL_SIZE = "	<< stencilBits << TestLog::EndMessage;
722 	log << TestLog::Message << "EGL_SAMPLES = "			<< numSamples << TestLog::EndMessage;
723 
724 	// Generate draw ops.
725 	drawOps.resize(numContexts*drawsPerCtx*numIters);
726 	for (vector<DrawPrimitiveOp>::iterator drawOp = drawOps.begin(); drawOp != drawOps.end(); ++drawOp)
727 		randomizeDrawOp(rnd, *drawOp);
728 
729 	// Create and setup programs per context
730 	for (int ctxNdx = 0; ctxNdx < numContexts; ctxNdx++)
731 	{
732 		EGLint				api			= contexts[ctxNdx].first;
733 		tcu::egl::Context*	context		= contexts[ctxNdx].second;
734 
735 		eglMakeCurrent(display.getEGLDisplay(), surface.getEGLSurface(), surface.getEGLSurface(), context->getEGLContext());
736 		TCU_CHECK_EGL();
737 
738 		programs[ctxNdx] = ProgramSp(createProgram(api));
739 		programs[ctxNdx]->setup();
740 	}
741 
742 	// Clear to black using first context.
743 	{
744 		EGLint				api			= contexts[0].first;
745 		tcu::egl::Context*	context		= contexts[0].second;
746 
747 		eglMakeCurrent(display.getEGLDisplay(), surface.getEGLSurface(), surface.getEGLSurface(), context->getEGLContext());
748 		TCU_CHECK_EGL();
749 
750 		clear(api, CLEAR_COLOR, CLEAR_DEPTH, CLEAR_STENCIL);
751 	}
752 
753 	// Render.
754 	for (int iterNdx = 0; iterNdx < numIters; iterNdx++)
755 	{
756 		for (int ctxNdx = 0; ctxNdx < numContexts; ctxNdx++)
757 		{
758 			EGLint				api			= contexts[ctxNdx].first;
759 			tcu::egl::Context*	context		= contexts[ctxNdx].second;
760 
761 			eglMakeCurrent(display.getEGLDisplay(), surface.getEGLSurface(), surface.getEGLSurface(), context->getEGLContext());
762 			TCU_CHECK_EGL();
763 
764 			for (int drawNdx = 0; drawNdx < drawsPerCtx; drawNdx++)
765 			{
766 				const DrawPrimitiveOp& drawOp = drawOps[iterNdx*numContexts*drawsPerCtx + ctxNdx*drawsPerCtx + drawNdx];
767 				draw(api, *programs[ctxNdx], drawOp);
768 			}
769 		}
770 	}
771 
772 	// Read pixels using first context. \todo [pyry] Randomize?
773 	{
774 		EGLint				api		= contexts[0].first;
775 		tcu::egl::Context*	context	= contexts[0].second;
776 
777 		eglMakeCurrent(display.getEGLDisplay(), surface.getEGLSurface(), surface.getEGLSurface(), context->getEGLContext());
778 		TCU_CHECK_EGL();
779 
780 		readPixels(api, frame);
781 	}
782 
783 	// Render reference.
784 	// \note Reference image is always generated using single-sampling.
785 	renderReference(refFrame.getAccess(), drawOps, pixelFmt, depthBits, stencilBits, 1);
786 
787 	// Compare images
788 	{
789 		bool imagesOk = tcu::fuzzyCompare(log, "ComparisonResult", "Image comparison result", refFrame, frame, threshold, tcu::COMPARE_LOG_RESULT);
790 
791 		if (!imagesOk)
792 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
793 	}
794 }
795 
796 // MultiThreadRenderCase
797 
798 class MultiThreadRenderCase : public MultiContextRenderCase
799 {
800 public:
801 						MultiThreadRenderCase		(EglTestContext& eglTestCtx, const char* name, const char* description, EGLint api, EGLint surfaceType, const std::vector<EGLint>& configIds, int numContextsPerApi);
802 
803 private:
804 	virtual void		executeForContexts			(tcu::egl::Display& display, tcu::egl::Surface& surface, EGLConfig config, const std::vector<std::pair<EGLint, tcu::egl::Context*> >& contexts);
805 };
806 
807 class RenderTestThread;
808 
809 typedef de::SharedPtr<RenderTestThread>	RenderTestThreadSp;
810 typedef de::SharedPtr<de::Semaphore>	SemaphoreSp;
811 
812 struct DrawOpPacket
813 {
DrawOpPacketdeqp::egl::DrawOpPacket814 	DrawOpPacket (void)
815 		: drawOps	(DE_NULL)
816 		, numOps	(0)
817 	{
818 	}
819 
820 	const DrawPrimitiveOp*	drawOps;
821 	int						numOps;
822 	SemaphoreSp				wait;
823 	SemaphoreSp				signal;
824 };
825 
826 class RenderTestThread : public de::Thread
827 {
828 public:
RenderTestThread(tcu::egl::Display & display,tcu::egl::Surface & surface,tcu::egl::Context & context,EGLint api,const Program & program,const std::vector<DrawOpPacket> & packets)829 	RenderTestThread (tcu::egl::Display& display, tcu::egl::Surface& surface, tcu::egl::Context& context, EGLint api, const Program& program, const std::vector<DrawOpPacket>& packets)
830 		: m_display	(display)
831 		, m_surface	(surface)
832 		, m_context	(context)
833 		, m_api		(api)
834 		, m_program	(program)
835 		, m_packets	(packets)
836 	{
837 	}
838 
run(void)839 	void run (void)
840 	{
841 		for (std::vector<DrawOpPacket>::const_iterator packetIter = m_packets.begin(); packetIter != m_packets.end(); packetIter++)
842 		{
843 			// Wait until it is our turn.
844 			packetIter->wait->decrement();
845 
846 			// Acquire context.
847 			eglMakeCurrent(m_display.getEGLDisplay(), m_surface.getEGLSurface(), m_surface.getEGLSurface(), m_context.getEGLContext());
848 
849 			// Execute rendering.
850 			for (int ndx = 0; ndx < packetIter->numOps; ndx++)
851 				draw(m_api, m_program, packetIter->drawOps[ndx]);
852 
853 			// Release context.
854 			eglMakeCurrent(m_display.getEGLDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
855 
856 			// Signal completion.
857 			packetIter->signal->increment();
858 		}
859 	}
860 
861 private:
862 	tcu::egl::Display&					m_display;
863 	tcu::egl::Surface&					m_surface;
864 	tcu::egl::Context&					m_context;
865 	EGLint								m_api;
866 	const Program&						m_program;
867 	const std::vector<DrawOpPacket>&	m_packets;
868 };
869 
MultiThreadRenderCase(EglTestContext & eglTestCtx,const char * name,const char * description,EGLint api,EGLint surfaceType,const std::vector<EGLint> & configIds,int numContextsPerApi)870 MultiThreadRenderCase::MultiThreadRenderCase (EglTestContext& eglTestCtx, const char* name, const char* description, EGLint api, EGLint surfaceType, const std::vector<EGLint>& configIds, int numContextsPerApi)
871 	: MultiContextRenderCase(eglTestCtx, name, description, api, surfaceType, configIds, numContextsPerApi)
872 {
873 }
874 
executeForContexts(tcu::egl::Display & display,tcu::egl::Surface & surface,EGLConfig config,const std::vector<std::pair<EGLint,tcu::egl::Context * >> & contexts)875 void MultiThreadRenderCase::executeForContexts (tcu::egl::Display& display, tcu::egl::Surface& surface, EGLConfig config, const std::vector<std::pair<EGLint, tcu::egl::Context*> >& contexts)
876 {
877 	const int				width				= surface.getWidth();
878 	const int				height				= surface.getHeight();
879 	const int				numContexts			= (int)contexts.size();
880 	const int				opsPerPacket		= 2;
881 	const int				packetsPerThread	= 2;
882 	const int				numThreads			= numContexts;
883 	const int				numPackets			= numThreads * packetsPerThread;
884 	const float				threshold			= 0.02f;
885 
886 	const tcu::PixelFormat	pixelFmt			= getPixelFormat(display, config);
887 	const int				depthBits			= display.getConfigAttrib(config, EGL_DEPTH_SIZE);
888 	const int				stencilBits			= display.getConfigAttrib(config, EGL_STENCIL_SIZE);
889 	const int				numSamples			= display.getConfigAttrib(config, EGL_SAMPLES);
890 
891 	TestLog&				log					= m_testCtx.getLog();
892 
893 	tcu::Surface			refFrame			(width, height);
894 	tcu::Surface			frame				(width, height);
895 
896 	de::Random				rnd					(deStringHash(getName()) ^ deInt32Hash(numContexts));
897 
898 	// Resources that need cleanup
899 	vector<ProgramSp>				programs	(numContexts);
900 	vector<SemaphoreSp>				semaphores	(numPackets+1);
901 	vector<DrawPrimitiveOp>			drawOps		(numPackets*opsPerPacket);
902 	vector<vector<DrawOpPacket> >	packets		(numThreads);
903 	vector<RenderTestThreadSp>		threads		(numThreads);
904 
905 	// Log basic information about config.
906 	log << TestLog::Message << "EGL_RED_SIZE = "		<< pixelFmt.redBits << TestLog::EndMessage;
907 	log << TestLog::Message << "EGL_GREEN_SIZE = "		<< pixelFmt.greenBits << TestLog::EndMessage;
908 	log << TestLog::Message << "EGL_BLUE_SIZE = "		<< pixelFmt.blueBits << TestLog::EndMessage;
909 	log << TestLog::Message << "EGL_ALPHA_SIZE = "		<< pixelFmt.alphaBits << TestLog::EndMessage;
910 	log << TestLog::Message << "EGL_DEPTH_SIZE = "		<< depthBits << TestLog::EndMessage;
911 	log << TestLog::Message << "EGL_STENCIL_SIZE = "	<< stencilBits << TestLog::EndMessage;
912 	log << TestLog::Message << "EGL_SAMPLES = "			<< numSamples << TestLog::EndMessage;
913 
914 	// Initialize semaphores.
915 	for (vector<SemaphoreSp>::iterator sem = semaphores.begin(); sem != semaphores.end(); ++sem)
916 		*sem = SemaphoreSp(new de::Semaphore(0));
917 
918 	// Create draw ops.
919 	for (vector<DrawPrimitiveOp>::iterator drawOp = drawOps.begin(); drawOp != drawOps.end(); ++drawOp)
920 		randomizeDrawOp(rnd, *drawOp);
921 
922 	// Create packets.
923 	for (int threadNdx = 0; threadNdx < numThreads; threadNdx++)
924 	{
925 		packets[threadNdx].resize(packetsPerThread);
926 
927 		for (int packetNdx = 0; packetNdx < packetsPerThread; packetNdx++)
928 		{
929 			DrawOpPacket& packet = packets[threadNdx][packetNdx];
930 
931 			// Threads take turns with packets.
932 			packet.wait		= semaphores[packetNdx*numThreads + threadNdx];
933 			packet.signal	= semaphores[packetNdx*numThreads + threadNdx + 1];
934 			packet.numOps	= opsPerPacket;
935 			packet.drawOps	= &drawOps[(packetNdx*numThreads + threadNdx)*opsPerPacket];
936 		}
937 	}
938 
939 	// Create and setup programs per context
940 	for (int ctxNdx = 0; ctxNdx < numContexts; ctxNdx++)
941 	{
942 		EGLint				api			= contexts[ctxNdx].first;
943 		tcu::egl::Context*	context		= contexts[ctxNdx].second;
944 
945 		eglMakeCurrent(display.getEGLDisplay(), surface.getEGLSurface(), surface.getEGLSurface(), context->getEGLContext());
946 		TCU_CHECK_EGL();
947 
948 		programs[ctxNdx] = ProgramSp(createProgram(api));
949 		programs[ctxNdx]->setup();
950 
951 		// Release context
952 		eglMakeCurrent(display.getEGLDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
953 	}
954 
955 	// Clear to black using first context.
956 	{
957 		EGLint				api			= contexts[0].first;
958 		tcu::egl::Context*	context		= contexts[0].second;
959 
960 		eglMakeCurrent(display.getEGLDisplay(), surface.getEGLSurface(), surface.getEGLSurface(), context->getEGLContext());
961 		TCU_CHECK_EGL();
962 
963 		clear(api, CLEAR_COLOR, CLEAR_DEPTH, CLEAR_STENCIL);
964 
965 		// Release context
966 		eglMakeCurrent(display.getEGLDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
967 	}
968 
969 	// Create and launch threads (actual rendering starts once first semaphore is signaled).
970 	for (int threadNdx = 0; threadNdx < numThreads; threadNdx++)
971 	{
972 		threads[threadNdx] = RenderTestThreadSp(new RenderTestThread(display, surface, *contexts[threadNdx].second, contexts[threadNdx].first, *programs[threadNdx], packets[threadNdx]));
973 		threads[threadNdx]->start();
974 	}
975 
976 	// Signal start and wait until complete.
977 	semaphores.front()->increment();
978 	semaphores.back()->decrement();
979 
980 	// Read pixels using first context. \todo [pyry] Randomize?
981 	{
982 		EGLint				api		= contexts[0].first;
983 		tcu::egl::Context*	context	= contexts[0].second;
984 
985 		eglMakeCurrent(display.getEGLDisplay(), surface.getEGLSurface(), surface.getEGLSurface(), context->getEGLContext());
986 		TCU_CHECK_EGL();
987 
988 		readPixels(api, frame);
989 	}
990 
991 	// Join threads.
992 	for (int threadNdx = 0; threadNdx < numThreads; threadNdx++)
993 		threads[threadNdx]->join();
994 
995 	// Render reference.
996 	renderReference(refFrame.getAccess(), drawOps, pixelFmt, depthBits, stencilBits, 1);
997 
998 	// Compare images
999 	{
1000 		bool imagesOk = tcu::fuzzyCompare(log, "ComparisonResult", "Image comparison result", refFrame, frame, threshold, tcu::COMPARE_LOG_RESULT);
1001 
1002 		if (!imagesOk)
1003 			m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
1004 	}
1005 }
1006 
RenderTests(EglTestContext & eglTestCtx)1007 RenderTests::RenderTests (EglTestContext& eglTestCtx)
1008 	: TestCaseGroup(eglTestCtx, "render", "Basic rendering with different client APIs")
1009 {
1010 }
1011 
~RenderTests(void)1012 RenderTests::~RenderTests (void)
1013 {
1014 }
1015 
1016 struct RenderGroupSpec
1017 {
1018 	const char*		name;
1019 	const char*		desc;
1020 	EGLint			apiBits;
1021 	int				numContextsPerApi;
1022 };
1023 
1024 template <class RenderClass>
createRenderGroups(EglTestContext & eglTestCtx,tcu::TestCaseGroup * group,const RenderGroupSpec * first,const RenderGroupSpec * last)1025 static void createRenderGroups (EglTestContext& eglTestCtx, tcu::TestCaseGroup* group, const RenderGroupSpec* first, const RenderGroupSpec* last)
1026 {
1027 	for (const RenderGroupSpec* groupIter = first; groupIter != last; groupIter++)
1028 	{
1029 		tcu::TestCaseGroup* configGroup = new tcu::TestCaseGroup(eglTestCtx.getTestContext(), groupIter->name, groupIter->desc);
1030 		group->addChild(configGroup);
1031 
1032 		vector<RenderConfigIdSet>	configSets;
1033 		eglu::FilterList			filters;
1034 		filters << (eglu::ConfigRenderableType() & groupIter->apiBits);
1035 		getDefaultRenderConfigIdSets(configSets, eglTestCtx.getConfigs(), filters);
1036 
1037 		for (vector<RenderConfigIdSet>::const_iterator setIter = configSets.begin(); setIter != configSets.end(); setIter++)
1038 			configGroup->addChild(new RenderClass(eglTestCtx, setIter->getName(), "", groupIter->apiBits, setIter->getSurfaceTypeMask(), setIter->getConfigIds(), groupIter->numContextsPerApi));
1039 	}
1040 }
1041 
init(void)1042 void RenderTests::init (void)
1043 {
1044 	static const RenderGroupSpec singleContextCases[] =
1045 	{
1046 //		{ "gles1",			"Primitive rendering using GLES1",												EGL_OPENGL_ES_BIT,										1 },
1047 		{ "gles2",			"Primitive rendering using GLES2",												EGL_OPENGL_ES2_BIT,										1 },
1048 		{ "gles3",			"Primitive rendering using GLES3",												EGL_OPENGL_ES3_BIT_KHR,									1 },
1049 //		{ "vg",				"Primitive rendering using OpenVG",												EGL_OPENVG_BIT,											1 }
1050 	};
1051 
1052 	static const RenderGroupSpec multiContextCases[] =
1053 	{
1054 //		{ "gles1",				"Primitive rendering using multiple GLES1 contexts to shared surface",		EGL_OPENGL_ES_BIT,												3 },
1055 		{ "gles2",				"Primitive rendering using multiple GLES2 contexts to shared surface",		EGL_OPENGL_ES2_BIT,												3 },
1056 		{ "gles3",				"Primitive rendering using multiple GLES3 contexts to shared surface",		EGL_OPENGL_ES3_BIT_KHR,											3 },
1057 //		{ "vg",					"Primitive rendering using multiple OpenVG contexts to shared surface",		EGL_OPENVG_BIT,													3 },
1058 //		{ "gles1_gles2",		"Primitive rendering using multiple APIs to shared surface",				EGL_OPENGL_ES_BIT|EGL_OPENGL_ES2_BIT,							1 },
1059 //		{ "gles1_gles2_gles3",	"Primitive rendering using multiple APIs to shared surface",				EGL_OPENGL_ES_BIT|EGL_OPENGL_ES2_BIT|EGL_OPENGL_ES3_BIT_KHR,	1 },
1060 		{ "gles2_gles3",		"Primitive rendering using multiple APIs to shared surface",				EGL_OPENGL_ES2_BIT|EGL_OPENGL_ES3_BIT_KHR,						1 },
1061 //		{ "gles1_vg",			"Primitive rendering using multiple APIs to shared surface",				EGL_OPENGL_ES_BIT|EGL_OPENVG_BIT,								1 },
1062 //		{ "gles2_vg",			"Primitive rendering using multiple APIs to shared surface",				EGL_OPENGL_ES2_BIT|EGL_OPENVG_BIT,								1 },
1063 //		{ "gles3_vg",			"Primitive rendering using multiple APIs to shared surface",				EGL_OPENGL_ES3_BIT_KHR|EGL_OPENVG_BIT,							1 },
1064 //		{ "gles1_gles2_vg",		"Primitive rendering using multiple APIs to shared surface",				EGL_OPENGL_ES_BIT|EGL_OPENGL_ES2_BIT|EGL_OPENVG_BIT,			1 }
1065 	};
1066 
1067 	tcu::TestCaseGroup* singleContextGroup = new tcu::TestCaseGroup(m_testCtx, "single_context", "Single-context rendering");
1068 	addChild(singleContextGroup);
1069 	createRenderGroups<SingleThreadRenderCase>(m_eglTestCtx, singleContextGroup, &singleContextCases[0], &singleContextCases[DE_LENGTH_OF_ARRAY(singleContextCases)]);
1070 
1071 	tcu::TestCaseGroup* multiContextGroup = new tcu::TestCaseGroup(m_testCtx, "multi_context", "Multi-context rendering with shared surface");
1072 	addChild(multiContextGroup);
1073 	createRenderGroups<SingleThreadRenderCase>(m_eglTestCtx, multiContextGroup, &multiContextCases[0], &multiContextCases[DE_LENGTH_OF_ARRAY(multiContextCases)]);
1074 
1075 	tcu::TestCaseGroup* multiThreadGroup = new tcu::TestCaseGroup(m_testCtx, "multi_thread", "Multi-thread rendering with shared surface");
1076 	addChild(multiThreadGroup);
1077 	createRenderGroups<MultiThreadRenderCase>(m_eglTestCtx, multiThreadGroup, &multiContextCases[0], &multiContextCases[DE_LENGTH_OF_ARRAY(multiContextCases)]);
1078 }
1079 
1080 } // egl
1081 } // deqp
1082