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