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