diff -r 000000000000 -r bde4ae8d615e os/graphics/egl/egltest/endpointtestsuite/automated/tsrc/egltest_surface.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/os/graphics/egl/egltest/endpointtestsuite/automated/tsrc/egltest_surface.cpp Fri Jun 15 03:10:57 2012 +0200 @@ -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 +#include +#include +#include + + +#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; + } + }