First public contribution.
1 // Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
14 // This class does performance tests for eglSwapBuffers() and eglSwapBuffersRegionNOK().
15 // The function eglSwapBuffersRegionNOK() is a vendor specific EGL extension and allows users to
16 // perform region based surface updates. The test should show how the performance of the
17 // extension function compares to the default one.
25 #include "egltest_benchmark_swapbuffers.h"
27 #include <VG/openvg.h>
28 #include <test/tprofiler.h>
29 #include <test/egltestcommonutils.h>
30 #include <test/egltestcommoninisettings.h>
32 _LIT(KSwapBuffersSection, "SwapBuffers");
34 // The test draws alternating backgrounds to show the affect
35 // of different swapBuffer functions
36 static const TInt KMaxClearColors = 2;
37 static const VGfloat KClearColors[KMaxClearColors][4] =
39 {0.5f, 0.5f, 0.5f, 1.0f}, // gray
40 {0.1f, 0.2f, 0.4f, 1.0f} // blue
43 // Number of iterations, it defines how often the swapBuffer function is called
44 static const TInt KIterationsToTest = 10;
46 // Maximum number of rectangles for eglSwapBuffersRegionNOK() stress test
47 static const TInt KStressTestMaxNoRects = 100;
48 // Defines the increase of number of rectangles for each iteration
49 static const TInt KStressTestNoRectsStepSize = 5;
50 // Gap between the dirty Rectangles
51 static const TInt KStressTestRectGap = 3;
53 // This test step meassures the performance of eglSwapBuffers()
54 _LIT(KTestStep0528,"GRAPHICS-EGL-0528");
55 // This test step meassures the performance of eglSwapBuffersRegionNOK()
56 _LIT(KTestStep0529,"GRAPHICS-EGL-0529");
57 // This test step meassures the performance of eglSwapBuffersRegionNOK() with a lot of dirty rectangles
58 _LIT(KTestStep0530,"GRAPHICS-EGL-0530");
60 _LIT(KErrEglConfigNotSupported, "EGL config is not supported.");
61 _LIT(KInfoRectangles, "Number of dirty rectangles: %d");
62 _LIT(KWarnStressTestRectCount, "Dirty rectangles for stress test don't fit onto window surface (%d of %d).");
64 _LIT(KEglSwapBuffersRegionNokMsg, "eglSwapBuffersRegionNOK extension is not supported.");
66 CEglTest_Benchmark_SwapBuffers::CEglTest_Benchmark_SwapBuffers()
68 SetTestStepName(KBenchmark_SwapBuffers);
71 CEglTest_Benchmark_SwapBuffers::~CEglTest_Benchmark_SwapBuffers()
77 * It's called by the test framework before the actual test. It's used
78 * to do the preparation for the test. It's important to call the
79 * baseclass implementation also.
81 * @return test framework code
82 * @leave Standard system errors
84 TVerdict CEglTest_Benchmark_SwapBuffers::doTestStepPreambleL()
86 CEglTestStep::doTestStepPreambleL();
87 iProfiler = CTProfiler::NewL(*this);
88 //read parameters from config (WindowSize)
89 CEglTestCommonIniSettings* iniParser = CEglTestCommonIniSettings::NewL();
90 CleanupStack::PushL(iniParser);
91 iWindowSize = iniParser->GetWindowSize(KSwapBuffersSection);
92 if(iWindowSize == TSize(0,0))
94 ERR_PRINTF1(_L("The window size whether is not specified in INI file or is TSize(0,0), the test will not be executed!"));
95 User::Leave(KErrArgument);
97 CleanupStack::PopAndDestroy(iniParser);
99 // Establish the connection to the window server and create
100 // a WindowGroup and a Window object
101 TESTL(iWs.Connect() == KErrNone);
102 iWindowGroup = RWindowGroup(iWs);
103 TESTL(iWindowGroup.Construct(0) == KErrNone);
104 iWindow = RWindow(iWs);
105 // The window is automatically fullscreen if it's a child of a window group
106 TESTL(iWindow.Construct(iWindowGroup, reinterpret_cast<TUint32>(this)) == KErrNone);
107 iWindow.SetSize(iWindowSize);
109 const TPoint KWindowPosition(30, 30);
110 iWindow.SetPosition(KWindowPosition);
113 // Create display object
114 CEglTestStep::GetDisplayL();
115 ASSERT_EGL_TRUE(eglInitialize(iDisplay, 0, 0));
118 EGLConfig matchingConfigs[1];
119 EGLint numConfigs = 0;
120 eglChooseConfig(iDisplay, KConfigAttribs[2], matchingConfigs, 1, &numConfigs);
121 if (numConfigs <= 0) // Abort the test if the EGL config is not supported
123 ERR_PRINTF1(KErrEglConfigNotSupported);
124 SetTestStepError(KErrNotSupported);
125 return TestStepResult();
128 // Use OpenVG to draw
129 ASSERT_EGL_TRUE(eglBindAPI(EGL_OPENVG_API));
131 // Create the window surface and the egl context and make them current
132 iEglSurface = eglCreateWindowSurface(iDisplay, matchingConfigs[0], &iWindow, KPixmapAttribsVgAlphaFormatPre);
133 ASSERT_EGL_TRUE(iEglSurface != EGL_NO_SURFACE);
134 iEglContext = eglCreateContext(iDisplay, matchingConfigs[0], EGL_NO_CONTEXT, NULL);
135 ASSERT_EGL_TRUE(iEglContext != EGL_NO_CONTEXT);
136 ASSERT_EGL_TRUE(eglMakeCurrent(iDisplay, iEglSurface, iEglSurface, iEglContext));
138 // Get the function pointer for eglSwapBuffersRegionNOK()
139 iPfnEglSwapBuffersRegionNok = reinterpret_cast<PFNEGLSWAPBUFFERSREGIONNOKPROC>(eglGetProcAddress("eglSwapBuffersRegionNOK"));
141 return TestStepResult();
144 TVerdict CEglTest_Benchmark_SwapBuffers::doTestStepPostambleL()
146 // Make sure that this EGL status is active
147 eglMakeCurrent(iDisplay, iEglSurface, iEglSurface, iEglContext);
148 // Call eglMakeCurrent() to ensure the surfaces and contexts are truly destroyed
149 eglMakeCurrent(iDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
150 if (iEglContext != EGL_NO_CONTEXT)
152 eglDestroyContext(iDisplay, iEglContext);
154 if (iEglSurface != EGL_NO_SURFACE)
156 eglDestroySurface(iDisplay, iEglSurface);
158 eglTerminate(iDisplay);
162 iWindowGroup.Close();
168 return CEglTestStep::doTestStepPostambleL();
172 * Override of base class pure virtual function.
173 * This implementation only gets called if the base class doTestStepPreambleL() did
174 * not leave. That being the case, the current test result value should be EPass.
176 * @return test framework code
178 TVerdict CEglTest_Benchmark_SwapBuffers::doTestStepL()
180 // Tests the performance of eglSwapBuffers()
181 SetTestStepID(KTestStep0528);
182 TRAPD(err, EglSwapBufferL());
185 SetTestStepResult(EAbort);
189 // We only perform swap region benchmark test if eglSwapBuffersRegionNOK extension is supported
190 if (iPfnEglSwapBuffersRegionNok != NULL)
192 // Tests the maximum performance of eglSwapBuffersRegionNOK()
193 SetTestStepID(KTestStep0529);
194 TRAP(err, EglSwapBufferRegionL());
197 SetTestStepResult(EAbort);
201 // Stress tests the performance of eglSwapBuffersRegionNOK()
202 SetTestStepID(KTestStep0530);
203 for (TInt noRects = KStressTestNoRectsStepSize; noRects <= KStressTestMaxNoRects; noRects += KStressTestNoRectsStepSize)
205 // TRAP here is on purpose, normally you shouldn't use it in loops
206 TRAP(err, EglSwapBufferRegionStressL(noRects));
209 ERR_PRINTF2(_L("EglSwapBufferRegionStressL (leave code: %d)."), err);
210 SetTestStepResult(EAbort);
217 INFO_PRINTF1(KEglSwapBuffersRegionNokMsg);
220 // Close the test and return result to the testframework
221 CloseTMSGraphicsStep();
222 return TestStepResult();
226 @SYMTestCaseID GRAPHICS-EGL-0528
233 Tests how long it takes to swap window surface buffers if the whole surface is updated.
236 Clear the window surface with alternating background colors, swap the surface buffers
237 (using eglSwapBuffers extension)and measure how long it takes.
239 @SYMTestExpectedResults
240 Test should pass and print the average framerate to a log file.
242 void CEglTest_Benchmark_SwapBuffers::EglSwapBufferL()
244 //------- start profiling
245 iProfiler->InitResults();
247 for(TInt i = KIterationsToTest; i > 0; --i)
249 // Clean the surface with the background color
250 vgSetfv(VG_CLEAR_COLOR, 4, KClearColors[i % KMaxClearColors]);
251 vgClear(0, 0, iWindowSize.iWidth, iWindowSize.iHeight);
252 // Swap the surface buffers
253 ASSERT_EGL_TRUE(eglSwapBuffers(iDisplay, iEglSurface));
255 // Mark the time and print the results to the log file
256 iProfiler->MarkResultSetL();
257 iProfiler->ResultsAnalysisFrameRate(KTestStep0528, 0, 0, 0,
258 KIterationsToTest, iWindowSize.iWidth * iWindowSize.iHeight);
262 @SYMTestCaseID GRAPHICS-EGL-0529
269 Tests how long it takes to swap window surface buffers if only a small region is updated. This
270 test should show the maximum possible performance increase.
273 Clear the window surface with alternating background colors, swap the surface buffers
274 and measure how long it takes.
276 @SYMTestExpectedResults
277 Test should pass and print the average framerate to a log file.
278 The average time shall be made available in an easy-to-use format for further
279 analysis and comparison.
281 void CEglTest_Benchmark_SwapBuffers::EglSwapBufferRegionL()
283 // Region dimensions (top left hand corner and bottom right hand corner)
284 const TRect KRegionRect(50, 50, 60, 60);
285 // Rectangle for partial swap buffer function
286 const EGLint rects[] = {KRegionRect.iTl.iX, KRegionRect.iTl.iY, KRegionRect.Width(), KRegionRect.Height()};
287 // Number of rectangles (one rectangle consist of 4 values)
288 const EGLint count = (sizeof(rects) / (sizeof(rects[0] * 4)));
290 // We obtain the func ptr in doTestStepPreambleL and only execute this test if it is not null
291 TESTL(iPfnEglSwapBuffersRegionNok != NULL);
294 vgSetfv(VG_CLEAR_COLOR, 4, KClearColors[0]);
295 vgClear(0, 0, iWindowSize.iWidth, iWindowSize.iHeight);
296 ASSERT_EGL_TRUE(eglSwapBuffers(iDisplay, iEglSurface));
298 // Initialise uibench and reset the timer
299 iProfiler->InitResults();
301 for(TInt i = KIterationsToTest; i > 0; --i)
303 // Clean the surface with the background color
304 vgSetfv(VG_CLEAR_COLOR, 4, KClearColors[i % KMaxClearColors]);
305 vgClear(0, 0, iWindowSize.iWidth, iWindowSize.iHeight);
306 // Swap the surface buffers
307 ASSERT_EGL_TRUE(iPfnEglSwapBuffersRegionNok(iDisplay, iEglSurface, count, rects));
309 // Mark the time and print the results to the log file
310 iProfiler->MarkResultSetL();
311 iProfiler->ResultsAnalysisFrameRate(KTestStep0529, 0, 0, 0,
312 KIterationsToTest, iWindowSize.iWidth * iWindowSize.iHeight);
316 @SYMTestCaseID GRAPHICS-EGL-0530
323 Stress test to show maximum possible performance increase when adding Rectangles to the region i.e. adding 100 rectangles with step size 5
326 Clear the window surface with alternating background colors, swap the surface buffers
327 and measure how long it takes.
329 @SYMTestExpectedResults
330 Test should pass and print the average framerate to a log file.
333 Number of rectangles to add to the region
335 void CEglTest_Benchmark_SwapBuffers::EglSwapBufferRegionStressL(EGLint aCount)
337 TInt* rects = static_cast<TInt*>(User::AllocLC(sizeof(TInt) * 4 * aCount));
338 TInt actualRectCount = 0;
340 // Size of the dirty rectangles for the stress test
341 const TSize KStressTestRectSize(10, 10);
342 for (TInt y = 0; (y < iWindowSize.iHeight - KStressTestRectSize.iHeight - 1) && (actualRectCount < aCount); y += KStressTestRectSize.iHeight + KStressTestRectGap)
344 for (TInt x = 0; (x < iWindowSize.iWidth - KStressTestRectSize.iWidth - 1) && (actualRectCount < aCount); x += KStressTestRectSize.iWidth + KStressTestRectGap)
348 rects[idx++] = KStressTestRectSize.iWidth;
349 rects[idx++] = KStressTestRectSize.iHeight;
353 TESTL(actualRectCount > 0);
354 if (actualRectCount != aCount)
356 WARN_PRINTF3(KWarnStressTestRectCount, actualRectCount, aCount);
359 // We obtain the func ptr in doTestStepPreambleL and only execute this test if it is not null
360 TESTL(iPfnEglSwapBuffersRegionNok != NULL);
363 vgSetfv(VG_CLEAR_COLOR, 4, KClearColors[0]);
364 vgClear(0, 0, iWindowSize.iWidth, iWindowSize.iHeight);
365 ASSERT_EGL_TRUE(eglSwapBuffers(iDisplay, iEglSurface));
367 // Initialise uibench and reset the timer
368 iProfiler->InitResults();
370 for(TInt i = KIterationsToTest; i > 0; --i)
372 // Clean the surface with the background color
373 vgSetfv(VG_CLEAR_COLOR, 4, KClearColors[i % KMaxClearColors]);
374 vgClear(0, 0, iWindowSize.iWidth, iWindowSize.iHeight);
375 // Swap the surface buffers
376 ASSERT_EGL_TRUE(iPfnEglSwapBuffersRegionNok(iDisplay, iEglSurface, actualRectCount, rects));
378 // Mark the time and print the results to the log file
379 iProfiler->MarkResultSetL();
380 INFO_PRINTF2(KInfoRectangles, aCount);
381 iProfiler->ResultsAnalysisFrameRate(KTestStep0530, 0, 0, 0,
382 KIterationsToTest, iWindowSize.iWidth * iWindowSize.iHeight);
383 CleanupStack::PopAndDestroy(rects);