graphicstest/uibench/s60/src/tests_egl/teglswapbuffer.cpp
changeset 36 01a6848ebfd7
parent 0 5d03bc08d59c
child 43 7579f232bae7
child 45 36b2e23a8629
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 /**
       
    22  @file
       
    23  @test
       
    24  @internalComponent - Internal Symbian test code 
       
    25 */
       
    26 
       
    27 
       
    28 #include "teglswapbuffer.h"
       
    29 
       
    30 #include <VG/openvg.h>
       
    31 
       
    32 
       
    33 // If the condition that is passed to the macro is false
       
    34 // the macro leaves with the EGL error code
       
    35 #define EGL_CHECK_ERRORL(PASS) { if (!(PASS)) { SetTestStepResult(EFail); ERR_PRINTF2(KErrEgl, eglGetError()); User::Leave(eglGetError()); } }
       
    36 
       
    37 // Configuration for a Color16MAP - Window
       
    38 static const EGLint KConfigAttribs[] =
       
    39     {
       
    40     EGL_BUFFER_SIZE,     32,
       
    41     EGL_RED_SIZE,        8,
       
    42     EGL_GREEN_SIZE,      8,
       
    43     EGL_BLUE_SIZE,       8,
       
    44     EGL_ALPHA_SIZE,      8,
       
    45     EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT,
       
    46     EGL_SURFACE_TYPE,    EGL_WINDOW_BIT | EGL_VG_ALPHA_FORMAT_PRE_BIT,    
       
    47     EGL_NONE
       
    48     };
       
    49 
       
    50 // Additional attributes for the window surface
       
    51 static const EGLint KWindowSurfaceAttribs[] = 
       
    52     {
       
    53     EGL_VG_ALPHA_FORMAT, EGL_VG_ALPHA_FORMAT_PRE,
       
    54     EGL_NONE
       
    55     };
       
    56 
       
    57 // The test draws alternating backgrounds to show the affect
       
    58 // of different swapBuffer functions 
       
    59 static const TInt KMaxClearColors = 2;
       
    60 static const VGfloat KClearColors[KMaxClearColors][4] = 
       
    61     {
       
    62         {0.5f, 0.5f, 0.5f, 1.0f}, // gray
       
    63         {0.1f, 0.2f, 0.4f, 1.0f}  // blue
       
    64     };
       
    65 
       
    66 // Datatype for a function pointer to eglSwapBuffersRegionNOK()
       
    67 typedef EGLBoolean (*TFPtrEglSwapBuffersRegionNok) (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint* rects);
       
    68 
       
    69 // Number of iterations, it defines how often the swapBuffer function is called
       
    70 const TInt KIterationsToTest = 1000;
       
    71 
       
    72 // Maximum number of rectangles for eglSwapBuffersRegionNOK() stress test
       
    73 const TInt KStressTestMaxNoRects = 100;
       
    74 // Defines the increase of number of rectangles for each iteration
       
    75 const TInt KStressTestNoRectsStepSize = 5;
       
    76 // Size of the dirty rectangles for the stress test
       
    77 const TSize KStressTestRectSize(10, 10);
       
    78 // Gap between the dirty Rectangles
       
    79 const TInt KStressTestRectGap = 3;
       
    80 
       
    81 // Window dimensions
       
    82 const TSize KWindowSize(200, 200);
       
    83 const TPoint KWindowPosition(30, 30);
       
    84 // Region dimensions (top left hand corner and bottom right hand corner)
       
    85 const TRect KRegionRect(50, 50, 60, 60);
       
    86 
       
    87 // This test step meassures the performance of eglSwapBuffers()
       
    88 _LIT(KTestStep0018,"GRAPHICS-UI-BENCH-S60-0018");
       
    89 // This test step meassures the performance of eglSwapBuffersRegionNOK()
       
    90 _LIT(KTestStep0019,"GRAPHICS-UI-BENCH-S60-0019");
       
    91 // This test step meassures the performance of eglSwapBuffersRegionNOK() with a lot of dirty rectangles
       
    92 _LIT(KTestStep0020,"GRAPHICS-UI-BENCH-S60-0020");
       
    93 
       
    94 _LIT(KErrEgl, "EGL error 0x%x");
       
    95 _LIT(KErrEglConfigNotSupported, "EGL config is not supported.");
       
    96 _LIT(KInfoRectangles, "Number of dirty rectangles: %d");
       
    97 _LIT(KWarnStressTestRectCount, "Dirty rectangles for stress test don't fit onto window surface (%d of %d).");
       
    98 
       
    99 
       
   100 CTEglSwapBuffer::CTEglSwapBuffer()
       
   101 	{
       
   102 	SetTestStepName(KTEglSwapBuffer);
       
   103 	}
       
   104 	
       
   105 CTEglSwapBuffer::~CTEglSwapBuffer()	
       
   106 	{
       
   107     // Make sure that this EGL status is active
       
   108     eglMakeCurrent(iEglDisplay, iEglSurface, iEglSurface, iEglContext);
       
   109     if (iEglContext != EGL_NO_CONTEXT)
       
   110         {
       
   111         eglDestroyContext(iEglDisplay, iEglContext);
       
   112         }
       
   113     if (iEglSurface != EGL_NO_SURFACE)
       
   114         {
       
   115         eglDestroySurface(iEglDisplay, iEglSurface);
       
   116         }   
       
   117     // Call eglMakeCurrent() to ensure the surfaces and contexts are truly destroyed
       
   118     eglMakeCurrent(iEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
       
   119     eglTerminate(iEglDisplay);
       
   120     eglReleaseThread();
       
   121     
       
   122     iWindow.Close();
       
   123     iWindowGroup.Close();
       
   124     iWs.Close();
       
   125 	}
       
   126 
       
   127 /**
       
   128  * It's called by the test framework before the actual test. It's used
       
   129  * to do the preparation for the test. It's important to call the
       
   130  * baseclass implementation also.
       
   131  * 
       
   132  * @return TVerdict code
       
   133  */
       
   134 TVerdict CTEglSwapBuffer::doTestStepPreambleL()
       
   135     {
       
   136     CTe_graphicsperformanceSuiteStepBase::doTestStepPreambleL();
       
   137     
       
   138     // Establish the connection to the window server and create
       
   139     // a WindowGroup and a Window object
       
   140     TESTNOERRORL(iWs.Connect());    
       
   141     iWindowGroup = RWindowGroup(iWs);
       
   142     TESTNOERRORL(iWindowGroup.Construct(0));
       
   143     iWindow = RWindow(iWs);
       
   144     // The window is automatically fullscreen if it's a child of a window group
       
   145     TESTNOERRORL(iWindow.Construct(iWindowGroup, reinterpret_cast<TUint32>(this)));
       
   146     iWindow.SetSize(KWindowSize);
       
   147     iWindow.SetPosition(KWindowPosition);
       
   148     iWindow.Activate();
       
   149         
       
   150     // Create display object
       
   151     iEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
       
   152     EGL_CHECK_ERRORL(iEglDisplay != EGL_NO_DISPLAY);
       
   153     EGL_CHECK_ERRORL(eglInitialize(iEglDisplay, 0, 0));
       
   154         
       
   155     // Choose EGL config
       
   156     EGLConfig matchingConfigs[1];
       
   157     EGLint numConfigs = 0;
       
   158     eglChooseConfig(iEglDisplay, KConfigAttribs, matchingConfigs, 1, &numConfigs);
       
   159     if (numConfigs <= 0) // Abort the test if the EGL config is not supported
       
   160         {
       
   161         ERR_PRINTF1(KErrEglConfigNotSupported);
       
   162         SetTestStepError(KErrNotSupported);
       
   163         return TestStepResult();
       
   164         }
       
   165     
       
   166     // Use OpenVG to draw
       
   167     EGL_CHECK_ERRORL(eglBindAPI(EGL_OPENVG_API));
       
   168     
       
   169     // Create the window surface and the egl context and make them current
       
   170     iEglSurface = eglCreateWindowSurface(iEglDisplay, matchingConfigs[0], &iWindow, KWindowSurfaceAttribs);
       
   171     EGL_CHECK_ERRORL(iEglSurface != EGL_NO_SURFACE);
       
   172     iEglContext = eglCreateContext(iEglDisplay, matchingConfigs[0], EGL_NO_CONTEXT, NULL);
       
   173     EGL_CHECK_ERRORL(iEglContext != EGL_NO_CONTEXT);
       
   174     EGL_CHECK_ERRORL(eglMakeCurrent(iEglDisplay, iEglSurface, iEglSurface, iEglContext));
       
   175     
       
   176     return TestStepResult();
       
   177     }
       
   178 
       
   179 /**
       
   180  * Override of base class pure virtual function.
       
   181  * This implementation only gets called if the base class doTestStepPreambleL() did
       
   182  * not leave. That being the case, the current test result value should be EPass.
       
   183  *
       
   184  * @return TVerdict code
       
   185  */
       
   186 TVerdict CTEglSwapBuffer::doTestStepL()
       
   187     {
       
   188     // Tests  the performance of eglSwapBuffers()
       
   189     SetTestStepID(KTestStep0018);    
       
   190     TRAPD(err, EglSwapBufferL());
       
   191     if (err != KErrNone)
       
   192         {
       
   193         SetTestStepResult(EAbort);
       
   194         }    
       
   195     RecordTestResultL();
       
   196     
       
   197     // Tests the maximum performance of eglSwapBuffersRegionNOK()
       
   198     SetTestStepID(KTestStep0019);    
       
   199     TRAP(err, EglSwapBufferRegionL());
       
   200     if (err != KErrNone)
       
   201         {
       
   202         SetTestStepResult(EAbort);
       
   203         }    
       
   204     RecordTestResultL();
       
   205     
       
   206     // Stress tests the performance of eglSwapBuffersRegionNOK()
       
   207     SetTestStepID(KTestStep0020);    
       
   208     for (TInt noRects = KStressTestNoRectsStepSize; noRects <= KStressTestMaxNoRects; noRects += KStressTestNoRectsStepSize)
       
   209         {
       
   210         // TRAP here is on purpose, normally you shouldn't use it in loops
       
   211         TRAP(err, EglSwapBufferRegionStressL(noRects));
       
   212         if (err != KErrNone)
       
   213             {
       
   214             SetTestStepResult(EAbort);
       
   215             }
       
   216         }
       
   217     RecordTestResultL();
       
   218     
       
   219     // Close the test and return result to the testframework
       
   220     CloseTMSGraphicsStep();    
       
   221     return TestStepResult();
       
   222 	}
       
   223 
       
   224 /**
       
   225 @SYMTestCaseID GRAPHICS-UI-BENCH-S60-0018
       
   226 
       
   227 @SYMTestPriority 1
       
   228 
       
   229 @SYMPREQ 2677
       
   230 
       
   231 @SYMTestCaseDesc
       
   232 Tests how long it takes to swap window surface buffers if the whole surface is updated.
       
   233 
       
   234 @SYMTestActions
       
   235 Clear the window surface with alternating background colors, swap the surface buffers
       
   236 and measure how long it takes.
       
   237 
       
   238 @SYMTestExpectedResults
       
   239 Test should pass and print the average framerate to a log file.
       
   240 */
       
   241 void CTEglSwapBuffer::EglSwapBufferL()
       
   242     {    
       
   243     // Initialise uibench and reset the timer
       
   244     iProfiler->InitResults();
       
   245     // Perform the test
       
   246     for(TInt i = KIterationsToTest; i > 0; --i)
       
   247         {
       
   248         // Clean the surface with the background color
       
   249         vgSetfv(VG_CLEAR_COLOR, 4, KClearColors[i % KMaxClearColors]);
       
   250         vgClear(0, 0, KWindowSize.iWidth, KWindowSize.iHeight);
       
   251         // Swap the surface buffers
       
   252         EGL_CHECK_ERRORL(eglSwapBuffers(iEglDisplay, iEglSurface));
       
   253         }
       
   254     // Mark the time and print the results to the log file
       
   255     iProfiler->MarkResultSetL();
       
   256     iProfiler->ResultsAnalysisFrameRate(KTestStep0018, 0, 0, 0,
       
   257             KIterationsToTest, KWindowSize.iWidth * KWindowSize.iHeight);   
       
   258     }
       
   259 
       
   260 /**
       
   261 @SYMTestCaseID GRAPHICS-UI-BENCH-S60-0019
       
   262 
       
   263 @SYMTestPriority 1
       
   264 
       
   265 @SYMPREQ 2677
       
   266 
       
   267 @SYMTestCaseDesc
       
   268 Tests how long it takes to swap window surface buffers if only a small region is updated. This
       
   269 test should show the maximum possible performance increase.
       
   270 
       
   271 @SYMTestActions
       
   272 Clear the window surface with alternating background colors, swap the surface buffers
       
   273 and measure how long it takes.
       
   274 
       
   275 @SYMTestExpectedResults
       
   276 Test should pass and print the average framerate to a log file.
       
   277 */
       
   278 void CTEglSwapBuffer::EglSwapBufferRegionL()
       
   279     {
       
   280     // Number of rectangles
       
   281     EGLint count = 1;
       
   282     // Rectangle for partial swap buffer function
       
   283     EGLint rects[] = {KRegionRect.iTl.iX, KRegionRect.iTl.iY, KRegionRect.Width(), KRegionRect.Height()};
       
   284     // Get the function pointer for eglSwapBuffersRegionNOK()
       
   285     TFPtrEglSwapBuffersRegionNok pfnEglSwapBuffersRegionNok = reinterpret_cast<TFPtrEglSwapBuffersRegionNok>(eglGetProcAddress("eglSwapBuffersRegionNOK"));
       
   286     EGL_CHECK_ERRORL(pfnEglSwapBuffersRegionNok);
       
   287     
       
   288     // Clear the surface
       
   289     vgSetfv(VG_CLEAR_COLOR, 4, KClearColors[0]);
       
   290     vgClear(0, 0, KWindowSize.iWidth, KWindowSize.iHeight);
       
   291     EGL_CHECK_ERRORL(eglSwapBuffers(iEglDisplay, iEglSurface));
       
   292     
       
   293     // Initialise uibench and reset the timer
       
   294     iProfiler->InitResults();
       
   295     // Perform the test
       
   296     for(TInt i = KIterationsToTest; i > 0; --i)
       
   297         {
       
   298         // Clean the surface with the background color
       
   299         vgSetfv(VG_CLEAR_COLOR, 4, KClearColors[i % KMaxClearColors]);
       
   300         vgClear(0, 0, KWindowSize.iWidth, KWindowSize.iHeight);
       
   301         // Swap the surface buffers
       
   302         EGL_CHECK_ERRORL(pfnEglSwapBuffersRegionNok(iEglDisplay, iEglSurface, count, rects));
       
   303         }
       
   304     // Mark the time and print the results to the log file
       
   305     iProfiler->MarkResultSetL();
       
   306     iProfiler->ResultsAnalysisFrameRate(KTestStep0019, 0, 0, 0,
       
   307             KIterationsToTest, KWindowSize.iWidth * KWindowSize.iHeight);
       
   308     }
       
   309 
       
   310 /**
       
   311 @SYMTestCaseID GRAPHICS-UI-BENCH-S60-0020
       
   312 
       
   313 @SYMTestPriority 1
       
   314 
       
   315 @SYMPREQ 2677
       
   316 
       
   317 @SYMTestCaseDesc
       
   318 Tests how long it takes to swap window surface buffers if only a small region is updated. This
       
   319 test should show the maximum possible performance increase.
       
   320 
       
   321 @SYMTestActions
       
   322 Clear the window surface with alternating background colors, swap the surface buffers
       
   323 and measure how long it takes.
       
   324 
       
   325 @SYMTestExpectedResults
       
   326 Test should pass and print the average framerate to a log file.
       
   327 */
       
   328 void CTEglSwapBuffer::EglSwapBufferRegionStressL(EGLint aCount)
       
   329     {
       
   330     TInt* rects = static_cast<TInt*>(User::AllocLC(sizeof(TInt) * 4 * aCount));
       
   331     TInt actualRectCount = 0;
       
   332     TInt idx = 0;
       
   333     for (TInt y = 0; (y < KWindowSize.iHeight - KStressTestRectSize.iHeight - 1) && (actualRectCount < aCount); y += KStressTestRectSize.iHeight + KStressTestRectGap)
       
   334         {
       
   335         for (TInt x = 0; (x < KWindowSize.iWidth - KStressTestRectSize.iWidth - 1) && (actualRectCount < aCount); x += KStressTestRectSize.iWidth + KStressTestRectGap)
       
   336             {
       
   337             rects[idx++] = x;
       
   338             rects[idx++] = y;
       
   339             rects[idx++] = KStressTestRectSize.iWidth;
       
   340             rects[idx++] = KStressTestRectSize.iHeight;
       
   341             actualRectCount++;
       
   342             }
       
   343         }
       
   344     TESTL(actualRectCount > 0);
       
   345     if (actualRectCount != aCount)
       
   346         {
       
   347         WARN_PRINTF3(KWarnStressTestRectCount, actualRectCount, aCount);
       
   348         }
       
   349     
       
   350     // Get the function pointer for eglSwapBuffersRegionNOK()
       
   351     TFPtrEglSwapBuffersRegionNok pfnEglSwapBuffersRegionNok = reinterpret_cast<TFPtrEglSwapBuffersRegionNok>(eglGetProcAddress("eglSwapBuffersRegionNOK"));
       
   352     EGL_CHECK_ERRORL(pfnEglSwapBuffersRegionNok);
       
   353     
       
   354     // Clear the surface
       
   355     vgSetfv(VG_CLEAR_COLOR, 4, KClearColors[0]);
       
   356     vgClear(0, 0, KWindowSize.iWidth, KWindowSize.iHeight);
       
   357     EGL_CHECK_ERRORL(eglSwapBuffers(iEglDisplay, 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, KWindowSize.iWidth, KWindowSize.iHeight);
       
   367         // Swap the surface buffers
       
   368         EGL_CHECK_ERRORL(pfnEglSwapBuffersRegionNok(iEglDisplay, 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(KTestStep0020, 0, 0, 0,
       
   374             KIterationsToTest, KWindowSize.iWidth * KWindowSize.iHeight);
       
   375     CleanupStack::PopAndDestroy(rects);
       
   376     }