os/graphics/egl/egltest/src/egltest_benchmark_swapbuffers.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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 _LIT(KEglSwapBuffersRegionNokMsg, "eglSwapBuffersRegionNOK extension is not supported.");
    65 
    66 CEglTest_Benchmark_SwapBuffers::CEglTest_Benchmark_SwapBuffers()
    67 	{
    68 	SetTestStepName(KBenchmark_SwapBuffers);
    69 	}
    70 	
    71 CEglTest_Benchmark_SwapBuffers::~CEglTest_Benchmark_SwapBuffers()	
    72 	{
    73     // empty
    74 	}
    75 
    76 /**
    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.
    80  * 
    81  * @return test framework code
    82  * @leave Standard system errors
    83  */
    84 TVerdict CEglTest_Benchmark_SwapBuffers::doTestStepPreambleL()
    85     {
    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))
    93         {
    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);      
    96         }
    97     CleanupStack::PopAndDestroy(iniParser);
    98     
    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);
   108     // Window dimensions
   109     const TPoint KWindowPosition(30, 30);
   110     iWindow.SetPosition(KWindowPosition);
   111     iWindow.Activate();
   112         
   113     // Create display object
   114     CEglTestStep::GetDisplayL();
   115     ASSERT_EGL_TRUE(eglInitialize(iDisplay, 0, 0));
   116         
   117     // Choose EGL config
   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
   122         {
   123         ERR_PRINTF1(KErrEglConfigNotSupported);
   124         SetTestStepError(KErrNotSupported);
   125         return TestStepResult();
   126         }
   127     
   128     // Use OpenVG to draw
   129     ASSERT_EGL_TRUE(eglBindAPI(EGL_OPENVG_API));
   130     
   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));
   137     
   138     // Get the function pointer for eglSwapBuffersRegionNOK()
   139     iPfnEglSwapBuffersRegionNok = reinterpret_cast<PFNEGLSWAPBUFFERSREGIONNOKPROC>(eglGetProcAddress("eglSwapBuffersRegionNOK"));
   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     // We only perform swap region benchmark test if eglSwapBuffersRegionNOK extension is supported
   190     if (iPfnEglSwapBuffersRegionNok != NULL)
   191         {
   192         // Tests the maximum performance of eglSwapBuffersRegionNOK()
   193         SetTestStepID(KTestStep0529);    
   194         TRAP(err, EglSwapBufferRegionL());
   195         if (err != KErrNone)
   196             {
   197             SetTestStepResult(EAbort);
   198             }    
   199         RecordTestResultL();
   200         
   201         // Stress tests the performance of eglSwapBuffersRegionNOK()
   202         SetTestStepID(KTestStep0530);    
   203         for (TInt noRects = KStressTestNoRectsStepSize; noRects <= KStressTestMaxNoRects; noRects += KStressTestNoRectsStepSize)
   204             {
   205             // TRAP here is on purpose, normally you shouldn't use it in loops
   206             TRAP(err, EglSwapBufferRegionStressL(noRects));
   207             if (err != KErrNone)
   208                 {
   209                 ERR_PRINTF2(_L("EglSwapBufferRegionStressL (leave code: %d)."), err);
   210                 SetTestStepResult(EAbort);
   211                 }
   212             }
   213         RecordTestResultL();
   214         }
   215     else
   216         {
   217         INFO_PRINTF1(KEglSwapBuffersRegionNokMsg);
   218         }
   219     
   220     // Close the test and return result to the testframework
   221     CloseTMSGraphicsStep();    
   222     return TestStepResult();
   223 	}
   224 
   225 /**
   226 @SYMTestCaseID GRAPHICS-EGL-0528
   227 
   228 @SYMTestPriority 1
   229 
   230 @SYMPREQ 2677
   231 
   232 @SYMTestCaseDesc
   233 Tests how long it takes to swap window surface buffers if the whole surface is updated.
   234 
   235 @SYMTestActions
   236 Clear the window surface with alternating background colors, swap the surface buffers 
   237 (using eglSwapBuffers extension)and measure how long it takes.
   238 
   239 @SYMTestExpectedResults
   240 Test should pass and print the average framerate to a log file.
   241 */
   242 void CEglTest_Benchmark_SwapBuffers::EglSwapBufferL()
   243     {    
   244     //-------   start profiling
   245     iProfiler->InitResults();
   246     // Perform the test
   247     for(TInt i = KIterationsToTest; i > 0; --i)
   248         {
   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));
   254         }
   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);   
   259     }
   260 
   261 /**
   262 @SYMTestCaseID GRAPHICS-EGL-0529
   263 
   264 @SYMTestPriority 1
   265 
   266 @SYMPREQ 2677
   267 
   268 @SYMTestCaseDesc
   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.
   271 
   272 @SYMTestActions
   273 Clear the window surface with alternating background colors, swap the surface buffers
   274 and measure how long it takes.
   275 
   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.
   280 */
   281 void CEglTest_Benchmark_SwapBuffers::EglSwapBufferRegionL()
   282     {
   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)));
   289             
   290     // We obtain the func ptr in doTestStepPreambleL and only execute this test if it is not null
   291     TESTL(iPfnEglSwapBuffersRegionNok != NULL);
   292     
   293     // Clear the surface
   294     vgSetfv(VG_CLEAR_COLOR, 4, KClearColors[0]);
   295     vgClear(0, 0, iWindowSize.iWidth, iWindowSize.iHeight);
   296     ASSERT_EGL_TRUE(eglSwapBuffers(iDisplay, iEglSurface));
   297     
   298     // Initialise uibench and reset the timer
   299     iProfiler->InitResults();
   300     // Perform the test
   301     for(TInt i = KIterationsToTest; i > 0; --i)
   302         {
   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));
   308         }
   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);
   313     }
   314 
   315 /**
   316 @SYMTestCaseID GRAPHICS-EGL-0530
   317 
   318 @SYMTestPriority 1
   319 
   320 @SYMPREQ 2677
   321 
   322 @SYMTestCaseDesc
   323 Stress test to show maximum possible performance increase when adding Rectangles to the region i.e. adding 100 rectangles with step size 5 
   324 
   325 @SYMTestActions
   326 Clear the window surface with alternating background colors, swap the surface buffers
   327 and measure how long it takes.
   328 
   329 @SYMTestExpectedResults
   330 Test should pass and print the average framerate to a log file.
   331 
   332 @Param aCount
   333 Number of rectangles to add to the region
   334 */
   335 void CEglTest_Benchmark_SwapBuffers::EglSwapBufferRegionStressL(EGLint aCount)
   336     {
   337     TInt* rects = static_cast<TInt*>(User::AllocLC(sizeof(TInt) * 4 * aCount));
   338     TInt actualRectCount = 0;
   339     TInt idx = 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)
   343         {
   344         for (TInt x = 0; (x < iWindowSize.iWidth - KStressTestRectSize.iWidth - 1) && (actualRectCount < aCount); x += KStressTestRectSize.iWidth + KStressTestRectGap)
   345             {
   346             rects[idx++] = x;
   347             rects[idx++] = y;
   348             rects[idx++] = KStressTestRectSize.iWidth;
   349             rects[idx++] = KStressTestRectSize.iHeight;
   350             actualRectCount++;
   351             }
   352         }
   353     TESTL(actualRectCount > 0);
   354     if (actualRectCount != aCount)
   355         {
   356         WARN_PRINTF3(KWarnStressTestRectCount, actualRectCount, aCount);
   357         }
   358     
   359     // We obtain the func ptr in doTestStepPreambleL and only execute this test if it is not null
   360     TESTL(iPfnEglSwapBuffersRegionNok != NULL);
   361     
   362     // Clear the surface
   363     vgSetfv(VG_CLEAR_COLOR, 4, KClearColors[0]);
   364     vgClear(0, 0, iWindowSize.iWidth, iWindowSize.iHeight);
   365     ASSERT_EGL_TRUE(eglSwapBuffers(iDisplay, iEglSurface));
   366     
   367     // Initialise uibench and reset the timer
   368     iProfiler->InitResults();
   369     // Perform the test
   370     for(TInt i = KIterationsToTest; i > 0; --i)
   371         {
   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));
   377         }
   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);
   384     }