Home | History | Annotate | Download | only in egl
      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 
    107 	EGLContext			getEGLContext	(void) { return m_eglContext; }
    108 
    109 	GLuint				getCoordBuffer	(void) const { return m_coordBuffer;	}
    110 	GLuint				getIndexBuffer	(void) const { return m_indexBuffer;	}
    111 	GLuint				getTexture		(void) const { return m_texture;		}
    112 	GLuint				getProgram		(void) const { return m_program;		}
    113 	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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    777 TestThread::~TestThread (void)
    778 {
    779 	m_contexts.clear();
    780 }
    781 
    782 void TestThread::log (TestLog& testLog)
    783 {
    784 	if (!m_isOk)
    785 		testLog << TestLog::Message << "Thread failed: " << m_errorString << TestLog::EndMessage;
    786 }
    787 
    788 void TestThread::start (void)
    789 {
    790 	m_startBeginUs = deGetMicroseconds();
    791 	de::Thread::start();
    792 	m_startEndUs = deGetMicroseconds();
    793 }
    794 
    795 void TestThread::join (void)
    796 {
    797 	m_joinBeginUs = deGetMicroseconds();
    798 	de::Thread::join();
    799 	m_joinEndUs = deGetMicroseconds();
    800 }
    801 
    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 
    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 
    853 SharedRenderingPerfCase::~SharedRenderingPerfCase (void)
    854 {
    855 	deinit();
    856 }
    857 
    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 
    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 
    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 
    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 
    927 void startThreads (vector<TestThread*>& threads)
    928 {
    929 	for (int threadNdx = 0; threadNdx < (int)threads.size(); threadNdx++)
    930 		threads[threadNdx]->start();
    931 }
    932 
    933 void joinThreads (vector<TestThread*>& threads)
    934 {
    935 	for (int threadNdx = 0; threadNdx < (int)threads.size(); threadNdx++)
    936 		threads[threadNdx]->join();
    937 }
    938 
    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 
    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 
    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 
   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 
   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 
   1094 GLES2SharedRenderingPerfTests::GLES2SharedRenderingPerfTests (EglTestContext& eglTestCtx)
   1095 	: TestCaseGroup(eglTestCtx, "gles2_shared_render", "")
   1096 {
   1097 }
   1098 
   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