• 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 GLES2 resource sharing performnace tests.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "teglGLES2SharedRenderingPerfTests.hpp"
25 
26 #include "tcuTestLog.hpp"
27 
28 #include "gluDefs.hpp"
29 #include "glwDefs.hpp"
30 #include "glwEnums.hpp"
31 #include "glwFunctions.hpp"
32 
33 #include "deThread.hpp"
34 #include "deClock.h"
35 #include "deStringUtil.hpp"
36 
37 #include <vector>
38 #include <string>
39 #include <algorithm>
40 #include <cmath>
41 
42 #include <EGL/egl.h>
43 #include <EGL/eglext.h>
44 
45 #include <GLES2/gl2.h>
46 #include <GLES2/gl2ext.h>
47 
48 using tcu::TestLog;
49 using std::vector;
50 using std::string;
51 
52 namespace deqp
53 {
54 namespace egl
55 {
56 
57 namespace
58 {
59 
60 struct TestConfig
61 {
62 	enum TextureType
63 	{
64 		TEXTURETYPE_TEXTURE = 0,
65 		TEXTURETYPE_SHARED_TEXTURE,
66 		TEXTURETYPE_IMAGE,
67 		TEXTURETYPE_SHARED_IMAGE,
68 		TEXTURETYPE_SHARED_IMAGE_TEXTURE
69 	};
70 
71 	int			threadCount;
72 	int			perThreadContextCount;
73 
74 	int			frameCount;
75 	int			drawCallCount;
76 	int			triangleCount;
77 
78 	bool		sharedContexts;
79 
80 	bool		useCoordBuffer;
81 	bool		sharedCoordBuffer;
82 
83 	bool		useIndices;
84 	bool		useIndexBuffer;
85 	bool		sharedIndexBuffer;
86 
87 	bool		useTexture;
88 	TextureType	textureType;
89 
90 	bool		sharedProgram;
91 
92 	int			textureWidth;
93 	int			textureHeight;
94 
95 	int			surfaceWidth;
96 	int			surfaceHeight;
97 };
98 
99 class TestContext
100 {
101 public:
102 						TestContext		(EglTestContext& eglTestCtx, EGLConfig eglConfig, const TestConfig& config, bool share, TestContext* parent);
103 						~TestContext	(void);
104 
105 	void				render			(void);
106 
getEGLContext(void)107 	EGLContext			getEGLContext	(void) { return m_eglContext; }
108 
getCoordBuffer(void) const109 	GLuint				getCoordBuffer	(void) const { return m_coordBuffer;	}
getIndexBuffer(void) const110 	GLuint				getIndexBuffer	(void) const { return m_indexBuffer;	}
getTexture(void) const111 	GLuint				getTexture		(void) const { return m_texture;		}
getProgram(void) const112 	GLuint				getProgram		(void) const { return m_program;		}
getEGLImage(void) const113 	EGLImageKHR			getEGLImage		(void) const { return m_eglImage;		}
114 
115 private:
116 	TestContext*				m_parent;
117 	EglTestContext&				m_testCtx;
118 	TestConfig					m_config;
119 	EGLContext					m_eglContext;
120 	EGLSurface					m_eglSurface;
121 
122 	glw::Functions				m_gl;
123 
124 	PFNEGLCREATEIMAGEKHRPROC	m_eglCreateImageKHR;
125 	PFNEGLDESTROYIMAGEKHRPROC	m_eglDestroyImageKHR;
126 
127 	PFNGLEGLIMAGETARGETTEXTURE2DOESPROC	m_glEGLImageTargetTexture2DOES;
128 
129 	GLuint						m_coordBuffer;
130 	GLuint						m_indexBuffer;
131 	GLuint						m_texture;
132 	GLuint						m_program;
133 
134 	EGLImageKHR					m_eglImage;
135 
136 	GLuint						m_coordLoc;
137 	GLuint						m_textureLoc;
138 
139 	vector<float>				m_coordData;
140 	vector<deUint16>			m_indexData;
141 
142 	EGLImageKHR					createEGLImage			(void);
143 	GLuint						createTextureFromImage	(EGLImageKHR image);
144 
145 	// Not supported
146 	TestContext&	operator=		(const TestContext&);
147 					TestContext		(const TestContext&);
148 };
149 
150 namespace
151 {
152 
checkExtension(const char * extensions,const char * extension)153 bool checkExtension (const char* extensions, const char* extension)
154 {
155 	TCU_CHECK(extensions);
156 
157 	std::istringstream	stream(extensions);
158 	string				ext;
159 
160 	while (std::getline(stream, ext, ' '))
161 	{
162 		if (ext == extension)
163 			return true;
164 	}
165 
166 	return false;
167 }
168 
createCoordData(vector<float> & data,const TestConfig & config)169 void createCoordData (vector<float>& data, const TestConfig& config)
170 {
171 	if (config.useIndices)
172 	{
173 		for (int triangleNdx = 0; triangleNdx < 2; triangleNdx++)
174 		{
175 			const float x1 = -1.0f;
176 			const float y1 = -1.0f;
177 
178 			const float x2 = 1.0f;
179 			const float y2 = 1.0f;
180 
181 			const float side = ((triangleNdx % 2) == 0 ? 1.0f : -1.0f);
182 
183 			data.push_back(side * x1);
184 			data.push_back(side * y1);
185 
186 			data.push_back(side * x2);
187 			data.push_back(side * y1);
188 
189 			data.push_back(side * x2);
190 			data.push_back(side * y2);
191 		}
192 	}
193 	else
194 	{
195 		data.reserve(config.triangleCount * 3 * 2);
196 
197 		for (int triangleNdx = 0; triangleNdx < config.triangleCount; triangleNdx++)
198 		{
199 			const float x1 = -1.0f;
200 			const float y1 = -1.0f;
201 
202 			const float x2 = 1.0f;
203 			const float y2 = 1.0f;
204 
205 			const float side = ((triangleNdx % 2) == 0 ? 1.0f : -1.0f);
206 
207 			data.push_back(side * x1);
208 			data.push_back(side * y1);
209 
210 			data.push_back(side * x2);
211 			data.push_back(side * y1);
212 
213 			data.push_back(side * x2);
214 			data.push_back(side * y2);
215 		}
216 	}
217 }
218 
createCoordBuffer(const glw::Functions & gl,const TestConfig & config)219 GLuint createCoordBuffer (const glw::Functions& gl, const TestConfig& config)
220 {
221 	GLuint			buffer;
222 	vector<float>	data;
223 
224 	createCoordData(data, config);
225 
226 	gl.genBuffers(1, &buffer);
227 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers()");
228 	gl.bindBuffer(GL_ARRAY_BUFFER, buffer);
229 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer()");
230 	gl.bufferData(GL_ARRAY_BUFFER, (GLsizei)(data.size() * sizeof(float)), &(data[0]), GL_STATIC_DRAW);
231 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData()");
232 	gl.bindBuffer(GL_ARRAY_BUFFER, 0);
233 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer()");
234 
235 	return buffer;
236 }
237 
createIndexData(vector<deUint16> & data,const TestConfig & config)238 void createIndexData (vector<deUint16>& data, const TestConfig& config)
239 {
240 	for (int triangleNdx = 0; triangleNdx < config.triangleCount; triangleNdx++)
241 	{
242 		if ((triangleNdx % 2) == 0)
243 		{
244 			data.push_back(0);
245 			data.push_back(1);
246 			data.push_back(2);
247 		}
248 		else
249 		{
250 			data.push_back(2);
251 			data.push_back(3);
252 			data.push_back(0);
253 		}
254 	}
255 }
256 
createIndexBuffer(const glw::Functions & gl,const TestConfig & config)257 GLuint createIndexBuffer (const glw::Functions& gl, const TestConfig& config)
258 {
259 	GLuint				buffer;
260 	vector<deUint16>	data;
261 
262 	createIndexData(data, config);
263 
264 	gl.genBuffers(1, &buffer);
265 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenBuffers()");
266 	gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer);
267 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer()");
268 	gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, (GLsizei)(data.size() * sizeof(deUint16)), &(data[0]), GL_STATIC_DRAW);
269 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBufferData()");
270 	gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
271 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindBuffer()");
272 
273 	return buffer;
274 }
275 
createTextureData(vector<deUint8> & data,const TestConfig & config)276 void createTextureData (vector<deUint8>& data, const TestConfig& config)
277 {
278 	for (int x = 0; x < config.textureWidth; x++)
279 	{
280 		for (int y = 0; y < config.textureHeight; y++)
281 		{
282 			data.push_back((255*x)/255);
283 			data.push_back((255*y)/255);
284 			data.push_back((255*x*y)/(255*255));
285 			data.push_back(255);
286 		}
287 	}
288 }
289 
createTexture(const glw::Functions & gl,const TestConfig & config)290 GLuint createTexture (const glw::Functions& gl, const TestConfig& config)
291 {
292 	GLuint			texture;
293 	vector<deUint8>	data;
294 
295 	createTextureData(data, config);
296 
297 	gl.genTextures(1, &texture);
298 	GLU_EXPECT_NO_ERROR(gl.getError(), "glGenTextures()");
299 	gl.bindTexture(GL_TEXTURE_2D, texture);
300 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture()");
301 	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
302 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri");
303 	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
304 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri");
305 	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
306 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri");
307 	gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
308 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTexParameteri");
309 	gl.texImage2D(GL_TEXTURE_2D, 0, GL_RGBA, config.textureWidth, config.textureWidth, 0, GL_RGBA, GL_UNSIGNED_BYTE, &(data[0]));
310 	GLU_EXPECT_NO_ERROR(gl.getError(), "glTexImage2D()");
311 	gl.bindTexture(GL_TEXTURE_2D, 0);
312 	GLU_EXPECT_NO_ERROR(gl.getError(), "glBindTexture()");
313 
314 	return texture;
315 }
316 
createProgram(const glw::Functions & gl,const TestConfig & config)317 GLuint createProgram (const glw::Functions& gl, const TestConfig& config)
318 {
319 	GLuint	vertexShader	= gl.createShader(GL_VERTEX_SHADER);
320 	GLuint	fragmentShader	= gl.createShader(GL_FRAGMENT_SHADER);
321 
322 	if (config.useTexture)
323 	{
324 		const char* vertexShaderSource =
325 		"attribute mediump vec2 a_coord;\n"
326 		"varying mediump vec2 v_texCoord;\n"
327 		"void main(void)\n"
328 		"{\n"
329 		"\tv_texCoord = 0.5 * a_coord + vec2(0.5);\n"
330 		"\tgl_Position = vec4(a_coord, 0.0, 1.0);\n"
331 		"}\n";
332 
333 		const char* fragmentShaderSource =
334 		"uniform sampler2D u_sampler;\n"
335 		"varying mediump vec2 v_texCoord;\n"
336 		"void main(void)\n"
337 		"{\n"
338 		"\tgl_FragColor = texture2D(u_sampler, v_texCoord);\n"
339 		"}\n";
340 
341 		gl.shaderSource(vertexShader, 1, &vertexShaderSource, NULL);
342 		GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource()");
343 		gl.shaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
344 		GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource()");
345 	}
346 	else
347 	{
348 		const char* vertexShaderSource =
349 		"attribute mediump vec2 a_coord;\n"
350 		"varying mediump vec4 v_color;\n"
351 		"void main(void)\n"
352 		"{\n"
353 		"\tv_color = vec4(0.5 * a_coord + vec2(0.5), 0.5, 1.0);\n"
354 		"\tgl_Position = vec4(a_coord, 0.0, 1.0);\n"
355 		"}\n";
356 
357 		const char* fragmentShaderSource =
358 		"varying mediump vec4 v_color;\n"
359 		"void main(void)\n"
360 		"{\n"
361 		"\tgl_FragColor = v_color;\n"
362 		"}\n";
363 
364 		gl.shaderSource(vertexShader, 1, &vertexShaderSource, NULL);
365 		GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource()");
366 		gl.shaderSource(fragmentShader, 1, &fragmentShaderSource, NULL);
367 		GLU_EXPECT_NO_ERROR(gl.getError(), "glShaderSource()");
368 	}
369 
370 	gl.compileShader(vertexShader);
371 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader()");
372 	gl.compileShader(fragmentShader);
373 	GLU_EXPECT_NO_ERROR(gl.getError(), "glCompileShader()");
374 
375 	{
376 		GLint status;
377 
378 		gl.getShaderiv(vertexShader, GL_COMPILE_STATUS, &status);
379 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv()");
380 
381 		if (!status)
382 		{
383 			string	log;
384 			GLint length;
385 
386 			gl.getShaderiv(vertexShader, GL_INFO_LOG_LENGTH, &length);
387 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv()");
388 			log.resize(length, 0);
389 
390 			gl.getShaderInfoLog(vertexShader, (GLsizei)log.size(), &length, &(log[0]));
391 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderInfoLog()");
392 
393 			throw std::runtime_error(log.c_str());
394 		}
395 	}
396 
397 	{
398 		GLint status;
399 
400 		gl.getShaderiv(fragmentShader, GL_COMPILE_STATUS, &status);
401 		GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv()");
402 
403 		if (!status)
404 		{
405 			string	log;
406 			GLint length;
407 
408 			gl.getShaderiv(fragmentShader, GL_INFO_LOG_LENGTH, &length);
409 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderiv()");
410 			log.resize(length, 0);
411 
412 			gl.getShaderInfoLog(fragmentShader, (GLsizei)log.size(), &length, &(log[0]));
413 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetShaderInfoLog()");
414 
415 			throw std::runtime_error(log.c_str());
416 		}
417 	}
418 
419 	{
420 		GLuint program = gl.createProgram();
421 
422 		gl.attachShader(program, vertexShader);
423 		GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader()");
424 		gl.attachShader(program, fragmentShader);
425 		GLU_EXPECT_NO_ERROR(gl.getError(), "glAttachShader()");
426 
427 		gl.linkProgram(program);
428 		GLU_EXPECT_NO_ERROR(gl.getError(), "glLinkProgram()");
429 
430 		{
431 			GLint status;
432 
433 			gl.getProgramiv(program, GL_LINK_STATUS, &status);
434 			GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramiv()");
435 
436 			if (!status)
437 			{
438 				string	log;
439 				GLsizei	length;
440 
441 				gl.getProgramInfoLog(program, 0, &length, NULL);
442 				GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInfoLog()");
443 				log.resize(length, 0);
444 
445 				gl.getProgramInfoLog(program, (GLsizei)log.size(), &length, &(log[0]));
446 				GLU_EXPECT_NO_ERROR(gl.getError(), "glGetProgramInfoLog()");
447 
448 				throw std::runtime_error(log.c_str());
449 			}
450 		}
451 
452 		gl.deleteShader(vertexShader);
453 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteShader()");
454 		gl.deleteShader(fragmentShader);
455 		GLU_EXPECT_NO_ERROR(gl.getError(), "glDeleteShader()");
456 
457 		return program;
458 	}
459 }
460 
createEGLContext(EglTestContext & testCtx,EGLConfig eglConfig,EGLContext share)461 EGLContext createEGLContext (EglTestContext& testCtx, EGLConfig eglConfig, EGLContext share)
462 {
463 	const EGLint attribList[] = {
464 		EGL_CONTEXT_CLIENT_VERSION, 2,
465 		EGL_NONE
466 	};
467 
468 	TCU_CHECK_EGL_CALL(eglBindAPI(EGL_OPENGL_ES_API));
469 
470 	EGLContext context = eglCreateContext(testCtx.getDisplay().getEGLDisplay(), eglConfig, share, attribList);
471 	TCU_CHECK_EGL_MSG("eglCreateContext()");
472 
473 	return context;
474 }
475 
createEGLSurface(EglTestContext & testCtx,EGLConfig eglConfig,const TestConfig & config)476 EGLSurface createEGLSurface (EglTestContext& testCtx, EGLConfig eglConfig, const TestConfig& config)
477 {
478 	const EGLint attribList[] = {
479 		EGL_WIDTH,	config.surfaceWidth,
480 		EGL_HEIGHT, config.surfaceHeight,
481 		EGL_NONE
482 	};
483 
484 	EGLSurface surface = eglCreatePbufferSurface(testCtx.getDisplay().getEGLDisplay(), eglConfig, attribList);
485 	TCU_CHECK_EGL_MSG("eglCreatePbufferSurface()");
486 
487 	return surface;
488 }
489 
490 } // anonymous
491 
TestContext(EglTestContext & testCtx,EGLConfig eglConfig,const TestConfig & config,bool share,TestContext * parent)492 TestContext::TestContext (EglTestContext& testCtx, EGLConfig eglConfig, const TestConfig& config, bool share, TestContext* parent)
493 	: m_parent				(parent)
494 	, m_testCtx				(testCtx)
495 	, m_config				(config)
496 	, m_eglContext			(EGL_NO_CONTEXT)
497 	, m_eglSurface			(EGL_NO_SURFACE)
498 
499 	, m_eglCreateImageKHR	(NULL)
500 	, m_eglDestroyImageKHR	(NULL)
501 
502 	, m_glEGLImageTargetTexture2DOES			(NULL)
503 
504 	, m_coordBuffer			(0)
505 	, m_indexBuffer			(0)
506 	, m_texture				(0)
507 	, m_program				(0)
508 	, m_eglImage			(EGL_NO_IMAGE_KHR)
509 {
510 	if (m_config.textureType == TestConfig::TEXTURETYPE_IMAGE
511 		|| m_config.textureType == TestConfig::TEXTURETYPE_SHARED_IMAGE
512 		|| m_config.textureType == TestConfig::TEXTURETYPE_SHARED_IMAGE_TEXTURE)
513 	{
514 		if (	!checkExtension(eglQueryString(m_testCtx.getDisplay().getEGLDisplay(), EGL_EXTENSIONS), "EGL_KHR_image_base")
515 			||	!checkExtension(eglQueryString(m_testCtx.getDisplay().getEGLDisplay(), EGL_EXTENSIONS), "EGL_KHR_gl_texture_2D_image"))
516 			throw tcu::NotSupportedError("EGL_KHR_image_base extensions not supported", "", __FILE__, __LINE__);
517 
518 		m_eglCreateImageKHR		= (PFNEGLCREATEIMAGEKHRPROC)eglGetProcAddress("eglCreateImageKHR");
519 		m_eglDestroyImageKHR	= (PFNEGLDESTROYIMAGEKHRPROC)eglGetProcAddress("eglDestroyImageKHR");
520 
521 		TCU_CHECK(m_eglCreateImageKHR);
522 		TCU_CHECK(m_eglDestroyImageKHR);
523 	}
524 
525 	m_eglContext = createEGLContext(m_testCtx, eglConfig, (share && parent ? parent->getEGLContext() : EGL_NO_CONTEXT));
526 	m_eglSurface = createEGLSurface(m_testCtx, eglConfig, config);
527 
528 	TCU_CHECK_EGL_CALL(eglMakeCurrent(m_testCtx.getDisplay().getEGLDisplay(), m_eglSurface, m_eglSurface, m_eglContext));
529 
530 	m_testCtx.getGLFunctions(m_gl, glu::ApiType::es(2,0));
531 
532 	if (m_config.textureType == TestConfig::TEXTURETYPE_IMAGE
533 		|| m_config.textureType == TestConfig::TEXTURETYPE_SHARED_IMAGE
534 		|| m_config.textureType == TestConfig::TEXTURETYPE_SHARED_IMAGE_TEXTURE)
535 	{
536 		if (!checkExtension((const char*)m_gl.getString(GL_EXTENSIONS), "GL_OES_EGL_image"))
537 			throw tcu::NotSupportedError("GL_OES_EGL_image extensions not supported", "", __FILE__, __LINE__);
538 
539 		m_glEGLImageTargetTexture2DOES = (PFNGLEGLIMAGETARGETTEXTURE2DOESPROC)eglGetProcAddress("glEGLImageTargetTexture2DOES");
540 
541 		TCU_CHECK(m_glEGLImageTargetTexture2DOES);
542 	}
543 
544 	if (m_config.useCoordBuffer && (!m_config.sharedCoordBuffer || !parent))
545 		m_coordBuffer = createCoordBuffer(m_gl, m_config);
546 	else if (m_config.useCoordBuffer && m_config.sharedCoordBuffer)
547 		m_coordBuffer = parent->getCoordBuffer();
548 	else
549 		createCoordData(m_coordData, m_config);
550 
551 	if (m_config.useIndexBuffer && (!m_config.sharedIndexBuffer || !parent))
552 		m_indexBuffer = createIndexBuffer(m_gl, m_config);
553 	else if (m_config.useIndexBuffer && m_config.sharedIndexBuffer)
554 		m_indexBuffer = parent->getIndexBuffer();
555 	else if (m_config.useIndices)
556 		createIndexData(m_indexData, m_config);
557 
558 	if (m_config.useTexture)
559 	{
560 		if (m_config.textureType == TestConfig::TEXTURETYPE_TEXTURE)
561 			m_texture = createTexture(m_gl, m_config);
562 		else if (m_config.textureType == TestConfig::TEXTURETYPE_SHARED_TEXTURE)
563 		{
564 			if (parent)
565 				m_texture = parent->getTexture();
566 			else
567 				m_texture = createTexture(m_gl, m_config);
568 		}
569 		else if (m_config.textureType == TestConfig::TEXTURETYPE_IMAGE)
570 		{
571 			m_eglImage	= createEGLImage();
572 			m_texture	= createTextureFromImage(m_eglImage);
573 		}
574 		else if (m_config.textureType == TestConfig::TEXTURETYPE_SHARED_IMAGE)
575 		{
576 			if (parent)
577 				m_eglImage = parent->getEGLImage();
578 			else
579 				m_eglImage = createEGLImage();
580 
581 			m_texture = createTextureFromImage(m_eglImage);
582 		}
583 		else if (m_config.textureType == TestConfig::TEXTURETYPE_SHARED_IMAGE_TEXTURE)
584 		{
585 			if (parent)
586 				m_texture = parent->getTexture();
587 			else
588 			{
589 				m_eglImage	= createEGLImage();
590 				m_texture	= createTextureFromImage(m_eglImage);
591 			}
592 		}
593 	}
594 
595 	if (!m_config.sharedProgram || !parent)
596 		m_program = createProgram(m_gl, m_config);
597 	else if (m_config.sharedProgram)
598 		m_program = parent->getProgram();
599 
600 	m_coordLoc = m_gl.getAttribLocation(m_program, "a_coord");
601 
602 	if (m_config.useTexture)
603 		m_textureLoc = m_gl.getUniformLocation(m_program, "u_sampler");
604 
605 	TCU_CHECK_EGL_CALL(eglMakeCurrent(m_testCtx.getDisplay().getEGLDisplay(), EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
606 }
607 
createEGLImage(void)608 EGLImageKHR TestContext::createEGLImage (void)
609 {
610 	GLuint sourceTexture = createTexture(m_gl, m_config);
611 
612 	try
613 	{
614 		const EGLint attribList[] = {
615 			EGL_GL_TEXTURE_LEVEL_KHR, 0,
616 			EGL_NONE
617 		};
618 
619 		EGLImageKHR image = m_eglCreateImageKHR(m_testCtx.getDisplay().getEGLDisplay(), m_eglContext, EGL_GL_TEXTURE_2D_KHR, (EGLClientBuffer)(deUintptr)sourceTexture, attribList);
620 		TCU_CHECK_EGL_MSG("eglCreateImageKHR()");
621 
622 		m_gl.deleteTextures(1, &sourceTexture);
623 		GLU_EXPECT_NO_ERROR(m_gl.getError(), "eglCreateImageKHR()");
624 
625 		return image;
626 	}
627 	catch (...)
628 	{
629 		m_gl.deleteTextures(1, &sourceTexture);
630 		throw;
631 	}
632 }
633 
createTextureFromImage(EGLImageKHR image)634 GLuint TestContext::createTextureFromImage (EGLImageKHR image)
635 {
636 	GLuint texture = 0;
637 
638 	try
639 	{
640 		m_gl.genTextures(1, &texture);
641 		m_gl.bindTexture(GL_TEXTURE_2D, texture);
642 		m_glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image);
643 		m_gl.bindTexture(GL_TEXTURE_2D, 0);
644 
645 		return texture;
646 	}
647 	catch (...)
648 	{
649 		m_gl.deleteTextures(1, &texture);
650 		throw;
651 	}
652 }
653 
654 
~TestContext(void)655 TestContext::~TestContext (void)
656 {
657 	EGLDisplay display = m_testCtx.getDisplay().getEGLDisplay();
658 
659 	TCU_CHECK_EGL_CALL(eglMakeCurrent(display, m_eglSurface, m_eglSurface, m_eglContext));
660 
661 	if (m_parent == NULL && m_eglImage)
662 		TCU_CHECK_EGL_CALL(m_eglDestroyImageKHR(display, m_eglImage));
663 
664 	TCU_CHECK_EGL_CALL(eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
665 	TCU_CHECK_EGL_CALL(eglDestroyContext(display, m_eglContext));
666 	TCU_CHECK_EGL_CALL(eglDestroySurface(display, m_eglSurface));
667 }
668 
render(void)669 void TestContext::render (void)
670 {
671 	EGLDisplay display = m_testCtx.getDisplay().getEGLDisplay();
672 
673 	eglMakeCurrent(display, m_eglSurface, m_eglSurface, m_eglContext);
674 
675 	for (int frameNdx = 0; frameNdx < m_config.frameCount; frameNdx++)
676 	{
677 		m_gl.clearColor(0.75f, 0.6f, 0.5f, 1.0f);
678 		m_gl.clear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);
679 
680 		for (int callNdx = 0; callNdx < m_config.drawCallCount; callNdx++)
681 		{
682 			m_gl.useProgram(m_program);
683 			m_gl.enableVertexAttribArray(m_coordLoc);
684 
685 			if (m_config.useCoordBuffer)
686 			{
687 				m_gl.bindBuffer(GL_ARRAY_BUFFER, m_coordBuffer);
688 				m_gl.vertexAttribPointer(m_coordLoc, 2, GL_FLOAT, GL_FALSE, 0, 0);
689 				m_gl.bindBuffer(GL_ARRAY_BUFFER, 0);
690 			}
691 			else
692 				m_gl.vertexAttribPointer(m_coordLoc, 2, GL_FLOAT, GL_FALSE, 0, &(m_coordData[0]));
693 
694 			if (m_config.useTexture)
695 			{
696 				m_gl.bindTexture(GL_TEXTURE_2D, m_texture);
697 				m_gl.uniform1i(m_textureLoc, 0);
698 			}
699 
700 			if (m_config.useIndices)
701 			{
702 				if (m_config.useIndexBuffer)
703 				{
704 					m_gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_indexBuffer);
705 					m_gl.drawElements(GL_TRIANGLES, m_config.triangleCount, GL_UNSIGNED_SHORT, 0);
706 				}
707 				else
708 					m_gl.drawElements(GL_TRIANGLES, m_config.triangleCount, GL_UNSIGNED_SHORT, &(m_indexData[0]));
709 			}
710 			else
711 				m_gl.drawArrays(GL_TRIANGLES, 0, m_config.triangleCount);
712 
713 
714 			if (m_config.useTexture)
715 				m_gl.bindTexture(GL_TEXTURE_2D, 0);
716 
717 			m_gl.disableVertexAttribArray(m_coordLoc);
718 
719 			m_gl.useProgram(0);
720 		}
721 
722 
723 		eglSwapBuffers(display, m_eglSurface);
724 	}
725 
726 	m_gl.finish();
727 	GLU_EXPECT_NO_ERROR(m_gl.getError(), "glFinish()");
728 	TCU_CHECK_EGL_CALL(eglMakeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
729 }
730 
731 class TestThread : de::Thread
732 {
733 public:
734 					TestThread		(const vector<TestContext*> contexts);
735 					~TestThread		(void);
736 
737 	void			start			(void);
738 	void			join			(void);
739 	void			log				(TestLog& log);
740 
resultOk(void)741 	bool			resultOk		(void) { return m_isOk; }
742 
743 private:
744 	vector<TestContext*>	m_contexts;
745 	bool					m_isOk;
746 	string					m_errorString;
747 
748 	deUint64				m_beginTimeUs;
749 	deUint64				m_endTimeUs;
750 
751 	deUint64				m_joinBeginUs;
752 	deUint64				m_joinEndUs;
753 
754 	deUint64				m_startBeginUs;
755 	deUint64				m_startEndUs;
756 
757 
758 	virtual void	run			(void);
759 
760 	TestThread&		operator=	(const TestThread&);
761 					TestThread	(const TestThread&);
762 };
763 
TestThread(const vector<TestContext * > contexts)764 TestThread::TestThread (const vector<TestContext*> contexts)
765 	: m_contexts		(contexts)
766 	, m_isOk			(false)
767 	, m_errorString		("")
768 	, m_beginTimeUs		(0)
769 	, m_endTimeUs		(0)
770 	, m_joinBeginUs		(0)
771 	, m_joinEndUs		(0)
772 	, m_startBeginUs	(0)
773 	, m_startEndUs		(0)
774 {
775 }
776 
~TestThread(void)777 TestThread::~TestThread (void)
778 {
779 	m_contexts.clear();
780 }
781 
log(TestLog & testLog)782 void TestThread::log (TestLog& testLog)
783 {
784 	if (!m_isOk)
785 		testLog << TestLog::Message << "Thread failed: " << m_errorString << TestLog::EndMessage;
786 }
787 
start(void)788 void TestThread::start (void)
789 {
790 	m_startBeginUs = deGetMicroseconds();
791 	de::Thread::start();
792 	m_startEndUs = deGetMicroseconds();
793 }
794 
join(void)795 void TestThread::join (void)
796 {
797 	m_joinBeginUs = deGetMicroseconds();
798 	de::Thread::join();
799 	m_joinEndUs = deGetMicroseconds();
800 }
801 
run(void)802 void TestThread::run (void)
803 {
804 	try
805 	{
806 		m_beginTimeUs = deGetMicroseconds();
807 
808 		for (int contextNdx = 0; contextNdx < (int)m_contexts.size(); contextNdx++)
809 			m_contexts[contextNdx]->render();
810 
811 		m_isOk		= true;
812 		m_endTimeUs = deGetMicroseconds();
813 	}
814 	catch (const std::runtime_error& error)
815 	{
816 		m_isOk			= false;
817 		m_errorString	= error.what();
818 	}
819 	catch (...)
820 	{
821 		m_isOk			= false;
822 		m_errorString	= "Got unknown exception";
823 	}
824 }
825 
826 class SharedRenderingPerfCase : public TestCase
827 {
828 public:
829 								SharedRenderingPerfCase		(EglTestContext& eglTestCtx, const TestConfig& config, const char* name, const char* description);
830 								~SharedRenderingPerfCase	(void);
831 
832 	void						init						(void);
833 	void						deinit						(void);
834 	IterateResult				iterate						(void);
835 
836 private:
837 	TestConfig					m_config;
838 	const int					m_iterationCount;
839 	vector<TestContext*>		m_contexts;
840 	vector<deUint64>			m_results;
841 
842 	SharedRenderingPerfCase&	operator=					(const SharedRenderingPerfCase&);
843 								SharedRenderingPerfCase		(const SharedRenderingPerfCase&);
844 };
845 
SharedRenderingPerfCase(EglTestContext & eglTestCtx,const TestConfig & config,const char * name,const char * description)846 SharedRenderingPerfCase::SharedRenderingPerfCase (EglTestContext& eglTestCtx, const TestConfig& config, const char* name, const char* description)
847 	: TestCase			(eglTestCtx, tcu::NODETYPE_PERFORMANCE, name, description)
848 	, m_config			(config)
849 	, m_iterationCount	(30)
850 {
851 }
852 
~SharedRenderingPerfCase(void)853 SharedRenderingPerfCase::~SharedRenderingPerfCase (void)
854 {
855 	deinit();
856 }
857 
init(void)858 void SharedRenderingPerfCase::init (void)
859 {
860 	EGLConfig eglConfig;
861 
862 	{
863 		const EGLint	attribList[] = {
864 			EGL_SURFACE_TYPE,		EGL_PBUFFER_BIT,
865 			EGL_RENDERABLE_TYPE,	EGL_OPENGL_ES2_BIT,
866 			EGL_NONE
867 		};
868 
869 		EGLint		configCount = 0;
870 		EGLDisplay	display	= m_eglTestCtx.getDisplay().getEGLDisplay();
871 
872 		TCU_CHECK_EGL_CALL(eglChooseConfig(display, attribList, &eglConfig, 1, &configCount));
873 
874 		TCU_CHECK(configCount != 0);
875 	}
876 
877 	// Create contexts and resources
878 	for (int threadNdx = 0; threadNdx < m_config.threadCount * m_config.perThreadContextCount; threadNdx++)
879 		m_contexts.push_back(new TestContext(m_eglTestCtx, eglConfig, m_config, m_config.sharedContexts, (threadNdx == 0 ? NULL : m_contexts[threadNdx-1])));
880 }
881 
deinit(void)882 void SharedRenderingPerfCase::deinit (void)
883 {
884 	// Destroy resources and contexts
885 	for (int threadNdx = 0; threadNdx < (int)m_contexts.size(); threadNdx++)
886 	{
887 		delete m_contexts[threadNdx];
888 		m_contexts[threadNdx] = NULL;
889 	}
890 
891 	m_contexts.clear();
892 	m_results.clear();
893 }
894 
895 namespace
896 {
897 
createThreads(vector<TestThread * > & threads,int threadCount,int perThreadContextCount,vector<TestContext * > & contexts)898 void createThreads (vector<TestThread*>& threads, int threadCount, int perThreadContextCount, vector<TestContext*>& contexts)
899 {
900 	DE_ASSERT(threadCount * perThreadContextCount == (int)contexts.size());
901 	DE_ASSERT(threads.empty());
902 
903 	vector<TestContext*> threadContexts;
904 
905 	for (int threadNdx = 0; threadNdx < threadCount; threadNdx++)
906 	{
907 		for (int contextNdx = 0; contextNdx < perThreadContextCount; contextNdx++)
908 			threadContexts.push_back(contexts[threadNdx * perThreadContextCount + contextNdx]);
909 
910 		threads.push_back(new TestThread(threadContexts));
911 
912 		threadContexts.clear();
913 	}
914 }
915 
destroyThreads(vector<TestThread * > & threads)916 void destroyThreads (vector<TestThread*>& threads)
917 {
918 	for (int threadNdx = 0; threadNdx < (int)threads.size(); threadNdx++)
919 	{
920 		delete threads[threadNdx];
921 		threads[threadNdx] = NULL;
922 	}
923 
924 	threads.clear();
925 }
926 
startThreads(vector<TestThread * > & threads)927 void startThreads (vector<TestThread*>& threads)
928 {
929 	for (int threadNdx = 0; threadNdx < (int)threads.size(); threadNdx++)
930 		threads[threadNdx]->start();
931 }
932 
joinThreads(vector<TestThread * > & threads)933 void joinThreads (vector<TestThread*>& threads)
934 {
935 	for (int threadNdx = 0; threadNdx < (int)threads.size(); threadNdx++)
936 		threads[threadNdx]->join();
937 }
938 
threadResultsOk(const vector<TestThread * > & threads)939 bool threadResultsOk (const vector<TestThread*>& threads)
940 {
941 	for (int threadNdx = 0; threadNdx < (int)threads.size(); threadNdx++)
942 	{
943 		if (!threads[threadNdx]->resultOk())
944 			return false;
945 	}
946 
947 	return true;
948 }
949 
logAndSetResults(tcu::TestContext & testCtx,const vector<deUint64> & r)950 void logAndSetResults (tcu::TestContext& testCtx, const vector<deUint64>& r)
951 {
952 	TestLog& log		= testCtx.getLog();
953 	vector<deUint64>	resultsUs = r;
954 	deUint64			sum = 0;
955 	deUint64			average;
956 	deUint64			median;
957 	double				deviation;
958 
959 	log << TestLog::SampleList("Result", "Result")
960 		<< TestLog::SampleInfo << TestLog::ValueInfo("Time", "Time", "us", QP_SAMPLE_VALUE_TAG_RESPONSE)
961 		<< TestLog::EndSampleInfo;
962 
963 	for (int resultNdx = 0; resultNdx < (int)resultsUs.size(); resultNdx++)
964 		log << TestLog::Sample << deInt64(resultsUs[resultNdx]) << TestLog::EndSample;
965 
966 	log << TestLog::EndSampleList;
967 
968 	std::sort(resultsUs.begin(), resultsUs.end());
969 
970 	for (int resultNdx = 0; resultNdx < (int)resultsUs.size(); resultNdx++)
971 		sum += resultsUs[resultNdx];
972 
973 	average	= sum / resultsUs.size();
974 	median	= resultsUs[resultsUs.size() / 2];
975 
976 	deviation = 0.0;
977 	for (int resultNdx = 0; resultNdx < (int)resultsUs.size(); resultNdx++)
978 		deviation += (resultsUs[resultNdx] - average) * (resultsUs[resultNdx] - average);
979 
980 	deviation = std::sqrt((double)(deviation/resultsUs.size()));
981 
982 	{
983 		tcu::ScopedLogSection	section(log, "Statistics from results", "Statistics from results");
984 
985 		log << TestLog::Message
986 		<< "Average: "					<< (average/1000.0)											<< "ms\n"
987 		<< "Standart deviation: "		<< (deviation/1000.0)										<< "ms\n"
988 		<< "Standart error of mean: "	<< ((deviation/std::sqrt((double)resultsUs.size()))/1000.0)	<< "ms\n"
989 		<< "Median: "					<< (median/1000.0)											<< "ms\n"
990 		<< TestLog::EndMessage;
991 	}
992 
993 	testCtx.setTestResult(QP_TEST_RESULT_PASS, de::floatToString((float)(average/1000.0), 2).c_str());
994 }
995 
logTestConfig(TestLog & log,const TestConfig & config)996 void logTestConfig (TestLog& log, const TestConfig& config)
997 {
998 	tcu::ScopedLogSection threadSection(log, "Test info", "Test information");
999 
1000 	log << TestLog::Message << "Total triangles rendered: : "							<< config.triangleCount * config.drawCallCount * config.frameCount * config.perThreadContextCount * config.threadCount << TestLog::EndMessage;
1001 	log << TestLog::Message << "Number of threads: "									<< config.threadCount << TestLog::EndMessage;
1002 	log << TestLog::Message << "Number of contexts used to render with each thread: "	<< config.perThreadContextCount << TestLog::EndMessage;
1003 	log << TestLog::Message << "Number of frames rendered with each context: "			<< config.frameCount << TestLog::EndMessage;
1004 	log << TestLog::Message << "Number of draw calls performed by each frame: "			<< config.drawCallCount << TestLog::EndMessage;
1005 	log << TestLog::Message << "Number of triangles rendered by each draw call: "		<< config.triangleCount << TestLog::EndMessage;
1006 
1007 	if (config.sharedContexts)
1008 		log << TestLog::Message << "Shared contexts." << TestLog::EndMessage;
1009 	else
1010 		log << TestLog::Message << "No shared contexts." << TestLog::EndMessage;
1011 
1012 	if (config.useCoordBuffer)
1013 		log << TestLog::Message << (config.sharedCoordBuffer ? "Shared " : "") << "Coordinate buffer" << TestLog::EndMessage;
1014 	else
1015 		log << TestLog::Message << "Coordinates from pointer" << TestLog::EndMessage;
1016 
1017 	if (config.useIndices)
1018 		log << TestLog::Message << "Using glDrawElements with indices from " << (config.sharedIndexBuffer ? "shared " : "") << (config.useIndexBuffer ? "buffer." : "pointer.") << TestLog::EndMessage;
1019 
1020 	if (config.useTexture)
1021 	{
1022 		if (config.textureType == TestConfig::TEXTURETYPE_TEXTURE)
1023 			log << TestLog::Message << "Use texture." << TestLog::EndMessage;
1024 		else if (config.textureType == TestConfig::TEXTURETYPE_SHARED_TEXTURE)
1025 			log << TestLog::Message << "Use shared texture." << TestLog::EndMessage;
1026 		else if (config.textureType == TestConfig::TEXTURETYPE_IMAGE)
1027 			log << TestLog::Message << "Use texture created from EGLImage." << TestLog::EndMessage;
1028 		else if (config.textureType == TestConfig::TEXTURETYPE_SHARED_IMAGE)
1029 			log << TestLog::Message << "Use texture created from shared EGLImage." << TestLog::EndMessage;
1030 		else if (config.textureType == TestConfig::TEXTURETYPE_SHARED_IMAGE_TEXTURE)
1031 			log << TestLog::Message << "Use shared texture created from EGLImage." << TestLog::EndMessage;
1032 		else
1033 			DE_ASSERT(false);
1034 
1035 		log << TestLog::Message << "Texture size: " << config.textureWidth << "x" << config.textureHeight << TestLog::EndMessage;
1036 	}
1037 
1038 	if (config.sharedProgram)
1039 		log << TestLog::Message << "Shared program." << TestLog::EndMessage;
1040 
1041 	log << TestLog::Message << "Surface size: " << config.surfaceWidth << "x" << config.surfaceHeight << TestLog::EndMessage;
1042 }
1043 
1044 } // anonymous
1045 
iterate(void)1046 TestCase::IterateResult SharedRenderingPerfCase::iterate (void)
1047 {
1048 	deUint64			beginTimeUs;
1049 	deUint64			endTimeUs;
1050 	vector<TestThread*>	threads;
1051 
1052 	if (m_results.empty())
1053 		logTestConfig(m_testCtx.getLog(), m_config);
1054 
1055 	createThreads(threads, m_config.threadCount, m_config.perThreadContextCount, m_contexts);
1056 
1057 	beginTimeUs = deGetMicroseconds();
1058 
1059 	startThreads(threads);
1060 	joinThreads(threads);
1061 
1062 	endTimeUs = deGetMicroseconds();
1063 
1064 	if (!threadResultsOk(threads))
1065 	{
1066 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
1067 		return STOP;
1068 	}
1069 
1070 	destroyThreads(threads);
1071 
1072 	m_results.push_back(endTimeUs - beginTimeUs);
1073 
1074 	if ((int)m_results.size() == m_iterationCount)
1075 	{
1076 		logAndSetResults(m_testCtx, m_results);
1077 		return STOP;
1078 	}
1079 	else
1080 		return CONTINUE;
1081 }
1082 
createTestName(int threads,int perThreadContextCount)1083 string createTestName(int threads, int perThreadContextCount)
1084 {
1085 	std::ostringstream stream;
1086 
1087 	stream << threads << (threads == 1 ? "_thread_" : "_threads_") << perThreadContextCount << (perThreadContextCount == 1 ? "_context" : "_contexts");
1088 
1089 	return stream.str();
1090 }
1091 
1092 } // anonymous
1093 
GLES2SharedRenderingPerfTests(EglTestContext & eglTestCtx)1094 GLES2SharedRenderingPerfTests::GLES2SharedRenderingPerfTests (EglTestContext& eglTestCtx)
1095 	: TestCaseGroup(eglTestCtx, "gles2_shared_render", "")
1096 {
1097 }
1098 
init(void)1099 void GLES2SharedRenderingPerfTests::init (void)
1100 {
1101 	TestConfig basicConfig;
1102 
1103 	basicConfig.threadCount					= 1;
1104 	basicConfig.perThreadContextCount		= 1;
1105 
1106 	basicConfig.sharedContexts				= true;
1107 	basicConfig.frameCount					= 10;
1108 	basicConfig.drawCallCount				= 10;
1109 	basicConfig.triangleCount				= 100;
1110 
1111 	basicConfig.useCoordBuffer				= true;
1112 	basicConfig.sharedCoordBuffer			= false;
1113 
1114 	basicConfig.useIndices					= true;
1115 	basicConfig.useIndexBuffer				= true;
1116 	basicConfig.sharedIndexBuffer			= false;
1117 
1118 	basicConfig.useTexture					= true;
1119 	basicConfig.textureType					= TestConfig::TEXTURETYPE_TEXTURE;
1120 
1121 	basicConfig.sharedProgram				= false;
1122 
1123 	basicConfig.textureWidth				= 128;
1124 	basicConfig.textureHeight				= 128;
1125 
1126 	basicConfig.surfaceWidth				= 256;
1127 	basicConfig.surfaceHeight				= 256;
1128 
1129 	const int	threadCounts[]				= { 1, 2, 4 };
1130 	const int	perThreadContextCounts[]	= { 1, 2, 4 };
1131 
1132 	// Add no sharing tests
1133 	{
1134 		TestCaseGroup* sharedNoneGroup = new TestCaseGroup(m_eglTestCtx, "no_shared_context", "Tests without sharing contexts.");
1135 
1136 		for (int threadCountNdx = 0; threadCountNdx < DE_LENGTH_OF_ARRAY(threadCounts); threadCountNdx++)
1137 		{
1138 			int threadCount = threadCounts[threadCountNdx];
1139 
1140 			for (int contextCountNdx = 0; contextCountNdx < DE_LENGTH_OF_ARRAY(perThreadContextCounts); contextCountNdx++)
1141 			{
1142 				int contextCount = perThreadContextCounts[contextCountNdx];
1143 
1144 				if (threadCount * contextCount != 4 && threadCount * contextCount != 1)
1145 					continue;
1146 
1147 				TestConfig config 				= basicConfig;
1148 				config.threadCount				= threadCount;
1149 				config.perThreadContextCount	= contextCount;
1150 				config.sharedContexts			= false;
1151 
1152 				{
1153 					TestConfig smallConfig		= config;
1154 					smallConfig.triangleCount	= 1;
1155 					smallConfig.drawCallCount	= 1000;
1156 					smallConfig.frameCount		= 10;
1157 
1158 					if (threadCount * contextCount == 1)
1159 						smallConfig.frameCount *= 4;
1160 
1161 					sharedNoneGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, smallConfig, (createTestName(threadCount, contextCount) + "_small_call").c_str(), ""));
1162 				}
1163 
1164 				{
1165 					TestConfig bigConfig	= config;
1166 					bigConfig.triangleCount	= 1000;
1167 					bigConfig.drawCallCount	= 1;
1168 					bigConfig.frameCount	= 10;
1169 
1170 					if (threadCount * contextCount == 1)
1171 						bigConfig.frameCount *= 4;
1172 
1173 					sharedNoneGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, bigConfig, (createTestName(threadCount, contextCount) + "_big_call").c_str(), ""));
1174 				}
1175 			}
1176 		}
1177 
1178 		addChild(sharedNoneGroup);
1179 	}
1180 
1181 	// Add no resource sharing tests
1182 	{
1183 		TestCaseGroup* sharedNoneGroup = new TestCaseGroup(m_eglTestCtx, "no_shared_resource", "Tests without shared resources.");
1184 
1185 		for (int threadCountNdx = 0; threadCountNdx < DE_LENGTH_OF_ARRAY(threadCounts); threadCountNdx++)
1186 		{
1187 			int threadCount = threadCounts[threadCountNdx];
1188 
1189 			for (int contextCountNdx = 0; contextCountNdx < DE_LENGTH_OF_ARRAY(perThreadContextCounts); contextCountNdx++)
1190 			{
1191 				int contextCount = perThreadContextCounts[contextCountNdx];
1192 
1193 				if (threadCount * contextCount != 4 && threadCount * contextCount != 1)
1194 					continue;
1195 
1196 				TestConfig config				= basicConfig;
1197 				config.threadCount				= threadCount;
1198 				config.perThreadContextCount	= contextCount;
1199 
1200 				{
1201 					TestConfig smallConfig		= config;
1202 					smallConfig.triangleCount	= 1;
1203 					smallConfig.drawCallCount	= 1000;
1204 					smallConfig.frameCount		= 10;
1205 
1206 					if (threadCount * contextCount == 1)
1207 						smallConfig.frameCount *= 4;
1208 
1209 					sharedNoneGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, smallConfig, (createTestName(threadCount, contextCount) + "_small_call").c_str(), ""));
1210 				}
1211 
1212 				{
1213 					TestConfig bigConfig	= config;
1214 					bigConfig.triangleCount	= 1000;
1215 					bigConfig.drawCallCount	= 1;
1216 					bigConfig.frameCount	= 10;
1217 
1218 					if (threadCount * contextCount == 1)
1219 						bigConfig.frameCount *= 4;
1220 
1221 					sharedNoneGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, bigConfig, (createTestName(threadCount, contextCount) + "_big_call").c_str(), ""));
1222 				}
1223 			}
1224 		}
1225 
1226 		addChild(sharedNoneGroup);
1227 	}
1228 
1229 	// Add shared coord buffer tests
1230 	{
1231 		TestCaseGroup* sharedCoordBufferGroup = new TestCaseGroup(m_eglTestCtx, "shared_coord_buffer", "Shared coordinate bufffer");
1232 
1233 		for (int threadCountNdx = 0; threadCountNdx < DE_LENGTH_OF_ARRAY(threadCounts); threadCountNdx++)
1234 		{
1235 			int threadCount = threadCounts[threadCountNdx];
1236 
1237 			for (int contextCountNdx = 0; contextCountNdx < DE_LENGTH_OF_ARRAY(perThreadContextCounts); contextCountNdx++)
1238 			{
1239 				int contextCount = perThreadContextCounts[contextCountNdx];
1240 
1241 				if (threadCount * contextCount != 4 && threadCount * contextCount != 1)
1242 					continue;
1243 
1244 				TestConfig config				= basicConfig;
1245 				config.sharedCoordBuffer		= true;
1246 				config.threadCount				= threadCount;
1247 				config.perThreadContextCount	= contextCount;
1248 
1249 				{
1250 					TestConfig smallConfig		= config;
1251 					smallConfig.triangleCount	= 1;
1252 					smallConfig.drawCallCount	= 1000;
1253 					smallConfig.frameCount		= 10;
1254 
1255 					if (threadCount * contextCount == 1)
1256 						smallConfig.frameCount *= 4;
1257 
1258 					sharedCoordBufferGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, smallConfig, (createTestName(threadCount, contextCount) + "_small_call").c_str(), ""));
1259 				}
1260 
1261 				{
1262 					TestConfig bigConfig	= config;
1263 					bigConfig.triangleCount	= 1000;
1264 					bigConfig.drawCallCount	= 1;
1265 					bigConfig.frameCount	= 10;
1266 
1267 					if (threadCount * contextCount == 1)
1268 						bigConfig.frameCount *= 4;
1269 
1270 					sharedCoordBufferGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, bigConfig, (createTestName(threadCount, contextCount) + "_big_call").c_str(), ""));
1271 				}
1272 			}
1273 		}
1274 
1275 		addChild(sharedCoordBufferGroup);
1276 	}
1277 
1278 	// Add shared index buffer tests
1279 	{
1280 		TestCaseGroup* sharedIndexBufferGroup = new TestCaseGroup(m_eglTestCtx, "shared_index_buffer", "Shared index bufffer");
1281 
1282 		for (int threadCountNdx = 0; threadCountNdx < DE_LENGTH_OF_ARRAY(threadCounts); threadCountNdx++)
1283 		{
1284 			int threadCount = threadCounts[threadCountNdx];
1285 
1286 			for (int contextCountNdx = 0; contextCountNdx < DE_LENGTH_OF_ARRAY(perThreadContextCounts); contextCountNdx++)
1287 			{
1288 				int contextCount = perThreadContextCounts[contextCountNdx];
1289 
1290 				if (threadCount * contextCount != 4 && threadCount * contextCount != 1)
1291 					continue;
1292 
1293 				TestConfig config				= basicConfig;
1294 				config.sharedIndexBuffer		= true;
1295 				config.threadCount				= threadCount;
1296 				config.perThreadContextCount	= contextCount;
1297 
1298 				{
1299 					TestConfig smallConfig		= config;
1300 					smallConfig.triangleCount	= 1;
1301 					smallConfig.drawCallCount	= 1000;
1302 					smallConfig.frameCount		= 10;
1303 
1304 					if (threadCount * contextCount == 1)
1305 						smallConfig.frameCount *= 4;
1306 
1307 					sharedIndexBufferGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, smallConfig, (createTestName(threadCount, contextCount) + "_small_call").c_str(), ""));
1308 				}
1309 
1310 				{
1311 					TestConfig bigConfig	= config;
1312 					bigConfig.triangleCount	= 1000;
1313 					bigConfig.drawCallCount	= 1;
1314 					bigConfig.frameCount	= 10;
1315 
1316 					if (threadCount * contextCount == 1)
1317 						bigConfig.frameCount *= 4;
1318 
1319 					sharedIndexBufferGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, bigConfig, (createTestName(threadCount, contextCount) + "_big_call").c_str(), ""));
1320 				}
1321 			}
1322 		}
1323 
1324 		addChild(sharedIndexBufferGroup);
1325 	}
1326 
1327 	// Add shared texture tests
1328 	{
1329 		TestCaseGroup* sharedTextureGroup = new TestCaseGroup(m_eglTestCtx, "shared_texture", "Shared texture tests.");
1330 
1331 		for (int threadCountNdx = 0; threadCountNdx < DE_LENGTH_OF_ARRAY(threadCounts); threadCountNdx++)
1332 		{
1333 			int threadCount = threadCounts[threadCountNdx];
1334 
1335 			for (int contextCountNdx = 0; contextCountNdx < DE_LENGTH_OF_ARRAY(perThreadContextCounts); contextCountNdx++)
1336 			{
1337 				int contextCount = perThreadContextCounts[contextCountNdx];
1338 
1339 				if (threadCount * contextCount != 4 && threadCount * contextCount != 1)
1340 					continue;
1341 
1342 				TestConfig config				= basicConfig;
1343 				config.textureType				= TestConfig::TEXTURETYPE_SHARED_TEXTURE;
1344 				config.threadCount				= threadCount;
1345 				config.perThreadContextCount	= contextCount;
1346 
1347 				{
1348 					TestConfig smallConfig		= config;
1349 					smallConfig.triangleCount	= 1;
1350 					smallConfig.drawCallCount	= 1000;
1351 					smallConfig.frameCount		= 10;
1352 
1353 					if (threadCount * contextCount == 1)
1354 						smallConfig.frameCount *= 4;
1355 
1356 					sharedTextureGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, smallConfig, (createTestName(threadCount, contextCount) + "_small_call").c_str(), ""));
1357 				}
1358 
1359 				{
1360 					TestConfig bigConfig	= config;
1361 					bigConfig.triangleCount	= 1000;
1362 					bigConfig.drawCallCount	= 1;
1363 					bigConfig.frameCount	= 10;
1364 
1365 					if (threadCount * contextCount == 1)
1366 						bigConfig.frameCount *= 4;
1367 
1368 					sharedTextureGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, bigConfig, (createTestName(threadCount, contextCount) + "_big_call").c_str(), ""));
1369 				}
1370 			}
1371 		}
1372 
1373 		addChild(sharedTextureGroup);
1374 	}
1375 
1376 	// Add shared program tests
1377 	{
1378 		TestCaseGroup* sharedProgramGroup = new TestCaseGroup(m_eglTestCtx, "shared_program", "Shared program tests.");
1379 
1380 		for (int threadCountNdx = 0; threadCountNdx < DE_LENGTH_OF_ARRAY(threadCounts); threadCountNdx++)
1381 		{
1382 			int threadCount = threadCounts[threadCountNdx];
1383 
1384 			for (int contextCountNdx = 0; contextCountNdx < DE_LENGTH_OF_ARRAY(perThreadContextCounts); contextCountNdx++)
1385 			{
1386 				int contextCount = perThreadContextCounts[contextCountNdx];
1387 
1388 				if (threadCount * contextCount != 4 && threadCount * contextCount != 1)
1389 					continue;
1390 
1391 				TestConfig config				= basicConfig;
1392 				config.sharedProgram			= true;
1393 				config.threadCount				= threadCount;
1394 				config.perThreadContextCount	= contextCount;
1395 
1396 				{
1397 					TestConfig smallConfig		= config;
1398 					smallConfig.triangleCount	= 1;
1399 					smallConfig.drawCallCount	= 1000;
1400 					smallConfig.frameCount		= 10;
1401 
1402 					if (threadCount * contextCount == 1)
1403 						smallConfig.frameCount *= 4;
1404 
1405 					sharedProgramGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, smallConfig, (createTestName(threadCount, contextCount) + "_small_call").c_str(), ""));
1406 				}
1407 
1408 				{
1409 					TestConfig bigConfig	= config;
1410 					bigConfig.triangleCount	= 1000;
1411 					bigConfig.drawCallCount	= 1;
1412 					bigConfig.frameCount	= 10;
1413 
1414 					if (threadCount * contextCount == 1)
1415 						bigConfig.frameCount *= 4;
1416 
1417 					sharedProgramGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, bigConfig, (createTestName(threadCount, contextCount) + "_big_call").c_str(), ""));
1418 				}
1419 			}
1420 		}
1421 
1422 		addChild(sharedProgramGroup);
1423 	}
1424 
1425 	// Add shared all tests
1426 	{
1427 		TestCaseGroup* sharedallGroup = new TestCaseGroup(m_eglTestCtx, "shared_all", "Share all possible resources.");
1428 
1429 		for (int threadCountNdx = 0; threadCountNdx < DE_LENGTH_OF_ARRAY(threadCounts); threadCountNdx++)
1430 		{
1431 			int threadCount = threadCounts[threadCountNdx];
1432 
1433 			for (int contextCountNdx = 0; contextCountNdx < DE_LENGTH_OF_ARRAY(perThreadContextCounts); contextCountNdx++)
1434 			{
1435 				int contextCount = perThreadContextCounts[contextCountNdx];
1436 
1437 				if (threadCount * contextCount != 4 && threadCount * contextCount != 1)
1438 					continue;
1439 
1440 				TestConfig config				= basicConfig;
1441 				config.sharedCoordBuffer		= true;
1442 				config.sharedIndexBuffer		= true;
1443 				config.sharedProgram			= true;
1444 				config.textureType				= TestConfig::TEXTURETYPE_SHARED_TEXTURE;
1445 				config.threadCount				= threadCount;
1446 				config.perThreadContextCount	= contextCount;
1447 
1448 				{
1449 					TestConfig smallConfig		= config;
1450 					smallConfig.triangleCount	= 1;
1451 					smallConfig.drawCallCount	= 1000;
1452 					smallConfig.frameCount		= 10;
1453 
1454 					if (threadCount * contextCount == 1)
1455 						smallConfig.frameCount *= 4;
1456 
1457 					sharedallGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, smallConfig, (createTestName(threadCount, contextCount) + "_small_call").c_str(), ""));
1458 				}
1459 
1460 				{
1461 					TestConfig bigConfig	= config;
1462 					bigConfig.triangleCount	= 1000;
1463 					bigConfig.drawCallCount	= 1;
1464 					bigConfig.frameCount	= 10;
1465 
1466 					if (threadCount * contextCount == 1)
1467 						bigConfig.frameCount *= 4;
1468 
1469 					sharedallGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, bigConfig, (createTestName(threadCount, contextCount) + "_big_call").c_str(), ""));
1470 				}
1471 			}
1472 		}
1473 
1474 		addChild(sharedallGroup);
1475 	}
1476 
1477 	// Add EGLImage tests
1478 	{
1479 		TestCaseGroup* sharedTextureGroup = new TestCaseGroup(m_eglTestCtx, "egl_image", "EGL image tests.");
1480 
1481 		for (int threadCountNdx = 0; threadCountNdx < DE_LENGTH_OF_ARRAY(threadCounts); threadCountNdx++)
1482 		{
1483 			int threadCount = threadCounts[threadCountNdx];
1484 
1485 			for (int contextCountNdx = 0; contextCountNdx < DE_LENGTH_OF_ARRAY(perThreadContextCounts); contextCountNdx++)
1486 			{
1487 				int contextCount = perThreadContextCounts[contextCountNdx];
1488 
1489 				if (threadCount * contextCount != 4 && threadCount * contextCount != 1)
1490 					continue;
1491 
1492 				TestConfig config = basicConfig;
1493 
1494 				config.textureType				= TestConfig::TEXTURETYPE_IMAGE;
1495 				config.threadCount				= threadCount;
1496 				config.perThreadContextCount	= contextCount;
1497 				config.sharedContexts			= false;
1498 
1499 				{
1500 					TestConfig smallConfig		= config;
1501 					smallConfig.triangleCount	= 1;
1502 					smallConfig.drawCallCount	= 1000;
1503 					smallConfig.frameCount		= 10;
1504 
1505 					if (threadCount * contextCount == 1)
1506 						smallConfig.frameCount *= 4;
1507 
1508 					sharedTextureGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, smallConfig, (createTestName(threadCount, contextCount) + "_small_call").c_str(), ""));
1509 				}
1510 
1511 				{
1512 					TestConfig bigConfig	= config;
1513 					bigConfig.triangleCount	= 1000;
1514 					bigConfig.drawCallCount	= 1;
1515 					bigConfig.frameCount	= 10;
1516 
1517 					if (threadCount * contextCount == 1)
1518 						bigConfig.frameCount *= 4;
1519 
1520 					sharedTextureGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, bigConfig, (createTestName(threadCount, contextCount) + "_big_call").c_str(), ""));
1521 				}
1522 			}
1523 		}
1524 
1525 		addChild(sharedTextureGroup);
1526 	}
1527 
1528 	// Add shared EGLImage tests
1529 	{
1530 		TestCaseGroup* sharedTextureGroup = new TestCaseGroup(m_eglTestCtx, "shared_egl_image", "Shared EGLImage tests.");
1531 
1532 		for (int threadCountNdx = 0; threadCountNdx < DE_LENGTH_OF_ARRAY(threadCounts); threadCountNdx++)
1533 		{
1534 			int threadCount = threadCounts[threadCountNdx];
1535 
1536 			for (int contextCountNdx = 0; contextCountNdx < DE_LENGTH_OF_ARRAY(perThreadContextCounts); contextCountNdx++)
1537 			{
1538 				int contextCount = perThreadContextCounts[contextCountNdx];
1539 
1540 				if (threadCount * contextCount != 4 && threadCount * contextCount != 1)
1541 					continue;
1542 
1543 				TestConfig config				= basicConfig;
1544 
1545 				config.textureType				= TestConfig::TEXTURETYPE_SHARED_IMAGE;
1546 				config.threadCount				= threadCount;
1547 				config.perThreadContextCount	= contextCount;
1548 				config.sharedContexts			= false;
1549 
1550 				{
1551 					TestConfig smallConfig		= config;
1552 					smallConfig.triangleCount	= 1;
1553 					smallConfig.drawCallCount	= 1000;
1554 					smallConfig.frameCount		= 10;
1555 
1556 					if (threadCount * contextCount == 1)
1557 						smallConfig.frameCount *= 4;
1558 
1559 					sharedTextureGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, smallConfig, (createTestName(threadCount, contextCount) + "_small_call").c_str(), ""));
1560 				}
1561 
1562 				{
1563 					TestConfig bigConfig	= config;
1564 					bigConfig.triangleCount	= 1000;
1565 					bigConfig.drawCallCount	= 1;
1566 					bigConfig.frameCount	= 10;
1567 
1568 					if (threadCount * contextCount == 1)
1569 						bigConfig.frameCount *= 4;
1570 
1571 					sharedTextureGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, bigConfig, (createTestName(threadCount, contextCount) + "_big_call").c_str(), ""));
1572 				}
1573 			}
1574 		}
1575 
1576 		addChild(sharedTextureGroup);
1577 	}
1578 
1579 	// Shared EGLImage texture test
1580 	{
1581 		TestCaseGroup* sharedTextureGroup = new TestCaseGroup(m_eglTestCtx, "shared_egl_image_texture", "Shared EGLImage texture tests.");
1582 
1583 		for (int threadCountNdx = 0; threadCountNdx < DE_LENGTH_OF_ARRAY(threadCounts); threadCountNdx++)
1584 		{
1585 			int threadCount = threadCounts[threadCountNdx];
1586 
1587 			for (int contextCountNdx = 0; contextCountNdx < DE_LENGTH_OF_ARRAY(perThreadContextCounts); contextCountNdx++)
1588 			{
1589 				int contextCount = perThreadContextCounts[contextCountNdx];
1590 
1591 				if (threadCount * contextCount != 4 && threadCount * contextCount != 1)
1592 					continue;
1593 
1594 				TestConfig config				= basicConfig;
1595 				config.textureType				= TestConfig::TEXTURETYPE_SHARED_IMAGE_TEXTURE;
1596 				config.threadCount				= threadCount;
1597 				config.perThreadContextCount	= contextCount;
1598 
1599 				{
1600 					TestConfig smallConfig		= config;
1601 					smallConfig.triangleCount	= 1;
1602 					smallConfig.drawCallCount	= 1000;
1603 					smallConfig.frameCount		= 10;
1604 
1605 					if (threadCount * contextCount == 1)
1606 						smallConfig.frameCount *= 4;
1607 
1608 					sharedTextureGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, smallConfig, (createTestName(threadCount, contextCount) + "_small_call").c_str(), ""));
1609 				}
1610 
1611 				{
1612 					TestConfig bigConfig	= config;
1613 					bigConfig.triangleCount	= 1000;
1614 					bigConfig.drawCallCount	= 1;
1615 					bigConfig.frameCount	= 10;
1616 
1617 					if (threadCount * contextCount == 1)
1618 						bigConfig.frameCount *= 4;
1619 
1620 					sharedTextureGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, bigConfig, (createTestName(threadCount, contextCount) + "_big_call").c_str(), ""));
1621 				}
1622 			}
1623 		}
1624 
1625 		addChild(sharedTextureGroup);
1626 	}
1627 
1628 }
1629 
1630 } // egl
1631 } // deqp
1632