diff -r 000000000000 -r 5d03bc08d59c egl/egltest/src/egltestcommonsession.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/egl/egltest/src/egltestcommonsession.cpp Tue Feb 02 01:47:50 2010 +0200 @@ -0,0 +1,2093 @@ +// 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 +*/ + +#include "egltestcommonsession.h" +#include "egltestcommonutils.h" +#include "egltestcommonsgimageinfo.h" + +#include +#include +#ifdef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE +#include +#else +#include +#include +#endif //SYMBIAN_GRAPHICS_EGL_SGIMAGELITE +#include +#include + + +#define CHECK_EXPECTED_ERROR(aFunctionReturnValue) \ + if(!(CheckExpectedError(aFunctionReturnValue))) \ + { \ + ERR_PRINTF2(_L("thread %d: Unexpected EGL error information"), iThreadIdx); \ + User::Leave(KErrTEFUnitFail); \ + } + +const TMapEglConfigToPixelFormat KMapEglConfigToPixelFormat[] = + { + {16, 0, 5,6,5, 0, EGL_RGB_BUFFER, EUidPixelFormatRGB_565, EColor64K}, + {32, 0, 8,8,8, 0, EGL_RGB_BUFFER, EUidPixelFormatXRGB_8888, EColor16MU}, + {32, 8, 8,8,8, EGL_VG_ALPHA_FORMAT_NONPRE, EGL_RGB_BUFFER, EUidPixelFormatARGB_8888, EColor16MA}, + {32, 8, 8,8,8, EGL_VG_ALPHA_FORMAT_PRE, EGL_RGB_BUFFER, EUidPixelFormatARGB_8888_PRE, EColor16MAP} + }; + +EXPORT_C CTestEglSession::CTestEglSession(CTestExecuteLogger& aLogger, EGLDisplay& aDisplay, TInt aThreadIdx) + : iLogger(aLogger), iThreadIdx(aThreadIdx), iExtensionGroupCached(EIsUndefined), iDisplay(aDisplay), iExpectedErrorCode(EGL_SUCCESS) + {} + +EXPORT_C CTestEglSession* CTestEglSession::NewLC(CTestExecuteLogger& aLogger, EGLDisplay& aDisplay, TInt aThreadIdx) + { + CTestEglSession* self = new (ELeave) CTestEglSession(aLogger, aDisplay, aThreadIdx); + CleanupStack::PushL(self); + return self; + } + +EXPORT_C CTestEglSession* CTestEglSession::NewL(CTestExecuteLogger& aLogger, EGLDisplay& aDisplay, TInt aThreadIdx) + { + CTestEglSession* self = CTestEglSession::NewLC(aLogger, aDisplay, aThreadIdx); + CleanupStack::Pop(self); + return self; + } + +EXPORT_C CTestEglSession::~CTestEglSession() + { + iExtensionStrings.Reset(); + EGLBoolean ret; + if (iDisplay != EGL_NO_DISPLAY) + { + // Unbind and destroy context only if we successfuly created it + if (iContext != EGL_NO_CONTEXT) + { + INFO_PRINTF2(_L("thread %d: Calling eglMakeCurrent(NULL values) from ~CTestEglSession..."), iThreadIdx); + ret = eglMakeCurrent(iDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + if(ret == EGL_FALSE) + { + WARN_PRINTF3(_L("thread %d: eglMakeCurrent returned error = %x ~CTestEglSession..."), iThreadIdx, eglGetError()); + } + + // Warn because this should be done by the test, rather than relying on the d'tor + // which may not leave if there is an error (so no CHECK_EXPECTED_ERROR) + WARN_PRINTF2(_L("thread %d: Calling eglDestroyContext() from ~CTestEglSession..."), iThreadIdx); + ret = eglDestroyContext(iDisplay, iContext); + if(ret == EGL_FALSE) + { + WARN_PRINTF3(_L("thread %d: eglDestroyContext returned error = %x ~CTestEglSession..."), iThreadIdx, eglGetError()); + } + } + + if (iSurface != EGL_NO_SURFACE) + { + // Warn because this should be done by the test, rather than relying on the d'tor + // which may not leave if there is an error (so no CHECK_EXPECTED_ERROR) + WARN_PRINTF2(_L("thread %d: Calling eglDestroySurface() from ~CTestEglSession..."), iThreadIdx); + ret = eglDestroySurface(iDisplay, iSurface); + if(ret == EGL_FALSE) + { + WARN_PRINTF3(_L("thread %d: eglDestroySurface returned error = %x ~CTestEglSession..."), iThreadIdx, eglGetError()); + } + } + + if (iTerminateDisplay) + { + INFO_PRINTF1(_L("Calling eglTerminate...")); + ret = eglTerminate(iDisplay); + iDisplay = EGL_NO_DISPLAY; + if(ret == EGL_FALSE) + { + WARN_PRINTF3(_L("thread %d: eglTerminate returned error = %x ~CTestEglSession..."), iThreadIdx, eglGetError()); + } + } + } + + // Only destroy native resource after the surface and context that wraps it has been destroyed. + delete iFbsBitmap; + CloseFbsSession(); + + iSgImage.Close(); + CloseSgDriver(); + } + +EXPORT_C void CTestEglSession::SetExpectedError(EGLint aExpectedErrorCode) + { + VERBOSE_INFO_PRINTF3(_L("thread %d: Setting the expected error code for the next EGL call to %x"), iThreadIdx, aExpectedErrorCode); + { + iExpectedErrorCode = aExpectedErrorCode; + } + } + +EXPORT_C void CTestEglSession::ResetExpectedError() + { + iExpectedErrorCode = EGL_SUCCESS; + } + +/** +Checks whether the call to an EGL method returned the correct error information. +The method checks whether eglGetError() returns the expected error value as specified by calling SetExpectedError() +It also checks that the value returned by the EGL method was appropriate for the expected error value. +@param aFunctionReturnValue Pass in the value retured from the EGL method +@return Whether the expected error information was returned from a call to an EGL method. +*/ +EXPORT_C TBool CTestEglSession::CheckExpectedError(EGLint aFunctionReturnValue) + { + TBool isExpectedError = ETrue; + EGLint eglErr = eglGetError(); + + // First check that we got the correct return value + if ((iExpectedErrorCode == EGL_SUCCESS) && !aFunctionReturnValue) + { + ERR_PRINTF3(_L("thread %d: Wrong function return value: %d"), iThreadIdx, aFunctionReturnValue); + isExpectedError = EFalse; + } + // Also check that we got the + if (eglErr != iExpectedErrorCode) + { + ERR_PRINTF4(_L("thread %d: eglGetError() returned %x, but expected %x"), iThreadIdx, eglErr, iExpectedErrorCode); + isExpectedError = EFalse; + } + else if (eglErr != EGL_SUCCESS) + { + VERBOSE_INFO_PRINTF3(_L("thread %d: eglGetError() returned %x, as expected"), iThreadIdx, eglErr); + } + + // Reset the expected error + ResetExpectedError(); + + return isExpectedError; + } + +EXPORT_C void CTestEglSession::CheckExpectedErrorL(EGLint aExpectedErrorCode) + { + EGLint eglErr = eglGetError(); + // check that we got the expected error + if (eglErr != aExpectedErrorCode) + { + ERR_PRINTF4(_L("thread %d: eglGetError() returned %x, but expected %x"), iThreadIdx, eglErr, aExpectedErrorCode); + User::Leave(KErrTEFUnitFail); + } + } + +void CTestEglSession::QueryExtensionsL(TExtensionsGroups aExtensionBelongsTo) + { + // reset the cached extensions + iExtensionStrings.Reset(); + + const char* extensionsString = NULL; + if(aExtensionBelongsTo == EIsEGL) + { + INFO_PRINTF2(_L("thread %d: Calling eglQueryString for EGL_EXTENSIONS)"), iThreadIdx); + extensionsString = eglQueryString(iDisplay, EGL_EXTENSIONS); + } + else if(aExtensionBelongsTo == EIsVG) + { + INFO_PRINTF2(_L("thread %d: Calling vgGetString for VG_EXTENSIONS)"), iThreadIdx); + + // OpenVG needs a current VG context before it will allow the call to vgGetString + TSgImageInfoOpenVgTarget imageInfo; + imageInfo.iSizeInPixels = KPixmapSize; + imageInfo.iPixelFormat = EUidPixelFormatXRGB_8888; +#ifdef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE + imageInfo.iUsage = ESgUsageBitOpenVgSurface; +#else + imageInfo.iUsage = ESgUsageOpenVgTarget; +#endif + CreatePixmapSurfaceAndMakeCurrentAndMatchL(imageInfo,CTestEglSession::EResourceCloseSgImageEarly); + + extensionsString = (const char*) vgGetString(VG_EXTENSIONS); + + //cleanup the context & surface + CleanupSurfaceSgImageL(); + } + else + { + ERR_PRINTF2(_L("CTestEglSession::QueryExtensionsL() - Unknown extension group provided (%d)."), aExtensionBelongsTo); + User::Leave(KErrArgument); + } + CHECK_EXPECTED_ERROR(extensionsString!=NULL); + + TPtrC8 ptrExtensions((const TUint8 *) extensionsString ); + TBuf16<128> bufExtensions; + bufExtensions.Copy(ptrExtensions.Left(128)); + INFO_PRINTF3(_L("thread %d: QueryExtensionsL: \"%S\""), iThreadIdx, &bufExtensions); + + TInt posSpace=1; + while (posSpace > 0 && ptrExtensions.Length() > 0) + { + posSpace = ptrExtensions.Locate(' '); // strictly looking for a single space + ASSERT_FALSE(posSpace==0); // Would imply extension starting with a space or with 2 spaces in a row + if (posSpace > 0) + { + iExtensionStrings.Append(ptrExtensions.Left(posSpace)); + if (posSpace <= ptrExtensions.Length()) + { + ptrExtensions.Set(ptrExtensions.Mid(posSpace+1)); + } + } + else + { + iExtensionStrings.Append(ptrExtensions); + } + } + } + +TBool CTestEglSession::FindExtensionStringL(TExtensionsGroups aExtensionBelongsTo, const TDesC8& aExtensionString) + { + //Load the extensions for this group if not already cached + if (iExtensionGroupCached != aExtensionBelongsTo) + { + QueryExtensionsL(aExtensionBelongsTo); // Load extension info + iExtensionGroupCached = aExtensionBelongsTo; + } + + TInt countExtensionStrings = iExtensionStrings.Count(); + for(TUint i=0; i bufMissingExtension16; + bufMissingExtension16.Copy(aExtensionString.Left(KBufLenMissingExtension)); + + WARN_PRINTF2(_L("EGL extension missing: [%S]"), &bufMissingExtension16); + return EFalse; + } + +/** + Converts from TRgb space to Vg floating point colour + */ +EXPORT_C void CTestEglSession::ConvertColor(const TRgb& aSource, VGfloat* aTarget) +//static + { + aTarget[0] = (VGfloat)aSource.Red() / 255.f; + aTarget[1] = (VGfloat)aSource.Green() / 255.f; + aTarget[2] = (VGfloat)aSource.Blue() / 255.f; + aTarget[3] = (VGfloat)aSource.Alpha() / 255.f; + } + +/** Breakpoint to manually view available configs while debugging */ +EXPORT_C void CTestEglSession::ViewConfigsL() + { + EGLConfig configs[KMaxEglConfigs]; + EGLint numConfigs=0; + + // Query number of configs available + INFO_PRINTF1(_L("Calling eglGetConfigs to get the number of configs available...")); + CHECK_EXPECTED_ERROR(eglGetConfigs(iDisplay, NULL, KMaxTInt, &numConfigs)); + + INFO_PRINTF1(_L("Checking number of configs...")); + ASSERT_TRUE(numConfigs >= 1); + INFO_PRINTF2(_L("Found %d configs"), numConfigs); + + // Get the configs + INFO_PRINTF1(_L("Calling eglGetConfigs to get configs...")); + CHECK_EXPECTED_ERROR(eglGetConfigs(iDisplay, configs, KMaxEglConfigs, &numConfigs)); + + for(TUint index = 0; index < numConfigs; index++) + { + EGLint EGL_BUFFER_SIZE_value; + EGLint EGL_ALPHA_SIZE_value; + EGLint EGL_BLUE_SIZE_value; + EGLint EGL_GREEN_SIZE_value; + EGLint EGL_RED_SIZE_value; +#ifdef PRINT_ALL_CONFIGS_DETAILS + EGLint EGL_DEPTH_SIZE_value; + EGLint EGL_STENCIL_SIZE_value; + EGLint EGL_CONFIG_CAVEAT_value; + EGLint EGL_CONFIG_ID_value; + EGLint EGL_LEVEL_value; + EGLint EGL_MAX_PBUFFER_HEIGHT_value; + EGLint EGL_MAX_PBUFFER_PIXELS_value; + EGLint EGL_MAX_PBUFFER_WIDTH_value; + EGLint EGL_NATIVE_RENDERABLE_value; + EGLint EGL_NATIVE_VISUAL_ID_value; + EGLint EGL_NATIVE_VISUAL_TYPE_value; + EGLint EGL_SAMPLES_value; + EGLint EGL_SAMPLE_BUFFERS_value; +#endif + EGLint EGL_SURFACE_TYPE_value; +#ifdef PRINT_ALL_CONFIGS_DETAILS + EGLint EGL_TRANSPARENT_TYPE_value; + EGLint EGL_TRANSPARENT_BLUE_VALUE_value; + EGLint EGL_TRANSPARENT_GREEN_VALUE_value; + EGLint EGL_TRANSPARENT_RED_VALUE_value; + EGLint EGL_BIND_TO_TEXTURE_RGB_value; + EGLint EGL_BIND_TO_TEXTURE_RGBA_value; + EGLint EGL_MIN_SWAP_INTERVAL_value; + EGLint EGL_MAX_SWAP_INTERVAL_value; + EGLint EGL_LUMINANCE_SIZE_value; + EGLint EGL_ALPHA_MASK_SIZE_value; + EGLint EGL_COLOR_BUFFER_TYPE_value; +#endif + EGLint EGL_RENDERABLE_TYPE_value; + + eglGetConfigAttrib(iDisplay, configs[index], EGL_BUFFER_SIZE, &EGL_BUFFER_SIZE_value); + eglGetConfigAttrib(iDisplay, configs[index], EGL_ALPHA_SIZE, &EGL_ALPHA_SIZE_value); + eglGetConfigAttrib(iDisplay, configs[index], EGL_BLUE_SIZE, &EGL_BLUE_SIZE_value); + eglGetConfigAttrib(iDisplay, configs[index], EGL_GREEN_SIZE, &EGL_GREEN_SIZE_value); + eglGetConfigAttrib(iDisplay, configs[index], EGL_RED_SIZE, &EGL_RED_SIZE_value); +#ifdef PRINT_ALL_CONFIGS_DETAILS + eglGetConfigAttrib(iDisplay, configs[index], EGL_DEPTH_SIZE, &EGL_DEPTH_SIZE_value); + eglGetConfigAttrib(iDisplay, configs[index], EGL_STENCIL_SIZE, &EGL_STENCIL_SIZE_value); + eglGetConfigAttrib(iDisplay, configs[index], EGL_CONFIG_CAVEAT, &EGL_CONFIG_CAVEAT_value); + eglGetConfigAttrib(iDisplay, configs[index], EGL_CONFIG_ID, &EGL_CONFIG_ID_value); + eglGetConfigAttrib(iDisplay, configs[index], EGL_LEVEL, &EGL_LEVEL_value); + eglGetConfigAttrib(iDisplay, configs[index], EGL_MAX_PBUFFER_HEIGHT, &EGL_MAX_PBUFFER_HEIGHT_value); + eglGetConfigAttrib(iDisplay, configs[index], EGL_MAX_PBUFFER_PIXELS, &EGL_MAX_PBUFFER_PIXELS_value); + eglGetConfigAttrib(iDisplay, configs[index], EGL_MAX_PBUFFER_WIDTH, &EGL_MAX_PBUFFER_WIDTH_value); + eglGetConfigAttrib(iDisplay, configs[index], EGL_NATIVE_RENDERABLE, &EGL_NATIVE_RENDERABLE_value); + eglGetConfigAttrib(iDisplay, configs[index], EGL_NATIVE_VISUAL_ID, &EGL_NATIVE_VISUAL_ID_value); + eglGetConfigAttrib(iDisplay, configs[index], EGL_NATIVE_VISUAL_TYPE, &EGL_NATIVE_VISUAL_TYPE_value); + eglGetConfigAttrib(iDisplay, configs[index], EGL_SAMPLES, &EGL_SAMPLES_value); + eglGetConfigAttrib(iDisplay, configs[index], EGL_SAMPLE_BUFFERS, &EGL_SAMPLE_BUFFERS_value); +#endif + eglGetConfigAttrib(iDisplay, configs[index], EGL_SURFACE_TYPE, &EGL_SURFACE_TYPE_value); +#ifdef PRINT_ALL_CONFIGS_DETAILS + eglGetConfigAttrib(iDisplay, configs[index], EGL_TRANSPARENT_TYPE, &EGL_TRANSPARENT_TYPE_value); + eglGetConfigAttrib(iDisplay, configs[index], EGL_TRANSPARENT_BLUE_VALUE, &EGL_TRANSPARENT_BLUE_VALUE_value); + eglGetConfigAttrib(iDisplay, configs[index], EGL_TRANSPARENT_GREEN_VALUE, &EGL_TRANSPARENT_GREEN_VALUE_value); + eglGetConfigAttrib(iDisplay, configs[index], EGL_TRANSPARENT_RED_VALUE, &EGL_TRANSPARENT_RED_VALUE_value); + eglGetConfigAttrib(iDisplay, configs[index], EGL_BIND_TO_TEXTURE_RGB, &EGL_BIND_TO_TEXTURE_RGB_value); + eglGetConfigAttrib(iDisplay, configs[index], EGL_BIND_TO_TEXTURE_RGBA, &EGL_BIND_TO_TEXTURE_RGBA_value); + eglGetConfigAttrib(iDisplay, configs[index], EGL_MIN_SWAP_INTERVAL, &EGL_MIN_SWAP_INTERVAL_value); + eglGetConfigAttrib(iDisplay, configs[index], EGL_MAX_SWAP_INTERVAL, &EGL_MAX_SWAP_INTERVAL_value); + eglGetConfigAttrib(iDisplay, configs[index], EGL_LUMINANCE_SIZE, &EGL_LUMINANCE_SIZE_value); + eglGetConfigAttrib(iDisplay, configs[index], EGL_ALPHA_MASK_SIZE, &EGL_ALPHA_MASK_SIZE_value); + eglGetConfigAttrib(iDisplay, configs[index], EGL_COLOR_BUFFER_TYPE, &EGL_COLOR_BUFFER_TYPE_value); +#endif + eglGetConfigAttrib(iDisplay, configs[index], EGL_RENDERABLE_TYPE, &EGL_RENDERABLE_TYPE_value); + + TBool good = ETrue; + + INFO_PRINTF7(_L("(idx: %3d) RGBA=(%2d) %2d,%2d,%2d,%2d"), index, EGL_BUFFER_SIZE_value, + EGL_RED_SIZE_value, EGL_GREEN_SIZE_value, EGL_BLUE_SIZE_value, + EGL_ALPHA_SIZE_value); + if (!(EGL_RED_SIZE_value == 8 && EGL_GREEN_SIZE_value == 8 && EGL_BLUE_SIZE_value == 8 && EGL_ALPHA_SIZE_value == 0)) + { + continue; + } + + INFO_PRINTF2(_L("\n\n^^^^^^ CONFIG [%d] VALUES ******"), index); + if (EGL_SURFACE_TYPE_value & EGL_PIXMAP_BIT) + { + INFO_PRINTF2(_L("EGL_SURFACE_TYPE=%d. <<< Has EGL_PIXMAP_BIT"), EGL_SURFACE_TYPE_value); + } + else + { + INFO_PRINTF2(_L("EGL_SURFACE_TYPE=%d. <<< BAD (not pixmap)"), EGL_SURFACE_TYPE_value); + good = EFalse; + } + + if (EGL_RENDERABLE_TYPE_value & EGL_OPENVG_BIT) + { + INFO_PRINTF2(_L("EGL_RENDERABLE_TYPE=%d. <<< Has EGL_OPENVG_BIT"), EGL_RENDERABLE_TYPE_value); + } + else + { + INFO_PRINTF2(_L("EGL_RENDERABLE_TYPE=%d. <<< BAD (not open vg)"), EGL_RENDERABLE_TYPE_value); + good = EFalse; + } + + if (good) + { + INFO_PRINTF1(_L("^^^^^^^ GOOD ^^^^^^^")); + } + +#ifdef PRINT_ALL_CONFIGS_DETAILS + INFO_PRINTF2(_L("\n\n***** CONFIG [%d] VALUES ******"), index); + INFO_PRINTF2(_L("EGL_BUFFER_SIZE=%d."), EGL_BUFFER_SIZE_value); + INFO_PRINTF2(_L("EGL_ALPHA_SIZE=%d."), EGL_ALPHA_SIZE_value); + INFO_PRINTF2(_L("EGL_BLUE_SIZE=%d."), EGL_BLUE_SIZE_value); + INFO_PRINTF2(_L("EGL_GREEN_SIZE=%d."), EGL_GREEN_SIZE_value); + INFO_PRINTF2(_L("EGL_RED_SIZE=%d."), EGL_RED_SIZE_value); + INFO_PRINTF2(_L("EGL_DEPTH_SIZE=%d."), EGL_DEPTH_SIZE_value); + INFO_PRINTF2(_L("EGL_STENCIL_SIZE=%d."), EGL_STENCIL_SIZE_value); + INFO_PRINTF2(_L("EGL_CONFIG_CAVEAT=%d."), EGL_CONFIG_CAVEAT_value); + INFO_PRINTF2(_L("EGL_CONFIG_ID=%d."), EGL_CONFIG_ID_value); + INFO_PRINTF2(_L("EGL_LEVEL=%d."), EGL_LEVEL_value); + INFO_PRINTF2(_L("EGL_MAX_PBUFFER_HEIGHT=%d."), EGL_MAX_PBUFFER_HEIGHT_value); + INFO_PRINTF2(_L("EGL_MAX_PBUFFER_PIXELS=%d."), EGL_MAX_PBUFFER_PIXELS_value); + INFO_PRINTF2(_L("EGL_MAX_PBUFFER_WIDTH=%d."), EGL_MAX_PBUFFER_WIDTH_value); + INFO_PRINTF2(_L("EGL_NATIVE_RENDERABLE=%d."), EGL_NATIVE_RENDERABLE_value); + INFO_PRINTF2(_L("EGL_NATIVE_VISUAL_ID=%d."), EGL_NATIVE_VISUAL_ID_value); + INFO_PRINTF2(_L("EGL_NATIVE_VISUAL_TYPE=%d."), EGL_NATIVE_VISUAL_TYPE_value); + INFO_PRINTF2(_L("EGL_SAMPLES=%d."), EGL_SAMPLES_value); + INFO_PRINTF2(_L("EGL_SAMPLE_BUFFERS=%d."), EGL_SAMPLE_BUFFERS_value); + INFO_PRINTF2(_L("EGL_SURFACE_TYPE=%d."), EGL_SURFACE_TYPE_value); + INFO_PRINTF2(_L("EGL_TRANSPARENT_TYPE=%d."), EGL_TRANSPARENT_TYPE_value); + INFO_PRINTF2(_L("EGL_TRANSPARENT_BLUE_VALUE=%d."), EGL_TRANSPARENT_BLUE_VALUE_value); + INFO_PRINTF2(_L("EGL_TRANSPARENT_GREEN_VALUE=%d."), EGL_TRANSPARENT_GREEN_VALUE_value); + INFO_PRINTF2(_L("EGL_TRANSPARENT_RED_VALUE=%d."), EGL_TRANSPARENT_RED_VALUE_value); + INFO_PRINTF2(_L("EGL_BIND_TO_TEXTURE_RGB=%d."), EGL_BIND_TO_TEXTURE_RGB_value); + INFO_PRINTF2(_L("EGL_BIND_TO_TEXTURE_RGBA=%d."), EGL_BIND_TO_TEXTURE_RGBA_value); + INFO_PRINTF2(_L("EGL_MIN_SWAP_INTERVAL=%d."), EGL_MIN_SWAP_INTERVAL_value); + INFO_PRINTF2(_L("EGL_MAX_SWAP_INTERVAL=%d."), EGL_MAX_SWAP_INTERVAL_value); + INFO_PRINTF2(_L("EGL_LUMINANCE_SIZE=%d."), EGL_LUMINANCE_SIZE_value); + INFO_PRINTF2(_L("EGL_ALPHA_MASK_SIZE=%d."), EGL_ALPHA_MASK_SIZE_value); + INFO_PRINTF2(_L("EGL_COLOR_BUFFER_TYPE=%d."), EGL_COLOR_BUFFER_TYPE_value); + INFO_PRINTF2(_L("EGL_RENDERABLE_TYPE=%d."), EGL_RENDERABLE_TYPE_value); + INFO_PRINTF2(_L("\n*********************************\n\n"), index); +#endif + } + } + +EXPORT_C static TEglConfigMatchType GetMatchType(EGLint aAttrib, TEglConfigMatchRule aMatchRule) + { + const TConfigMatchRuleItem* curMatchRuleItem = KConfigMatchRules[aMatchRule]; + + while(curMatchRuleItem->iAttrib != EGL_NONE) + { + if (aAttrib == curMatchRuleItem->iAttrib) + { + return curMatchRuleItem->iMatchType; + } + curMatchRuleItem++; + } + + RDebug::Printf("Unknown attrib %x", aAttrib); + return eMatchUnknown; + } + +/** + Returns the first index of a config that matches the requested config extactly + */ +TInt CTestEglSession::GetFullMatchConfigIndex(EGLDisplay aDisplay, EGLConfig *aConfigs, TInt aNumConfigs, + const EGLint aWantedAttribs[], TEglConfigMatchRule aMatchRule) + { + EGLint value=0; + for(TUint idxConfig=0; idxConfig="! + { + match = EFalse; + } + break; + case eMatchBitMask: + if ((value & curAttrib[1]) != curAttrib[1]) + { + match = EFalse; + } + break; + case eMatchAlways: + break; + + default: + // We should not get here. + ASSERT(FALSE); + break; + } + curAttrib += 2; + } + + // If we get here with match set, we have matched all attributes, and have found a match. + if (match) + { + return idxConfig; + } + } + return KErrNotFound; + } + +TInt CTestEglSession::ConfigToPixelFormatTableLength() const + { + return sizeof(KMapEglConfigToPixelFormat) / sizeof(TMapEglConfigToPixelFormat); + } + +const TMapEglConfigToPixelFormat& CTestEglSession::ConfigToPixelFormatTable(TInt aIndex) const + { + return KMapEglConfigToPixelFormat[aIndex]; + } + +/** + Returns pixel format inforamtion for a given EGL config. + @param aConfig The EGL config for which pixel format information will be returned. + @return A pointer to the pixel format information for the given EGL config. + Tf the config cannot be mapped, then NULL is returned. + */ +EXPORT_C const TMapEglConfigToPixelFormat* CTestEglSession::GetPixelFormatFromEglConfigL(EGLConfig aConfig) + { + EGLint bufferSize=0; + EGLint alphaSize=0; + EGLint redSize=0; + EGLint greenSize=0; + EGLint blueSize=0; + EGLint colorBufferType=0; + EGLint surfaceType = 0; + + CHECK_EXPECTED_ERROR(eglGetConfigAttrib(iDisplay, aConfig, EGL_BUFFER_SIZE, &bufferSize)); + CHECK_EXPECTED_ERROR(eglGetConfigAttrib(iDisplay, aConfig, EGL_ALPHA_SIZE, &alphaSize)); + CHECK_EXPECTED_ERROR(eglGetConfigAttrib(iDisplay, aConfig, EGL_RED_SIZE, &redSize)); + CHECK_EXPECTED_ERROR(eglGetConfigAttrib(iDisplay, aConfig, EGL_GREEN_SIZE, &greenSize)); + CHECK_EXPECTED_ERROR(eglGetConfigAttrib(iDisplay, aConfig, EGL_BLUE_SIZE, &blueSize)); + CHECK_EXPECTED_ERROR(eglGetConfigAttrib(iDisplay, aConfig, EGL_COLOR_BUFFER_TYPE, &colorBufferType)); + CHECK_EXPECTED_ERROR(eglGetConfigAttrib(iDisplay, aConfig, EGL_SURFACE_TYPE, &surfaceType)); + + INFO_PRINTF7(_L(">>>>> Config info: %d, %d, %d,%d,%d, 0x%x"), bufferSize, alphaSize, redSize, greenSize, blueSize, colorBufferType); + + for(TUint i=0; i= EEglTestConfigMax ) + { + ERR_PRINTF1(_L("Attribute index out of range, please check the INI file")); + User::Leave(KErrArgument); + } + + EGLConfig configs[KMaxEglConfigs]; + EGLint numConfigs=0; + ASSERT_EGL_TRUE(eglChooseConfig(iDisplay, KConfigAttribs[aConfigAttribIndex], configs, KMaxEglConfigs, &numConfigs)); + if (numConfigs <= 0) + { + // we just WARN, as we don't know if this is expected yet (if it is, then catch the leaving error) + WARN_PRINTF1(_L("GetConfigExactMatchL - Could not find a matching config, eglChooseConfig returned 0 configs!")); + User::Leave(KTestNoMatchingConfig); + } + + // Check that any of the configs returned matches the desired attributes + TInt match = GetFullMatchConfigIndex(iDisplay, configs, numConfigs, KConfigAttribs[aConfigAttribIndex], aMatchRule); + if (match == KErrNotFound) + { + // we just WARN, as we don't know if this is expected yet (if it is, then catch the leaving error) + WARN_PRINTF1(_L("GetConfigExactMatchL - Could not find a matching config amongst those returned by eglChooseConfig!")); + User::Leave(KTestNoMatchingConfig); + } + return configs[match]; + } + +/** +Creates a pixmap surface from a CFbsBitmap, draws to it and checks that the drawing operation succeeded. +*/ +EXPORT_C void CTestEglSession::TryUsePixmapCFbsBitmapL() + { + INFO_PRINTF2(_L("thread %d: TryUsePixmapCFbsBitmapL"), iThreadIdx); + EGLConfig currentConfig = GetConfigExactMatchL(EPixmapAttribsColor64K); + TryUsePixmapCFbsBitmapOpenVgL(currentConfig, KPixmapSize, EColor64K); + } + +/** +Creates a pixmap surface from a CFbsBitmap, draws to it and checks that the drawing operation succeeded. +*/ +EXPORT_C void CTestEglSession::TryUsePixmapCFbsBitmapOpenVgL(EGLConfig aConfig, const TSize& aSize, TDisplayMode aDisplayMode) + { + CreatePixmapSurfaceAndMakeCurrentL(aConfig, aSize, aDisplayMode); + DrawOpenVgL(); + + // Wait for the drawing to complete + eglWaitClient(); + + CheckImageDataL(iFbsBitmap); + CheckImageDataVgL(VG_sRGB_565); + CleanupSurfaceFbsBitmapL(); + CloseFbsSession(); + } + +/** +Creates a pixmap surface from a CFbsBitmap, draws to it and checks that the drawing operation succeeded. +*/ +EXPORT_C void CTestEglSession::TryUsePixmapCFbsBitmapOpenGlesL(EGLConfig aConfig, const TSize& aSize, TDisplayMode aDisplayMode, TInt aRenderVersion) + { + CreatePixmapSurfaceAndMakeCurrentL(aConfig, aSize, aDisplayMode,EGL_OPENGL_ES_API, aRenderVersion); + DrawOpenGLesL(); + + // Wait for the drawing to complete + eglWaitClient(); + + CheckImageDataFullRedishL(iFbsBitmap); + CleanupSurfaceFbsBitmapL(); + CloseFbsSession(); + } + +/** + Creates a pixmap surface from a RSgImage, draws to it and checks that the drawing operation succeeded. + */ +EXPORT_C void CTestEglSession::TryUsePixmapRSgImageL() + { + INFO_PRINTF2(_L("thread %d: TryUsePixmapRSgImageL"), iThreadIdx); + TSgImageInfo imageInfo; + imageInfo.iSizeInPixels = KPixmapSize; + imageInfo.iPixelFormat = EUidPixelFormatXRGB_8888; + // will draw to and read from the image using OpenVg +#ifdef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE + imageInfo.iUsage = ESgUsageBitOpenVgSurface | ESgUsageBitOpenVgImage; +#else + // will also read from the image using DirectGdi + imageInfo.iUsage = ESgUsageOpenVgTarget | ESgUsageDirectGdiSource; + imageInfo.iShareable = EFalse; + imageInfo.iCpuAccess = ESgCpuAccessNone; + imageInfo.iScreenId = KSgScreenIdMain; + imageInfo.iUserAttributes = NULL; + imageInfo.iUserAttributeCount=0; +#endif + CreatePixmapSurfaceAndMakeCurrentAndMatchL(imageInfo, EResourceCloseSgImageLate); + DrawOpenVgL(); + + // Wait for the drawing to complete + eglWaitClient(); + + //we can't retrieve data directly from the SgImage as + //non-unified architecture doesn't allow readback from the GPU + CheckImageDataVgL(VG_sXRGB_8888); + CleanupSurfaceSgImageL(); + CloseSgDriver(); + } + +EXPORT_C TBool CTestEglSession::TryUsePixmapRSgImageOpenGlesL(EGLConfig aConfig, const TSgImageInfo& aImageInfo, TResourceCloseRule aResourceCloseRule, TInt aRenderVersion) + { + CreatePixmapSurfaceAndMakeCurrentL(aConfig, aImageInfo, aResourceCloseRule ,EGL_OPENGL_ES_API, aRenderVersion); + + DrawOpenGLesL(); + + // Wait for the drawing to complete + eglWaitClient(); + + //we can't retrieve data directly from SgImage as non-unified + //architecture doesn't allow readback from the GPU + + if (aImageInfo.iPixelFormat == EUidPixelFormatXRGB_8888 || + aImageInfo.iPixelFormat == EUidPixelFormatARGB_8888_PRE) + { + CheckImageDataGLesL(); + } + + CleanupSurfaceSgImageL(); + CloseSgDriver(); + return ETrue; + } + +/** +Compound operation that constructs an RSgImage and uses it to create a pixmap suface. +It then draws to the surface using OpenVG and checks whether the drawing succeeded. +It cleans up the pixmap surface it destroyed. +@param aConfig The EGL config to be used when creating the pixmap surface +@param aImageInfo Used to create the RSgImage pixmap +@param aCloseNativeImageEarly When ETrue, the RSgImage is closed as soon as the pixmap surface has been + created. Otherwise, the RSgImage is closed during cleanup, when the pixmap surface is destroyed. +@return Whether it was possible to create an iSgImage for the given aImageInfo +*/ +EXPORT_C TBool CTestEglSession::TryUsePixmapRSgImageOpenVgL(EGLConfig aConfig, const TSgImageInfo& aImageInfo, TResourceCloseRule aResourceCloseRule) + { + CreatePixmapSurfaceAndMakeCurrentL(aConfig, aImageInfo, aResourceCloseRule); + + DrawOpenVgL(); + + // Wait for the drawing to complete + eglWaitClient(); + + //we can't retrieve data directly from the SgImage as + //non-unified architecture doesn't allow readback from the GPU + CheckImageDataVgL(VG_sXRGB_8888); + CleanupSurfaceSgImageL(); + CloseSgDriver(); + return ETrue; + } + +EXPORT_C void CTestEglSession::CreateWindowSurfaceAndMakeCurrentL(EGLConfig aConfig, RWindow& aWindow, EGLenum aBindAPI, TInt aRenderVersionNumber) + { + ASSERT_EQUALS(iSurface, EGL_NO_SURFACE); + ASSERT_EQUALS(iContext, EGL_NO_CONTEXT); + + ASSERT_EGL_TRUE(eglBindAPI(aBindAPI)); + + // Create a Window surface from the native image + EGLint EGL_RENDERABLE_TYPE_value = 0; + ASSERT_EGL_TRUE(eglGetConfigAttrib(iDisplay, aConfig, EGL_RENDERABLE_TYPE, &EGL_RENDERABLE_TYPE_value)); + const EGLint* pixmapAttribs = ((aWindow.DisplayMode() == EColor16MAP) && (EGL_RENDERABLE_TYPE_value & EGL_OPENVG_BIT)) ? KPixmapAttribsVgAlphaFormatPre : KPixmapAttribsNone; + iSurface = eglCreateWindowSurface(iDisplay, aConfig, &aWindow, pixmapAttribs); + ASSERT_EGL_TRUE(iSurface != EGL_NO_SURFACE); + + // Create a context for drawing to/reading from the pixmap surface and make it current + const EGLint KAttribsListCtxNone[] = { EGL_NONE };; + const EGLint KAttribsListCtxGles2[] = { EGL_CONTEXT_CLIENT_VERSION, aRenderVersionNumber, EGL_NONE }; + const EGLint* attrib_list_ctx = (aBindAPI == EGL_OPENGL_ES_API && aRenderVersionNumber == 2) ? KAttribsListCtxGles2 : KAttribsListCtxNone; + iContext = eglCreateContext(iDisplay, aConfig, EGL_NO_CONTEXT, attrib_list_ctx); + ASSERT_EGL_TRUE(iContext != EGL_NO_CONTEXT); + ASSERT_EGL_TRUE(eglMakeCurrent(iDisplay, iSurface, iSurface, iContext)); + } + + +EXPORT_C TBool CTestEglSession::CongfigSupportsOpenVgL(EGLConfig aConfig) + { + EGLint EGL_RENDERABLE_TYPE_value = 0; + ASSERT_EGL_TRUE(eglGetConfigAttrib(iDisplay, aConfig, EGL_RENDERABLE_TYPE, &EGL_RENDERABLE_TYPE_value)); + return (EGL_RENDERABLE_TYPE_value&EGL_OPENVG_BIT)>0; + } + +EXPORT_C void CTestEglSession::CreatePixmapSurfaceAndMakeCurrentAndMatchL(const TSgImageInfo& aImageInfo, TResourceCloseRule aResourceCloseRule, EGLenum aBindAPI, TInt aRenderVersionNumber) + { + ASSERT_EQUALS(iSurface, EGL_NO_SURFACE); + ASSERT_EQUALS(iContext, EGL_NO_CONTEXT); + + OpenSgDriverL(); + ASSERT_EQUALS(iSgImage.Create(aImageInfo, NULL, 0), KErrNone); + + EGLint renderableType = 0; + if(aBindAPI == EGL_OPENVG_API) + { + renderableType = EGL_OPENVG_BIT; + } + else if(aBindAPI == EGL_OPENGL_ES_API && aRenderVersionNumber==1) + { + renderableType = EGL_OPENGL_ES_BIT; + } + else if(aBindAPI == EGL_OPENGL_ES_API && aRenderVersionNumber==2) + { + renderableType = EGL_OPENGL_ES2_BIT; + } + else + { + ERR_PRINTF1(_L("CreatePixmapSurfaceAndMakeCurrentAndMatchL - Unkown API requested!")); + User::Leave(KErrArgument); + } + EGLint attrib_list[] = { + EGL_MATCH_NATIVE_PIXMAP,(TInt)&iSgImage, + EGL_RENDERABLE_TYPE,renderableType, + EGL_SURFACE_TYPE,EGL_PIXMAP_BIT, + EGL_NONE}; + + ASSERT_EGL_TRUE(eglBindAPI(aBindAPI)); + + EGLConfig config; + EGLint numConfigs; + ASSERT_EGL_TRUE(eglChooseConfig(iDisplay,attrib_list,&config,1,&numConfigs)); + if (numConfigs <= 0) + { + // we just WARN, as we don't know if this is expected yet (if it is, then catch the leaving error) + WARN_PRINTF1(_L("CreatePixmapSurfaceAndMakeCurrentAndMatchL - Could not find a matching config!")); + iSgImage.Close(); + CloseSgDriver(); + // Leave with a unique knonwn error code - useful to catch this error in negative tests + User::Leave(KTestNoMatchingConfig); + } + + // Create a pixmap surface from the native image + EGLint EGL_RENDERABLE_TYPE_value = 0; + ASSERT_EGL_TRUE(eglGetConfigAttrib(iDisplay, config, EGL_RENDERABLE_TYPE, &EGL_RENDERABLE_TYPE_value)); + const EGLint* pixmapAttribs = ((aImageInfo.iPixelFormat == EUidPixelFormatARGB_8888_PRE) && (EGL_RENDERABLE_TYPE_value & EGL_OPENVG_BIT)) ? KPixmapAttribsVgAlphaFormatPre : KPixmapAttribsNone; + iSurface = eglCreatePixmapSurface(iDisplay, config, &iSgImage, pixmapAttribs); + ASSERT_EGL_TRUE(iSurface != EGL_NO_SURFACE); + + if (aResourceCloseRule == EResourceCloseSgImageEarly) + { + // EGL should have taken its own reference to the SgImage, so it should be able to continue + // to use the underlying data after this local image has been closed. + iSgImage.Close(); + } + + if (aResourceCloseRule == EResourceCloseSgDriverAndImageEarly) + { + // EGL should have taken its own reference to the SgDriver, so it should be able to continue + // to use its reference to the image resource after this local reference to the driver has + // been closed. + iSgImage.Close(); + CloseSgDriver(); + } + + // Create a context for drawing to/reading from the pixmap surface and make it current + const EGLint KAttribsListCtxNone[] = { EGL_NONE };; + const EGLint KAttribsListCtxGles2[] = { EGL_CONTEXT_CLIENT_VERSION, aRenderVersionNumber, EGL_NONE }; + const EGLint* attrib_list_ctx = (aBindAPI == EGL_OPENGL_ES_API && aRenderVersionNumber == 2) ? KAttribsListCtxGles2 : KAttribsListCtxNone; + iContext = eglCreateContext(iDisplay, config, EGL_NO_CONTEXT, attrib_list_ctx); + ASSERT_EGL_TRUE(iContext != EGL_NO_CONTEXT); + ASSERT_EGL_TRUE(eglMakeCurrent(iDisplay, iSurface, iSurface, iContext)); + } + +/** +Compound operation that constructs an RSgImage and uses it to create a pixmap suface. +It then makes it current to the thread. +@param aConfig The EGL config to be used when creating the pixmap surface +@param aImageInfo Used to create the RSgImage pixmap +@param aCloseNativeImageEarly When ETrue, the RSgImage is closed as soon as the pixmap surface has been + created. Otherwise, the RSgImage is left to be destroyed later by some other method + - e.g at the same time as destroying the surface. +@return Whether it was possible to create an iSgImage for the given aImageInfo +*/ +EXPORT_C void CTestEglSession::CreatePixmapSurfaceAndMakeCurrentL(EGLConfig aConfig, const TSgImageInfo& aImageInfo, TResourceCloseRule aResourceCloseRule, EGLenum aBindAPI, TInt aRenderVersionNumber) + { + ASSERT_EQUALS(iSurface, EGL_NO_SURFACE); + ASSERT_EQUALS(iContext, EGL_NO_CONTEXT); + + OpenSgDriverL(); + ASSERT_EQUALS(iSgImage.Create(aImageInfo, NULL, 0), KErrNone); + + ASSERT_EGL_TRUE(eglBindAPI(aBindAPI)); + + // Create a pixmap surface from the native image + EGLint EGL_RENDERABLE_TYPE_value = 0; + ASSERT_EGL_TRUE(eglGetConfigAttrib(iDisplay, aConfig, EGL_RENDERABLE_TYPE, &EGL_RENDERABLE_TYPE_value)); + const EGLint* pixmapAttribs = ((aImageInfo.iPixelFormat == EUidPixelFormatARGB_8888_PRE) && (EGL_RENDERABLE_TYPE_value & EGL_OPENVG_BIT)) ? KPixmapAttribsVgAlphaFormatPre : KPixmapAttribsNone; + iSurface = eglCreatePixmapSurface(iDisplay, aConfig, &iSgImage, pixmapAttribs); + ASSERT_EGL_TRUE(iSurface != EGL_NO_SURFACE); + + if (aResourceCloseRule == EResourceCloseSgImageEarly) + { + // EGL should have taken its own reference to the SgImage, so it should be able to continue + // to use the underlying data after this local image has been closed. + iSgImage.Close(); + } + if (aResourceCloseRule == EResourceCloseSgDriverAndImageEarly) + { + // EGL should have taken its own reference to the SgDriver, so it should be able to continue + // to use its reference to the image resource after this local reference to the driver has + // been closed. + iSgImage.Close(); + CloseSgDriver(); + } + + // Create a context for drawing to/reading from the pixmap surface and make it current + const EGLint KAttribsListCtxNone[] = { EGL_NONE };; + const EGLint KAttribsListCtxGles2[] = { EGL_CONTEXT_CLIENT_VERSION, aRenderVersionNumber, EGL_NONE }; + const EGLint* attrib_list_ctx = (aBindAPI == EGL_OPENGL_ES_API && aRenderVersionNumber == 2) ? KAttribsListCtxGles2 : KAttribsListCtxNone; + iContext = eglCreateContext(iDisplay, aConfig, EGL_NO_CONTEXT, attrib_list_ctx); + ASSERT_EGL_TRUE(iContext != EGL_NO_CONTEXT); + ASSERT_EGL_TRUE(eglMakeCurrent(iDisplay, iSurface, iSurface, iContext)); + } + +EXPORT_C TInt CTestEglSession::CreateBitmap(CFbsBitmap* aFbsBitmap, const TSize& aSize, TDisplayMode aDisplayMode) + { + //Fist try with CreateHardwareBitmap to check whether we are on hardware + TInt result = aFbsBitmap->CreateHardwareBitmap(aSize, aDisplayMode, KUidEglTestServer); + + if(result == KErrNotSupported) + { + //we are not on hardware + result = aFbsBitmap->Create(aSize, aDisplayMode); + } + return result; + } + +EXPORT_C void CTestEglSession::CreatePixmapSurfaceAndMakeCurrentL(EGLConfig aConfig, const TSize& aSize, TDisplayMode displayMode, EGLenum aBindAPI, TInt aRenderVersionNumber) + { + ASSERT_EQUALS(iSurface, EGL_NO_SURFACE); + ASSERT_EQUALS(iContext, EGL_NO_CONTEXT); + + // Create an empty native CFbsBitmap + OpenFbsSessionL(); + iFbsBitmap = new(ELeave)CFbsBitmap; + ASSERT_EQUALS(CreateBitmap(iFbsBitmap, aSize, displayMode), KErrNone); + + const EGLint* attrib_list = NULL; + if(aBindAPI == EGL_OPENVG_API) + { + // no attribs to modify + } + else if(aBindAPI == EGL_OPENGL_ES_API) + { + // no attribs to modify + } + else if(aBindAPI == EGL_OPENGL_ES_API && aRenderVersionNumber==2) + { + const EGLint KAttribGLES2[] = {EGL_CONTEXT_CLIENT_VERSION, aRenderVersionNumber, EGL_NONE}; + attrib_list=KAttribGLES2; + } + else + { + ERR_PRINTF1(_L("CreatePixmapSurfaceAndMakeCurrentL - Unkown API requested!")); + User::Leave(KErrArgument); + } + ASSERT_EGL_TRUE(eglBindAPI(aBindAPI)); + + // Create a pixmap surface from the native image + EGLint EGL_RENDERABLE_TYPE_value = 0; + ASSERT_EGL_TRUE(eglGetConfigAttrib(iDisplay, aConfig, EGL_RENDERABLE_TYPE, &EGL_RENDERABLE_TYPE_value)); + const EGLint* pixmapAttribs = ((displayMode == EColor16MAP) && (EGL_RENDERABLE_TYPE_value & EGL_OPENVG_BIT)) ? KPixmapAttribsVgAlphaFormatPre : KPixmapAttribsNone; + iSurface = eglCreatePixmapSurface(iDisplay, aConfig, iFbsBitmap, pixmapAttribs); + ASSERT_EGL_TRUE(iSurface != EGL_NO_SURFACE); + + // Create a context for drawing to/reading from the pixmap surface and make it current + iContext = eglCreateContext(iDisplay, aConfig, EGL_NO_CONTEXT, attrib_list); + ASSERT_EGL_TRUE(iContext != EGL_NO_CONTEXT); + ASSERT_EGL_TRUE(eglMakeCurrent(iDisplay, iSurface, iSurface, iContext)); + } + +EXPORT_C void CTestEglSession::CreatePixmapSurfaceAndMakeCurrentAndMatchL(const TSize& aSize, TDisplayMode displayMode, EGLenum aBindAPI, TInt aRenderVersionNumber) + { + ASSERT_EQUALS(iSurface, EGL_NO_SURFACE); + ASSERT_EQUALS(iContext, EGL_NO_CONTEXT); + + OpenFbsSessionL(); + iFbsBitmap = new(ELeave)CFbsBitmap; + ASSERT_EQUALS(CreateBitmap(iFbsBitmap, aSize, displayMode), KErrNone); + + EGLint renderableType = 0; + if(aBindAPI == EGL_OPENVG_API) + { + renderableType = EGL_OPENVG_BIT; + } + else if(aBindAPI == EGL_OPENGL_ES_API && aRenderVersionNumber==1) + { + renderableType = EGL_OPENGL_ES_BIT; + } + else if(aBindAPI == EGL_OPENGL_ES_API && aRenderVersionNumber==2) + { + renderableType = EGL_OPENGL_ES2_BIT; + } + else + { + ERR_PRINTF1(_L("CreatePixmapSurfaceAndMakeCurrentAndMatchL - Unkown API requested!")); + User::Leave(KErrArgument); + } + EGLint attrib_list[] = { + EGL_MATCH_NATIVE_PIXMAP,(TInt)iFbsBitmap, + EGL_RENDERABLE_TYPE,renderableType, + EGL_SURFACE_TYPE,EGL_PIXMAP_BIT, + EGL_NONE}; + + ASSERT_EGL_TRUE(eglBindAPI(aBindAPI)); + + EGLConfig config; + EGLint numConfigs; + ASSERT_EGL_TRUE(eglChooseConfig(iDisplay,attrib_list,&config,1,&numConfigs)); + if (numConfigs <= 0) + { + // we just WARN, as we don't know if this is expected yet (if it is, then catch the leaving error) + WARN_PRINTF1(_L("CreatePixmapSurfaceAndMakeCurrentAndMatchL - Could not find a matching config!")); + iSgImage.Close(); + CloseSgDriver(); + // Leave with a unique knonwn error code - useful to catch this error in negative tests + User::Leave(KTestNoMatchingConfig); + } + + // Create a pixmap surface from the native image + EGLint EGL_RENDERABLE_TYPE_value = 0; + ASSERT_EGL_TRUE(eglGetConfigAttrib(iDisplay, config, EGL_RENDERABLE_TYPE, &EGL_RENDERABLE_TYPE_value)); + const EGLint* pixmapAttribs = ((displayMode == EColor16MAP) && (EGL_RENDERABLE_TYPE_value & EGL_OPENVG_BIT)) ? KPixmapAttribsVgAlphaFormatPre : KPixmapAttribsNone; + iSurface = eglCreatePixmapSurface(iDisplay, config, iFbsBitmap, pixmapAttribs); + ASSERT_EGL_TRUE(iSurface != EGL_NO_SURFACE); + + // Create a context for drawing to/reading from the pixmap surface and make it current + const EGLint KAttribsListCtxNone[] = { EGL_NONE };; + const EGLint KAttribsListCtxGles2[] = { EGL_CONTEXT_CLIENT_VERSION, aRenderVersionNumber, EGL_NONE }; + const EGLint* attrib_list_ctx = (aBindAPI == EGL_OPENGL_ES_API && aRenderVersionNumber == 2) ? KAttribsListCtxGles2 : KAttribsListCtxNone; + iContext = eglCreateContext(iDisplay, config, EGL_NO_CONTEXT, attrib_list_ctx); + ASSERT_EGL_TRUE(iContext != EGL_NO_CONTEXT); + ASSERT_EGL_TRUE(eglMakeCurrent(iDisplay, iSurface, iSurface, iContext)); + } + +EXPORT_C void CTestEglSession::CreatePbufferSurfaceAndMakeCurrentL(EGLConfig aConfig, const TSize& aSize, EGLenum aBindAPI, TInt aRenderVersionNumber) + { + ASSERT_EQUALS(iSurface, EGL_NO_SURFACE); + ASSERT_EQUALS(iContext, EGL_NO_CONTEXT); + + ASSERT_EQUALS(iSurface, EGL_NO_SURFACE); + ASSERT_EQUALS(iContext, EGL_NO_CONTEXT); + + ASSERT_EGL_TRUE(eglBindAPI(aBindAPI)); + + // PBuffer attribs options are: + // EGL_WIDTH, EGL_HEIGHT, EGL_LARGEST_PBUFFER, + // EGL_TEXTURE_FORMAT, EGL_TEXTURE_TARGET, EGL_MIPMAP_TEXTURE, + // EGL_VG_COLORSPACE, and EGL_VG_ALPHA_FORMAT + // Create a pbuffer surface of the given size + const EGLint KPbufferAttribs[] = { + EGL_WIDTH, aSize.iWidth, + EGL_HEIGHT, aSize.iHeight, + EGL_NONE }; + iSurface = eglCreatePbufferSurface(iDisplay, aConfig, KPbufferAttribs); + ASSERT_EGL_TRUE(iSurface != EGL_NO_SURFACE); + + // Create a context for drawing to/reading from the pixmap surface and make it current + const EGLint KAttribsListCtxNone[] = { EGL_NONE };; + const EGLint KAttribsListCtxGles2[] = { EGL_CONTEXT_CLIENT_VERSION, aRenderVersionNumber, EGL_NONE }; + const EGLint* attrib_list_ctx = (aBindAPI == EGL_OPENGL_ES_API && aRenderVersionNumber == 2) ? KAttribsListCtxGles2 : KAttribsListCtxNone; + iContext = eglCreateContext(iDisplay, aConfig, EGL_NO_CONTEXT, attrib_list_ctx); + ASSERT_EGL_TRUE(iContext != EGL_NO_CONTEXT); + ASSERT_EGL_TRUE(eglMakeCurrent(iDisplay, iSurface, iSurface, iContext)); + } + +EXPORT_C void CTestEglSession::DrawOpenVgL() + { + ASSERT_TRUE(iSurface != EGL_NO_SURFACE); + ASSERT_TRUE(iContext != EGL_NO_CONTEXT); + + // Draw to the pixmap surface + // Clear it: redish + VGfloat colorBackground[4]; + ConvertColor(KRgbReddish, colorBackground); + vgSetfv(VG_CLEAR_COLOR, 4, colorBackground); + vgClear(0, 0, KPixmapSize.iWidth, KPixmapSize.iHeight); + + // And add a square: greenish + VGfloat colorSquare[4]; + ConvertColor(KRgbGreenish, colorSquare); + vgSetfv(VG_CLEAR_COLOR, 4, colorSquare); + vgClear(KPixmapSquare.iTl.iX, KPixmapSquare.iTl.iX, KPixmapSquare.Width(), KPixmapSquare.Height()); + } + +EXPORT_C void CTestEglSession::DrawOpenGLesL() + { + ASSERT_TRUE(iSurface != EGL_NO_SURFACE); + ASSERT_TRUE(iContext != EGL_NO_CONTEXT); + //GreenishRGB 0x46, 0xDC, 0x78 + const GLfloat glRed = KRgbReddish.Red(); + const GLfloat glGreen = KRgbReddish.Green(); + const GLfloat glBlue = KRgbReddish.Blue(); + const GLfloat glAlpha = KRgbReddish.Alpha(); + const GLfloat glRedBits = 255.f; + const GLfloat glGreenBits = 255.f; + const GLfloat glBlueBits = 255.f; + const GLfloat glAlphaBits = 255.f; + + // Disable cdither - when using exact comparison to reference bitmap + // because reference bitmap cannot be created to match dither exactly + glDisable(GL_DITHER); + // Clear the surface to the colour specified + glClearColor((glRed)/glRedBits, (glGreen)/glGreenBits, (glBlue)/glBlueBits, glAlpha/glAlphaBits); + + //glColor3f(KRgbGreenish.Red(),KRgbGreenish.Green(),KRgbGreenish.Blue()); + //glRectf(KPixmapSquare.iTl.iX, KPixmapSquare.iTl.iY,KPixmapSquare.iTl.iX + KPixmapSquare.Width(),KPixmapSquare.iTl.iY + KPixmapSquare.Height()); + + glClear(GL_COLOR_BUFFER_BIT); + } + +EXPORT_C void CTestEglSession::CheckImageDataL(CFbsBitmap* aFbsBitmap) + { + // Use native API's to check pixel values in the surface - note that this is not an OpenVG test, so no boundary pixels are tested + TRgb rgbPixelSample; + // Outside the square + aFbsBitmap->GetPixel(rgbPixelSample, TPoint(10,10)); + ASSERT_TRUE(PixelsMatch(KRgbReddish, rgbPixelSample, EFalse)); + aFbsBitmap->GetPixel(rgbPixelSample, TPoint(90,90)); + ASSERT_TRUE(PixelsMatch(KRgbReddish, rgbPixelSample, EFalse)); + + // Inside the square + aFbsBitmap->GetPixel(rgbPixelSample, TPoint(30,30)); + ASSERT_TRUE(PixelsMatch(KRgbGreenish, rgbPixelSample, EFalse)); + aFbsBitmap->GetPixel(rgbPixelSample, TPoint(70,70)); + ASSERT_TRUE(PixelsMatch(KRgbGreenish, rgbPixelSample, EFalse)); + } + +EXPORT_C void CTestEglSession::CheckImageDataFullRedishL(CFbsBitmap* aFbsBitmap) + { + // Use native API's to check pixel values in the surface - note that this is not an OpenVG test, so no boundary pixels are tested + TRgb rgbPixelSample; + // Outside the square + aFbsBitmap->GetPixel(rgbPixelSample, TPoint(10,10)); + ASSERT_TRUE(PixelsMatch(KRgbReddish, rgbPixelSample, EFalse)); + aFbsBitmap->GetPixel(rgbPixelSample, TPoint(90,90)); + ASSERT_TRUE(PixelsMatch(KRgbReddish, rgbPixelSample, EFalse)); + + // Inside the square + aFbsBitmap->GetPixel(rgbPixelSample, TPoint(30,30)); + ASSERT_TRUE(PixelsMatch(KRgbReddish, rgbPixelSample, EFalse)); + aFbsBitmap->GetPixel(rgbPixelSample, TPoint(70,70)); + ASSERT_TRUE(PixelsMatch(KRgbReddish, rgbPixelSample, EFalse)); + } + +/** +Use OpenVG to check pixel values +@param aDataFormat The VG image data format of the current surface +*/ +EXPORT_C void CTestEglSession::CheckImageDataVgL(VGImageFormat aDataFormat) + { + switch(aDataFormat) + { + case VG_sRGB_565: + { + TUint16 intPixelSample=0; + + // Outside the square + vgReadPixels(&intPixelSample, 1, aDataFormat, 10,10, 1,1); + ASSERT_TRUE(PixelsMatch(KRgbReddish, TRgb::Color64K(intPixelSample), EFalse)); + vgReadPixels(&intPixelSample, 1, aDataFormat, 90,90, 1,1); + ASSERT_TRUE(PixelsMatch(KRgbReddish, TRgb::Color64K(intPixelSample), EFalse)); + + // Inside the square + vgReadPixels(&intPixelSample, 1, aDataFormat, 30,30, 1,1); + ASSERT_TRUE(PixelsMatch(KRgbGreenish, TRgb::Color64K(intPixelSample), EFalse)); + vgReadPixels(&intPixelSample, 1, aDataFormat, 70,70, 1,1); + ASSERT_TRUE(PixelsMatch(KRgbGreenish, TRgb::Color64K(intPixelSample), EFalse)); + break; + } + case VG_sXRGB_8888: + { + TUint32 intPixelSample=0; + + // Outside the square + vgReadPixels(&intPixelSample, 1, aDataFormat, 10,10, 1,1); + ASSERT_TRUE(PixelsMatch(KRgbReddish, TRgb::Color16MU(intPixelSample), EFalse)); + vgReadPixels(&intPixelSample, 1, aDataFormat, 90,90, 1,1); + ASSERT_TRUE(PixelsMatch(KRgbReddish, TRgb::Color16MU(intPixelSample), EFalse)); + + // Inside the square + vgReadPixels(&intPixelSample, 1, aDataFormat, 30,30, 1,1); + ASSERT_TRUE(PixelsMatch(KRgbGreenish, TRgb::Color16MU(intPixelSample), EFalse)); + vgReadPixels(&intPixelSample, 1, aDataFormat, 70,70, 1,1); + ASSERT_TRUE(PixelsMatch(KRgbGreenish, TRgb::Color16MU(intPixelSample), EFalse)); + break; + } + case VG_sARGB_8888: + { + TUint32 intPixelSample=0; + + // Outside the square + vgReadPixels(&intPixelSample, 1, aDataFormat, 10,10, 1,1); + ASSERT_TRUE(PixelsMatch(KRgbReddish, TRgb::Color16MA(intPixelSample), EFalse)); + vgReadPixels(&intPixelSample, 1, aDataFormat, 90,90, 1,1); + ASSERT_TRUE(PixelsMatch(KRgbReddish, TRgb::Color16MA(intPixelSample), EFalse)); + + // Inside the square + vgReadPixels(&intPixelSample, 1, aDataFormat, 30,30, 1,1); + ASSERT_TRUE(PixelsMatch(KRgbGreenish, TRgb::Color16MA(intPixelSample), EFalse)); + vgReadPixels(&intPixelSample, 1, aDataFormat, 70,70, 1,1); + ASSERT_TRUE(PixelsMatch(KRgbGreenish, TRgb::Color16MA(intPixelSample), EFalse)); + break; + } + default: + WARN_PRINTF2(_L("Unexpected image data format %d in CTestEglSession::CheckImageDataVgL"), aDataFormat); + ASSERT_TRUE(EFalse); + } + } + +/** +Use OpenGLes to check pixel values +@param aDataFormat The VG image data format of the current surface +*/ +EXPORT_C void CTestEglSession::CheckImageDataGLesL() + { + TUint32 intPixelSample; + glReadPixels(10,10,1,1,GL_RGBA,GL_UNSIGNED_BYTE ,&intPixelSample); + SwapChannels(intPixelSample); + ASSERT_TRUE(PixelsMatch(KRgbReddish, TRgb::Color16MU(intPixelSample), EFalse)); + + glReadPixels(45,45,1,1,GL_RGBA,GL_UNSIGNED_BYTE ,&intPixelSample); + SwapChannels(intPixelSample); + ASSERT_TRUE(PixelsMatch(KRgbReddish, TRgb::Color16MU(intPixelSample), EFalse)); + + glReadPixels(55,55,1,1,GL_RGBA,GL_UNSIGNED_BYTE ,&intPixelSample); + SwapChannels(intPixelSample); + ASSERT_TRUE(PixelsMatch(KRgbReddish, TRgb::Color16MU(intPixelSample), EFalse)); + + glReadPixels(99,99,1,1,GL_RGBA,GL_UNSIGNED_BYTE ,&intPixelSample); + SwapChannels(intPixelSample); + ASSERT_TRUE(PixelsMatch(KRgbReddish, TRgb::Color16MU(intPixelSample), EFalse)); + + } + +EXPORT_C void CTestEglSession::SwapChannels(TUint32 &aSwapMe) + { + TUint32 buff = aSwapMe; + + aSwapMe = 0; + aSwapMe |= (buff & 0x000000FF) << 16; + aSwapMe |= (buff & 0x0000FF00); + aSwapMe |= (buff & 0x00FF0000) >> 16; + aSwapMe |= (buff & 0xFF000000); + } + +/** +Destroys the surface and underlying RSgImage object. +Nulls the current context. +*/ +EXPORT_C void CTestEglSession::CleanupSurfaceSgImageL() + { + CleanupSurfaceAndContextL(); + + iSgImage.Close(); + } + +/** +Resets the internal surface and context handles without destroying them. +Also closes the internal RSgImage handled that is associated to the surface. + +EGL destroys all surface and context handles associated with a display when +eglTerminate() is called. +*/ +EXPORT_C void CTestEglSession::ResetSurfaceAndContextSgImageL() + { + INFO_PRINTF1(_L("CTestEglSession::ResetSurfaceAndContextSgImageL()")); + + iContext = EGL_NO_CONTEXT; + iSurface = EGL_NO_SURFACE; + iSgImage.Close(); + } + +/** + Check that the pixel values match within a predefined tolerance + @param aExpected the expected pixel colour vaule + @param aActual the actual pixel colour value + @param aCheckAlpha Whether to check the alpha channel value + @return Whether the pixel values match - within the allowed tolerance + */ +EXPORT_C TBool CTestEglSession::PixelsMatch(const TRgb& aExpected, const TRgb& aActual, TBool aCheckAlpha) + { + // This value has been carefully selected. If it is too high it could be hidding genuine pixel value + // differences, while too low will be too strict to allow for pixel conversions, i.e. from 16bpp to 32bpp + const TInt KPixelTolerance = 8; + + if (aCheckAlpha && aExpected.Alpha()== 0 && + aActual.Red() == 0 && + aActual.Green() == 0 && + aActual.Blue() == 0 && + aActual.Alpha() == 0) + { + // if the expected value for alpha is 0, all actual values should be 0 + return ETrue; + } + else if (Abs(aExpected.Red() - aActual.Red()) > KPixelTolerance || + Abs(aExpected.Green() - aActual.Green()) > KPixelTolerance || + Abs(aExpected.Blue() - aActual.Blue()) > KPixelTolerance || + aCheckAlpha && Abs(aExpected.Alpha() - aActual.Alpha()) > KPixelTolerance) + { + // one or more of the actual values differ by more than the allowed tolerance + ERR_PRINTF6(_L("thread %d: Expected r:%d g:%d b:%d a:%d"), iThreadIdx, aExpected.Red(), aExpected.Green(), aExpected.Blue(), aExpected.Alpha()); + ERR_PRINTF6(_L("thread %d: Actual r:%d g:%d b:%d a:%d"), iThreadIdx, aActual.Red(), aActual.Green(), aActual.Blue(), aActual.Alpha()); + ERR_PRINTF6(_L("thread %d: diff r:%d g:%d b:%d a:%d"), iThreadIdx, Abs(aExpected.Red() - aActual.Red()), Abs(aExpected.Green() - aActual.Green()), Abs(aExpected.Blue() - aActual.Blue()), Abs(aExpected.Alpha() - aActual.Alpha())); + return EFalse; + } + return ETrue; + } + +EXPORT_C void CTestEglSession::InitializeL(TBool aTerminateDisplay) + { + // Initialize display object + INFO_PRINTF2(_L("thread %d: Calling eglInitialize..."), iThreadIdx); + EGLint major=0; + EGLint minor=0; + CHECK_EXPECTED_ERROR(eglInitialize(iDisplay, &major, &minor)); + // Remember if the user wants us to terminate the display. + iTerminateDisplay = aTerminateDisplay; + + INFO_PRINTF4(_L("thread %d: Initialised: EGL Version %d.%d"), iThreadIdx, major, minor); + } + + +EXPORT_C void CTestEglSession::TerminateDisplayL() + { + if (iSurface != EGL_NO_SURFACE) + { + WARN_PRINTF2(_L("thread %d: iSurface has not been destoroyed in TerminateDisplayL..."), iThreadIdx); + } + if (iContext != EGL_NO_CONTEXT) + { + WARN_PRINTF2(_L("thread %d: iContext has not been destoroyed in TerminateDisplayL..."), iThreadIdx); + } + if (iDisplay != EGL_NO_DISPLAY) + { + INFO_PRINTF2(_L("thread %d: Calling eglMakeCurrent(NULL values) from TerminateDisplayL..."), iThreadIdx); + + ASSERT_EGL_TRUE(eglMakeCurrent(iDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT)); + + INFO_PRINTF1(_L("Calling eglTerminate...")); + ASSERT_EGL_TRUE(eglTerminate(iDisplay)); + iDisplay = EGL_NO_DISPLAY; + } + iTerminateDisplay = EFalse; + } + +EXPORT_C void CTestEglSession::OpenSgDriverL() + { + if (!iSgDriverOpen) + { + VERBOSE_INFO_PRINTF2(_L("CTestEglSession<0x%08x> Opening SgDriver"), this); +#ifdef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE + TInt ret=iSgDriver.Open(); +#else + TInt ret=SgDriver::Open(); +#endif //SYMBIAN_GRAPHICS_EGL_SGIMAGELITE + ASSERT_EQUALS(ret, KErrNone); + iSgDriverOpen = ETrue; + } + } + +EXPORT_C void CTestEglSession::CloseSgDriver() + { + if (iSgDriverOpen) + { + VERBOSE_INFO_PRINTF2(_L("CTestEglSession<0x%08x> Closing SgDriver"), this); +#ifdef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE + iSgDriver.Close(); +#else + SgDriver::Close(); +#endif //SYMBIAN_GRAPHICS_EGL_SGIMAGELITE + iSgDriverOpen = EFalse; + } + } + +EXPORT_C void CTestEglSession::OpenFbsSessionL() + { + if (!iFbsSessionOpen) + { + INFO_PRINTF2(_L("CTestEglSession<0x%08x> Opening FbsSession"), this); + TInt ret=RFbsSession::Connect(); + ASSERT_EQUALS(ret, KErrNone); + iFbsSessionOpen = ETrue; + } + } + +EXPORT_C void CTestEglSession::CloseFbsSession() + { + if (iFbsSessionOpen) + { + INFO_PRINTF2(_L("CTestEglSession<0x%08x> Closing FbsSession"), this); + RFbsSession::Disconnect(); + iFbsSessionOpen = EFalse; + } + } + +EXPORT_C TBool CTestEglSession::FetchProcEglCreateImageKhr() + { + if (!ipfnEglCreateImageKHR) + { + INFO_PRINTF2(_L("thread %d: Calling eglGetProcAddress(\"eglCreateImageKHR\")"), iThreadIdx); + ipfnEglCreateImageKHR = reinterpret_cast(eglGetProcAddress("eglCreateImageKHR")); + if (ipfnEglCreateImageKHR==NULL) + { + EGLint eglError = eglGetError(); + WARN_PRINTF2(_L("eglCreateImageKHR() not found - EGL Error: 0x%x"), eglError); + } + } + return (ipfnEglCreateImageKHR!=NULL); + } + +EXPORT_C EGLImageKHR CTestEglSession::eglCreateImageKhrL(EGLDisplay aDisplay,EGLContext aContext,EGLenum aTarget,RSgImage* aSgImage,const EGLint *aAttr_List) + { + TBool bSuccess = FetchProcEglCreateImageKhr(); + ASSERT_TRUE(bSuccess); + VERBOSE_INFO_PRINTF2(_L("thread %d: Calling eglCreateImageKHR"), iThreadIdx); + EGLImageKHR eglImage = ipfnEglCreateImageKHR(aDisplay,aContext,aTarget,reinterpret_cast(aSgImage),const_cast(aAttr_List)); + return eglImage; + } + +EXPORT_C EGLImageKHR CTestEglSession::eglCreateImageKhrL(EGLDisplay aDisplay,EGLContext aContext,EGLenum aTarget,CFbsBitmap &aCFbsBitmap, const EGLint *aAttr_List) + { + TBool bSuccess = FetchProcEglCreateImageKhr(); + ASSERT_TRUE(bSuccess); + INFO_PRINTF2(_L("thread %d: Calling eglCreateImageKHR, with CFBsBitmap)"), iThreadIdx); + //the following call to eglCreateImageKHR MUST fail, error handling is made outside + EGLImageKHR eglImage = ipfnEglCreateImageKHR(aDisplay,aContext,aTarget,reinterpret_cast(&aCFbsBitmap),const_cast(aAttr_List)); + return eglImage; + } + +EXPORT_C TBool CTestEglSession::FetchProcEglDestroyImageKhr() + { + if (!ipfnEglDestroyImageKHR) + { + INFO_PRINTF2(_L("thread %d: Calling eglGetProcAddress(\"eglDestroyImageKHR\")"), iThreadIdx); + ipfnEglDestroyImageKHR = reinterpret_cast(eglGetProcAddress("eglDestroyImageKHR")); + if (ipfnEglDestroyImageKHR==NULL) + { + EGLint eglError = eglGetError(); + WARN_PRINTF2(_L("eglDestroyImageKHR() not found - EGL Error: 0x%x"), eglError); + } + } + return (ipfnEglDestroyImageKHR!=NULL); + } + +EXPORT_C TBool CTestEglSession::DestroyEGLImage(EGLDisplay aDisplay, EGLImageKHR aEGLImageKHR) + { + TBool bSuccess = FetchProcEglDestroyImageKhr(); + ASSERT_TRUE(bSuccess); + VERBOSE_INFO_PRINTF2(_L("thread %d: Calling eglDestroyImageKHR"), iThreadIdx); + return ipfnEglDestroyImageKHR(aDisplay,aEGLImageKHR); + } + +EXPORT_C TBool CTestEglSession::FetchProcvgCreateImageTargetKhr() + { + if (!ipfnvgCreateImageTargetKHR) + { + INFO_PRINTF2(_L("thread %d: Calling eglGetProcAddress (\"vgCreateEGLImageTargetKHR\")"), iThreadIdx); + ipfnvgCreateImageTargetKHR = reinterpret_cast(eglGetProcAddress("vgCreateEGLImageTargetKHR")); + if (ipfnvgCreateImageTargetKHR==NULL) + { + EGLint eglError = eglGetError(); + WARN_PRINTF2(_L("vgCreateImageTargetKHR() not found - EGL Error: 0x%x"), eglError); + } + } + return (ipfnvgCreateImageTargetKHR!=NULL); + } + +EXPORT_C VGImage CTestEglSession::vgCreateImageTargetKHR(VGeglImageKHR aImage) + { + TBool bSuccess = FetchProcvgCreateImageTargetKhr(); + ASSERT_TRUE(bSuccess); + VERBOSE_INFO_PRINTF2(_L("thread %d: Calling vgCreateEGLImageTargetKHR"), iThreadIdx); + return ipfnvgCreateImageTargetKHR(aImage); + } + +EXPORT_C TBool CTestEglSession::IsACompatibleConfig(EGLConfig aConfig,RSgImage& aImage,TBool aLog) + { + EGLint EGL_BUFFER_SIZE_value; + EGLint EGL_ALPHA_SIZE_value; + EGLint EGL_BLUE_SIZE_value; + EGLint EGL_GREEN_SIZE_value; + EGLint EGL_RED_SIZE_value; + EGLint EGL_SURFACE_TYPE_value; + EGLint EGL_RENDERABLE_TYPE_value; + EGLint EGL_CONFIG_ID_value; + + eglGetConfigAttrib(iDisplay, aConfig, EGL_CONFIG_ID, &EGL_CONFIG_ID_value); + eglGetConfigAttrib(iDisplay, aConfig, EGL_BUFFER_SIZE, &EGL_BUFFER_SIZE_value); + eglGetConfigAttrib(iDisplay, aConfig, EGL_ALPHA_SIZE, &EGL_ALPHA_SIZE_value); + eglGetConfigAttrib(iDisplay, aConfig, EGL_BLUE_SIZE, &EGL_BLUE_SIZE_value); + eglGetConfigAttrib(iDisplay, aConfig, EGL_GREEN_SIZE, &EGL_GREEN_SIZE_value); + eglGetConfigAttrib(iDisplay, aConfig, EGL_RED_SIZE, &EGL_RED_SIZE_value); + eglGetConfigAttrib(iDisplay, aConfig, EGL_SURFACE_TYPE, &EGL_SURFACE_TYPE_value); + eglGetConfigAttrib(iDisplay, aConfig, EGL_RENDERABLE_TYPE, &EGL_RENDERABLE_TYPE_value); +#ifdef PRINTG_CONFIGS_LOG + INFO_PRINTF7(_L("(Config: %3d) RGBA=(%2d) %2d,%2d,%2d,%2d"), EGL_CONFIG_ID_value, EGL_BUFFER_SIZE_value, + EGL_RED_SIZE_value, EGL_GREEN_SIZE_value, EGL_BLUE_SIZE_value, + EGL_ALPHA_SIZE_value); + INFO_PRINTF2(_L("RENDERABLE_TYPE %d"),EGL_RENDERABLE_TYPE_value); +#endif + + if(!(EGL_SURFACE_TYPE_value & EGL_PIXMAP_BIT)) + { + return EFalse; + } + + TBool good = ETrue; + //requested usage bits + TSgImageInfo requestedImageInfo; + aImage.GetInfo(requestedImageInfo); + +#ifndef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE + //potential usage bits + RSgImage potential; + potential.Open(aImage.Id(),ESgDoNotRestrictUsage); + TSgImageInfo potentialImageInfo; + potential.GetInfo(potentialImageInfo); + potential.Close(); +#endif + + switch(requestedImageInfo.iPixelFormat) + { + case EUidPixelFormatRGB_565: + if (!(EGL_RED_SIZE_value == 5 && EGL_GREEN_SIZE_value == 6 && EGL_BLUE_SIZE_value == 5 && EGL_ALPHA_SIZE_value == 0)) + { + good = EFalse; + } + break; + case EUidPixelFormatXRGB_8888: + if (!(EGL_RED_SIZE_value == 8 && EGL_GREEN_SIZE_value == 8 && EGL_BLUE_SIZE_value == 8 && EGL_ALPHA_SIZE_value == 0)) + { + good = EFalse; + } + break; + case EUidPixelFormatARGB_8888_PRE: + if (!(EGL_RED_SIZE_value == 8 && EGL_GREEN_SIZE_value == 8 && EGL_BLUE_SIZE_value == 8 && EGL_ALPHA_SIZE_value == 8)) + { + good = EFalse; + } + //just OVG cares about the premultiplied alpha + if(EGL_RENDERABLE_TYPE_value& EGL_OPENVG_BIT) + //if(requestedImageInfo.iUsage & ESgUsageBitOpenVgSurface) + { + if(!(EGL_SURFACE_TYPE_value & EGL_VG_ALPHA_FORMAT_PRE_BIT)) + { + if(aLog) + { + WARN_PRINTF2(_L("This Config can't be used with Pre-multipliedAlpha becasue EGL_SURFACE_TYPE has the wrong bits = %x"), EGL_SURFACE_TYPE_value); + } + good = EFalse; + } + } + break; + default: + if(aLog) + { + ERR_PRINTF2(_L("Wrong PixelFormat for a target, %x"), requestedImageInfo.iPixelFormat); + } + good = EFalse; + } + if(!good) + { + return EFalse; + } + +#ifdef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE + // + //Check if strict matching requirements are met: + //- All the supported APIs included in the EGL_RENDERABLE_TYPE of the + // EGLConfig must be matched by the corresponding iUsage of RSgImage + //- The following usages included in the iUsage of the RSgImage must be + // matched by the corresponding API in EGL_RENDERABLE_TYPE of the EGLConfig: + // ESgUsageBitOpenGlSurface-> EGL_OPENGL_BIT + // ESgUsageBitOpenGlesSurface-> EGL_OPENGL_ES_BIT + // ESgUsageBitOpenGles2Surface-> EGL_OPENGL_ES2_BIT + // ESgUsageBitOpenVgSurface->EGL_OPENVG_BIT + + EGLint usageBitsMask = 0; + if(requestedImageInfo.iUsage & ESgUsageBitOpenVgSurface) + { + usageBitsMask |= EGL_OPENVG_BIT; + } + if(requestedImageInfo.iUsage & ESgUsageBitOpenGles2Surface) + { + usageBitsMask |= EGL_OPENGL_ES2_BIT; + } + if(requestedImageInfo.iUsage & ESgUsageBitOpenGlesSurface) + { + usageBitsMask |= EGL_OPENGL_ES_BIT; + } + if(requestedImageInfo.iUsage & ESgUsageBitOpenGlSurface) + { + usageBitsMask |= EGL_OPENGL_BIT; + } + + if(usageBitsMask != EGL_RENDERABLE_TYPE_value) + { + return EFalse; + } +#else + // requested usage & RENDERABLE_TYPE > 0 + EGLint usageBitsMask = 0; + if(requestedImageInfo.iUsage & ESgUsageOpenVgTarget) + { + usageBitsMask |= EGL_OPENVG_BIT; + } + if(requestedImageInfo.iUsage & ESgUsageOpenGlesTarget) + { + usageBitsMask |= EGL_OPENGL_ES_BIT; + } + if(requestedImageInfo.iUsage & ESgUsageOpenGles2Target) + { + usageBitsMask |= EGL_OPENGL_ES2_BIT; + } + if(!(usageBitsMask & EGL_RENDERABLE_TYPE_value)) + { + return EFalse; + } + + // potential usage >= RENDERABLE_TYPE + + EGLint potentialUsageBitsMask = 0; + if(potentialImageInfo.iUsage & ESgUsageOpenVgTarget) + { + potentialUsageBitsMask |= EGL_OPENVG_BIT; + } + if(potentialImageInfo.iUsage & ESgUsageOpenGlesTarget) + { + potentialUsageBitsMask |= EGL_OPENGL_ES_BIT; + } + if(potentialImageInfo.iUsage & ESgUsageOpenGles2Target) + { + potentialUsageBitsMask |= EGL_OPENGL_ES2_BIT; + } + + potentialUsageBitsMask = EGL_RENDERABLE_TYPE_value &~ potentialUsageBitsMask; + if(potentialUsageBitsMask) + { + return EFalse; + } +#endif //SYMBIAN_GRAPHICS_EGL_SGIMAGELITE + return good; + } + +EXPORT_C TBool CTestEglSession::CheckNeededExtensionL(TInt aExtension, const TDesC& aExtensionName) + { + TBuf8<128> extensionName; + extensionName.Copy(aExtensionName); + if(aExtension & KEGL_RSgimage || extensionName.Compare(KEglRSgImage)==0) + { + TBool bFoundExtensionEGL_NOK_pixmap_type_rsgimage = FindExtensionStringL(EIsEGL,KEglRSgImage); + if (!bFoundExtensionEGL_NOK_pixmap_type_rsgimage) + { + // The extension is not supported + return EFalse; + } + } + if(aExtension & KEGL_KHR_image_base || extensionName.Compare(KEglKhrImageBase)==0) + { + TBool bFoundExtensionEGL_KHR_image = FindExtensionStringL(EIsEGL,KEglKhrImageBase); + if (!bFoundExtensionEGL_KHR_image) + { + // The extension is not supported + return EFalse; + } + } + if(aExtension & KEGL_KHR_image_pixmap || extensionName.Compare(KEglKhrImagePixmap)==0) + { + TBool bFoundExtensionEGL_KHR_image = FindExtensionStringL(EIsEGL,KEglKhrImagePixmap); + if (!bFoundExtensionEGL_KHR_image) + { + // The extension is not supported + return EFalse; + } + } + if(aExtension & KVG_KHR_EGL_image || extensionName.Compare(KVgKhrEglImage)==0) + { + TBool bFoundExtensionVG_KHR_EGL_image = FindExtensionStringL(EIsVG,KVgKhrEglImage); + if (!bFoundExtensionVG_KHR_EGL_image) + { + // The extension is not supported + return EFalse; + } + } + if(aExtension & KEGL_KHR_reusable_sync || extensionName.Compare(KEglKhrReusableSync)==0) + { + TBool bFoundExtensionEGL_KHR_reusable_sync = FindExtensionStringL(EIsEGL,KEglKhrReusableSync); + if (!bFoundExtensionEGL_KHR_reusable_sync) + { + // The extension is not supported + return EFalse; + } + } + if(aExtension & KEGL_NOK__private__signal_sync) + { + TBool bFoundExtensionEGL_NOK__private__signal_sync = FindExtensionStringL(EIsEGL,KEglNokPrivateSignalSync); + if (!bFoundExtensionEGL_NOK__private__signal_sync) + { + // The extension is not supported + return EFalse; + } + } + if(aExtension & KEGL_NOKIA_swap_buffers) + { + TBool bFoundExtensionEGL_NOKIA_swap_buffer = FindExtensionStringL(EIsEGL,KEglNokiaSwapBuffers); + if (!bFoundExtensionEGL_NOKIA_swap_buffer) + { + // The extension is not supported + return EFalse; + } + } +#ifndef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE + if(aExtension & KEGL_SYMBIAN_image_preserved) + { + TBool bFoundExtensionEGL_SYMBIAN_image_preserved = FindExtensionStringL(EIsEGL,KEglSymbianImagePreserved); + if (!bFoundExtensionEGL_SYMBIAN_image_preserved) + { + // The extension is not supported + return EFalse; + } + } +#endif //SYMBIAN_GRAPHICS_EGL_SGIMAGELITE + + return ETrue; + } + +EXPORT_C CFbsBitmap* CTestEglSession::CreateReferenceBitmapL(TDisplayMode aMode) + { + if(aMode == ENone ) + { + ERR_PRINTF1(_L("Queried Reference Bitmap dispaly mode equal to ENone")); + User::Leave(KErrTEFUnitFail); + } + return CreateReferenceBitmapL(aMode,KRgbGreenish); + } + +EXPORT_C CFbsBitmap* CTestEglSession::CreateReferenceBitmapL(TDisplayMode aMode,const TRgb& aColour) + { + OpenFbsSessionL(); + CFbsBitmap* bitmap = new(ELeave) CFbsBitmap(); + CleanupStack::PushL(bitmap); + if(bitmap->Create(KPixmapSize,aMode) != KErrNone) + { + return NULL; + } + CFbsBitmapDevice* bitmapDevice = CFbsBitmapDevice::NewL(bitmap); + CleanupStack::PushL(bitmapDevice); + CFbsBitGc* fbsBitGc = CFbsBitGc::NewL(); + CleanupStack::PushL(fbsBitGc); + fbsBitGc->Activate(bitmapDevice); + fbsBitGc->SetBrushColor(aColour); + fbsBitGc->Clear(); + CleanupStack::PopAndDestroy(2,bitmapDevice); + CleanupStack::Pop(bitmap); + return bitmap; + } + +EXPORT_C CFbsBitmap* CTestEglSession::CreateReferenceMaskedBitmapL(TDisplayMode aRefBitmapMode, const TRgb& aPenBitmapColor, const CFbsBitmap* aMaskBitmap) + { + OpenFbsSessionL(); + + // create the refBitmat (same size as the mask bitmap) + // Note that we clear it to 'opaque black' as we assume the target surface has been cleared to 'opaque black' too + // If either the surface or the refBitmap are cleared to another colour, update the other accordingly + CFbsBitmap* refBitmap = new(ELeave) CFbsBitmap(); + CleanupStack::PushL(refBitmap); + User::LeaveIfError(refBitmap->Create(aMaskBitmap->SizeInPixels(), aRefBitmapMode)); + CFbsBitmapDevice* bitmapDevice = CFbsBitmapDevice::NewL(refBitmap); + CleanupStack::PushL(bitmapDevice); + CFbsBitGc* fbsBitGc = CFbsBitGc::NewL(); + CleanupStack::PushL(fbsBitGc); + fbsBitGc->Activate(bitmapDevice); + fbsBitGc->SetBrushColor(KRgbBlack); + fbsBitGc->Clear(); + + // create the penBitmap (same size as the mask bitmap) + CFbsBitmap* penBitmap = new(ELeave) CFbsBitmap(); + CleanupStack::PushL(penBitmap); + User::LeaveIfError(penBitmap->Create(aMaskBitmap->SizeInPixels(), aRefBitmapMode)); + CFbsBitmapDevice* penbitmapDevice = CFbsBitmapDevice::NewL(penBitmap); + CleanupStack::PushL(penbitmapDevice); + CFbsBitGc* penBitGc = CFbsBitGc::NewL(); + CleanupStack::PushL(penBitGc); + penBitGc->Activate(penbitmapDevice); + penBitGc->SetBrushColor(aPenBitmapColor); + penBitGc->Clear(); + + // perform a masked bitmap transfer to the active refBitmap + TRect bmpRect(TPoint(0, 0), refBitmap->SizeInPixels()); + fbsBitGc->Activate(bitmapDevice); + fbsBitGc->BitBltMasked(TPoint(0, 0), penBitmap, bmpRect, aMaskBitmap, EFalse); + + CleanupStack::PopAndDestroy(5, bitmapDevice); + CleanupStack::Pop(refBitmap); + return refBitmap; + } + + +EXPORT_C CFbsBitmap* CTestEglSession::CreateReferenceBitmapL(TDisplayMode aMode, const TSize &aSize, const TInt aIndex) + { + OpenFbsSessionL(); + CFbsBitmap* bitmap = new(ELeave) CFbsBitmap(); + CleanupStack::PushL(bitmap); + User::LeaveIfError(bitmap->Create(aSize,aMode)); + + TInt height = bitmap->SizeInPixels().iHeight; + TInt width = bitmap->SizeInPixels().iWidth; + + // Initialise colour values to a random value (guarantees pixel uniqueness if update is done accordingly) + TInt red=0; + TInt green=127; + TInt blue=127; + TInt alpha=255; + + TBitmapUtil bmpUtil(bitmap); + bmpUtil.Begin(TPoint(0,0)); + for (TInt colIndex = 0; colIndex < width; ++colIndex) + + { + bmpUtil.SetPos(TPoint(colIndex, 0)); + for (TInt rowIndex =0; rowIndex < height; ++rowIndex) + { + TRgb rgb(red, green, blue, alpha); + switch(bitmap->DisplayMode()) + { + case EColor64K: + { + bmpUtil.SetPixel(rgb.Color64K()); + break; + } + case EColor16MU: + { + bmpUtil.SetPixel(rgb.Color16MU()); + break; + } + case EColor16MA: + { + bmpUtil.SetPixel(rgb.Color16MA()); + break; + } + case EColor16MAP: + { + bmpUtil.SetPixel(rgb.Color16MAP()); + break; + } + case EGray256: + { + bmpUtil.SetPixel(rgb.Gray256()); + break; + } + default: + { + // We should not get here - colour mode not supported by these tests + ERR_PRINTF1(_L("CTestEglSession::CreateReferenceBitmapL - Colour mode not supported!")); + ASSERT(FALSE); + } + } + bmpUtil.IncYPos(); + + // Update red bit + red = ++red + aIndex; + if (red>255) + red = red - 256; + + // Update green bit + green = --green - aIndex; + if (green<0) + green = green + 256; + + // Update blue bit + blue = ++blue + aIndex; + if (blue>255) + blue = blue - 256; + + // Update alpha bit + alpha = --alpha - aIndex; + if (alpha<0) + alpha = alpha + 256; + } + } + bmpUtil.End(); + CleanupStack::Pop(bitmap); + return bitmap; + } + +EXPORT_C void CTestEglSession::CheckVgDrawingL(VGImageFormat aDataFormat, const CFbsBitmap* aReferenceBitmap) + { + TRgb refPixel; + TInt height = aReferenceBitmap->SizeInPixels().iHeight; + TInt width = aReferenceBitmap->SizeInPixels().iWidth; + + switch(aDataFormat) + { + case VG_sRGB_565: + { + TUint16* vgPixel = new(ELeave) TUint16[width]; + CleanupArrayDeletePushL(vgPixel); + for (TInt y=0; y < height; y++) + { + // Mind the fact that CFbsBitmap and VGImages use different coordinates origin! + vgReadPixels(vgPixel, 1, aDataFormat, 0,height-y-1, width,1); + + for (TInt x=0; x < width; x++) + { + aReferenceBitmap->GetPixel(refPixel, TPoint(x,y)); + if(!PixelsMatch(refPixel, TRgb::Color64K(vgPixel[x]), EFalse)) + { + User::Leave(KErrTEFUnitFail); + } + } + } + CleanupStack::PopAndDestroy(vgPixel); + break; + } + + case VG_sXRGB_8888: + { + TUint32* vgPixel = new(ELeave) TUint32[width]; + CleanupArrayDeletePushL(vgPixel); + for (TInt y=0; y < height; y++) + { + // Mind the fact that CFbsBitmap and VGImages use different coordinates origin! + vgReadPixels(vgPixel, 1, aDataFormat, 0,height-y-1, width,1); + + for (TInt x=0; x < width; x++) + { + aReferenceBitmap->GetPixel(refPixel, TPoint(x,y)); + if(!PixelsMatch(refPixel, TRgb::Color16MU(vgPixel[x]), EFalse)) + { + User::Leave(KErrTEFUnitFail); + } + } + } + CleanupStack::PopAndDestroy(vgPixel); + break; + } + + case VG_sARGB_8888: + { + TUint32* vgPixel = new(ELeave) TUint32[width]; + CleanupArrayDeletePushL(vgPixel); + for (TInt y=0; y < height; y++) + { + // Mind the fact that CFbsBitmap and VGImages use different coordinates origin! + vgReadPixels(vgPixel, 1, aDataFormat, 0,height-y-1, width,1); + + for (TInt x=0; x < width; x++) + { + aReferenceBitmap->GetPixel(refPixel, TPoint(x,y)); + if(!PixelsMatch(refPixel, TRgb::Color16MA(vgPixel[x]), ETrue)) + { + User::Leave(KErrTEFUnitFail); + } + } + } + CleanupStack::PopAndDestroy(vgPixel); + break; + } + + case VG_sARGB_8888_PRE: + { + TUint32* vgPixel = new(ELeave) TUint32[width]; + CleanupArrayDeletePushL(vgPixel); + for (TInt y=0; y < height; y++) + { + // Mind the fact that CFbsBitmap and VGImages use different coordinates origin! + vgReadPixels(vgPixel, 1, aDataFormat, 0,height-y-1, width,1); + + for (TInt x=0; x < width; x++) + { + aReferenceBitmap->GetPixel(refPixel, TPoint(x,y)); + if(!PixelsMatch(refPixel, TRgb::Color16MAP(vgPixel[x]), ETrue)) + { + User::Leave(KErrTEFUnitFail); + } + } + } + CleanupStack::PopAndDestroy(vgPixel); + break; + } + + default: + // We should not get here - colour mode not supported by these tests + ERR_PRINTF1(_L("CTestEglSession::CheckVgDrawingL - Colour mode not supported!")); + ASSERT(FALSE); + break; + } + } + +EXPORT_C TBool CTestEglSession::IsOpenGLESSupported() + { + if(!iIsSupportedRenderInitialized) + { + CheckAllAvailableRenders(); + } + return iIsOpenGLESSupported; + } + +EXPORT_C TBool CTestEglSession::IsOpenGLES2Supported() + { + if(!iIsSupportedRenderInitialized) + { + CheckAllAvailableRenders(); + } + return iIsOpenGLES2Supported; + } +EXPORT_C TBool CTestEglSession::IsOpenVGSupported() + { + if(!iIsSupportedRenderInitialized) + { + CheckAllAvailableRenders(); + } + return iIsOpenVGSupported; + } + +void CTestEglSession::CheckAllAvailableRenders() + { + ASSERT_EGL_TRUE(iDisplay != EGL_NO_DISPLAY); + TPtrC8 ptrEglClientApis((const TText8 *)eglQueryString(iDisplay, EGL_CLIENT_APIS)); + _LIT8(KOpenGLES, "OpenGL_ES"); + EGLint numConfigs= 0; + EGLConfig config; + if(ptrEglClientApis.Find(KOpenGLES) != KErrNotFound) + { + //check GLES2 + const EGLint KAttrib_list_gles2[] = { EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT, + EGL_NONE }; + EGLBoolean eglRes = eglChooseConfig(iDisplay, KAttrib_list_gles2, &config,1, &numConfigs); + ASSERT_EGL_TRUE(eglRes == EGL_TRUE); + if(numConfigs > 0) + { + iIsOpenGLES2Supported = ETrue; + } + //check GLES + numConfigs = 0; + const EGLint KAttrib_list_gles[] = { EGL_RENDERABLE_TYPE, EGL_OPENGL_ES_BIT, + EGL_NONE }; + eglRes = eglChooseConfig(iDisplay, KAttrib_list_gles, &config,1, &numConfigs); + ASSERT_EGL_TRUE(eglRes == EGL_TRUE); + if(numConfigs > 0) + { + iIsOpenGLESSupported = ETrue; + } + } + _LIT8(KOpenVG, "OpenVG"); + if(ptrEglClientApis.Find(KOpenVG) != KErrNotFound) + { + numConfigs= 0; + //check VG + const EGLint KAttrib_list_vg[] = { EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT, + EGL_NONE }; + EGLBoolean eglRes = eglChooseConfig(iDisplay, KAttrib_list_vg, &config,1, &numConfigs); + ASSERT_EGL_TRUE(eglRes == EGL_TRUE); + if(numConfigs > 0) + { + iIsOpenVGSupported = ETrue; + } + } + iIsSupportedRenderInitialized = ETrue; + } + +