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	if (m_display != EGL_NO_DISPLAY)
186	{
187		m_eglTestCtx.getLibrary().terminate(m_display);
188		m_display = EGL_NO_DISPLAY;
189	}
190}
191
192void 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
213void 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
253void 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
272void 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
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	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
330void 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
371void 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
390void 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
408void 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
428void 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) / totalIterationCount));
464		iterationTimeMedianUs	= ((float)(((double)m_samples[m_samples.size() / 2]) / 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 /= 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)/totalIterationCount), 2).c_str());
505	}
506}
507
508TestCase::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
544MakeCurrentPerfTests::MakeCurrentPerfTests (EglTestContext& eglTestCtx)
545	: TestCaseGroup(eglTestCtx, "make_current", "eglMakeCurrent performance tests")
546{
547}
548
549void 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