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