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