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