--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/egl/egltest/endpointtestsuite/automated/tsrc/egltest_surface.cpp Tue Aug 31 16:31:06 2010 +0300
@@ -0,0 +1,1106 @@
+// Copyright (c) 2007-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:
+//
+
+/**
+ @file
+ @test
+ @internalComponent - Internal Symbian test code
+*/
+
+
+#include "egltest_surface.h"
+#include "egltest_endpoint_images.h"
+#include <graphics/surfaceconfiguration.h>
+#include <e32std.h>
+#include <e32math.h>
+#include <VG/vgu.h>
+
+
+#define SURF_ASSERT(x) { if (!(x)) { RDebug::Printf("ASSERT(%s) failed at %s:%d", #x, __FILE__, __LINE__); User::Panic(_L("ASSERT SURF"), __LINE__); }}
+
+// Macros for indicating what is what.
+#define SIZE(x, y) x, y
+#define Buffers(x) x
+#define DefaultAlignment 32 // Pick some value that is valid.
+#define Alignment(x) x
+#define Stride(x) x
+#define DefaultStride 0
+// Note: Offset to first buffer.
+#define Offset(x) x
+#define WindowPos(x, y) x, y
+#define WindowMode(m) m
+
+#define LARGEST_POSSIBLE_FLAG 0x80000000
+
+static const TSurfaceParamsCommon KSurfaceParams[] =
+{
+ {
+ EStandardSurface,
+ SIZE(100, 100),
+ Buffers(2),
+ DefaultAlignment,
+ DefaultStride,
+ Offset(0),
+ EUidPixelFormatARGB_8888_PRE,
+ EFalse,
+ { 0 },
+ WindowPos(0, 0),
+ WindowMode(EColor16MAP)
+ },
+ {
+ EBadAttribSurface,
+ SIZE(100, 100),
+ Buffers(2),
+ DefaultAlignment,
+ DefaultStride,
+ Offset(0),
+ EUidPixelFormatARGB_8888_PRE,
+ ETrue,
+ { 1, 1, EGL_NONE },
+ WindowPos(0, 0),
+ WindowMode(EColor16MAP)
+ },
+ {
+ EEmptyAttribSurface,
+ SIZE(100, 100),
+ Buffers(2),
+ DefaultAlignment,
+ DefaultStride,
+ Offset(0),
+ EUidPixelFormatARGB_8888_PRE,
+ ETrue,
+ { EGL_NONE },
+ WindowPos(0, 0),
+ WindowMode(EColor16MAP)
+ },
+ {
+ EStandard128sqSurface,
+ SIZE(128, 128),
+ Buffers(3),
+ DefaultAlignment,
+ DefaultStride,
+ Offset(0),
+ EUidPixelFormatARGB_8888_PRE,
+ EFalse,
+ { 0 },
+ WindowPos(20, 20),
+ WindowMode(EColor16MAP)
+ },
+ {
+ EUnusualStrideSurface,
+ SIZE(167,263),
+ Buffers(2),
+ Alignment(8),
+ Stride(167*4+64),
+ Offset(200),
+ EUidPixelFormatARGB_8888_PRE,
+ EFalse,
+ { 0 },
+ WindowPos(0, 0),
+ WindowMode(EColor16MAP)
+ },
+ {
+ EUnalignedPixelSizeSurface,
+ SIZE(103, 107),
+ Buffers(2),
+ Alignment(8),
+ Stride(103*4),
+ Offset(0),
+ EUidPixelFormatARGB_8888_PRE,
+ EFalse,
+ { 0 },
+ WindowPos(0, 0),
+ WindowMode(EColor16MAP)
+ },
+ {
+ ELargeSurface,
+ SIZE(800, 600),
+ Buffers(2),
+ DefaultAlignment,
+ DefaultStride,
+ Offset(0),
+ EUidPixelFormatARGB_8888_PRE,
+ EFalse,
+ { 0 },
+ WindowPos(0, 0),
+ WindowMode(EColor16MAP)
+ },
+ {
+ ELargestPossibleSurface,
+ SIZE(LARGEST_POSSIBLE_FLAG, LARGEST_POSSIBLE_FLAG),
+ Buffers(2),
+ DefaultAlignment,
+ DefaultStride,
+ Offset(0),
+ EUidPixelFormatARGB_8888_PRE,
+ EFalse,
+ { 0 },
+ WindowPos(0, 0),
+ WindowMode(EColor16MAP)
+ },
+ {
+ ESmallSurface,
+ SIZE(16, 16),
+ Buffers(1),
+ DefaultAlignment,
+ DefaultStride,
+ Offset(0),
+ EUidPixelFormatARGB_8888_PRE,
+ EFalse,
+ { 0 },
+ WindowPos(0, 0),
+ WindowMode(EColor16MAP)
+ },
+ {
+ ETinySurface,
+ SIZE(8, 8),
+ Buffers(1),
+ DefaultAlignment,
+ DefaultStride,
+ Offset(0),
+ EUidPixelFormatARGB_8888_PRE,
+ EFalse,
+ { 0 },
+ WindowPos(0, 0),
+ WindowMode(EColor16MAP)
+ },
+};
+
+const TInt KSurfaceMaxIndex = sizeof(KSurfaceParams) / sizeof(KSurfaceParams[0]);
+
+struct TSurfaceSize
+ {
+ TInt iWidth;
+ TInt iHeight;
+ };
+
+static const TSurfaceSize KSurfaceSizes[] =
+ {
+ { 320, 240 },
+ { 640, 480 },
+ { 720, 480 },
+ { 854, 480 },
+ { 720, 576 },
+ { 854, 576 },
+ { 1280, 720 },
+ { 1024, 768 },
+ { 1280, 1024 },
+ { 1920, 1080 },
+ { 1600, 1200 },
+#if 0
+ { 2048, 1536 },
+ { 2560, 1920 },
+ { 3648, 2736 },
+ { 4216, 2638 },
+ { 4000, 3000 },
+ { 4616, 2600 },
+#endif
+ };
+
+const TInt KMaxSurfaceSizes = sizeof(KSurfaceSizes) / sizeof(KSurfaceSizes[0]);
+
+LOCAL_C TUint RandomNumberInRange(TUint aLow, TUint aHigh)
+ {
+ TReal32 rand = Math::Random();
+ rand /= KMaxTUint;
+ rand *= aHigh - aLow;
+ rand += aLow;
+ return TUint(rand);
+ }
+
+
+void CSurface::CreateL(TInt aIndex)
+ {
+ CreateL(aIndex, TPoint(0, 0));
+ }
+
+
+TSize CSurface::Size()
+ {
+ return iActualSize;
+ }
+
+
+TInt CSurface::SizeInBytes() const
+ {
+ RSurfaceManager::TInfoBuf infoBuf;
+ RSurfaceManager surfMgr;
+ TInt err = surfMgr.Open();
+ if (err != KErrNone)
+ {
+ RDebug::Printf("Error opening surface manager... Err=%d", err);
+ return 0;
+ }
+ err = surfMgr.SurfaceInfo(SurfaceId(), infoBuf);
+ if (err != KErrNone)
+ {
+ RDebug::Printf("Could not get surface info - err = %d", err);
+ return 0;
+ }
+ TInt size = infoBuf().iBuffers * infoBuf().iSize.iHeight * infoBuf().iStride;
+ surfMgr.Close();
+ return size;
+ }
+
+
+CRawSurface* CRawSurface::NewL()
+ {
+ CRawSurface* obj = new (ELeave) CRawSurface();
+ CleanupStack::PushL(obj);
+ obj->ConstructL();
+ CleanupStack::Pop(obj);
+ return obj;
+ }
+
+
+
+CRawSurface::CRawSurface() : iDrawBuffer(0), iBuffers(0)
+ {
+ }
+
+
+void CRawSurface::ConstructL()
+ {
+ iSurfaceId = TSurfaceId::CreateNullId();
+ User::LeaveIfError(iSurfaceManager.Open());
+ User::LeaveIfError(iSurfaceUpdate.Connect());
+ }
+
+
+CRawSurface::~CRawSurface()
+ {
+ iSurfaceUpdate.Close();
+ if(!iSurfaceId.IsNull())
+ {
+ iSurfaceManager.CloseSurface(iSurfaceId);
+ }
+ iSurfaceManager.Close();
+ }
+
+
+TInt CRawSurface::PixelSize(TUidPixelFormat aPixelFormat)
+ {
+ switch(aPixelFormat)
+ {
+ case EUidPixelFormatARGB_8888_PRE:
+ case EUidPixelFormatARGB_8888:
+ case EUidPixelFormatABGR_8888:
+ case EUidPixelFormatABGR_8888_PRE:
+ return 4;
+
+ case EUidPixelFormatARGB_4444:
+ case EUidPixelFormatRGB_565:
+ return 2;
+
+ default:
+ SURF_ASSERT(0);
+ break;
+ }
+ return 0; // Make sure no compiler moans about "not all paths return a value".
+ }
+
+
+void CRawSurface::GetSurfAttribs(RSurfaceManager::TSurfaceCreationAttributesBuf &aSurfaceAttribs,
+ TInt aIndex, TInt aSizeIndex)
+ {
+ SURF_ASSERT(aIndex < KSurfaceMaxIndex);
+ SURF_ASSERT(aIndex == KSurfaceParams[aIndex].iIndex);
+ iParamIndex = aIndex;
+ if (KSurfaceParams[aIndex].iXSize & LARGEST_POSSIBLE_FLAG)
+ {
+
+ aSurfaceAttribs().iSize =
+ TSize(KSurfaceSizes[aSizeIndex].iWidth, KSurfaceSizes[aSizeIndex].iHeight);
+ }
+ else
+ {
+ aSurfaceAttribs().iSize =
+ TSize(KSurfaceParams[aIndex].iXSize, KSurfaceParams[aIndex].iYSize);
+ }
+ iBuffers = KSurfaceParams[aIndex].iBuffers;
+ aSurfaceAttribs().iBuffers = iBuffers;
+ aSurfaceAttribs().iPixelFormat = KSurfaceParams[aIndex].iPixelFormat;
+ TInt stride = KSurfaceParams[aIndex].iStrideInBytes;
+ if (stride == 0)
+ {
+ stride = aSurfaceAttribs().iSize.iWidth * PixelSize(KSurfaceParams[aIndex].iPixelFormat);
+ }
+ aSurfaceAttribs().iStride = stride;
+ aSurfaceAttribs().iOffsetToFirstBuffer = KSurfaceParams[aIndex].iOffsetToFirstBuffer;
+ aSurfaceAttribs().iAlignment = KSurfaceParams[aIndex].iAlignment;
+ aSurfaceAttribs().iContiguous = EFalse;
+ aSurfaceAttribs().iCacheAttrib = RSurfaceManager::ECached;
+ aSurfaceAttribs().iOffsetBetweenBuffers = 0;
+ aSurfaceAttribs().iSurfaceHints = NULL;
+ aSurfaceAttribs().iHintCount = 0;
+ aSurfaceAttribs().iMappable = ETrue;
+ }
+
+
+void CRawSurface::CreateL(TInt aIndex, const TPoint &/* aPoint */)
+ {
+ RSurfaceManager::TSurfaceCreationAttributesBuf surfaceAttribs;
+ SURF_ASSERT(aIndex < KSurfaceMaxIndex);
+ TInt sizeIndex = 0;
+ if (KSurfaceParams[aIndex].iXSize & LARGEST_POSSIBLE_FLAG)
+ {
+ sizeIndex = KMaxSurfaceSizes-1;
+
+ }
+ TInt err = KErrNone;
+ do
+ {
+ GetSurfAttribs(surfaceAttribs, aIndex, sizeIndex);
+ err = iSurfaceManager.CreateSurface(surfaceAttribs, iSurfaceId);
+ iActualSize = surfaceAttribs().iSize;
+ sizeIndex--;
+ }
+ while(err != KErrNone && sizeIndex >= 0);
+ User::LeaveIfError(err);
+ }
+
+
+TUint8* CRawSurface::MapSurfaceAndGetInfoLC(RSurfaceManager::TSurfaceInfoV01& aInfo)
+ {
+ SURF_ASSERT(!iSurfaceId.IsNull());
+ User::LeaveIfError(iSurfaceManager.MapSurface(iSurfaceId, iSurfaceChunk));
+ CleanupClosePushL(iSurfaceChunk);
+ RSurfaceManager::TInfoBuf infoBuf;
+ User::LeaveIfError(iSurfaceManager.SurfaceInfo(iSurfaceId, infoBuf));
+ aInfo = infoBuf();
+ TInt offset = -1000; // So we hopefully detect when it goes horribly wrong.
+ User::LeaveIfError(iSurfaceManager.GetBufferOffset(iSurfaceId, iDrawBuffer, offset));
+ SURF_ASSERT(offset >= 0);
+ return iSurfaceChunk.Base() + offset;
+ }
+
+
+void CRawSurface::DrawContentL(TInt aImageIndex)
+ {
+ CTestCFbsImage *image = CTestCFbsImage::NewL(aImageIndex);
+ CleanupStack::PushL(image);
+
+ RSurfaceManager::TSurfaceInfoV01 info;
+ TUint8 *dataAddress = MapSurfaceAndGetInfoLC(info);
+ TInt stride = info.iStride;
+
+ CFbsBitmap *bitmap = image->Bitmap();
+ TDisplayMode displaymode = bitmap->DisplayMode();
+ TInt pixelStride = stride / CFbsBitmap::ScanLineLength(1, displaymode);
+ for(TInt y = 0; y < image->Size().iHeight; y++)
+ {
+ TPtr8 buf(dataAddress + y * stride, stride);
+
+ // TODO: We need to check that the bitsperpixel matches between the surface and bitmap.
+ bitmap->GetScanLine(buf, TPoint(0, y), pixelStride, displaymode);
+ }
+
+ CleanupStack::PopAndDestroy(2, image);
+ }
+
+void CRawSurface::DrawContentL(const TRgb& aColour)
+ {
+ //Map the surface and get its info.
+ RSurfaceManager::TSurfaceInfoV01 surfaceInfo;
+ TUint32* buffer = (TUint32*)MapSurfaceAndGetInfoLC(surfaceInfo);
+
+ //Currently this function only supports drawing into ARGB_8888_PRE surfaces.
+ //This is because the only test that uses this function uses this type of surface.
+ //If this functionallity needs expanding, you must correctly convert the TRgb colour
+ //and pack it into the surface buffer correctly.
+ SURF_ASSERT(surfaceInfo.iPixelFormat == EUidPixelFormatARGB_8888_PRE);
+
+ TUint32 fillColour = aColour._Color16MAP();
+
+ //Loop over each pixel in the surface and colour it.
+ //This is deliberately slow since it is only used for the tearing test
+ //and we want to spend most of our time drawing so that the chances of the other thread
+ //picking up a buffer in the middle of drawing is increased.
+ for(TInt y=0; y < surfaceInfo.iSize.iHeight; ++y)
+ {
+ for(TInt x=0; x < surfaceInfo.iSize.iWidth; ++x)
+ {
+ buffer[x] = fillColour;
+ }
+ buffer += surfaceInfo.iStride >> 2;
+ }
+
+ CleanupStack::PopAndDestroy();
+ }
+
+
+void CRawSurface::DrawComplexL(const TRgb& aColour)
+ {
+ DrawContentL(aColour);
+ }
+
+
+TInt CRawSurface::SubmitContent(TBool aShouldWaitForDisplay, TInt /* aRectsIndex */)
+ {
+ TRequestStatus displayNotify = KRequestPending;
+ TTimeStamp timeStamp;
+
+ if(aShouldWaitForDisplay)
+ {
+ Notify(ENotifyWhenDisplayed, displayNotify, 0);
+ }
+
+ TInt err = iSurfaceUpdate.SubmitUpdate(KAllScreens, iSurfaceId, iDrawBuffer, NULL);
+ if (err != KErrNone)
+ {
+ if (err != KErrNone)
+ {
+ RDebug::Printf("%s:%d: SubmitUpdate gave unexpected error %d", __FILE__, __LINE__, err);
+ }
+ return err;
+ }
+ iDrawBuffer = (iDrawBuffer + 1) % iBuffers;
+
+ if(aShouldWaitForDisplay)
+ {
+ TUint32 dummy;
+ err = WaitFor(ENotifyWhenDisplayed, displayNotify, 100 * 1000, dummy);
+ if (err != KErrNone && err != KErrNotVisible && err != KErrOverflow)
+ {
+// RDebug::Printf("%s:%d: NotifyWhenDisplayed gave unexpected error %d", __FILE__, __LINE__, err);
+ return err;
+ }
+ }
+ return KErrNone;
+ }
+
+
+TSurfaceId CRawSurface::SurfaceId() const
+ {
+ return iSurfaceId;
+ }
+
+
+void CRawSurface::GetSurfaceParamsL(TSurfaceParamsRemote &aParams)
+ {
+ aParams.iCommonParams = KSurfaceParams[iParamIndex];
+ aParams.iCommonParams.iBuffers = iBuffers; // May have been changed if it's a single buffered surface...
+ aParams.iSurfaceId = SurfaceId();
+ }
+
+const TText *CRawSurface::GetSurfaceTypeStr() const
+ {
+ return _S("CRawSurface");
+ }
+
+TInt CRawSurface::Notify(TNotification aWhen, TRequestStatus& aStatus, TUint32 aXTimes)
+ {
+ aStatus = KRequestPending;
+ switch(aWhen)
+ {
+ case ENotifyWhenAvailable:
+ iSurfaceUpdate.NotifyWhenAvailable(aStatus);
+ break;
+ case ENotifyWhenDisplayed:
+ iSurfaceUpdate.NotifyWhenDisplayed(aStatus, iTimeStamp);
+ break;
+ case ENotifyWhenDispXTimes:
+ iSurfaceUpdate.NotifyWhenDisplayedXTimes(aXTimes, aStatus);
+ break;
+ default:
+ RDebug::Printf("%s:%d: Invalid notification: %d. Panicking...", __FILE__, __LINE__, aWhen);
+ User::Panic(_L("CRawSurface::Notify()"), __LINE__);
+ break;
+ }
+ return KErrNone;
+ }
+
+
+TInt CRawSurface::WaitFor(TNotification aWhen, TRequestStatus& aStatus, TInt aTimeoutInMicroSeconds, TUint32& aTimeStamp)
+ {
+ RTimer timer;
+ TInt err = timer.CreateLocal();
+ if (err != KErrNone)
+ {
+ RDebug::Printf("%s:%d: Could not create timer... err= %d", __FILE__, __LINE__, err);
+ return err;
+ }
+ TRequestStatus timerStatus = KRequestPending;
+#if __WINS__
+ // Windows timer isn't very precise - add some "fuzz" to the timeout to ensure we do not wait "too little".
+ const TInt KTimeOutExtra = 20000;
+#else
+ // On hardware, we should be able to run with less "fuzz".
+ const TInt KTimeOutExtra = 10000;
+#endif
+ timer.HighRes(timerStatus, aTimeoutInMicroSeconds + KTimeOutExtra);
+ User::WaitForRequest(timerStatus, aStatus);
+ if (aStatus == KRequestPending)
+ {
+ if (aWhen == ENotifyWhenDisplayed)
+ {
+ aTimeStamp = User::FastCounter();
+ }
+ return KErrTimedOut;
+ }
+ if (aWhen == ENotifyWhenDisplayed)
+ {
+ aTimeStamp = iTimeStamp();
+ }
+ timer.Cancel();
+ timer.Close();
+ TInt result = aStatus.Int();
+ aStatus = KRequestPending;
+ return result;
+ }
+
+const TText *CRawSingleBufferSurface::GetSurfaceTypeStr() const
+ {
+ return _S("CRawSingleBufferedSurface");
+ }
+
+CRawSingleBufferSurface *CRawSingleBufferSurface::NewL()
+ {
+ CRawSingleBufferSurface* obj = new (ELeave) CRawSingleBufferSurface();
+ CleanupStack::PushL(obj);
+ obj->ConstructL();
+ CleanupStack::Pop(obj);
+ return obj;
+ }
+
+
+void CRawSingleBufferSurface::CreateL(TInt aIndex, const TPoint & /*aPoint */)
+ {
+ RSurfaceManager::TSurfaceCreationAttributesBuf surfaceAttribs;
+
+ TInt sizeIndex = 0;
+ if (KSurfaceParams[aIndex].iXSize & LARGEST_POSSIBLE_FLAG)
+ {
+ sizeIndex = KMaxSurfaceSizes-1;
+ }
+ TInt err = KErrNone;
+ do
+ {
+ GetSurfAttribs(surfaceAttribs, aIndex, sizeIndex);
+ iBuffers = 1;
+ surfaceAttribs().iBuffers = 1;
+ err = iSurfaceManager.CreateSurface(surfaceAttribs, iSurfaceId);
+ iActualSize = surfaceAttribs().iSize;
+ sizeIndex--;
+ }
+ while(err != KErrNone && sizeIndex >= 0);
+ }
+
+CRawSingleBufferSurface::~CRawSingleBufferSurface()
+ {
+ }
+
+
+TInt CEglSurfaceBase::Activate()
+ {
+ if (!eglMakeCurrent(iDisplay, iSurface, iSurface, iContext))
+ {
+ EGLint err = eglGetError();
+ RDebug::Printf("%s:%d: eglMakeCurrent gave error 0x%x", __FILE__, __LINE__, err);
+ return KErrBadHandle;
+ }
+ return KErrNone;
+ }
+
+void CEglSurfaceBase::ActivateL()
+ {
+ User::LeaveIfError(Activate());
+ }
+
+void CEglSurfaceBase::DrawComplexL(const TRgb& aColour)
+ {
+ ActivateL();
+
+ TSize size;
+ eglQuerySurface(iDisplay, iSurface, EGL_WIDTH, &size.iWidth);
+ eglQuerySurface(iDisplay, iSurface, EGL_HEIGHT, &size.iHeight);
+
+ //Paint lots of random circles to keep the GPU busy.
+ for(TInt i=0; i < 300; i++)
+ {
+ VGPaint paint = vgCreatePaint();
+ VGPath path = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1.0f, 0.0f, 0, 0, VG_PATH_CAPABILITY_APPEND_TO);
+
+ TInt minDim = Min(size.iWidth, size.iHeight);
+ VGfloat cx = RandomNumberInRange(0, size.iWidth);
+ VGfloat cy = RandomNumberInRange(0, size.iHeight);
+ VGfloat diameter = RandomNumberInRange(minDim / 20, minDim / 3);
+ TRgb fillColour(RandomNumberInRange(0, 255), RandomNumberInRange(0, 255), RandomNumberInRange(0, 255), RandomNumberInRange(0, 255));
+
+ vguEllipse(path, cx, cy, diameter, diameter);
+ vgSetPaint(paint, VG_FILL_PATH);
+ vgSetColor(paint, fillColour.Value());
+ vgDrawPath(path, VG_FILL_PATH);
+
+ vgDestroyPath(path);
+ vgDestroyPaint(paint);
+ }
+
+ //Paint the top corner with aColour so we can identify the drawing.
+ VGfloat fillColour[4];
+ fillColour[0] = (VGfloat)aColour.Red() / 255.0f;
+ fillColour[1] = (VGfloat)aColour.Green() / 255.0f;
+ fillColour[2] = (VGfloat)aColour.Blue() / 255.0f;
+ fillColour[3] = (VGfloat)aColour.Alpha() / 255.0f;
+
+ vgSetfv(VG_CLEAR_COLOR, 4, fillColour);
+ vgClear(0, 0, 20, size.iHeight);
+ }
+
+void CEglSurfaceBase::DrawContentL(const TRgb& aColour)
+ {
+ ActivateL();
+
+ TSize size;
+ eglQuerySurface(iDisplay, iSurface, EGL_WIDTH, &size.iWidth);
+ eglQuerySurface(iDisplay, iSurface, EGL_HEIGHT, &size.iHeight);
+
+ VGfloat fillColour[4];
+ fillColour[0] = (VGfloat)aColour.Red() / 255.0f;
+ fillColour[1] = (VGfloat)aColour.Green() / 255.0f;
+ fillColour[2] = (VGfloat)aColour.Blue() / 255.0f;
+ fillColour[3] = (VGfloat)aColour.Alpha() / 255.0f;
+
+ vgSetfv(VG_CLEAR_COLOR, 4, fillColour);
+ vgClear(0, 0, size.iWidth, size.iHeight);
+ }
+
+void CEglSurfaceBase::CreateL(TInt aIndex, const TPoint &aOffset)
+ {
+ SURF_ASSERT(aIndex < KSurfaceMaxIndex);
+ SURF_ASSERT(aIndex == KSurfaceParams[aIndex].iIndex);
+
+ TInt sizeIndex = 0;
+ if (KSurfaceParams[aIndex].iXSize & LARGEST_POSSIBLE_FLAG)
+ {
+ sizeIndex = KMaxSurfaceSizes-1;
+ }
+ TInt err = KErrNone;
+ do
+ {
+ TRAP(err, DoCreateL(aIndex, aOffset, sizeIndex));
+ sizeIndex--;
+ }
+ while(err != KErrNone && sizeIndex >= 0);
+ if (err != KErrNone)
+ {
+// RDebug::Printf("%s:%d: err=%d (%d x %d)", __FILE__, __LINE__, err, iActualSize.iWidth, iActualSize.iHeight);
+ User::Leave(err);
+ }
+ }
+
+TInt CEglSurfaceBase::SubmitContent(TBool aShouldWaitForDisplay, TInt /* aRectsIndex */)
+ {
+ TInt err = Activate();
+ if (err != KErrNone)
+ {
+ return err;
+ }
+ if (!eglSwapBuffers(iDisplay, iSurface))
+ {
+ EGLint err = eglGetError();
+ RDebug::Printf("%s:%d: eglSwapBuffers gave error 0x%x", __FILE__, __LINE__, err);
+ return KErrBadHandle;
+ }
+ if (aShouldWaitForDisplay)
+ {
+ // We are cheating: We just wait for a bit to ensure that the swapbuffer is actually finished.
+ // There is no way to determine how long this takes, so we just grab a number that should be
+ // large enough...
+ User::After(100 * 1000); // Wait 100ms.
+ }
+ return KErrNone;
+ }
+
+void CEglSurfaceBase::DrawContentL(TInt aIndex)
+ {
+ ActivateL();
+ CTestVgImage *vgImage = CTestVgImage::NewL(aIndex);
+ CleanupStack::PushL(vgImage);
+ vgDrawImage(vgImage->VGImage());
+ CleanupStack::PopAndDestroy(vgImage);
+ }
+
+void CEglSurfaceBase::GetSurfaceParamsL(TSurfaceParamsRemote &aParams)
+ {
+ RSurfaceManager surfaceManager;
+ User::LeaveIfError(surfaceManager.Open());
+ RSurfaceManager::TInfoBuf infoBuf;
+ TInt err = surfaceManager.SurfaceInfo(SurfaceId(), infoBuf);
+ User::LeaveIfError(err);
+ surfaceManager.Close();
+ RSurfaceManager::TSurfaceInfoV01& info = infoBuf();
+ aParams.iSurfaceId = SurfaceId();
+ aParams.iCommonParams.iAlignment = -1; // N/A
+ aParams.iCommonParams.iBuffers = info.iBuffers;
+ aParams.iCommonParams.iOffsetToFirstBuffer = -1;
+ aParams.iCommonParams.iPixelFormat = info.iPixelFormat;
+ aParams.iCommonParams.iStrideInBytes = info.iStride;
+ aParams.iCommonParams.iXSize = info.iSize.iWidth;
+ aParams.iCommonParams.iYSize = info.iSize.iHeight;
+ aParams.iCommonParams.iUseAttribList = KSurfaceParams[iParamIndex].iUseAttribList;
+ for(TInt i = 0; i < KNumAttribs; i++)
+ {
+ aParams.iCommonParams.iAttribs[i] = KSurfaceParams[iParamIndex].iAttribs[i];
+ }
+ }
+
+
+TInt CEglSurfaceBase::Notify(TNotification /*aWhen*/, TRequestStatus& /*aStatus*/, TUint32 /*aXTImes*/)
+ {
+ return KErrNotSupported;
+ }
+
+TInt CEglSurfaceBase::WaitFor(TNotification /*aWhen*/, TRequestStatus& /*aStatus*/,
+ TInt /*aTimeoutinMicroseconds*/, TUint32 & /*aTimeStamp*/)
+ {
+ return KErrNotSupported;
+ }
+
+void CEglSurfaceBase::BaseCreateL(TInt aIndex, EGLint aSurfaceType)
+ {
+ iParamIndex = aIndex;
+ iDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
+
+ EGLint err;
+ if (iDisplay == EGL_NO_DISPLAY)
+ {
+ err = eglGetError();
+ RDebug::Printf("%s:%d: err = 0x%x", __FILE__, __LINE__, err);
+ User::Leave(KErrNotSupported);
+ }
+
+ EGLint nConfigs = 0;
+
+ // TODO: Need to use differnet config attribs based on aIndex.
+ EGLint configAttribs[] =
+ {
+ EGL_BUFFER_SIZE, 32,
+ EGL_RED_SIZE, 8,
+ EGL_GREEN_SIZE, 8,
+ EGL_BLUE_SIZE, 8,
+ EGL_ALPHA_SIZE, 8,
+ EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
+ EGL_RENDERABLE_TYPE,EGL_OPENVG_BIT,
+ EGL_NONE
+ };
+
+ // Update surfacetype type to match
+ for(TInt i = 0; configAttribs[i] != EGL_NONE; i += 2)
+ {
+ if (configAttribs[i] == EGL_SURFACE_TYPE)
+ {
+ configAttribs[i+1] = aSurfaceType;
+ }
+ }
+ // Need some way to configure the attribs ...
+ eglChooseConfig(iDisplay, configAttribs, &iConfig, 1, &nConfigs);
+ if (!nConfigs)
+ {
+ err = eglGetError();
+ RDebug::Printf("%s:%d: err = %d", __FILE__, __LINE__, err);
+ User::Leave(KErrNotSupported);
+ }
+
+ if (!eglBindAPI(EGL_OPENVG_API))
+ {
+ err = eglGetError();
+ RDebug::Printf("%s:%d: err = %d", __FILE__, __LINE__, err);
+ User::Leave(KErrNotSupported);
+ }
+ iContext = eglCreateContext(iDisplay, iConfig, 0, NULL);
+ if (iContext == EGL_NO_CONTEXT)
+ {
+ err = eglGetError();
+ //RDebug::Printf("%s:%d: err = %d", __FILE__, __LINE__, err);
+ User::Leave(KErrNotSupported);
+ }
+ }
+
+void CEglSurfaceBase::Destroy()
+ {
+ eglMakeCurrent(iDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
+ if (iSurface != EGL_NO_SURFACE)
+ {
+ eglDestroySurface(iDisplay, iSurface);
+ iSurface = EGL_NO_SURFACE;
+ }
+
+ if (iDisplay != EGL_NO_DISPLAY)
+ {
+ eglDestroyContext(iDisplay, iContext);
+ }
+ }
+
+
+class CWindow: public CBase
+ {
+public:
+ static CWindow *NewL(TInt aIndex, const TPoint &aOffset, TInt aSizeIndex);
+ RWindow& Window();
+ ~CWindow();
+private:
+ void ConstructL(TInt aIndex, const TPoint &aOffset, TInt aSizeIndex);
+ CWindow();
+
+private:
+ RWindow iWindow;
+ RWindowGroup iWindowGroup;
+ RWsSession iWsSession;
+ };
+
+
+CWindow* CWindow::NewL(TInt aIndex, const TPoint &aOffset, TInt aSizeIndex)
+ {
+ CWindow *self = new (ELeave) CWindow;
+ CleanupStack::PushL(self);
+ self->ConstructL(aIndex, aOffset, aSizeIndex);
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+
+void CWindow::ConstructL(TInt aIndex, const TPoint &aOffset, TInt aSizeIndex)
+ {
+ RFbsSession::Connect();
+ if (aIndex >= KSurfaceMaxIndex)
+ {
+ User::Leave(KErrOverflow);
+ }
+ User::LeaveIfError(iWsSession.Connect());
+ iWindowGroup = RWindowGroup(iWsSession);
+ User::LeaveIfError(iWindowGroup.Construct((TUint32)this));
+ iWindow = RWindow(iWsSession);
+ User::LeaveIfError(iWindow.Construct(iWindowGroup, -1U));
+ TSurfaceParamsCommon winAttrib = KSurfaceParams[aIndex];
+ TSize winSize;
+ if (winAttrib.iXSize & LARGEST_POSSIBLE_FLAG)
+ {
+ winSize = TSize(KSurfaceSizes[aSizeIndex].iWidth, KSurfaceSizes[aSizeIndex].iHeight);
+ }
+ else
+ {
+ winSize = TSize(winAttrib.iXSize, winAttrib.iYSize);
+ }
+ iWindow.SetExtent(TPoint(winAttrib.iXPos + aOffset.iX, winAttrib.iYPos + aOffset.iY), winSize);
+ iWindow.SetRequiredDisplayMode(winAttrib.iDisplayMode);
+ iWindow.Activate();
+ }
+
+
+CWindow::~CWindow()
+ {
+ iWindow.Close();
+ iWindowGroup.Close();
+ iWsSession.Close();
+ RFbsSession::Disconnect();
+ }
+
+
+CWindow::CWindow()
+ {
+ }
+
+
+RWindow& CWindow::Window()
+ {
+ return iWindow;
+ }
+
+
+CEglWindowSurface* CEglWindowSurface::NewL()
+ {
+ CEglWindowSurface* self = new (ELeave) CEglWindowSurface;
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+
+void CEglWindowSurface::ConstructL()
+ {
+ }
+
+
+CEglWindowSurface::CEglWindowSurface()
+ {
+ }
+
+
+void CEglWindowSurface::DoCreateL(TInt aIndex, const TPoint &aOffset, TInt aSizeIndex)
+ {
+ iParamIndex = aIndex;
+ iWindow = CWindow::NewL(aIndex, aOffset, aSizeIndex);
+ iActualSize = iWindow->Window().Size();
+
+ CEglSurfaceBase::BaseCreateL(aIndex, EGL_WINDOW_BIT);
+
+ iSurface = eglCreateWindowSurface(iDisplay, iConfig, &iWindow->Window(), NULL);
+ if (iSurface == EGL_NO_SURFACE)
+ {
+ EGLint err = eglGetError();
+ RDebug::Printf("%s:%d: err = %x (%d x %d)", __FILE__, __LINE__, err, iActualSize.iWidth, iActualSize.iHeight);
+ User::Leave(KErrNotSupported);
+ }
+ }
+
+
+CEglWindowSurface::~CEglWindowSurface()
+ {
+ Destroy();
+ eglReleaseThread();
+ delete iWindow;
+ }
+
+
+TSurfaceId CEglWindowSurface::SurfaceId() const
+ {
+ // Default constructor for id sets it to a NULL-value, so if no window is created, we get
+ // a defined surface id value that is invalid.
+ TSurfaceId id;
+ if (iWindow)
+ {
+ TSurfaceConfiguration surfConfig;
+ iWindow->Window().GetBackgroundSurface(surfConfig);
+ surfConfig.GetSurfaceId(id);
+ }
+ return id;
+ }
+
+
+const TText *CEglWindowSurface::GetSurfaceTypeStr() const
+ {
+ return _S("CEglWindowSurface");
+ }
+
+
+CEglPBufferSurface::CEglPBufferSurface()
+ {
+ }
+
+
+CEglPBufferSurface::~CEglPBufferSurface()
+ {
+ Destroy();
+ eglReleaseThread();
+ }
+
+
+CEglPBufferSurface* CEglPBufferSurface::NewL()
+ {
+ CEglPBufferSurface* self = new (ELeave) CEglPBufferSurface;
+ CleanupStack::PushL(self);
+ self->ConstructL();
+ CleanupStack::Pop(self);
+ return self;
+ }
+
+
+void CEglPBufferSurface::ConstructL()
+ {
+ }
+
+
+const TText *CEglPBufferSurface::GetSurfaceTypeStr() const
+ {
+ return _S("CEglPBufferSurface");
+ }
+
+
+void CEglPBufferSurface::DoCreateL(TInt aIndex, const TPoint &/*aOffset*/, TInt aSizeIndex)
+ {
+ CEglSurfaceBase::BaseCreateL(aIndex, EGL_PBUFFER_BIT);
+
+ EGLint attribs[] =
+ {
+ EGL_WIDTH, 0,
+ EGL_HEIGHT, 0,
+ EGL_NONE,
+ };
+ if (KSurfaceParams[aIndex].iXSize & ELargestPossibleSurface)
+ {
+ iActualSize.iWidth = KSurfaceSizes[aSizeIndex].iWidth;
+ iActualSize.iHeight = KSurfaceSizes[aSizeIndex].iHeight;
+ }
+ else
+ {
+ iActualSize.iWidth = KSurfaceParams[aIndex].iXSize;
+ iActualSize.iHeight = KSurfaceParams[aIndex].iYSize;
+ }
+ for(TInt i = 0; attribs[i] != EGL_NONE; i += 2)
+ {
+ switch(attribs[i])
+ {
+ case EGL_HEIGHT:
+ attribs[i+1] = iActualSize.iHeight;
+ break;
+ case EGL_WIDTH:
+ attribs[i+1] = iActualSize.iWidth;
+ break;
+ }
+ }
+
+ iSurface = eglCreatePbufferSurface(iDisplay, iConfig, attribs);
+ if (iSurface == EGL_NO_SURFACE)
+ {
+ EGLint err = eglGetError();
+ User::Leave(KErrNotSupported);
+ }
+ }
+
+
+TSurfaceId CEglPBufferSurface::SurfaceId() const
+ {
+ SURF_ASSERT(0); // We shouldn't call this!
+ return TSurfaceId::CreateNullId();
+ }
+
+TInt CEglPBufferSurface::SizeInBytes() const
+ {
+ // size of a pixel in bits.
+ EGLint size;
+ if (!eglGetConfigAttrib(iDisplay, iConfig, EGL_BUFFER_SIZE, &size))
+ {
+ RDebug::Printf("Unable to get EGL_BUFFER_SIZE from config %d, err = %04x", iConfig, eglGetError());
+ return 0;
+ }
+
+ return (KSurfaceParams[iParamIndex].iXSize * KSurfaceParams[iParamIndex].iYSize * size) / 8;
+ }
+
+
+// Factory function.
+CSurface *CSurface::SurfaceFactoryL(TSurfaceType aSurfaceType)
+ {
+ switch(aSurfaceType)
+ {
+ case ESurfTypeRaw:
+ return CRawSurface::NewL();
+
+ case ESurfTypeEglWindow:
+ return CEglWindowSurface::NewL();
+
+ case ESurfTypeRawSingleBuffered:
+ return CRawSingleBufferSurface::NewL();
+
+ case ESurfTypePBuffer:
+ return CEglPBufferSurface::NewL();
+
+ default:
+ SURF_ASSERT(0);
+ return NULL;
+ }
+ }