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 eglMakeCurrent performance tests.
     22  *//*--------------------------------------------------------------------*/
     23 
     24 #include "teglMakeCurrentPerfTests.hpp"
     25 
     26 #include "egluNativeWindow.hpp"
     27 #include "egluNativePixmap.hpp"
     28 #include "egluUtil.hpp"
     29 
     30 #include "eglwLibrary.hpp"
     31 #include "eglwEnums.hpp"
     32 
     33 #include "tcuTestLog.hpp"
     34 
     35 #include "deRandom.hpp"
     36 #include "deStringUtil.hpp"
     37 
     38 #include "deClock.h"
     39 #include "deString.h"
     40 
     41 #include <algorithm>
     42 #include <cmath>
     43 #include <limits>
     44 #include <sstream>
     45 #include <string>
     46 #include <vector>
     47 
     48 using std::ostringstream;
     49 using std::string;
     50 using std::vector;
     51 
     52 using tcu::TestLog;
     53 
     54 using namespace eglw;
     55 
     56 namespace deqp
     57 {
     58 namespace egl
     59 {
     60 
     61 class MakeCurrentPerfCase : public TestCase
     62 {
     63 public:
     64 	enum SurfaceType
     65 	{
     66 		SURFACETYPE_PBUFFER	= (1<<0),
     67 		SURFACETYPE_WINDOW	= (1<<1),
     68 		SURFACETYPE_PIXMAP	= (1<<2)
     69 	};
     70 
     71 	struct Spec
     72 	{
     73 		SurfaceType	surfaceTypes;
     74 		int			contextCount;
     75 		int			surfaceCount;
     76 
     77 		bool		release;
     78 
     79 		int			iterationCount;
     80 		int			sampleCount;
     81 
     82 		string		toName			(void) const;
     83 		string		toDescription	(void) const;
     84 	};
     85 					MakeCurrentPerfCase		(EglTestContext& eglTestCtx, const Spec& spec, const char* name, const char* description);
     86 					~MakeCurrentPerfCase	(void);
     87 
     88 	void			init					(void);
     89 	void			deinit					(void);
     90 	IterateResult	iterate					(void);
     91 
     92 private:
     93 	Spec						m_spec;
     94 	de::Random					m_rnd;
     95 
     96 	EGLDisplay					m_display;
     97 	EGLConfig					m_config;
     98 	vector<EGLContext>			m_contexts;
     99 	vector<EGLSurface>			m_surfaces;
    100 
    101 	vector<eglu::NativeWindow*>	m_windows;
    102 	vector<eglu::NativePixmap*>	m_pixmaps;
    103 
    104 	vector<deUint64>			m_samples;
    105 
    106 	void					chooseConfig	(void);
    107 	void					createSurfaces	(void);
    108 	void					createContexts	(void);
    109 
    110 	void					destroySurfaces	(void);
    111 	void					destroyContexts	(void);
    112 
    113 	void					createPBuffer	(void);
    114 	void					createWindow	(void);
    115 	void					createPixmap	(void);
    116 
    117 	void					logTestInfo		(void);
    118 	void					logResults		(void);
    119 	// Disabled
    120 							MakeCurrentPerfCase	(const MakeCurrentPerfCase&);
    121 	MakeCurrentPerfCase&	operator=			(const MakeCurrentPerfCase&);
    122 };
    123 
    124 string MakeCurrentPerfCase::Spec::toName (void) const
    125 {
    126 	ostringstream name;
    127 
    128 	name << "context";
    129 
    130 	if (contextCount > 1)
    131 		name << "s_" << contextCount;
    132 
    133 	if ((surfaceTypes & SURFACETYPE_WINDOW) != 0)
    134 		name << "_window" << (surfaceCount > 1 ? "s" : "");
    135 
    136 	if ((surfaceTypes & SURFACETYPE_PIXMAP) != 0)
    137 		name << "_pixmap" << (surfaceCount > 1 ? "s" : "");
    138 
    139 	if ((surfaceTypes & SURFACETYPE_PBUFFER) != 0)
    140 		name << "_pbuffer" << (surfaceCount > 1 ? "s" : "");
    141 
    142 	if (surfaceCount > 1)
    143 		name << "_" << surfaceCount;
    144 
    145 	if (release)
    146 		name << "_release";
    147 
    148 	return name.str();
    149 }
    150 
    151 string MakeCurrentPerfCase::Spec::toDescription (void) const
    152 {
    153 	// \todo [mika] Generate descrpition
    154 	return toName();
    155 }
    156 
    157 MakeCurrentPerfCase::MakeCurrentPerfCase (EglTestContext& eglTestCtx, const Spec& spec, const char* name, const char* description)
    158 	: TestCase		(eglTestCtx, tcu::NODETYPE_PERFORMANCE, name, description)
    159 	, m_spec		(spec)
    160 	, m_rnd			(deStringHash(name))
    161 	, m_display		(EGL_NO_DISPLAY)
    162 	, m_config		(DE_NULL)
    163 {
    164 }
    165 
    166 MakeCurrentPerfCase::~MakeCurrentPerfCase (void)
    167 {
    168 	deinit();
    169 }
    170 
    171 void MakeCurrentPerfCase::init (void)
    172 {
    173 	m_display = eglu::getAndInitDisplay(m_eglTestCtx.getNativeDisplay());
    174 
    175 	chooseConfig();
    176 	createContexts();
    177 	createSurfaces();
    178 }
    179 
    180 void MakeCurrentPerfCase::deinit (void)
    181 {
    182 	destroyContexts();
    183 	destroySurfaces();
    184 
    185 	if (m_display != EGL_NO_DISPLAY)
    186 	{
    187 		m_eglTestCtx.getLibrary().terminate(m_display);
    188 		m_display = EGL_NO_DISPLAY;
    189 	}
    190 }
    191 
    192 void MakeCurrentPerfCase::chooseConfig (void)
    193 {
    194 	const EGLint	surfaceBits	= ((m_spec.surfaceTypes & SURFACETYPE_WINDOW) != 0 ? EGL_WINDOW_BIT : 0)
    195 									| ((m_spec.surfaceTypes & SURFACETYPE_PIXMAP) != 0 ? EGL_PIXMAP_BIT : 0)
    196 									| ((m_spec.surfaceTypes & SURFACETYPE_PBUFFER) != 0 ? EGL_PBUFFER_BIT : 0);
    197 
    198 	const EGLint	attribList[] = {
    199 		EGL_SURFACE_TYPE,		surfaceBits,
    200 		EGL_RENDERABLE_TYPE,	EGL_OPENGL_ES2_BIT,
    201 		EGL_NONE
    202 	};
    203 
    204 	const Library&	egl			= m_eglTestCtx.getLibrary();
    205 	EGLint			configCount = 0;
    206 
    207 	EGLU_CHECK_CALL(egl, chooseConfig(m_display, attribList, &m_config, 1, &configCount));
    208 
    209 	if (configCount <= 0)
    210 		throw tcu::NotSupportedError("No compatible configs found");
    211 }
    212 
    213 void MakeCurrentPerfCase::createSurfaces (void)
    214 {
    215 	vector<SurfaceType> types;
    216 
    217 	if ((m_spec.surfaceTypes & SURFACETYPE_WINDOW) != 0)
    218 		types.push_back(SURFACETYPE_WINDOW);
    219 
    220 	if ((m_spec.surfaceTypes & SURFACETYPE_PIXMAP) != 0)
    221 		types.push_back(SURFACETYPE_PIXMAP);
    222 
    223 	if ((m_spec.surfaceTypes & SURFACETYPE_PBUFFER) != 0)
    224 		types.push_back(SURFACETYPE_PBUFFER);
    225 
    226 	DE_ASSERT((int)types.size() <= m_spec.surfaceCount);
    227 
    228 	// Create surfaces
    229 	for (int surfaceNdx = 0; surfaceNdx < m_spec.surfaceCount; surfaceNdx++)
    230 	{
    231 		SurfaceType type = types[surfaceNdx % types.size()];
    232 
    233 		switch (type)
    234 		{
    235 			case SURFACETYPE_PBUFFER:
    236 				createPBuffer();
    237 				break;
    238 
    239 			case SURFACETYPE_WINDOW:
    240 				createWindow();
    241 				break;
    242 
    243 			case SURFACETYPE_PIXMAP:
    244 				createPixmap();
    245 				break;
    246 
    247 			default:
    248 				DE_ASSERT(false);
    249 		};
    250 	}
    251 }
    252 
    253 void MakeCurrentPerfCase::createPBuffer (void)
    254 {
    255 	const Library&	egl		= m_eglTestCtx.getLibrary();
    256 	const EGLint	width	= 256;
    257 	const EGLint	height	= 256;
    258 
    259 	const EGLint attribList[] = {
    260 		EGL_WIDTH,	width,
    261 		EGL_HEIGHT, height,
    262 		EGL_NONE
    263 	};
    264 
    265 	EGLSurface	surface = egl.createPbufferSurface(m_display, m_config, attribList);
    266 
    267 	EGLU_CHECK_MSG(egl, "eglCreatePbufferSurface()");
    268 
    269 	m_surfaces.push_back(surface);
    270 }
    271 
    272 void MakeCurrentPerfCase::createWindow (void)
    273 {
    274 	const Library&						egl				= m_eglTestCtx.getLibrary();
    275 	const EGLint						width			= 256;
    276 	const EGLint						height			= 256;
    277 
    278 	const eglu::NativeWindowFactory&	windowFactory	= eglu::selectNativeWindowFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine());
    279 
    280 	eglu::NativeWindow*					window			= DE_NULL;
    281 	EGLSurface							surface			= EGL_NO_SURFACE;
    282 
    283 	try
    284 	{
    285 		window	= windowFactory.createWindow(&m_eglTestCtx.getNativeDisplay(), m_display, m_config, DE_NULL, eglu::WindowParams(width, height, eglu::parseWindowVisibility(m_eglTestCtx.getTestContext().getCommandLine())));
    286 		surface	= eglu::createWindowSurface(m_eglTestCtx.getNativeDisplay(), *window, m_display, m_config, DE_NULL);
    287 	}
    288 	catch (...)
    289 	{
    290 		if (surface != EGL_NO_SURFACE)
    291 			egl.destroySurface(m_display, surface);
    292 
    293 		delete window;
    294 		throw;
    295 	}
    296 
    297 	m_windows.push_back(window);
    298 	m_surfaces.push_back(surface);
    299 }
    300 
    301 void MakeCurrentPerfCase::createPixmap (void)
    302 {
    303 	const Library&						egl				= m_eglTestCtx.getLibrary();
    304 	const EGLint						width			= 256;
    305 	const EGLint						height			= 256;
    306 
    307 	const eglu::NativePixmapFactory&	pixmapFactory	= eglu::selectNativePixmapFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine());
    308 
    309 	eglu::NativePixmap*					pixmap			= DE_NULL;
    310 	EGLSurface							surface			= EGL_NO_SURFACE;
    311 
    312 	try
    313 	{
    314 		pixmap	= pixmapFactory.createPixmap(&m_eglTestCtx.getNativeDisplay(), m_display, m_config, DE_NULL, width, height);
    315 		surface	= eglu::createPixmapSurface(m_eglTestCtx.getNativeDisplay(), *pixmap, m_display, m_config, DE_NULL);
    316 	}
    317 	catch (...)
    318 	{
    319 		if (surface != EGL_NO_SURFACE)
    320 			egl.destroySurface(m_display, surface);
    321 
    322 		delete pixmap;
    323 		throw;
    324 	}
    325 
    326 	m_pixmaps.push_back(pixmap);
    327 	m_surfaces.push_back(surface);
    328 }
    329 
    330 void MakeCurrentPerfCase::destroySurfaces (void)
    331 {
    332 	const Library&	egl	= m_eglTestCtx.getLibrary();
    333 
    334 	if (m_surfaces.size() > 0)
    335 	{
    336 		EGLDisplay display = m_display;
    337 
    338 		// Destroy surfaces
    339 		for (vector<EGLSurface>::iterator iter = m_surfaces.begin(); iter != m_surfaces.end(); ++iter)
    340 		{
    341 			if (*iter != EGL_NO_SURFACE)
    342 				EGLU_CHECK_CALL(egl, destroySurface(display, *iter));
    343 			*iter = EGL_NO_SURFACE;
    344 		}
    345 
    346 		m_surfaces.clear();
    347 
    348 		// Destroy pixmaps
    349 		for (vector<eglu::NativePixmap*>::iterator iter = m_pixmaps.begin(); iter != m_pixmaps.end(); ++iter)
    350 		{
    351 			delete *iter;
    352 			*iter = NULL;
    353 		}
    354 
    355 		m_pixmaps.clear();
    356 
    357 		// Destroy windows
    358 		for (vector<eglu::NativeWindow*>::iterator iter = m_windows.begin(); iter != m_windows.end(); ++iter)
    359 		{
    360 			delete *iter;
    361 			*iter = NULL;
    362 		}
    363 
    364 		m_windows.clear();
    365 
    366 		// Clear all surface handles
    367 		m_surfaces.clear();
    368 	}
    369 }
    370 
    371 void MakeCurrentPerfCase::createContexts (void)
    372 {
    373 	const Library&	egl	= m_eglTestCtx.getLibrary();
    374 
    375 	for (int contextNdx = 0; contextNdx < m_spec.contextCount; contextNdx++)
    376 	{
    377 		const EGLint attribList[] = {
    378 			EGL_CONTEXT_CLIENT_VERSION, 2,
    379 			EGL_NONE
    380 		};
    381 
    382 		EGLU_CHECK_CALL(egl, bindAPI(EGL_OPENGL_ES_API));
    383 		EGLContext context = egl.createContext(m_display, m_config, EGL_NO_CONTEXT, attribList);
    384 		EGLU_CHECK_MSG(egl, "eglCreateContext()");
    385 
    386 		m_contexts.push_back(context);
    387 	}
    388 }
    389 
    390 void MakeCurrentPerfCase::destroyContexts (void)
    391 {
    392 	const Library&	egl	= m_eglTestCtx.getLibrary();
    393 	if (m_contexts.size() > 0)
    394 	{
    395 		EGLDisplay display = m_display;
    396 
    397 		for (vector<EGLContext>::iterator iter = m_contexts.begin(); iter != m_contexts.end(); ++iter)
    398 		{
    399 			if (*iter != EGL_NO_CONTEXT)
    400 				EGLU_CHECK_CALL(egl, destroyContext(display, *iter));
    401 			*iter = EGL_NO_CONTEXT;
    402 		}
    403 
    404 		m_contexts.clear();
    405 	}
    406 }
    407 
    408 void MakeCurrentPerfCase::logTestInfo (void)
    409 {
    410 	TestLog& log = m_testCtx.getLog();
    411 
    412 	{
    413 		tcu::ScopedLogSection	section(log, "Test Info", "Test case information.");
    414 
    415 		log << TestLog::Message << "Context count: "	<< m_contexts.size()											<< TestLog::EndMessage;
    416 		log << TestLog::Message << "Surfaces count: "	<< m_surfaces.size()											<< TestLog::EndMessage;
    417 		log << TestLog::Message << "Sample count: "	<< m_spec.sampleCount												<< TestLog::EndMessage;
    418 		log << TestLog::Message << "Iteration count: "	<< m_spec.iterationCount										<< TestLog::EndMessage;
    419 		log << TestLog::Message << "Window count: "	<< m_windows.size()													<< TestLog::EndMessage;
    420 		log << TestLog::Message << "Pixmap count: "	<< m_pixmaps.size()													<< TestLog::EndMessage;
    421 		log << TestLog::Message << "PBuffer count: "	<< (m_surfaces.size() - m_windows.size() - m_pixmaps.size())	<< TestLog::EndMessage;
    422 
    423 		if (m_spec.release)
    424 			log << TestLog::Message << "Context is released after each use. Both binding and releasing context are included in result time." << TestLog::EndMessage;
    425 	}
    426 }
    427 
    428 void MakeCurrentPerfCase::logResults (void)
    429 {
    430 	TestLog& log = m_testCtx.getLog();
    431 
    432 	log << TestLog::SampleList("Result", "Result")
    433 		<< TestLog::SampleInfo << TestLog::ValueInfo("Time", "Time", "us", QP_SAMPLE_VALUE_TAG_RESPONSE)
    434 		<< TestLog::EndSampleInfo;
    435 
    436 	for (int sampleNdx = 0; sampleNdx < (int)m_samples.size(); sampleNdx++)
    437 		log << TestLog::Sample << deInt64(m_samples[sampleNdx]) << TestLog::EndSample;
    438 
    439 	log << TestLog::EndSampleList;
    440 
    441 	// Log stats
    442 	{
    443 		deUint64	totalTimeUs				= 0;
    444 		deUint64	totalIterationCount		= 0;
    445 
    446 		float		iterationTimeMeanUs		= 0.0f;
    447 		float		iterationTimeMedianUs	= 0.0f;
    448 		float		iterationTimeVarianceUs	= 0.0f;
    449 		float		iterationTimeSkewnessUs	= 0.0f;
    450 		float		iterationTimeMinUs		= std::numeric_limits<float>::max();
    451 		float		iterationTimeMaxUs		= 0.0f;
    452 
    453 		std::sort(m_samples.begin(), m_samples.end());
    454 
    455 		// Calculate totals
    456 		for (int sampleNdx = 0; sampleNdx < (int)m_samples.size(); sampleNdx++)
    457 		{
    458 			totalTimeUs			+= m_samples[sampleNdx];
    459 			totalIterationCount	+= m_spec.iterationCount;
    460 		}
    461 
    462 		// Calculate mean and median
    463 		iterationTimeMeanUs		= ((float)(((double)totalTimeUs) / (double)totalIterationCount));
    464 		iterationTimeMedianUs	= ((float)(((double)m_samples[m_samples.size() / 2]) / (double)m_spec.iterationCount));
    465 
    466 		// Calculate variance
    467 		for (int sampleNdx = 0; sampleNdx < (int)m_samples.size(); sampleNdx++)
    468 		{
    469 			float iterationTimeUs	= (float)(((double)m_samples[sampleNdx]) / m_spec.iterationCount);
    470 			iterationTimeVarianceUs	+= std::pow(iterationTimeUs - iterationTimeMedianUs, 2.0f);
    471 		}
    472 
    473 		// Calculate min and max
    474 		for (int sampleNdx = 0; sampleNdx < (int)m_samples.size(); sampleNdx++)
    475 		{
    476 			float iterationTimeUs	= (float)(((double)m_samples[sampleNdx]) / m_spec.iterationCount);
    477 			iterationTimeMinUs		= std::min<float>(iterationTimeMinUs, iterationTimeUs);
    478 			iterationTimeMaxUs		= std::max<float>(iterationTimeMaxUs, iterationTimeUs);
    479 		}
    480 
    481 		iterationTimeVarianceUs /= (float)m_samples.size();
    482 
    483 		// Calculate skewness
    484 		for (int sampleNdx = 0; sampleNdx < (int)m_samples.size(); sampleNdx++)
    485 		{
    486 			float iterationTimeUs	= (float)(((double)m_samples[sampleNdx]) / m_spec.iterationCount);
    487 			iterationTimeSkewnessUs	= std::pow((iterationTimeUs - iterationTimeMedianUs) / iterationTimeVarianceUs, 2.0f);
    488 		}
    489 
    490 		iterationTimeSkewnessUs /= (float)m_samples.size();
    491 
    492 		{
    493 			tcu::ScopedLogSection	section(log, "Result", "Statistics from results.");
    494 
    495 			log << TestLog::Message << "Total time: "	<< totalTimeUs				<< "us" << TestLog::EndMessage;
    496 			log << TestLog::Message << "Mean: "			<< iterationTimeMeanUs		<< "us" << TestLog::EndMessage;
    497 			log << TestLog::Message << "Median: "		<< iterationTimeMedianUs	<< "us" << TestLog::EndMessage;
    498 			log << TestLog::Message << "Variance: "		<< iterationTimeVarianceUs	<< "us" << TestLog::EndMessage;
    499 			log << TestLog::Message << "Skewness: "		<< iterationTimeSkewnessUs	<< "us" << TestLog::EndMessage;
    500 			log << TestLog::Message << "Min: "			<< iterationTimeMinUs		<< "us" << TestLog::EndMessage;
    501 			log << TestLog::Message << "Max: "			<< iterationTimeMaxUs		<< "us" << TestLog::EndMessage;
    502 		}
    503 
    504 		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, de::floatToString((float)(((double)totalTimeUs)/(double)totalIterationCount), 2).c_str());
    505 	}
    506 }
    507 
    508 TestCase::IterateResult MakeCurrentPerfCase::iterate (void)
    509 {
    510 	const Library&	egl	= m_eglTestCtx.getLibrary();
    511 	if (m_samples.size() == 0)
    512 		logTestInfo();
    513 
    514 	{
    515 		EGLDisplay	display		= m_display;
    516 		deUint64	beginTimeUs	= deGetMicroseconds();
    517 
    518 		for (int iteration = 0; iteration < m_spec.iterationCount; iteration++)
    519 		{
    520 			EGLContext	context = m_contexts[m_rnd.getUint32() % m_contexts.size()];
    521 			EGLSurface	surface	= m_surfaces[m_rnd.getUint32() % m_surfaces.size()];
    522 
    523 			egl.makeCurrent(display, surface, surface, context);
    524 
    525 			if (m_spec.release)
    526 				egl.makeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
    527 		}
    528 
    529 		m_samples.push_back(deGetMicroseconds() - beginTimeUs);
    530 
    531 		egl.makeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
    532 		EGLU_CHECK_MSG(egl, "eglMakeCurrent()");
    533 	}
    534 
    535 	if ((int)m_samples.size() == m_spec.sampleCount)
    536 	{
    537 		logResults();
    538 		return STOP;
    539 	}
    540 	else
    541 		return CONTINUE;
    542 }
    543 
    544 MakeCurrentPerfTests::MakeCurrentPerfTests (EglTestContext& eglTestCtx)
    545 	: TestCaseGroup(eglTestCtx, "make_current", "eglMakeCurrent performance tests")
    546 {
    547 }
    548 
    549 void MakeCurrentPerfTests::init (void)
    550 {
    551 	const int iterationCount	= 100;
    552 	const int sampleCount		= 100;
    553 
    554 	// Add simple test group
    555 	{
    556 		TestCaseGroup* simple = new TestCaseGroup(m_eglTestCtx, "simple", "Simple eglMakeCurrent performance tests using single context and surface");
    557 
    558 		const MakeCurrentPerfCase::SurfaceType types[] = {
    559 			MakeCurrentPerfCase::SURFACETYPE_PBUFFER,
    560 			MakeCurrentPerfCase::SURFACETYPE_PIXMAP,
    561 			MakeCurrentPerfCase::SURFACETYPE_WINDOW
    562 		};
    563 
    564 		for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(types); typeNdx++)
    565 		{
    566 			for (int releaseNdx = 0; releaseNdx < 2; releaseNdx++)
    567 			{
    568 				MakeCurrentPerfCase::Spec spec;
    569 
    570 				spec.surfaceTypes	= types[typeNdx];
    571 				spec.contextCount	= 1;
    572 				spec.surfaceCount	= 1;
    573 				spec.release		= (releaseNdx == 1);
    574 				spec.iterationCount	= iterationCount;
    575 				spec.sampleCount	= sampleCount;
    576 
    577 				simple->addChild(new MakeCurrentPerfCase(m_eglTestCtx, spec, spec.toName().c_str(), spec.toDescription().c_str()));
    578 			}
    579 		}
    580 
    581 		addChild(simple);
    582 	}
    583 
    584 	// Add multi context test group
    585 	{
    586 		TestCaseGroup* multiContext = new TestCaseGroup(m_eglTestCtx, "multi_context", "eglMakeCurrent performance tests using multiple contexts and single surface");
    587 
    588 		const MakeCurrentPerfCase::SurfaceType types[] = {
    589 			MakeCurrentPerfCase::SURFACETYPE_PBUFFER,
    590 			MakeCurrentPerfCase::SURFACETYPE_PIXMAP,
    591 			MakeCurrentPerfCase::SURFACETYPE_WINDOW
    592 		};
    593 
    594 		const int contextCounts[] = {
    595 			10, 100
    596 		};
    597 
    598 		for (int contextCountNdx = 0; contextCountNdx < DE_LENGTH_OF_ARRAY(contextCounts); contextCountNdx++)
    599 		{
    600 			for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(types); typeNdx++)
    601 			{
    602 				for (int releaseNdx = 0; releaseNdx < 2; releaseNdx++)
    603 				{
    604 					MakeCurrentPerfCase::Spec spec;
    605 
    606 					spec.surfaceTypes	= types[typeNdx];
    607 					spec.contextCount	= contextCounts[contextCountNdx];
    608 					spec.surfaceCount	= 1;
    609 					spec.release		= (releaseNdx == 1);
    610 					spec.iterationCount	= iterationCount;
    611 					spec.sampleCount	= sampleCount;
    612 
    613 					multiContext->addChild(new MakeCurrentPerfCase(m_eglTestCtx, spec, spec.toName().c_str(), spec.toDescription().c_str()));
    614 				}
    615 			}
    616 		}
    617 
    618 		addChild(multiContext);
    619 	}
    620 
    621 	// Add multi surface test group
    622 	{
    623 		TestCaseGroup* multiSurface = new TestCaseGroup(m_eglTestCtx, "multi_surface", "eglMakeCurrent performance tests using single context and multiple surfaces");
    624 
    625 		const MakeCurrentPerfCase::SurfaceType types[] = {
    626 			MakeCurrentPerfCase::SURFACETYPE_PBUFFER,
    627 			MakeCurrentPerfCase::SURFACETYPE_PIXMAP,
    628 			MakeCurrentPerfCase::SURFACETYPE_WINDOW,
    629 
    630 			(MakeCurrentPerfCase::SurfaceType)(MakeCurrentPerfCase::SURFACETYPE_PBUFFER	|MakeCurrentPerfCase::SURFACETYPE_PIXMAP),
    631 			(MakeCurrentPerfCase::SurfaceType)(MakeCurrentPerfCase::SURFACETYPE_PBUFFER	|MakeCurrentPerfCase::SURFACETYPE_WINDOW),
    632 			(MakeCurrentPerfCase::SurfaceType)(MakeCurrentPerfCase::SURFACETYPE_PIXMAP	|MakeCurrentPerfCase::SURFACETYPE_WINDOW),
    633 
    634 			(MakeCurrentPerfCase::SurfaceType)(MakeCurrentPerfCase::SURFACETYPE_PBUFFER|MakeCurrentPerfCase::SURFACETYPE_PIXMAP|MakeCurrentPerfCase::SURFACETYPE_WINDOW)
    635 		};
    636 
    637 		const int surfaceCounts[] = {
    638 			10, 100
    639 		};
    640 
    641 		for (int surfaceCountNdx = 0; surfaceCountNdx < DE_LENGTH_OF_ARRAY(surfaceCounts); surfaceCountNdx++)
    642 		{
    643 			for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(types); typeNdx++)
    644 			{
    645 				for (int releaseNdx = 0; releaseNdx < 2; releaseNdx++)
    646 				{
    647 					MakeCurrentPerfCase::Spec spec;
    648 
    649 					spec.surfaceTypes	= types[typeNdx];
    650 					spec.surfaceCount	= surfaceCounts[surfaceCountNdx];
    651 					spec.contextCount	= 1;
    652 					spec.release		= (releaseNdx == 1);
    653 					spec.iterationCount	= iterationCount;
    654 					spec.sampleCount	= sampleCount;
    655 
    656 					multiSurface->addChild(new MakeCurrentPerfCase(m_eglTestCtx, spec, spec.toName().c_str(), spec.toDescription().c_str()));
    657 				}
    658 			}
    659 		}
    660 
    661 		addChild(multiSurface);
    662 	}
    663 
    664 	// Add Complex? test group
    665 	{
    666 		TestCaseGroup* multi = new TestCaseGroup(m_eglTestCtx, "complex", "eglMakeCurrent performance tests using multiple contexts and multiple surfaces");
    667 
    668 		const MakeCurrentPerfCase::SurfaceType types[] = {
    669 			MakeCurrentPerfCase::SURFACETYPE_PBUFFER,
    670 			MakeCurrentPerfCase::SURFACETYPE_PIXMAP,
    671 			MakeCurrentPerfCase::SURFACETYPE_WINDOW,
    672 
    673 			(MakeCurrentPerfCase::SurfaceType)(MakeCurrentPerfCase::SURFACETYPE_PBUFFER	|MakeCurrentPerfCase::SURFACETYPE_PIXMAP),
    674 			(MakeCurrentPerfCase::SurfaceType)(MakeCurrentPerfCase::SURFACETYPE_PBUFFER	|MakeCurrentPerfCase::SURFACETYPE_WINDOW),
    675 			(MakeCurrentPerfCase::SurfaceType)(MakeCurrentPerfCase::SURFACETYPE_PIXMAP	|MakeCurrentPerfCase::SURFACETYPE_WINDOW),
    676 
    677 			(MakeCurrentPerfCase::SurfaceType)(MakeCurrentPerfCase::SURFACETYPE_PBUFFER|MakeCurrentPerfCase::SURFACETYPE_PIXMAP|MakeCurrentPerfCase::SURFACETYPE_WINDOW)
    678 		};
    679 
    680 		const int surfaceCounts[] = {
    681 			10, 100
    682 		};
    683 
    684 
    685 		const int contextCounts[] = {
    686 			10, 100
    687 		};
    688 
    689 		for (int surfaceCountNdx = 0; surfaceCountNdx < DE_LENGTH_OF_ARRAY(surfaceCounts); surfaceCountNdx++)
    690 		{
    691 			for (int contextCountNdx = 0; contextCountNdx < DE_LENGTH_OF_ARRAY(contextCounts); contextCountNdx++)
    692 			{
    693 				for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(types); typeNdx++)
    694 				{
    695 					for (int releaseNdx = 0; releaseNdx < 2; releaseNdx++)
    696 					{
    697 						MakeCurrentPerfCase::Spec spec;
    698 
    699 						spec.surfaceTypes	= types[typeNdx];
    700 						spec.contextCount	= contextCounts[contextCountNdx];
    701 						spec.surfaceCount	= surfaceCounts[surfaceCountNdx];
    702 						spec.release		= (releaseNdx == 1);
    703 						spec.iterationCount	= iterationCount;
    704 						spec.sampleCount	= sampleCount;
    705 
    706 						multi->addChild(new MakeCurrentPerfCase(m_eglTestCtx, spec, spec.toName().c_str(), spec.toDescription().c_str()));
    707 					}
    708 				}
    709 			}
    710 		}
    711 
    712 		addChild(multi);
    713 	}
    714 }
    715 
    716 } // egl
    717 } // deqp
    718