--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/graphicstest/uibench/s60/src/tests_egl/teglswapbuffer.cpp Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,376 @@
+// Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// This class does performance tests for eglSwapBuffers() and eglSwapBuffersRegionNOK().
+// The function eglSwapBuffersRegionNOK() is a vendor specific EGL extension and allows users to
+// perform region based surface updates. The test should show how the performance of the
+// extension function compares to the default one.
+//
+
+
+/**
+ @file
+ @test
+ @internalComponent - Internal Symbian test code
+*/
+
+
+#include "teglswapbuffer.h"
+
+#include <VG/openvg.h>
+
+
+// If the condition that is passed to the macro is false
+// the macro leaves with the EGL error code
+#define EGL_CHECK_ERRORL(PASS) { if (!(PASS)) { SetTestStepResult(EFail); ERR_PRINTF2(KErrEgl, eglGetError()); User::Leave(eglGetError()); } }
+
+// Configuration for a Color16MAP - Window
+static const EGLint KConfigAttribs[] =
+ {
+ EGL_BUFFER_SIZE, 32,
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_ALPHA_SIZE, 8,
+ EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT,
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT | EGL_VG_ALPHA_FORMAT_PRE_BIT,
+ EGL_NONE
+ };
+
+// Additional attributes for the window surface
+static const EGLint KWindowSurfaceAttribs[] =
+ {
+ EGL_VG_ALPHA_FORMAT, EGL_VG_ALPHA_FORMAT_PRE,
+ EGL_NONE
+ };
+
+// The test draws alternating backgrounds to show the affect
+// of different swapBuffer functions
+static const TInt KMaxClearColors = 2;
+static const VGfloat KClearColors[KMaxClearColors][4] =
+ {
+ {0.5f, 0.5f, 0.5f, 1.0f}, // gray
+ {0.1f, 0.2f, 0.4f, 1.0f} // blue
+ };
+
+// Datatype for a function pointer to eglSwapBuffersRegionNOK()
+typedef EGLBoolean (*TFPtrEglSwapBuffersRegionNok) (EGLDisplay dpy, EGLSurface surface, EGLint numRects, const EGLint* rects);
+
+// Number of iterations, it defines how often the swapBuffer function is called
+const TInt KIterationsToTest = 1000;
+
+// Maximum number of rectangles for eglSwapBuffersRegionNOK() stress test
+const TInt KStressTestMaxNoRects = 100;
+// Defines the increase of number of rectangles for each iteration
+const TInt KStressTestNoRectsStepSize = 5;
+// Size of the dirty rectangles for the stress test
+const TSize KStressTestRectSize(10, 10);
+// Gap between the dirty Rectangles
+const TInt KStressTestRectGap = 3;
+
+// Window dimensions
+const TSize KWindowSize(200, 200);
+const TPoint KWindowPosition(30, 30);
+// Region dimensions (top left hand corner and bottom right hand corner)
+const TRect KRegionRect(50, 50, 60, 60);
+
+// This test step meassures the performance of eglSwapBuffers()
+_LIT(KTestStep0018,"GRAPHICS-UI-BENCH-S60-0018");
+// This test step meassures the performance of eglSwapBuffersRegionNOK()
+_LIT(KTestStep0019,"GRAPHICS-UI-BENCH-S60-0019");
+// This test step meassures the performance of eglSwapBuffersRegionNOK() with a lot of dirty rectangles
+_LIT(KTestStep0020,"GRAPHICS-UI-BENCH-S60-0020");
+
+_LIT(KErrEgl, "EGL error 0x%x");
+_LIT(KErrEglConfigNotSupported, "EGL config is not supported.");
+_LIT(KInfoRectangles, "Number of dirty rectangles: %d");
+_LIT(KWarnStressTestRectCount, "Dirty rectangles for stress test don't fit onto window surface (%d of %d).");
+
+
+CTEglSwapBuffer::CTEglSwapBuffer()
+ {
+ SetTestStepName(KTEglSwapBuffer);
+ }
+
+CTEglSwapBuffer::~CTEglSwapBuffer()
+ {
+ // Make sure that this EGL status is active
+ eglMakeCurrent(iEglDisplay, iEglSurface, iEglSurface, iEglContext);
+ if (iEglContext != EGL_NO_CONTEXT)
+ {
+ eglDestroyContext(iEglDisplay, iEglContext);
+ }
+ if (iEglSurface != EGL_NO_SURFACE)
+ {
+ eglDestroySurface(iEglDisplay, iEglSurface);
+ }
+ // Call eglMakeCurrent() to ensure the surfaces and contexts are truly destroyed
+ eglMakeCurrent(iEglDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ eglTerminate(iEglDisplay);
+ eglReleaseThread();
+
+ iWindow.Close();
+ iWindowGroup.Close();
+ iWs.Close();
+ }
+
+/**
+ * It's called by the test framework before the actual test. It's used
+ * to do the preparation for the test. It's important to call the
+ * baseclass implementation also.
+ *
+ * @return TVerdict code
+ */
+TVerdict CTEglSwapBuffer::doTestStepPreambleL()
+ {
+ CTe_graphicsperformanceSuiteStepBase::doTestStepPreambleL();
+
+ // Establish the connection to the window server and create
+ // a WindowGroup and a Window object
+ TESTNOERRORL(iWs.Connect());
+ iWindowGroup = RWindowGroup(iWs);
+ TESTNOERRORL(iWindowGroup.Construct(0));
+ iWindow = RWindow(iWs);
+ // The window is automatically fullscreen if it's a child of a window group
+ TESTNOERRORL(iWindow.Construct(iWindowGroup, reinterpret_cast<TUint32>(this)));
+ iWindow.SetSize(KWindowSize);
+ iWindow.SetPosition(KWindowPosition);
+ iWindow.Activate();
+
+ // Create display object
+ iEglDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+ EGL_CHECK_ERRORL(iEglDisplay != EGL_NO_DISPLAY);
+ EGL_CHECK_ERRORL(eglInitialize(iEglDisplay, 0, 0));
+
+ // Choose EGL config
+ EGLConfig matchingConfigs[1];
+ EGLint numConfigs = 0;
+ eglChooseConfig(iEglDisplay, KConfigAttribs, matchingConfigs, 1, &numConfigs);
+ if (numConfigs <= 0) // Abort the test if the EGL config is not supported
+ {
+ ERR_PRINTF1(KErrEglConfigNotSupported);
+ SetTestStepError(KErrNotSupported);
+ return TestStepResult();
+ }
+
+ // Use OpenVG to draw
+ EGL_CHECK_ERRORL(eglBindAPI(EGL_OPENVG_API));
+
+ // Create the window surface and the egl context and make them current
+ iEglSurface = eglCreateWindowSurface(iEglDisplay, matchingConfigs[0], &iWindow, KWindowSurfaceAttribs);
+ EGL_CHECK_ERRORL(iEglSurface != EGL_NO_SURFACE);
+ iEglContext = eglCreateContext(iEglDisplay, matchingConfigs[0], EGL_NO_CONTEXT, NULL);
+ EGL_CHECK_ERRORL(iEglContext != EGL_NO_CONTEXT);
+ EGL_CHECK_ERRORL(eglMakeCurrent(iEglDisplay, iEglSurface, iEglSurface, iEglContext));
+
+ return TestStepResult();
+ }
+
+/**
+ * Override of base class pure virtual function.
+ * This implementation only gets called if the base class doTestStepPreambleL() did
+ * not leave. That being the case, the current test result value should be EPass.
+ *
+ * @return TVerdict code
+ */
+TVerdict CTEglSwapBuffer::doTestStepL()
+ {
+ // Tests the performance of eglSwapBuffers()
+ SetTestStepID(KTestStep0018);
+ TRAPD(err, EglSwapBufferL());
+ if (err != KErrNone)
+ {
+ SetTestStepResult(EAbort);
+ }
+ RecordTestResultL();
+
+ // Tests the maximum performance of eglSwapBuffersRegionNOK()
+ SetTestStepID(KTestStep0019);
+ TRAP(err, EglSwapBufferRegionL());
+ if (err != KErrNone)
+ {
+ SetTestStepResult(EAbort);
+ }
+ RecordTestResultL();
+
+ // Stress tests the performance of eglSwapBuffersRegionNOK()
+ SetTestStepID(KTestStep0020);
+ for (TInt noRects = KStressTestNoRectsStepSize; noRects <= KStressTestMaxNoRects; noRects += KStressTestNoRectsStepSize)
+ {
+ // TRAP here is on purpose, normally you shouldn't use it in loops
+ TRAP(err, EglSwapBufferRegionStressL(noRects));
+ if (err != KErrNone)
+ {
+ SetTestStepResult(EAbort);
+ }
+ }
+ RecordTestResultL();
+
+ // Close the test and return result to the testframework
+ CloseTMSGraphicsStep();
+ return TestStepResult();
+ }
+
+/**
+@SYMTestCaseID GRAPHICS-UI-BENCH-S60-0018
+
+@SYMTestPriority 1
+
+@SYMPREQ 2677
+
+@SYMTestCaseDesc
+Tests how long it takes to swap window surface buffers if the whole surface is updated.
+
+@SYMTestActions
+Clear the window surface with alternating background colors, swap the surface buffers
+and measure how long it takes.
+
+@SYMTestExpectedResults
+Test should pass and print the average framerate to a log file.
+*/
+void CTEglSwapBuffer::EglSwapBufferL()
+ {
+ // Initialise uibench and reset the timer
+ iProfiler->InitResults();
+ // Perform the test
+ for(TInt i = KIterationsToTest; i > 0; --i)
+ {
+ // Clean the surface with the background color
+ vgSetfv(VG_CLEAR_COLOR, 4, KClearColors[i % KMaxClearColors]);
+ vgClear(0, 0, KWindowSize.iWidth, KWindowSize.iHeight);
+ // Swap the surface buffers
+ EGL_CHECK_ERRORL(eglSwapBuffers(iEglDisplay, iEglSurface));
+ }
+ // Mark the time and print the results to the log file
+ iProfiler->MarkResultSetL();
+ iProfiler->ResultsAnalysisFrameRate(KTestStep0018, 0, 0, 0,
+ KIterationsToTest, KWindowSize.iWidth * KWindowSize.iHeight);
+ }
+
+/**
+@SYMTestCaseID GRAPHICS-UI-BENCH-S60-0019
+
+@SYMTestPriority 1
+
+@SYMPREQ 2677
+
+@SYMTestCaseDesc
+Tests how long it takes to swap window surface buffers if only a small region is updated. This
+test should show the maximum possible performance increase.
+
+@SYMTestActions
+Clear the window surface with alternating background colors, swap the surface buffers
+and measure how long it takes.
+
+@SYMTestExpectedResults
+Test should pass and print the average framerate to a log file.
+*/
+void CTEglSwapBuffer::EglSwapBufferRegionL()
+ {
+ // Number of rectangles
+ EGLint count = 1;
+ // Rectangle for partial swap buffer function
+ EGLint rects[] = {KRegionRect.iTl.iX, KRegionRect.iTl.iY, KRegionRect.Width(), KRegionRect.Height()};
+ // Get the function pointer for eglSwapBuffersRegionNOK()
+ TFPtrEglSwapBuffersRegionNok pfnEglSwapBuffersRegionNok = reinterpret_cast<TFPtrEglSwapBuffersRegionNok>(eglGetProcAddress("eglSwapBuffersRegionNOK"));
+ EGL_CHECK_ERRORL(pfnEglSwapBuffersRegionNok);
+
+ // Clear the surface
+ vgSetfv(VG_CLEAR_COLOR, 4, KClearColors[0]);
+ vgClear(0, 0, KWindowSize.iWidth, KWindowSize.iHeight);
+ EGL_CHECK_ERRORL(eglSwapBuffers(iEglDisplay, iEglSurface));
+
+ // Initialise uibench and reset the timer
+ iProfiler->InitResults();
+ // Perform the test
+ for(TInt i = KIterationsToTest; i > 0; --i)
+ {
+ // Clean the surface with the background color
+ vgSetfv(VG_CLEAR_COLOR, 4, KClearColors[i % KMaxClearColors]);
+ vgClear(0, 0, KWindowSize.iWidth, KWindowSize.iHeight);
+ // Swap the surface buffers
+ EGL_CHECK_ERRORL(pfnEglSwapBuffersRegionNok(iEglDisplay, iEglSurface, count, rects));
+ }
+ // Mark the time and print the results to the log file
+ iProfiler->MarkResultSetL();
+ iProfiler->ResultsAnalysisFrameRate(KTestStep0019, 0, 0, 0,
+ KIterationsToTest, KWindowSize.iWidth * KWindowSize.iHeight);
+ }
+
+/**
+@SYMTestCaseID GRAPHICS-UI-BENCH-S60-0020
+
+@SYMTestPriority 1
+
+@SYMPREQ 2677
+
+@SYMTestCaseDesc
+Tests how long it takes to swap window surface buffers if only a small region is updated. This
+test should show the maximum possible performance increase.
+
+@SYMTestActions
+Clear the window surface with alternating background colors, swap the surface buffers
+and measure how long it takes.
+
+@SYMTestExpectedResults
+Test should pass and print the average framerate to a log file.
+*/
+void CTEglSwapBuffer::EglSwapBufferRegionStressL(EGLint aCount)
+ {
+ TInt* rects = static_cast<TInt*>(User::AllocLC(sizeof(TInt) * 4 * aCount));
+ TInt actualRectCount = 0;
+ TInt idx = 0;
+ for (TInt y = 0; (y < KWindowSize.iHeight - KStressTestRectSize.iHeight - 1) && (actualRectCount < aCount); y += KStressTestRectSize.iHeight + KStressTestRectGap)
+ {
+ for (TInt x = 0; (x < KWindowSize.iWidth - KStressTestRectSize.iWidth - 1) && (actualRectCount < aCount); x += KStressTestRectSize.iWidth + KStressTestRectGap)
+ {
+ rects[idx++] = x;
+ rects[idx++] = y;
+ rects[idx++] = KStressTestRectSize.iWidth;
+ rects[idx++] = KStressTestRectSize.iHeight;
+ actualRectCount++;
+ }
+ }
+ TESTL(actualRectCount > 0);
+ if (actualRectCount != aCount)
+ {
+ WARN_PRINTF3(KWarnStressTestRectCount, actualRectCount, aCount);
+ }
+
+ // Get the function pointer for eglSwapBuffersRegionNOK()
+ TFPtrEglSwapBuffersRegionNok pfnEglSwapBuffersRegionNok = reinterpret_cast<TFPtrEglSwapBuffersRegionNok>(eglGetProcAddress("eglSwapBuffersRegionNOK"));
+ EGL_CHECK_ERRORL(pfnEglSwapBuffersRegionNok);
+
+ // Clear the surface
+ vgSetfv(VG_CLEAR_COLOR, 4, KClearColors[0]);
+ vgClear(0, 0, KWindowSize.iWidth, KWindowSize.iHeight);
+ EGL_CHECK_ERRORL(eglSwapBuffers(iEglDisplay, iEglSurface));
+
+ // Initialise uibench and reset the timer
+ iProfiler->InitResults();
+ // Perform the test
+ for(TInt i = KIterationsToTest; i > 0; --i)
+ {
+ // Clean the surface with the background color
+ vgSetfv(VG_CLEAR_COLOR, 4, KClearColors[i % KMaxClearColors]);
+ vgClear(0, 0, KWindowSize.iWidth, KWindowSize.iHeight);
+ // Swap the surface buffers
+ EGL_CHECK_ERRORL(pfnEglSwapBuffersRegionNok(iEglDisplay, iEglSurface, actualRectCount, rects));
+ }
+ // Mark the time and print the results to the log file
+ iProfiler->MarkResultSetL();
+ INFO_PRINTF2(KInfoRectangles, aCount);
+ iProfiler->ResultsAnalysisFrameRate(KTestStep0020, 0, 0, 0,
+ KIterationsToTest, KWindowSize.iWidth * KWindowSize.iHeight);
+ CleanupStack::PopAndDestroy(rects);
+ }