egl/egltest/src/egltest_benchmark_swapbuffers.cpp
changeset 36 01a6848ebfd7
child 160 969102054596
equal deleted inserted replaced
0:5d03bc08d59c 36:01a6848ebfd7
       
     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".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description: 
       
    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. 
       
    18 // 
       
    19 
       
    20 /**
       
    21  @file
       
    22  @test 
       
    23 */
       
    24 
       
    25 #include "egltest_benchmark_swapbuffers.h"
       
    26 
       
    27 #include <VG/openvg.h>
       
    28 #include <test/tprofiler.h>
       
    29 #include <test/egltestcommonutils.h>
       
    30 #include <test/egltestcommoninisettings.h>
       
    31 
       
    32 _LIT(KSwapBuffersSection, "SwapBuffers");
       
    33 
       
    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] = 
       
    38     {
       
    39         {0.5f, 0.5f, 0.5f, 1.0f}, // gray
       
    40         {0.1f, 0.2f, 0.4f, 1.0f}  // blue
       
    41     };
       
    42 
       
    43 // Number of iterations, it defines how often the swapBuffer function is called
       
    44 static const TInt KIterationsToTest = 10;
       
    45 
       
    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;
       
    52 
       
    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");
       
    59 
       
    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).");
       
    63 
       
    64 
       
    65 CEglTest_Benchmark_SwapBuffers::CEglTest_Benchmark_SwapBuffers()
       
    66 	{
       
    67 	SetTestStepName(KBenchmark_SwapBuffers);
       
    68 	}
       
    69 	
       
    70 CEglTest_Benchmark_SwapBuffers::~CEglTest_Benchmark_SwapBuffers()	
       
    71 	{
       
    72     // empty
       
    73 	}
       
    74 
       
    75 /**
       
    76  * It's called by the test framework before the actual test. It's used
       
    77  * to do the preparation for the test. It's important to call the
       
    78  * baseclass implementation also.
       
    79  * 
       
    80  * @return test framework code
       
    81  * @leave Standard system errors
       
    82  */
       
    83 TVerdict CEglTest_Benchmark_SwapBuffers::doTestStepPreambleL()
       
    84     {
       
    85     CEglTestStep::doTestStepPreambleL();
       
    86     iProfiler = CTProfiler::NewL(*this);
       
    87     //read parameters from config (WindowSize)
       
    88     CEglTestCommonIniSettings* iniParser = CEglTestCommonIniSettings::NewL();
       
    89     CleanupStack::PushL(iniParser);
       
    90     iWindowSize = iniParser->GetWindowSize(KSwapBuffersSection);
       
    91     if(iWindowSize == TSize(0,0))
       
    92         {
       
    93         ERR_PRINTF1(_L("The window size whether is not specified in INI file or is TSize(0,0), the test will not be executed!"));
       
    94         User::Leave(KErrArgument);      
       
    95         }
       
    96     CleanupStack::PopAndDestroy(iniParser);
       
    97     
       
    98     // Establish the connection to the window server and create
       
    99     // a WindowGroup and a Window object
       
   100     TESTL(iWs.Connect() == KErrNone);    
       
   101     iWindowGroup = RWindowGroup(iWs);
       
   102     TESTL(iWindowGroup.Construct(0) == KErrNone);  
       
   103     iWindow = RWindow(iWs);
       
   104     // The window is automatically fullscreen if it's a child of a window group
       
   105     TESTL(iWindow.Construct(iWindowGroup, reinterpret_cast<TUint32>(this)) == KErrNone);
       
   106     iWindow.SetSize(iWindowSize);
       
   107     // Window dimensions
       
   108     const TPoint KWindowPosition(30, 30);
       
   109     iWindow.SetPosition(KWindowPosition);
       
   110     iWindow.Activate();
       
   111         
       
   112     // Create display object
       
   113     CEglTestStep::GetDisplayL();
       
   114     ASSERT_EGL_TRUE(eglInitialize(iDisplay, 0, 0));
       
   115         
       
   116     // Choose EGL config
       
   117     EGLConfig matchingConfigs[1];
       
   118     EGLint numConfigs = 0;
       
   119     eglChooseConfig(iDisplay, KConfigAttribs[2], matchingConfigs, 1, &numConfigs);
       
   120     if (numConfigs <= 0) // Abort the test if the EGL config is not supported
       
   121         {
       
   122         ERR_PRINTF1(KErrEglConfigNotSupported);
       
   123         SetTestStepError(KErrNotSupported);
       
   124         return TestStepResult();
       
   125         }
       
   126     
       
   127     // Use OpenVG to draw
       
   128     ASSERT_EGL_TRUE(eglBindAPI(EGL_OPENVG_API));
       
   129     
       
   130     // Create the window surface and the egl context and make them current
       
   131     iEglSurface = eglCreateWindowSurface(iDisplay, matchingConfigs[0], &iWindow, KPixmapAttribsVgAlphaFormatPre);
       
   132     ASSERT_EGL_TRUE(iEglSurface != EGL_NO_SURFACE);
       
   133     iEglContext = eglCreateContext(iDisplay, matchingConfigs[0], EGL_NO_CONTEXT, NULL);
       
   134     ASSERT_EGL_TRUE(iEglContext != EGL_NO_CONTEXT);
       
   135     ASSERT_EGL_TRUE(eglMakeCurrent(iDisplay, iEglSurface, iEglSurface, iEglContext));
       
   136     
       
   137     // Get the function pointer for eglSwapBuffersRegionNOK() and check SwapBuffers extension exist
       
   138     PFNEGLSWAPBUFFERSREGIONNOKPROC pfnEglSwapBuffersRegionNok = reinterpret_cast<PFNEGLSWAPBUFFERSREGIONNOKPROC>(eglGetProcAddress("eglSwapBuffersRegionNOK"));
       
   139     ASSERT_EGL_TRUE(pfnEglSwapBuffersRegionNok);
       
   140     
       
   141     return TestStepResult();
       
   142     }
       
   143 
       
   144 TVerdict CEglTest_Benchmark_SwapBuffers::doTestStepPostambleL()
       
   145     {
       
   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)
       
   151         {
       
   152         eglDestroyContext(iDisplay, iEglContext);
       
   153         }
       
   154     if (iEglSurface != EGL_NO_SURFACE)
       
   155         {
       
   156         eglDestroySurface(iDisplay, iEglSurface);
       
   157         }   
       
   158     eglTerminate(iDisplay);
       
   159     eglReleaseThread();
       
   160     
       
   161     iWindow.Close();
       
   162     iWindowGroup.Close();
       
   163     iWs.Close();
       
   164     
       
   165     delete iProfiler;
       
   166     iProfiler = NULL;
       
   167 
       
   168     return CEglTestStep::doTestStepPostambleL();
       
   169     }
       
   170 
       
   171 /**
       
   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.
       
   175  *
       
   176  * @return test framework code
       
   177  */
       
   178 TVerdict CEglTest_Benchmark_SwapBuffers::doTestStepL()
       
   179     {
       
   180     // Tests  the performance of eglSwapBuffers()
       
   181     SetTestStepID(KTestStep0528);    
       
   182     TRAPD(err, EglSwapBufferL());
       
   183     if (err != KErrNone)
       
   184         {
       
   185         SetTestStepResult(EAbort);
       
   186         }    
       
   187     RecordTestResultL();
       
   188     
       
   189     // Tests the maximum performance of eglSwapBuffersRegionNOK()
       
   190     SetTestStepID(KTestStep0529);    
       
   191     TRAP(err, EglSwapBufferRegionL());
       
   192     if (err != KErrNone)
       
   193         {
       
   194         SetTestStepResult(EAbort);
       
   195         }    
       
   196     RecordTestResultL();
       
   197     
       
   198     // Stress tests the performance of eglSwapBuffersRegionNOK()
       
   199     SetTestStepID(KTestStep0530);    
       
   200     for (TInt noRects = KStressTestNoRectsStepSize; noRects <= KStressTestMaxNoRects; noRects += KStressTestNoRectsStepSize)
       
   201         {
       
   202         // TRAP here is on purpose, normally you shouldn't use it in loops
       
   203         TRAP(err, EglSwapBufferRegionStressL(noRects));
       
   204         if (err != KErrNone)
       
   205             {
       
   206             ERR_PRINTF2(_L("EglSwapBufferRegionStressL (leave code: %d)."), err);
       
   207             SetTestStepResult(EAbort);
       
   208             }
       
   209         }
       
   210     RecordTestResultL();
       
   211     
       
   212     // Close the test and return result to the testframework
       
   213     CloseTMSGraphicsStep();    
       
   214     return TestStepResult();
       
   215 	}
       
   216 
       
   217 /**
       
   218 @SYMTestCaseID GRAPHICS-EGL-0528
       
   219 
       
   220 @SYMTestPriority 1
       
   221 
       
   222 @SYMPREQ 2677
       
   223 
       
   224 @SYMTestCaseDesc
       
   225 Tests how long it takes to swap window surface buffers if the whole surface is updated.
       
   226 
       
   227 @SYMTestActions
       
   228 Clear the window surface with alternating background colors, swap the surface buffers 
       
   229 (using eglSwapBuffers extension)and measure how long it takes.
       
   230 
       
   231 @SYMTestExpectedResults
       
   232 Test should pass and print the average framerate to a log file.
       
   233 */
       
   234 void CEglTest_Benchmark_SwapBuffers::EglSwapBufferL()
       
   235     {    
       
   236     //-------   start profiling
       
   237     iProfiler->InitResults();
       
   238     // Perform the test
       
   239     for(TInt i = KIterationsToTest; i > 0; --i)
       
   240         {
       
   241         // Clean the surface with the background color
       
   242         vgSetfv(VG_CLEAR_COLOR, 4, KClearColors[i % KMaxClearColors]);
       
   243         vgClear(0, 0, iWindowSize.iWidth, iWindowSize.iHeight);
       
   244         // Swap the surface buffers
       
   245         ASSERT_EGL_TRUE(eglSwapBuffers(iDisplay, iEglSurface));
       
   246         }
       
   247     // Mark the time and print the results to the log file
       
   248     iProfiler->MarkResultSetL();
       
   249     iProfiler->ResultsAnalysisFrameRate(KTestStep0528, 0, 0, 0,
       
   250             KIterationsToTest, iWindowSize.iWidth * iWindowSize.iHeight);   
       
   251     }
       
   252 
       
   253 /**
       
   254 @SYMTestCaseID GRAPHICS-EGL-0529
       
   255 
       
   256 @SYMTestPriority 1
       
   257 
       
   258 @SYMPREQ 2677
       
   259 
       
   260 @SYMTestCaseDesc
       
   261 Tests how long it takes to swap window surface buffers if only a small region is updated. This
       
   262 test should show the maximum possible performance increase.
       
   263 
       
   264 @SYMTestActions
       
   265 Clear the window surface with alternating background colors, swap the surface buffers
       
   266 and measure how long it takes.
       
   267 
       
   268 @SYMTestExpectedResults
       
   269 Test should pass and print the average framerate to a log file.
       
   270 The average time shall be made available in an easy-to-use format for further 
       
   271 analysis and comparison.
       
   272 */
       
   273 void CEglTest_Benchmark_SwapBuffers::EglSwapBufferRegionL()
       
   274     {
       
   275     // Region dimensions (top left hand corner and bottom right hand corner)
       
   276     const TRect KRegionRect(50, 50, 60, 60);
       
   277     // Rectangle for partial swap buffer function
       
   278     const EGLint rects[] = {KRegionRect.iTl.iX, KRegionRect.iTl.iY, KRegionRect.Width(), KRegionRect.Height()};
       
   279     // Number of rectangles (one rectangle consist of 4 values)
       
   280     const EGLint count = (sizeof(rects) / (sizeof(rects[0] * 4)));
       
   281             
       
   282     // Get the function pointer for eglSwapBuffersRegionNOK()
       
   283     PFNEGLSWAPBUFFERSREGIONNOKPROC pfnEglSwapBuffersRegionNok = reinterpret_cast<PFNEGLSWAPBUFFERSREGIONNOKPROC>(eglGetProcAddress("eglSwapBuffersRegionNOK"));
       
   284     
       
   285     // Clear the surface
       
   286     vgSetfv(VG_CLEAR_COLOR, 4, KClearColors[0]);
       
   287     vgClear(0, 0, iWindowSize.iWidth, iWindowSize.iHeight);
       
   288     ASSERT_EGL_TRUE(eglSwapBuffers(iDisplay, iEglSurface));
       
   289     
       
   290     // Initialise uibench and reset the timer
       
   291     iProfiler->InitResults();
       
   292     // Perform the test
       
   293     for(TInt i = KIterationsToTest; i > 0; --i)
       
   294         {
       
   295         // Clean the surface with the background color
       
   296         vgSetfv(VG_CLEAR_COLOR, 4, KClearColors[i % KMaxClearColors]);
       
   297         vgClear(0, 0, iWindowSize.iWidth, iWindowSize.iHeight);
       
   298         // Swap the surface buffers
       
   299         ASSERT_EGL_TRUE(pfnEglSwapBuffersRegionNok(iDisplay, iEglSurface, count, rects));
       
   300         }
       
   301     // Mark the time and print the results to the log file
       
   302     iProfiler->MarkResultSetL();
       
   303     iProfiler->ResultsAnalysisFrameRate(KTestStep0529, 0, 0, 0,
       
   304             KIterationsToTest, iWindowSize.iWidth * iWindowSize.iHeight);
       
   305     }
       
   306 
       
   307 /**
       
   308 @SYMTestCaseID GRAPHICS-EGL-0530
       
   309 
       
   310 @SYMTestPriority 1
       
   311 
       
   312 @SYMPREQ 2677
       
   313 
       
   314 @SYMTestCaseDesc
       
   315 Stress test to show maximum possible performance increase when adding Rectangles to the region i.e. adding 100 rectangles with step size 5 
       
   316 
       
   317 @SYMTestActions
       
   318 Clear the window surface with alternating background colors, swap the surface buffers
       
   319 and measure how long it takes.
       
   320 
       
   321 @SYMTestExpectedResults
       
   322 Test should pass and print the average framerate to a log file.
       
   323 
       
   324 @Param aCount
       
   325 Number of rectangles to add to the region
       
   326 */
       
   327 void CEglTest_Benchmark_SwapBuffers::EglSwapBufferRegionStressL(EGLint aCount)
       
   328     {
       
   329     TInt* rects = static_cast<TInt*>(User::AllocLC(sizeof(TInt) * 4 * aCount));
       
   330     TInt actualRectCount = 0;
       
   331     TInt idx = 0;
       
   332     // Size of the dirty rectangles for the stress test
       
   333     const TSize KStressTestRectSize(10, 10);
       
   334     for (TInt y = 0; (y < iWindowSize.iHeight - KStressTestRectSize.iHeight - 1) && (actualRectCount < aCount); y += KStressTestRectSize.iHeight + KStressTestRectGap)
       
   335         {
       
   336         for (TInt x = 0; (x < iWindowSize.iWidth - KStressTestRectSize.iWidth - 1) && (actualRectCount < aCount); x += KStressTestRectSize.iWidth + KStressTestRectGap)
       
   337             {
       
   338             rects[idx++] = x;
       
   339             rects[idx++] = y;
       
   340             rects[idx++] = KStressTestRectSize.iWidth;
       
   341             rects[idx++] = KStressTestRectSize.iHeight;
       
   342             actualRectCount++;
       
   343             }
       
   344         }
       
   345     TESTL(actualRectCount > 0);
       
   346     if (actualRectCount != aCount)
       
   347         {
       
   348         WARN_PRINTF3(KWarnStressTestRectCount, actualRectCount, aCount);
       
   349         }
       
   350     
       
   351     // Get the function pointer for eglSwapBuffersRegionNOK()
       
   352     PFNEGLSWAPBUFFERSREGIONNOKPROC pfnEglSwapBuffersRegionNok = reinterpret_cast<PFNEGLSWAPBUFFERSREGIONNOKPROC>(eglGetProcAddress("eglSwapBuffersRegionNOK"));
       
   353     
       
   354     // Clear the surface
       
   355     vgSetfv(VG_CLEAR_COLOR, 4, KClearColors[0]);
       
   356     vgClear(0, 0, iWindowSize.iWidth, iWindowSize.iHeight);
       
   357     ASSERT_EGL_TRUE(eglSwapBuffers(iDisplay, iEglSurface));
       
   358     
       
   359     // Initialise uibench and reset the timer
       
   360     iProfiler->InitResults();
       
   361     // Perform the test
       
   362     for(TInt i = KIterationsToTest; i > 0; --i)
       
   363         {
       
   364         // Clean the surface with the background color
       
   365         vgSetfv(VG_CLEAR_COLOR, 4, KClearColors[i % KMaxClearColors]);
       
   366         vgClear(0, 0, iWindowSize.iWidth, iWindowSize.iHeight);
       
   367         // Swap the surface buffers
       
   368         ASSERT_EGL_TRUE(pfnEglSwapBuffersRegionNok(iDisplay, iEglSurface, actualRectCount, rects));
       
   369         }
       
   370     // Mark the time and print the results to the log file
       
   371     iProfiler->MarkResultSetL();
       
   372     INFO_PRINTF2(KInfoRectangles, aCount);
       
   373     iProfiler->ResultsAnalysisFrameRate(KTestStep0530, 0, 0, 0,
       
   374             KIterationsToTest, iWindowSize.iWidth * iWindowSize.iHeight);
       
   375     CleanupStack::PopAndDestroy(rects);
       
   376     }