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