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