teglMakeCurrentPerfTests.cpp revision d2722f6ec95d6f745a9ee1bfa5f033574b91f235
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	try
281	{
282		window	= windowFactory.createWindow(&m_eglTestCtx.getNativeDisplay(), m_display, m_config, DE_NULL, eglu::WindowParams(width, height, eglu::parseWindowVisibility(m_eglTestCtx.getTestContext().getCommandLine())));
283		surface	= eglu::createWindowSurface(m_eglTestCtx.getNativeDisplay(), *window, m_display, m_config, DE_NULL);
284	}
285	catch (...)
286	{
287		if (surface != EGL_NO_SURFACE)
288			egl.destroySurface(m_display, surface);
289
290		delete window;
291		throw;
292	}
293
294	m_windows.push_back(window);
295	m_surfaces.push_back(surface);
296}
297
298void MakeCurrentPerfCase::createPixmap (void)
299{
300	const Library&						egl				= m_eglTestCtx.getLibrary();
301	const EGLint						width			= 256;
302	const EGLint						height			= 256;
303
304	const eglu::NativePixmapFactory&	pixmapFactory	= eglu::selectNativePixmapFactory(m_eglTestCtx.getNativeDisplayFactory(), m_testCtx.getCommandLine());
305
306	eglu::NativePixmap* 				pixmap			= DE_NULL;
307	EGLSurface							surface			= EGL_NO_SURFACE;
308
309	try
310	{
311		pixmap	= pixmapFactory.createPixmap(&m_eglTestCtx.getNativeDisplay(), m_display, m_config, DE_NULL, width, height);
312		surface	= eglu::createPixmapSurface(m_eglTestCtx.getNativeDisplay(), *pixmap, m_display, m_config, DE_NULL);
313	}
314	catch (...)
315	{
316		if (surface != EGL_NO_SURFACE)
317			egl.destroySurface(m_display, surface);
318
319		delete pixmap;
320		throw;
321	}
322
323	m_pixmaps.push_back(pixmap);
324	m_surfaces.push_back(surface);
325}
326
327void MakeCurrentPerfCase::destroySurfaces (void)
328{
329	const Library&	egl	= m_eglTestCtx.getLibrary();
330
331	if (m_surfaces.size() > 0)
332	{
333		EGLDisplay display = m_display;
334
335		// Destroy surfaces
336		for (vector<EGLSurface>::iterator iter = m_surfaces.begin(); iter != m_surfaces.end(); ++iter)
337		{
338			if (*iter != EGL_NO_SURFACE)
339				EGLU_CHECK_CALL(egl, destroySurface(display, *iter));
340			*iter = EGL_NO_SURFACE;
341		}
342
343		m_surfaces.clear();
344
345		// Destroy pixmaps
346		for (vector<eglu::NativePixmap*>::iterator iter = m_pixmaps.begin(); iter != m_pixmaps.end(); ++iter)
347		{
348			delete *iter;
349			*iter = NULL;
350		}
351
352		m_pixmaps.clear();
353
354		// Destroy windows
355		for (vector<eglu::NativeWindow*>::iterator iter = m_windows.begin(); iter != m_windows.end(); ++iter)
356		{
357			delete *iter;
358			*iter = NULL;
359		}
360
361		m_windows.clear();
362
363		// Clear all surface handles
364		m_surfaces.clear();
365	}
366}
367
368void MakeCurrentPerfCase::createContexts (void)
369{
370	const Library&	egl	= m_eglTestCtx.getLibrary();
371
372	for (int contextNdx = 0; contextNdx < m_spec.contextCount; contextNdx++)
373	{
374		const EGLint attribList[] = {
375			EGL_CONTEXT_CLIENT_VERSION, 2,
376			EGL_NONE
377		};
378
379		EGLU_CHECK_CALL(egl, bindAPI(EGL_OPENGL_ES_API));
380		EGLContext context = egl.createContext(m_display, m_config, EGL_NO_CONTEXT, attribList);
381		EGLU_CHECK_MSG(egl, "eglCreateContext()");
382
383		m_contexts.push_back(context);
384	}
385}
386
387void MakeCurrentPerfCase::destroyContexts (void)
388{
389	const Library&	egl	= m_eglTestCtx.getLibrary();
390	if (m_contexts.size() > 0)
391	{
392		EGLDisplay display = m_display;
393
394		for (vector<EGLContext>::iterator iter = m_contexts.begin(); iter != m_contexts.end(); ++iter)
395		{
396			if (*iter != EGL_NO_CONTEXT)
397				EGLU_CHECK_CALL(egl, destroyContext(display, *iter));
398			*iter = EGL_NO_CONTEXT;
399		}
400
401		m_contexts.clear();
402	}
403}
404
405void MakeCurrentPerfCase::logTestInfo (void)
406{
407	TestLog& log = m_testCtx.getLog();
408
409	{
410		tcu::ScopedLogSection	section(log, "Test Info", "Test case information.");
411
412		log << TestLog::Message << "Context count: "	<< m_contexts.size()											<< TestLog::EndMessage;
413		log << TestLog::Message << "Surfaces count: "	<< m_surfaces.size()											<< TestLog::EndMessage;
414		log << TestLog::Message << "Sample count: "	<< m_spec.sampleCount												<< TestLog::EndMessage;
415		log << TestLog::Message << "Iteration count: "	<< m_spec.iterationCount										<< TestLog::EndMessage;
416		log << TestLog::Message << "Window count: "	<< m_windows.size()													<< TestLog::EndMessage;
417		log << TestLog::Message << "Pixmap count: "	<< m_pixmaps.size()													<< TestLog::EndMessage;
418		log << TestLog::Message << "PBuffer count: "	<< (m_surfaces.size() - m_windows.size() - m_pixmaps.size())	<< TestLog::EndMessage;
419
420		if (m_spec.release)
421			log << TestLog::Message << "Context is released after each use. Both binding and releasing context are included in result time." << TestLog::EndMessage;
422	}
423}
424
425void MakeCurrentPerfCase::logResults (void)
426{
427	TestLog& log = m_testCtx.getLog();
428
429	log << TestLog::SampleList("Result", "Result")
430		<< TestLog::SampleInfo << TestLog::ValueInfo("Time", "Time", "us", QP_SAMPLE_VALUE_TAG_RESPONSE)
431		<< TestLog::EndSampleInfo;
432
433	for (int sampleNdx = 0; sampleNdx < (int)m_samples.size(); sampleNdx++)
434		log << TestLog::Sample << deInt64(m_samples[sampleNdx]) << TestLog::EndSample;
435
436	log << TestLog::EndSampleList;
437
438	// Log stats
439	{
440		deUint64	totalTimeUs				= 0;
441		deUint64	totalIterationCount		= 0;
442
443		float		iterationTimeMeanUs		= 0.0f;
444		float		iterationTimeMedianUs	= 0.0f;
445		float		iterationTimeVarianceUs	= 0.0f;
446		float		iterationTimeSkewnessUs	= 0.0f;
447		float		iterationTimeMinUs		= std::numeric_limits<float>::max();
448		float		iterationTimeMaxUs		= 0.0f;
449
450		std::sort(m_samples.begin(), m_samples.end());
451
452		// Calculate totals
453		for (int sampleNdx = 0; sampleNdx < (int)m_samples.size(); sampleNdx++)
454		{
455			totalTimeUs			+= m_samples[sampleNdx];
456			totalIterationCount	+= m_spec.iterationCount;
457		}
458
459		// Calculate mean and median
460		iterationTimeMeanUs		= ((float)(((double)totalTimeUs) / totalIterationCount));
461		iterationTimeMedianUs	= ((float)(((double)m_samples[m_samples.size() / 2]) / m_spec.iterationCount));
462
463		// Calculate variance
464		for (int sampleNdx = 0; sampleNdx < (int)m_samples.size(); sampleNdx++)
465		{
466			float iterationTimeUs	= (float)(((double)m_samples[sampleNdx]) / m_spec.iterationCount);
467			iterationTimeVarianceUs	+= std::pow(iterationTimeUs - iterationTimeMedianUs, 2.0f);
468		}
469
470		// Calculate min and max
471		for (int sampleNdx = 0; sampleNdx < (int)m_samples.size(); sampleNdx++)
472		{
473			float iterationTimeUs	= (float)(((double)m_samples[sampleNdx]) / m_spec.iterationCount);
474			iterationTimeMinUs		= std::min<float>(iterationTimeMinUs, iterationTimeUs);
475			iterationTimeMaxUs		= std::max<float>(iterationTimeMaxUs, iterationTimeUs);
476		}
477
478		iterationTimeVarianceUs /= m_samples.size();
479
480		// Calculate skewness
481		for (int sampleNdx = 0; sampleNdx < (int)m_samples.size(); sampleNdx++)
482		{
483			float iterationTimeUs	= (float)(((double)m_samples[sampleNdx]) / m_spec.iterationCount);
484			iterationTimeSkewnessUs	= std::pow((iterationTimeUs - iterationTimeMedianUs) / iterationTimeVarianceUs, 2.0f);
485		}
486
487		iterationTimeSkewnessUs /= (float)m_samples.size();
488
489		{
490			tcu::ScopedLogSection	section(log, "Result", "Statistics from results.");
491
492			log << TestLog::Message << "Total time: "	<< totalTimeUs				<< "us" << TestLog::EndMessage;
493			log << TestLog::Message << "Mean: "			<< iterationTimeMeanUs		<< "us" << TestLog::EndMessage;
494			log << TestLog::Message << "Median: "		<< iterationTimeMedianUs	<< "us" << TestLog::EndMessage;
495			log << TestLog::Message << "Variance: "		<< iterationTimeVarianceUs	<< "us" << TestLog::EndMessage;
496			log << TestLog::Message << "Skewness: "		<< iterationTimeSkewnessUs	<< "us" << TestLog::EndMessage;
497			log << TestLog::Message << "Min: "			<< iterationTimeMinUs		<< "us" << TestLog::EndMessage;
498			log << TestLog::Message << "Max: "			<< iterationTimeMaxUs		<< "us" << TestLog::EndMessage;
499		}
500
501		m_testCtx.setTestResult(QP_TEST_RESULT_PASS, de::floatToString((float)(((double)totalTimeUs)/totalIterationCount), 2).c_str());
502	}
503}
504
505TestCase::IterateResult MakeCurrentPerfCase::iterate (void)
506{
507	const Library&	egl	= m_eglTestCtx.getLibrary();
508	if (m_samples.size() == 0)
509		logTestInfo();
510
511	{
512		EGLDisplay	display		= m_display;
513		deUint64	beginTimeUs	= deGetMicroseconds();
514
515		for (int iteration = 0; iteration < m_spec.iterationCount; iteration++)
516		{
517			EGLContext	context = m_contexts[m_rnd.getUint32() % m_contexts.size()];
518			EGLSurface	surface	= m_surfaces[m_rnd.getUint32() % m_surfaces.size()];
519
520			egl.makeCurrent(display, surface, surface, context);
521
522			if (m_spec.release)
523				egl.makeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
524		}
525
526		m_samples.push_back(deGetMicroseconds() - beginTimeUs);
527
528		egl.makeCurrent(display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
529		EGLU_CHECK_MSG(egl, "eglMakeCurrent()");
530	}
531
532	if ((int)m_samples.size() == m_spec.sampleCount)
533	{
534		logResults();
535		return STOP;
536	}
537	else
538		return CONTINUE;
539}
540
541MakeCurrentPerfTests::MakeCurrentPerfTests (EglTestContext& eglTestCtx)
542	: TestCaseGroup(eglTestCtx, "make_current", "eglMakeCurrent performance tests")
543{
544}
545
546void MakeCurrentPerfTests::init (void)
547{
548	const int iterationCount	= 100;
549	const int sampleCount		= 100;
550
551	// Add simple test group
552	{
553		TestCaseGroup* simple = new TestCaseGroup(m_eglTestCtx, "simple", "Simple eglMakeCurrent performance tests using single context and surface");
554
555		const MakeCurrentPerfCase::SurfaceType types[] = {
556			MakeCurrentPerfCase::SURFACETYPE_PBUFFER,
557			MakeCurrentPerfCase::SURFACETYPE_PIXMAP,
558			MakeCurrentPerfCase::SURFACETYPE_WINDOW
559		};
560
561		for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(types); typeNdx++)
562		{
563			for (int releaseNdx = 0; releaseNdx < 2; releaseNdx++)
564			{
565				MakeCurrentPerfCase::Spec spec;
566
567				spec.surfaceTypes	= types[typeNdx];
568				spec.contextCount	= 1;
569				spec.surfaceCount	= 1;
570				spec.release		= (releaseNdx == 1);
571				spec.iterationCount	= iterationCount;
572				spec.sampleCount	= sampleCount;
573
574				simple->addChild(new MakeCurrentPerfCase(m_eglTestCtx, spec, spec.toName().c_str(), spec.toDescription().c_str()));
575			}
576		}
577
578		addChild(simple);
579	}
580
581	// Add multi context test group
582	{
583		TestCaseGroup* multiContext = new TestCaseGroup(m_eglTestCtx, "multi_context", "eglMakeCurrent performance tests using multiple contexts and single surface");
584
585		const MakeCurrentPerfCase::SurfaceType types[] = {
586			MakeCurrentPerfCase::SURFACETYPE_PBUFFER,
587			MakeCurrentPerfCase::SURFACETYPE_PIXMAP,
588			MakeCurrentPerfCase::SURFACETYPE_WINDOW
589		};
590
591		const int contextCounts[] = {
592			10, 100
593		};
594
595		for (int contextCountNdx = 0; contextCountNdx < DE_LENGTH_OF_ARRAY(contextCounts); contextCountNdx++)
596		{
597			for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(types); typeNdx++)
598			{
599				for (int releaseNdx = 0; releaseNdx < 2; releaseNdx++)
600				{
601					MakeCurrentPerfCase::Spec spec;
602
603					spec.surfaceTypes	= types[typeNdx];
604					spec.contextCount	= contextCounts[contextCountNdx];
605					spec.surfaceCount	= 1;
606					spec.release		= (releaseNdx == 1);
607					spec.iterationCount	= iterationCount;
608					spec.sampleCount	= sampleCount;
609
610					multiContext->addChild(new MakeCurrentPerfCase(m_eglTestCtx, spec, spec.toName().c_str(), spec.toDescription().c_str()));
611				}
612			}
613		}
614
615		addChild(multiContext);
616	}
617
618	// Add multi surface test group
619	{
620		TestCaseGroup* multiSurface = new TestCaseGroup(m_eglTestCtx, "multi_surface", "eglMakeCurrent performance tests using single context and multiple surfaces");
621
622		const MakeCurrentPerfCase::SurfaceType types[] = {
623			MakeCurrentPerfCase::SURFACETYPE_PBUFFER,
624			MakeCurrentPerfCase::SURFACETYPE_PIXMAP,
625			MakeCurrentPerfCase::SURFACETYPE_WINDOW,
626
627			(MakeCurrentPerfCase::SurfaceType)(MakeCurrentPerfCase::SURFACETYPE_PBUFFER	|MakeCurrentPerfCase::SURFACETYPE_PIXMAP),
628			(MakeCurrentPerfCase::SurfaceType)(MakeCurrentPerfCase::SURFACETYPE_PBUFFER	|MakeCurrentPerfCase::SURFACETYPE_WINDOW),
629			(MakeCurrentPerfCase::SurfaceType)(MakeCurrentPerfCase::SURFACETYPE_PIXMAP	|MakeCurrentPerfCase::SURFACETYPE_WINDOW),
630
631			(MakeCurrentPerfCase::SurfaceType)(MakeCurrentPerfCase::SURFACETYPE_PBUFFER|MakeCurrentPerfCase::SURFACETYPE_PIXMAP|MakeCurrentPerfCase::SURFACETYPE_WINDOW)
632		};
633
634		const int surfaceCounts[] = {
635			10, 100
636		};
637
638		for (int surfaceCountNdx = 0; surfaceCountNdx < DE_LENGTH_OF_ARRAY(surfaceCounts); surfaceCountNdx++)
639		{
640			for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(types); typeNdx++)
641			{
642				for (int releaseNdx = 0; releaseNdx < 2; releaseNdx++)
643				{
644					MakeCurrentPerfCase::Spec spec;
645
646					spec.surfaceTypes	= types[typeNdx];
647					spec.surfaceCount	= surfaceCounts[surfaceCountNdx];
648					spec.contextCount	= 1;
649					spec.release		= (releaseNdx == 1);
650					spec.iterationCount	= iterationCount;
651					spec.sampleCount	= sampleCount;
652
653					multiSurface->addChild(new MakeCurrentPerfCase(m_eglTestCtx, spec, spec.toName().c_str(), spec.toDescription().c_str()));
654				}
655			}
656		}
657
658		addChild(multiSurface);
659	}
660
661	// Add Complex? test group
662	{
663		TestCaseGroup* multi = new TestCaseGroup(m_eglTestCtx, "complex", "eglMakeCurrent performance tests using multiple contexts and multiple surfaces");
664
665		const MakeCurrentPerfCase::SurfaceType types[] = {
666			MakeCurrentPerfCase::SURFACETYPE_PBUFFER,
667			MakeCurrentPerfCase::SURFACETYPE_PIXMAP,
668			MakeCurrentPerfCase::SURFACETYPE_WINDOW,
669
670			(MakeCurrentPerfCase::SurfaceType)(MakeCurrentPerfCase::SURFACETYPE_PBUFFER	|MakeCurrentPerfCase::SURFACETYPE_PIXMAP),
671			(MakeCurrentPerfCase::SurfaceType)(MakeCurrentPerfCase::SURFACETYPE_PBUFFER	|MakeCurrentPerfCase::SURFACETYPE_WINDOW),
672			(MakeCurrentPerfCase::SurfaceType)(MakeCurrentPerfCase::SURFACETYPE_PIXMAP	|MakeCurrentPerfCase::SURFACETYPE_WINDOW),
673
674			(MakeCurrentPerfCase::SurfaceType)(MakeCurrentPerfCase::SURFACETYPE_PBUFFER|MakeCurrentPerfCase::SURFACETYPE_PIXMAP|MakeCurrentPerfCase::SURFACETYPE_WINDOW)
675		};
676
677		const int surfaceCounts[] = {
678			10, 100
679		};
680
681
682		const int contextCounts[] = {
683			10, 100
684		};
685
686		for (int surfaceCountNdx = 0; surfaceCountNdx < DE_LENGTH_OF_ARRAY(surfaceCounts); surfaceCountNdx++)
687		{
688			for (int contextCountNdx = 0; contextCountNdx < DE_LENGTH_OF_ARRAY(contextCounts); contextCountNdx++)
689			{
690				for (int typeNdx = 0; typeNdx < DE_LENGTH_OF_ARRAY(types); typeNdx++)
691				{
692					for (int releaseNdx = 0; releaseNdx < 2; releaseNdx++)
693					{
694						MakeCurrentPerfCase::Spec spec;
695
696						spec.surfaceTypes	= types[typeNdx];
697						spec.contextCount	= contextCounts[contextCountNdx];
698						spec.surfaceCount	= surfaceCounts[surfaceCountNdx];
699						spec.release		= (releaseNdx == 1);
700						spec.iterationCount	= iterationCount;
701						spec.sampleCount	= sampleCount;
702
703						multi->addChild(new MakeCurrentPerfCase(m_eglTestCtx, spec, spec.toName().c_str(), spec.toDescription().c_str()));
704					}
705				}
706			}
707		}
708
709		addChild(multi);
710	}
711}
712
713} // egl
714} // deqp
715