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 "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 
    109 	EGLContext			getEGLContext	(void) { return m_eglContext; }
    110 
    111 	GLuint				getCoordBuffer	(void) const { return m_coordBuffer;	}
    112 	GLuint				getIndexBuffer	(void) const { return m_indexBuffer;	}
    113 	GLuint				getTexture		(void) const { return m_texture;		}
    114 	GLuint				getProgram		(void) const { return m_program;		}
    115 	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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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);
    721 					~TestThread		(void);
    722 
    723 	void			start			(void);
    724 	void			join			(void);
    725 
    726 	bool			resultOk		(void) { return m_isOk; }
    727 
    728 private:
    729 	vector<TestContext*>	m_contexts;
    730 	bool					m_isOk;
    731 	string					m_errorString;
    732 
    733 	deUint64				m_beginTimeUs;
    734 	deUint64				m_endTimeUs;
    735 
    736 	deUint64				m_joinBeginUs;
    737 	deUint64				m_joinEndUs;
    738 
    739 	deUint64				m_startBeginUs;
    740 	deUint64				m_startEndUs;
    741 
    742 
    743 	virtual void	run			(void);
    744 
    745 	TestThread&		operator=	(const TestThread&);
    746 					TestThread	(const TestThread&);
    747 };
    748 
    749 TestThread::TestThread (const vector<TestContext*> contexts)
    750 	: m_contexts		(contexts)
    751 	, m_isOk			(false)
    752 	, m_errorString		("")
    753 	, m_beginTimeUs		(0)
    754 	, m_endTimeUs		(0)
    755 	, m_joinBeginUs		(0)
    756 	, m_joinEndUs		(0)
    757 	, m_startBeginUs	(0)
    758 	, m_startEndUs		(0)
    759 {
    760 }
    761 
    762 TestThread::~TestThread (void)
    763 {
    764 	m_contexts.clear();
    765 }
    766 
    767 void TestThread::start (void)
    768 {
    769 	m_startBeginUs = deGetMicroseconds();
    770 	de::Thread::start();
    771 	m_startEndUs = deGetMicroseconds();
    772 }
    773 
    774 void TestThread::join (void)
    775 {
    776 	m_joinBeginUs = deGetMicroseconds();
    777 	de::Thread::join();
    778 	m_joinEndUs = deGetMicroseconds();
    779 }
    780 
    781 void TestThread::run (void)
    782 {
    783 	try
    784 	{
    785 		m_beginTimeUs = deGetMicroseconds();
    786 
    787 		for (int contextNdx = 0; contextNdx < (int)m_contexts.size(); contextNdx++)
    788 			m_contexts[contextNdx]->render();
    789 
    790 		m_isOk		= true;
    791 		m_endTimeUs = deGetMicroseconds();
    792 	}
    793 	catch (const std::runtime_error& error)
    794 	{
    795 		m_isOk			= false;
    796 		m_errorString	= error.what();
    797 	}
    798 	catch (...)
    799 	{
    800 		m_isOk			= false;
    801 		m_errorString	= "Got unknown exception";
    802 	}
    803 }
    804 
    805 class SharedRenderingPerfCase : public TestCase
    806 {
    807 public:
    808 								SharedRenderingPerfCase		(EglTestContext& eglTestCtx, const TestConfig& config, const char* name, const char* description);
    809 								~SharedRenderingPerfCase	(void);
    810 
    811 	void						init						(void);
    812 	void						deinit						(void);
    813 	IterateResult				iterate						(void);
    814 
    815 private:
    816 	TestConfig					m_config;
    817 	const int					m_iterationCount;
    818 
    819 	EGLDisplay					m_display;
    820 	vector<TestContext*>		m_contexts;
    821 	vector<deUint64>			m_results;
    822 
    823 	SharedRenderingPerfCase&	operator=					(const SharedRenderingPerfCase&);
    824 								SharedRenderingPerfCase		(const SharedRenderingPerfCase&);
    825 };
    826 
    827 SharedRenderingPerfCase::SharedRenderingPerfCase (EglTestContext& eglTestCtx, const TestConfig& config, const char* name, const char* description)
    828 	: TestCase			(eglTestCtx, tcu::NODETYPE_PERFORMANCE, name, description)
    829 	, m_config			(config)
    830 	, m_iterationCount	(30)
    831 	, m_display			(EGL_NO_DISPLAY)
    832 {
    833 }
    834 
    835 SharedRenderingPerfCase::~SharedRenderingPerfCase (void)
    836 {
    837 	deinit();
    838 }
    839 
    840 void SharedRenderingPerfCase::init (void)
    841 {
    842 	m_display = eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay());
    843 
    844 	{
    845 		const Library&	egl				= m_eglTestCtx.getLibrary();
    846 		const EGLint	attribList[]	=
    847 		{
    848 			EGL_SURFACE_TYPE,		EGL_PBUFFER_BIT,
    849 			EGL_RENDERABLE_TYPE,	EGL_OPENGL_ES2_BIT,
    850 			EGL_NONE
    851 		};
    852 		EGLConfig		eglConfig		= eglu::chooseSingleConfig(egl, m_display, attribList);
    853 
    854 		// Create contexts and resources
    855 		for (int threadNdx = 0; threadNdx < m_config.threadCount * m_config.perThreadContextCount; threadNdx++)
    856 			m_contexts.push_back(new TestContext(m_eglTestCtx, m_display, eglConfig, m_config, m_config.sharedContexts, (threadNdx == 0 ? DE_NULL : m_contexts[threadNdx-1])));
    857 	}
    858 }
    859 
    860 void SharedRenderingPerfCase::deinit (void)
    861 {
    862 	// Destroy resources and contexts
    863 	for (int threadNdx = 0; threadNdx < (int)m_contexts.size(); threadNdx++)
    864 	{
    865 		delete m_contexts[threadNdx];
    866 		m_contexts[threadNdx] = DE_NULL;
    867 	}
    868 
    869 	m_contexts.clear();
    870 	m_results.clear();
    871 
    872 	if (m_display != EGL_NO_DISPLAY)
    873 	{
    874 		m_eglTestCtx.getLibrary().terminate(m_display);
    875 		m_display = EGL_NO_DISPLAY;
    876 	}
    877 }
    878 
    879 namespace
    880 {
    881 
    882 void createThreads (vector<TestThread*>& threads, int threadCount, int perThreadContextCount, vector<TestContext*>& contexts)
    883 {
    884 	DE_ASSERT(threadCount * perThreadContextCount == (int)contexts.size());
    885 	DE_ASSERT(threads.empty());
    886 
    887 	vector<TestContext*> threadContexts;
    888 
    889 	for (int threadNdx = 0; threadNdx < threadCount; threadNdx++)
    890 	{
    891 		for (int contextNdx = 0; contextNdx < perThreadContextCount; contextNdx++)
    892 			threadContexts.push_back(contexts[threadNdx * perThreadContextCount + contextNdx]);
    893 
    894 		threads.push_back(new TestThread(threadContexts));
    895 
    896 		threadContexts.clear();
    897 	}
    898 }
    899 
    900 void destroyThreads (vector<TestThread*>& threads)
    901 {
    902 	for (int threadNdx = 0; threadNdx < (int)threads.size(); threadNdx++)
    903 	{
    904 		delete threads[threadNdx];
    905 		threads[threadNdx] = DE_NULL;
    906 	}
    907 
    908 	threads.clear();
    909 }
    910 
    911 void startThreads (vector<TestThread*>& threads)
    912 {
    913 	for (int threadNdx = 0; threadNdx < (int)threads.size(); threadNdx++)
    914 		threads[threadNdx]->start();
    915 }
    916 
    917 void joinThreads (vector<TestThread*>& threads)
    918 {
    919 	for (int threadNdx = 0; threadNdx < (int)threads.size(); threadNdx++)
    920 		threads[threadNdx]->join();
    921 }
    922 
    923 bool threadResultsOk (const vector<TestThread*>& threads)
    924 {
    925 	for (int threadNdx = 0; threadNdx < (int)threads.size(); threadNdx++)
    926 	{
    927 		if (!threads[threadNdx]->resultOk())
    928 			return false;
    929 	}
    930 
    931 	return true;
    932 }
    933 
    934 void logAndSetResults (tcu::TestContext& testCtx, const vector<deUint64>& r)
    935 {
    936 	TestLog& log		= testCtx.getLog();
    937 	vector<deUint64>	resultsUs = r;
    938 	deUint64			sum = 0;
    939 	deUint64			average;
    940 	deUint64			median;
    941 	double				deviation;
    942 
    943 	log << TestLog::SampleList("Result", "Result")
    944 		<< TestLog::SampleInfo << TestLog::ValueInfo("Time", "Time", "us", QP_SAMPLE_VALUE_TAG_RESPONSE)
    945 		<< TestLog::EndSampleInfo;
    946 
    947 	for (int resultNdx = 0; resultNdx < (int)resultsUs.size(); resultNdx++)
    948 		log << TestLog::Sample << deInt64(resultsUs[resultNdx]) << TestLog::EndSample;
    949 
    950 	log << TestLog::EndSampleList;
    951 
    952 	std::sort(resultsUs.begin(), resultsUs.end());
    953 
    954 	for (int resultNdx = 0; resultNdx < (int)resultsUs.size(); resultNdx++)
    955 		sum += resultsUs[resultNdx];
    956 
    957 	average	= sum / resultsUs.size();
    958 	median	= resultsUs[resultsUs.size() / 2];
    959 
    960 	deviation = 0.0;
    961 	for (int resultNdx = 0; resultNdx < (int)resultsUs.size(); resultNdx++)
    962 		deviation += (double)((resultsUs[resultNdx] - average) * (resultsUs[resultNdx] - average));
    963 
    964 	deviation = std::sqrt(deviation/(double)resultsUs.size());
    965 
    966 	{
    967 		tcu::ScopedLogSection	section(log, "Statistics from results", "Statistics from results");
    968 
    969 		log << TestLog::Message
    970 		<< "Average: "					<< ((double)average/1000.0)											<< "ms\n"
    971 		<< "Standard deviation: "		<< ((double)deviation/1000.0)										<< "ms\n"
    972 		<< "Standard error of mean: "	<< (((double)deviation/std::sqrt((double)resultsUs.size()))/1000.0)	<< "ms\n"
    973 		<< "Median: "					<< ((double)median/1000.0)											<< "ms\n"
    974 		<< TestLog::EndMessage;
    975 	}
    976 
    977 	testCtx.setTestResult(QP_TEST_RESULT_PASS, de::floatToString((float)((double)average/1000.0), 2).c_str());
    978 }
    979 
    980 void logTestConfig (TestLog& log, const TestConfig& config)
    981 {
    982 	tcu::ScopedLogSection threadSection(log, "Test info", "Test information");
    983 
    984 	log << TestLog::Message << "Total triangles rendered: : "							<< config.triangleCount * config.drawCallCount * config.frameCount * config.perThreadContextCount * config.threadCount << TestLog::EndMessage;
    985 	log << TestLog::Message << "Number of threads: "									<< config.threadCount << TestLog::EndMessage;
    986 	log << TestLog::Message << "Number of contexts used to render with each thread: "	<< config.perThreadContextCount << TestLog::EndMessage;
    987 	log << TestLog::Message << "Number of frames rendered with each context: "			<< config.frameCount << TestLog::EndMessage;
    988 	log << TestLog::Message << "Number of draw calls performed by each frame: "			<< config.drawCallCount << TestLog::EndMessage;
    989 	log << TestLog::Message << "Number of triangles rendered by each draw call: "		<< config.triangleCount << TestLog::EndMessage;
    990 
    991 	if (config.sharedContexts)
    992 		log << TestLog::Message << "Shared contexts." << TestLog::EndMessage;
    993 	else
    994 		log << TestLog::Message << "No shared contexts." << TestLog::EndMessage;
    995 
    996 	if (config.useCoordBuffer)
    997 		log << TestLog::Message << (config.sharedCoordBuffer ? "Shared " : "") << "Coordinate buffer" << TestLog::EndMessage;
    998 	else
    999 		log << TestLog::Message << "Coordinates from pointer" << TestLog::EndMessage;
   1000 
   1001 	if (config.useIndices)
   1002 		log << TestLog::Message << "Using glDrawElements with indices from " << (config.sharedIndexBuffer ? "shared " : "") << (config.useIndexBuffer ? "buffer." : "pointer.") << TestLog::EndMessage;
   1003 
   1004 	if (config.useTexture)
   1005 	{
   1006 		if (config.textureType == TestConfig::TEXTURETYPE_TEXTURE)
   1007 			log << TestLog::Message << "Use texture." << TestLog::EndMessage;
   1008 		else if (config.textureType == TestConfig::TEXTURETYPE_SHARED_TEXTURE)
   1009 			log << TestLog::Message << "Use shared texture." << TestLog::EndMessage;
   1010 		else if (config.textureType == TestConfig::TEXTURETYPE_IMAGE)
   1011 			log << TestLog::Message << "Use texture created from EGLImage." << TestLog::EndMessage;
   1012 		else if (config.textureType == TestConfig::TEXTURETYPE_SHARED_IMAGE)
   1013 			log << TestLog::Message << "Use texture created from shared EGLImage." << TestLog::EndMessage;
   1014 		else if (config.textureType == TestConfig::TEXTURETYPE_SHARED_IMAGE_TEXTURE)
   1015 			log << TestLog::Message << "Use shared texture created from EGLImage." << TestLog::EndMessage;
   1016 		else
   1017 			DE_ASSERT(false);
   1018 
   1019 		log << TestLog::Message << "Texture size: " << config.textureWidth << "x" << config.textureHeight << TestLog::EndMessage;
   1020 	}
   1021 
   1022 	if (config.sharedProgram)
   1023 		log << TestLog::Message << "Shared program." << TestLog::EndMessage;
   1024 
   1025 	log << TestLog::Message << "Surface size: " << config.surfaceWidth << "x" << config.surfaceHeight << TestLog::EndMessage;
   1026 }
   1027 
   1028 } // anonymous
   1029 
   1030 TestCase::IterateResult SharedRenderingPerfCase::iterate (void)
   1031 {
   1032 	deUint64			beginTimeUs;
   1033 	deUint64			endTimeUs;
   1034 	vector<TestThread*>	threads;
   1035 
   1036 	if (m_results.empty())
   1037 		logTestConfig(m_testCtx.getLog(), m_config);
   1038 
   1039 	createThreads(threads, m_config.threadCount, m_config.perThreadContextCount, m_contexts);
   1040 
   1041 	beginTimeUs = deGetMicroseconds();
   1042 
   1043 	startThreads(threads);
   1044 	joinThreads(threads);
   1045 
   1046 	endTimeUs = deGetMicroseconds();
   1047 
   1048 	if (!threadResultsOk(threads))
   1049 	{
   1050 		m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
   1051 		return STOP;
   1052 	}
   1053 
   1054 	destroyThreads(threads);
   1055 
   1056 	m_results.push_back(endTimeUs - beginTimeUs);
   1057 
   1058 	if ((int)m_results.size() == m_iterationCount)
   1059 	{
   1060 		logAndSetResults(m_testCtx, m_results);
   1061 		return STOP;
   1062 	}
   1063 	else
   1064 		return CONTINUE;
   1065 }
   1066 
   1067 string createTestName(int threads, int perThreadContextCount)
   1068 {
   1069 	std::ostringstream stream;
   1070 
   1071 	stream << threads << (threads == 1 ? "_thread_" : "_threads_") << perThreadContextCount << (perThreadContextCount == 1 ? "_context" : "_contexts");
   1072 
   1073 	return stream.str();
   1074 }
   1075 
   1076 } // anonymous
   1077 
   1078 GLES2SharedRenderingPerfTests::GLES2SharedRenderingPerfTests (EglTestContext& eglTestCtx)
   1079 	: TestCaseGroup(eglTestCtx, "gles2_shared_render", "")
   1080 {
   1081 }
   1082 
   1083 void GLES2SharedRenderingPerfTests::init (void)
   1084 {
   1085 	TestConfig basicConfig;
   1086 
   1087 	basicConfig.threadCount					= 1;
   1088 	basicConfig.perThreadContextCount		= 1;
   1089 
   1090 	basicConfig.sharedContexts				= true;
   1091 	basicConfig.frameCount					= 10;
   1092 	basicConfig.drawCallCount				= 10;
   1093 	basicConfig.triangleCount				= 100;
   1094 
   1095 	basicConfig.useCoordBuffer				= true;
   1096 	basicConfig.sharedCoordBuffer			= false;
   1097 
   1098 	basicConfig.useIndices					= true;
   1099 	basicConfig.useIndexBuffer				= true;
   1100 	basicConfig.sharedIndexBuffer			= false;
   1101 
   1102 	basicConfig.useTexture					= true;
   1103 	basicConfig.textureType					= TestConfig::TEXTURETYPE_TEXTURE;
   1104 
   1105 	basicConfig.sharedProgram				= false;
   1106 
   1107 	basicConfig.textureWidth				= 128;
   1108 	basicConfig.textureHeight				= 128;
   1109 
   1110 	basicConfig.surfaceWidth				= 256;
   1111 	basicConfig.surfaceHeight				= 256;
   1112 
   1113 	const int	threadCounts[]				= { 1, 2, 4 };
   1114 	const int	perThreadContextCounts[]	= { 1, 2, 4 };
   1115 
   1116 	// Add no sharing tests
   1117 	{
   1118 		TestCaseGroup* sharedNoneGroup = new TestCaseGroup(m_eglTestCtx, "no_shared_context", "Tests without sharing contexts.");
   1119 
   1120 		for (int threadCountNdx = 0; threadCountNdx < DE_LENGTH_OF_ARRAY(threadCounts); threadCountNdx++)
   1121 		{
   1122 			int threadCount = threadCounts[threadCountNdx];
   1123 
   1124 			for (int contextCountNdx = 0; contextCountNdx < DE_LENGTH_OF_ARRAY(perThreadContextCounts); contextCountNdx++)
   1125 			{
   1126 				int contextCount = perThreadContextCounts[contextCountNdx];
   1127 
   1128 				if (threadCount * contextCount != 4 && threadCount * contextCount != 1)
   1129 					continue;
   1130 
   1131 				TestConfig config				= basicConfig;
   1132 				config.threadCount				= threadCount;
   1133 				config.perThreadContextCount	= contextCount;
   1134 				config.sharedContexts			= false;
   1135 
   1136 				{
   1137 					TestConfig smallConfig		= config;
   1138 					smallConfig.triangleCount	= 1;
   1139 					smallConfig.drawCallCount	= 1000;
   1140 					smallConfig.frameCount		= 10;
   1141 
   1142 					if (threadCount * contextCount == 1)
   1143 						smallConfig.frameCount *= 4;
   1144 
   1145 					sharedNoneGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, smallConfig, (createTestName(threadCount, contextCount) + "_small_call").c_str(), ""));
   1146 				}
   1147 
   1148 				{
   1149 					TestConfig bigConfig	= config;
   1150 					bigConfig.triangleCount	= 1000;
   1151 					bigConfig.drawCallCount	= 1;
   1152 					bigConfig.frameCount	= 10;
   1153 
   1154 					if (threadCount * contextCount == 1)
   1155 						bigConfig.frameCount *= 4;
   1156 
   1157 					sharedNoneGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, bigConfig, (createTestName(threadCount, contextCount) + "_big_call").c_str(), ""));
   1158 				}
   1159 			}
   1160 		}
   1161 
   1162 		addChild(sharedNoneGroup);
   1163 	}
   1164 
   1165 	// Add no resource sharing tests
   1166 	{
   1167 		TestCaseGroup* sharedNoneGroup = new TestCaseGroup(m_eglTestCtx, "no_shared_resource", "Tests without shared resources.");
   1168 
   1169 		for (int threadCountNdx = 0; threadCountNdx < DE_LENGTH_OF_ARRAY(threadCounts); threadCountNdx++)
   1170 		{
   1171 			int threadCount = threadCounts[threadCountNdx];
   1172 
   1173 			for (int contextCountNdx = 0; contextCountNdx < DE_LENGTH_OF_ARRAY(perThreadContextCounts); contextCountNdx++)
   1174 			{
   1175 				int contextCount = perThreadContextCounts[contextCountNdx];
   1176 
   1177 				if (threadCount * contextCount != 4 && threadCount * contextCount != 1)
   1178 					continue;
   1179 
   1180 				TestConfig config				= basicConfig;
   1181 				config.threadCount				= threadCount;
   1182 				config.perThreadContextCount	= contextCount;
   1183 
   1184 				{
   1185 					TestConfig smallConfig		= config;
   1186 					smallConfig.triangleCount	= 1;
   1187 					smallConfig.drawCallCount	= 1000;
   1188 					smallConfig.frameCount		= 10;
   1189 
   1190 					if (threadCount * contextCount == 1)
   1191 						smallConfig.frameCount *= 4;
   1192 
   1193 					sharedNoneGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, smallConfig, (createTestName(threadCount, contextCount) + "_small_call").c_str(), ""));
   1194 				}
   1195 
   1196 				{
   1197 					TestConfig bigConfig	= config;
   1198 					bigConfig.triangleCount	= 1000;
   1199 					bigConfig.drawCallCount	= 1;
   1200 					bigConfig.frameCount	= 10;
   1201 
   1202 					if (threadCount * contextCount == 1)
   1203 						bigConfig.frameCount *= 4;
   1204 
   1205 					sharedNoneGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, bigConfig, (createTestName(threadCount, contextCount) + "_big_call").c_str(), ""));
   1206 				}
   1207 			}
   1208 		}
   1209 
   1210 		addChild(sharedNoneGroup);
   1211 	}
   1212 
   1213 	// Add shared coord buffer tests
   1214 	{
   1215 		TestCaseGroup* sharedCoordBufferGroup = new TestCaseGroup(m_eglTestCtx, "shared_coord_buffer", "Shared coordinate bufffer");
   1216 
   1217 		for (int threadCountNdx = 0; threadCountNdx < DE_LENGTH_OF_ARRAY(threadCounts); threadCountNdx++)
   1218 		{
   1219 			int threadCount = threadCounts[threadCountNdx];
   1220 
   1221 			for (int contextCountNdx = 0; contextCountNdx < DE_LENGTH_OF_ARRAY(perThreadContextCounts); contextCountNdx++)
   1222 			{
   1223 				int contextCount = perThreadContextCounts[contextCountNdx];
   1224 
   1225 				if (threadCount * contextCount != 4 && threadCount * contextCount != 1)
   1226 					continue;
   1227 
   1228 				TestConfig config				= basicConfig;
   1229 				config.sharedCoordBuffer		= true;
   1230 				config.threadCount				= threadCount;
   1231 				config.perThreadContextCount	= contextCount;
   1232 
   1233 				{
   1234 					TestConfig smallConfig		= config;
   1235 					smallConfig.triangleCount	= 1;
   1236 					smallConfig.drawCallCount	= 1000;
   1237 					smallConfig.frameCount		= 10;
   1238 
   1239 					if (threadCount * contextCount == 1)
   1240 						smallConfig.frameCount *= 4;
   1241 
   1242 					sharedCoordBufferGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, smallConfig, (createTestName(threadCount, contextCount) + "_small_call").c_str(), ""));
   1243 				}
   1244 
   1245 				{
   1246 					TestConfig bigConfig	= config;
   1247 					bigConfig.triangleCount	= 1000;
   1248 					bigConfig.drawCallCount	= 1;
   1249 					bigConfig.frameCount	= 10;
   1250 
   1251 					if (threadCount * contextCount == 1)
   1252 						bigConfig.frameCount *= 4;
   1253 
   1254 					sharedCoordBufferGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, bigConfig, (createTestName(threadCount, contextCount) + "_big_call").c_str(), ""));
   1255 				}
   1256 			}
   1257 		}
   1258 
   1259 		addChild(sharedCoordBufferGroup);
   1260 	}
   1261 
   1262 	// Add shared index buffer tests
   1263 	{
   1264 		TestCaseGroup* sharedIndexBufferGroup = new TestCaseGroup(m_eglTestCtx, "shared_index_buffer", "Shared index bufffer");
   1265 
   1266 		for (int threadCountNdx = 0; threadCountNdx < DE_LENGTH_OF_ARRAY(threadCounts); threadCountNdx++)
   1267 		{
   1268 			int threadCount = threadCounts[threadCountNdx];
   1269 
   1270 			for (int contextCountNdx = 0; contextCountNdx < DE_LENGTH_OF_ARRAY(perThreadContextCounts); contextCountNdx++)
   1271 			{
   1272 				int contextCount = perThreadContextCounts[contextCountNdx];
   1273 
   1274 				if (threadCount * contextCount != 4 && threadCount * contextCount != 1)
   1275 					continue;
   1276 
   1277 				TestConfig config				= basicConfig;
   1278 				config.sharedIndexBuffer		= true;
   1279 				config.threadCount				= threadCount;
   1280 				config.perThreadContextCount	= contextCount;
   1281 
   1282 				{
   1283 					TestConfig smallConfig		= config;
   1284 					smallConfig.triangleCount	= 1;
   1285 					smallConfig.drawCallCount	= 1000;
   1286 					smallConfig.frameCount		= 10;
   1287 
   1288 					if (threadCount * contextCount == 1)
   1289 						smallConfig.frameCount *= 4;
   1290 
   1291 					sharedIndexBufferGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, smallConfig, (createTestName(threadCount, contextCount) + "_small_call").c_str(), ""));
   1292 				}
   1293 
   1294 				{
   1295 					TestConfig bigConfig	= config;
   1296 					bigConfig.triangleCount	= 1000;
   1297 					bigConfig.drawCallCount	= 1;
   1298 					bigConfig.frameCount	= 10;
   1299 
   1300 					if (threadCount * contextCount == 1)
   1301 						bigConfig.frameCount *= 4;
   1302 
   1303 					sharedIndexBufferGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, bigConfig, (createTestName(threadCount, contextCount) + "_big_call").c_str(), ""));
   1304 				}
   1305 			}
   1306 		}
   1307 
   1308 		addChild(sharedIndexBufferGroup);
   1309 	}
   1310 
   1311 	// Add shared texture tests
   1312 	{
   1313 		TestCaseGroup* sharedTextureGroup = new TestCaseGroup(m_eglTestCtx, "shared_texture", "Shared texture tests.");
   1314 
   1315 		for (int threadCountNdx = 0; threadCountNdx < DE_LENGTH_OF_ARRAY(threadCounts); threadCountNdx++)
   1316 		{
   1317 			int threadCount = threadCounts[threadCountNdx];
   1318 
   1319 			for (int contextCountNdx = 0; contextCountNdx < DE_LENGTH_OF_ARRAY(perThreadContextCounts); contextCountNdx++)
   1320 			{
   1321 				int contextCount = perThreadContextCounts[contextCountNdx];
   1322 
   1323 				if (threadCount * contextCount != 4 && threadCount * contextCount != 1)
   1324 					continue;
   1325 
   1326 				TestConfig config				= basicConfig;
   1327 				config.textureType				= TestConfig::TEXTURETYPE_SHARED_TEXTURE;
   1328 				config.threadCount				= threadCount;
   1329 				config.perThreadContextCount	= contextCount;
   1330 
   1331 				{
   1332 					TestConfig smallConfig		= config;
   1333 					smallConfig.triangleCount	= 1;
   1334 					smallConfig.drawCallCount	= 1000;
   1335 					smallConfig.frameCount		= 10;
   1336 
   1337 					if (threadCount * contextCount == 1)
   1338 						smallConfig.frameCount *= 4;
   1339 
   1340 					sharedTextureGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, smallConfig, (createTestName(threadCount, contextCount) + "_small_call").c_str(), ""));
   1341 				}
   1342 
   1343 				{
   1344 					TestConfig bigConfig	= config;
   1345 					bigConfig.triangleCount	= 1000;
   1346 					bigConfig.drawCallCount	= 1;
   1347 					bigConfig.frameCount	= 10;
   1348 
   1349 					if (threadCount * contextCount == 1)
   1350 						bigConfig.frameCount *= 4;
   1351 
   1352 					sharedTextureGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, bigConfig, (createTestName(threadCount, contextCount) + "_big_call").c_str(), ""));
   1353 				}
   1354 			}
   1355 		}
   1356 
   1357 		addChild(sharedTextureGroup);
   1358 	}
   1359 
   1360 	// Add shared program tests
   1361 	{
   1362 		TestCaseGroup* sharedProgramGroup = new TestCaseGroup(m_eglTestCtx, "shared_program", "Shared program tests.");
   1363 
   1364 		for (int threadCountNdx = 0; threadCountNdx < DE_LENGTH_OF_ARRAY(threadCounts); threadCountNdx++)
   1365 		{
   1366 			int threadCount = threadCounts[threadCountNdx];
   1367 
   1368 			for (int contextCountNdx = 0; contextCountNdx < DE_LENGTH_OF_ARRAY(perThreadContextCounts); contextCountNdx++)
   1369 			{
   1370 				int contextCount = perThreadContextCounts[contextCountNdx];
   1371 
   1372 				if (threadCount * contextCount != 4 && threadCount * contextCount != 1)
   1373 					continue;
   1374 
   1375 				TestConfig config				= basicConfig;
   1376 				config.sharedProgram			= true;
   1377 				config.threadCount				= threadCount;
   1378 				config.perThreadContextCount	= contextCount;
   1379 
   1380 				{
   1381 					TestConfig smallConfig		= config;
   1382 					smallConfig.triangleCount	= 1;
   1383 					smallConfig.drawCallCount	= 1000;
   1384 					smallConfig.frameCount		= 10;
   1385 
   1386 					if (threadCount * contextCount == 1)
   1387 						smallConfig.frameCount *= 4;
   1388 
   1389 					sharedProgramGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, smallConfig, (createTestName(threadCount, contextCount) + "_small_call").c_str(), ""));
   1390 				}
   1391 
   1392 				{
   1393 					TestConfig bigConfig	= config;
   1394 					bigConfig.triangleCount	= 1000;
   1395 					bigConfig.drawCallCount	= 1;
   1396 					bigConfig.frameCount	= 10;
   1397 
   1398 					if (threadCount * contextCount == 1)
   1399 						bigConfig.frameCount *= 4;
   1400 
   1401 					sharedProgramGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, bigConfig, (createTestName(threadCount, contextCount) + "_big_call").c_str(), ""));
   1402 				}
   1403 			}
   1404 		}
   1405 
   1406 		addChild(sharedProgramGroup);
   1407 	}
   1408 
   1409 	// Add shared all tests
   1410 	{
   1411 		TestCaseGroup* sharedallGroup = new TestCaseGroup(m_eglTestCtx, "shared_all", "Share all possible resources.");
   1412 
   1413 		for (int threadCountNdx = 0; threadCountNdx < DE_LENGTH_OF_ARRAY(threadCounts); threadCountNdx++)
   1414 		{
   1415 			int threadCount = threadCounts[threadCountNdx];
   1416 
   1417 			for (int contextCountNdx = 0; contextCountNdx < DE_LENGTH_OF_ARRAY(perThreadContextCounts); contextCountNdx++)
   1418 			{
   1419 				int contextCount = perThreadContextCounts[contextCountNdx];
   1420 
   1421 				if (threadCount * contextCount != 4 && threadCount * contextCount != 1)
   1422 					continue;
   1423 
   1424 				TestConfig config				= basicConfig;
   1425 				config.sharedCoordBuffer		= true;
   1426 				config.sharedIndexBuffer		= true;
   1427 				config.sharedProgram			= true;
   1428 				config.textureType				= TestConfig::TEXTURETYPE_SHARED_TEXTURE;
   1429 				config.threadCount				= threadCount;
   1430 				config.perThreadContextCount	= contextCount;
   1431 
   1432 				{
   1433 					TestConfig smallConfig		= config;
   1434 					smallConfig.triangleCount	= 1;
   1435 					smallConfig.drawCallCount	= 1000;
   1436 					smallConfig.frameCount		= 10;
   1437 
   1438 					if (threadCount * contextCount == 1)
   1439 						smallConfig.frameCount *= 4;
   1440 
   1441 					sharedallGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, smallConfig, (createTestName(threadCount, contextCount) + "_small_call").c_str(), ""));
   1442 				}
   1443 
   1444 				{
   1445 					TestConfig bigConfig	= config;
   1446 					bigConfig.triangleCount	= 1000;
   1447 					bigConfig.drawCallCount	= 1;
   1448 					bigConfig.frameCount	= 10;
   1449 
   1450 					if (threadCount * contextCount == 1)
   1451 						bigConfig.frameCount *= 4;
   1452 
   1453 					sharedallGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, bigConfig, (createTestName(threadCount, contextCount) + "_big_call").c_str(), ""));
   1454 				}
   1455 			}
   1456 		}
   1457 
   1458 		addChild(sharedallGroup);
   1459 	}
   1460 
   1461 	// Add EGLImage tests
   1462 	{
   1463 		TestCaseGroup* sharedTextureGroup = new TestCaseGroup(m_eglTestCtx, "egl_image", "EGL image tests.");
   1464 
   1465 		for (int threadCountNdx = 0; threadCountNdx < DE_LENGTH_OF_ARRAY(threadCounts); threadCountNdx++)
   1466 		{
   1467 			int threadCount = threadCounts[threadCountNdx];
   1468 
   1469 			for (int contextCountNdx = 0; contextCountNdx < DE_LENGTH_OF_ARRAY(perThreadContextCounts); contextCountNdx++)
   1470 			{
   1471 				int contextCount = perThreadContextCounts[contextCountNdx];
   1472 
   1473 				if (threadCount * contextCount != 4 && threadCount * contextCount != 1)
   1474 					continue;
   1475 
   1476 				TestConfig config = basicConfig;
   1477 
   1478 				config.textureType				= TestConfig::TEXTURETYPE_IMAGE;
   1479 				config.threadCount				= threadCount;
   1480 				config.perThreadContextCount	= contextCount;
   1481 				config.sharedContexts			= false;
   1482 
   1483 				{
   1484 					TestConfig smallConfig		= config;
   1485 					smallConfig.triangleCount	= 1;
   1486 					smallConfig.drawCallCount	= 1000;
   1487 					smallConfig.frameCount		= 10;
   1488 
   1489 					if (threadCount * contextCount == 1)
   1490 						smallConfig.frameCount *= 4;
   1491 
   1492 					sharedTextureGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, smallConfig, (createTestName(threadCount, contextCount) + "_small_call").c_str(), ""));
   1493 				}
   1494 
   1495 				{
   1496 					TestConfig bigConfig	= config;
   1497 					bigConfig.triangleCount	= 1000;
   1498 					bigConfig.drawCallCount	= 1;
   1499 					bigConfig.frameCount	= 10;
   1500 
   1501 					if (threadCount * contextCount == 1)
   1502 						bigConfig.frameCount *= 4;
   1503 
   1504 					sharedTextureGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, bigConfig, (createTestName(threadCount, contextCount) + "_big_call").c_str(), ""));
   1505 				}
   1506 			}
   1507 		}
   1508 
   1509 		addChild(sharedTextureGroup);
   1510 	}
   1511 
   1512 	// Add shared EGLImage tests
   1513 	{
   1514 		TestCaseGroup* sharedTextureGroup = new TestCaseGroup(m_eglTestCtx, "shared_egl_image", "Shared EGLImage tests.");
   1515 
   1516 		for (int threadCountNdx = 0; threadCountNdx < DE_LENGTH_OF_ARRAY(threadCounts); threadCountNdx++)
   1517 		{
   1518 			int threadCount = threadCounts[threadCountNdx];
   1519 
   1520 			for (int contextCountNdx = 0; contextCountNdx < DE_LENGTH_OF_ARRAY(perThreadContextCounts); contextCountNdx++)
   1521 			{
   1522 				int contextCount = perThreadContextCounts[contextCountNdx];
   1523 
   1524 				if (threadCount * contextCount != 4 && threadCount * contextCount != 1)
   1525 					continue;
   1526 
   1527 				TestConfig config				= basicConfig;
   1528 
   1529 				config.textureType				= TestConfig::TEXTURETYPE_SHARED_IMAGE;
   1530 				config.threadCount				= threadCount;
   1531 				config.perThreadContextCount	= contextCount;
   1532 				config.sharedContexts			= false;
   1533 
   1534 				{
   1535 					TestConfig smallConfig		= config;
   1536 					smallConfig.triangleCount	= 1;
   1537 					smallConfig.drawCallCount	= 1000;
   1538 					smallConfig.frameCount		= 10;
   1539 
   1540 					if (threadCount * contextCount == 1)
   1541 						smallConfig.frameCount *= 4;
   1542 
   1543 					sharedTextureGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, smallConfig, (createTestName(threadCount, contextCount) + "_small_call").c_str(), ""));
   1544 				}
   1545 
   1546 				{
   1547 					TestConfig bigConfig	= config;
   1548 					bigConfig.triangleCount	= 1000;
   1549 					bigConfig.drawCallCount	= 1;
   1550 					bigConfig.frameCount	= 10;
   1551 
   1552 					if (threadCount * contextCount == 1)
   1553 						bigConfig.frameCount *= 4;
   1554 
   1555 					sharedTextureGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, bigConfig, (createTestName(threadCount, contextCount) + "_big_call").c_str(), ""));
   1556 				}
   1557 			}
   1558 		}
   1559 
   1560 		addChild(sharedTextureGroup);
   1561 	}
   1562 
   1563 	// Shared EGLImage texture test
   1564 	{
   1565 		TestCaseGroup* sharedTextureGroup = new TestCaseGroup(m_eglTestCtx, "shared_egl_image_texture", "Shared EGLImage texture tests.");
   1566 
   1567 		for (int threadCountNdx = 0; threadCountNdx < DE_LENGTH_OF_ARRAY(threadCounts); threadCountNdx++)
   1568 		{
   1569 			int threadCount = threadCounts[threadCountNdx];
   1570 
   1571 			for (int contextCountNdx = 0; contextCountNdx < DE_LENGTH_OF_ARRAY(perThreadContextCounts); contextCountNdx++)
   1572 			{
   1573 				int contextCount = perThreadContextCounts[contextCountNdx];
   1574 
   1575 				if (threadCount * contextCount != 4 && threadCount * contextCount != 1)
   1576 					continue;
   1577 
   1578 				TestConfig config				= basicConfig;
   1579 				config.textureType				= TestConfig::TEXTURETYPE_SHARED_IMAGE_TEXTURE;
   1580 				config.threadCount				= threadCount;
   1581 				config.perThreadContextCount	= contextCount;
   1582 
   1583 				{
   1584 					TestConfig smallConfig		= config;
   1585 					smallConfig.triangleCount	= 1;
   1586 					smallConfig.drawCallCount	= 1000;
   1587 					smallConfig.frameCount		= 10;
   1588 
   1589 					if (threadCount * contextCount == 1)
   1590 						smallConfig.frameCount *= 4;
   1591 
   1592 					sharedTextureGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, smallConfig, (createTestName(threadCount, contextCount) + "_small_call").c_str(), ""));
   1593 				}
   1594 
   1595 				{
   1596 					TestConfig bigConfig	= config;
   1597 					bigConfig.triangleCount	= 1000;
   1598 					bigConfig.drawCallCount	= 1;
   1599 					bigConfig.frameCount	= 10;
   1600 
   1601 					if (threadCount * contextCount == 1)
   1602 						bigConfig.frameCount *= 4;
   1603 
   1604 					sharedTextureGroup->addChild(new SharedRenderingPerfCase(m_eglTestCtx, bigConfig, (createTestName(threadCount, contextCount) + "_big_call").c_str(), ""));
   1605 				}
   1606 			}
   1607 		}
   1608 
   1609 		addChild(sharedTextureGroup);
   1610 	}
   1611 
   1612 }
   1613 
   1614 } // egl
   1615 } // deqp
   1616