diff -r 000000000000 -r 15bf7259bb7c uiacceltk/hitchcock/coretoolkit/rendervg10/src/HuiVg10PBufferSurface.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uiacceltk/hitchcock/coretoolkit/rendervg10/src/HuiVg10PBufferSurface.cpp Tue Feb 02 07:56:43 2010 +0200 @@ -0,0 +1,587 @@ +/* +* Copyright (c) 2006-2008 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: Implementation of CHuiVg10PBufferSurface. CHuiGles10PBufferSurface is +* an OpenVG PBuffer surface object that implements the MHuiRenderSurface +* interface. +* +*/ + + + +#include "HuiVg10RenderPlugin.h" +#include "HuiVg10PBufferSurface.h" +#include "uiacceltk/HuiStatic.h" +#include "uiacceltk/HuiUtil.h" +#include "uiacceltk/HuiSegmentedTexture.h" +#include + +#include + +struct THuiColorModeData + { + TInt iColorMode; + TInt iBitCount; + TInt iRed; + TInt iGreen; + TInt iBlue; + TInt iAlpha; + }; + +const THuiColorModeData KHuiColorModeData[] = + { + {0, EGL_DONT_CARE, 0, 0, 0, 8}, // Do not use ENone as there might be many of those in headers + {EColor4K, 12, 4, 4, 4, 0}, + {EColor64K, 16, 5, 6, 5, 0}, + {EColor16M, 24, 8, 8, 8, 0}, + {EColor16MU, 32, 8, 8, 8, 0}, +#ifndef __NVG + {EColor16MA, 32, 8, 8, 8, 8} +#else + {EColor16MA, 32, 8, 8, 8, 8}, + {EColor16MAP, 32, 8, 8, 8, 8} +#endif + }; + + +CHuiVg10PBufferSurface* CHuiVg10PBufferSurface::NewLC(CHuiVg10RenderPlugin& aRenderer, + const TSize& aSize, + TInt aAlphaBits, + TInt aEglBufferType, + TInt aBufferColorMode) + { + CHuiVg10PBufferSurface* self = new (ELeave) CHuiVg10PBufferSurface( + aRenderer, aSize, aAlphaBits, aEglBufferType, aBufferColorMode); + CleanupStack::PushL(self); + self->ConstructL(); + return self; + } + + +CHuiVg10PBufferSurface* CHuiVg10PBufferSurface::NewLC(CHuiVg10RenderPlugin& aRenderer, + const TSize& aSize, + TInt aAlphaBits) + { + return NewLC(aRenderer, aSize, aAlphaBits, EGL_PBUFFER_BIT, 0); + } + + +CHuiVg10PBufferSurface* CHuiVg10PBufferSurface::NewL(const TSize& aSize, TInt aAlphaBits) + { + CHuiVg10PBufferSurface* self = CHuiVg10PBufferSurface::NewLC(aSize, aAlphaBits); + CleanupStack::Pop(self); + return self; + } + + +CHuiVg10PBufferSurface* CHuiVg10PBufferSurface::NewLC(const TSize& aSize, TInt aAlphaBits) + { + CHuiVg10RenderPlugin& render = CHuiStatic::Vg10Renderer(); + return NewLC(render, aSize, aAlphaBits); + } + + +CHuiVg10PBufferSurface::CHuiVg10PBufferSurface(CHuiVg10RenderPlugin& aRenderer, + const TSize& aSize, + TInt aAlphaBits, + TInt aEglBufferType, + TInt aBufferColorMode) + : iSize(aSize), iEglBufferType(aEglBufferType), iBufferColorMode(aBufferColorMode), + iAlphaBits(aAlphaBits),iRenderer(aRenderer) + { + } + + +void CHuiVg10PBufferSurface::ConstructL() + { + HUI_DEBUG(_L("CHuiVg10PBufferSurface::ConstructL() - Constructing OpenVG 1.0 PBuffer Rendering surface.")); + + // Create egl context and rendering surface + iEglContext = iEglSurface = NULL; + iIsHardwareAccelerated = EFalse; + RestoreL(); + + HUI_DEBUG(_L("CHuiVg10PBufferSurface::ConstructL() - Construction exited OK.")); + } + + +CHuiVg10PBufferSurface::~CHuiVg10PBufferSurface() + { + Release(); + } + + +TBool CHuiVg10PBufferSurface::GetScreenOrigin(TPoint& /*aOrigin*/) const + { + // This class does only off-screen rendering, so the on-screen origin + // cannot be determined. + return EFalse; + } + + +EGLConfig CHuiVg10PBufferSurface::DetermineConfig() + { + HUI_DEBUG1(_L("CHuiVg10PBufferSurface::DetermineConfig() enter. iBufferColorMode=%d"), iBufferColorMode); + // Define properties for the wanted EGLSurface. To get the best possible + // performance, choose an EGLConfig with a buffersize matching + // the current window's display mode. + + // Determine the buffer size +#ifdef __WINSCW__ + if (iBufferColorMode == ENone) + { + + // Determine the natively supported display mode + CWsScreenDevice* screenDevice = CHuiStatic::ScreenDevice(); + if(screenDevice) + { + screenDevice->DisplayMode(); + } + } +#endif + + // Find color mode data + THuiColorModeData cmData = KHuiColorModeData[0]; + //Mem::Copy(&cmData, (&KHuiColorModeData[0]), sizeof(THuiColorModeData)); // default mode + for (TInt colorModeIndex = 0; + colorModeIndex < (sizeof(KHuiColorModeData) / sizeof(THuiColorModeData)); + colorModeIndex++) + { + if (iBufferColorMode == KHuiColorModeData[colorModeIndex].iColorMode) + { + Mem::Copy(&cmData, &(KHuiColorModeData[colorModeIndex]), sizeof(THuiColorModeData)); + } + } + + // Define properties for the wanted EGLSurface. + EGLint attribListDefault[15]; // reserve enough space for configurations + int tmp = 0; + + attribListDefault[tmp++] = EGL_BUFFER_SIZE; + attribListDefault[tmp++] = cmData.iBitCount; + + attribListDefault[tmp++] = EGL_SURFACE_TYPE; + attribListDefault[tmp++] = iEglBufferType; + + attribListDefault[tmp++] = EGL_RENDERABLE_TYPE; + attribListDefault[tmp++] = EGL_OPENVG_BIT; + + attribListDefault[tmp++] = EGL_ALPHA_SIZE; + attribListDefault[tmp++] = cmData.iAlpha; + + /* +#ifndef __WINSCW__ + if( iIsHardwareAccelerated ) + { + // Emulator renders in software, so it does not antialias. + // MBX is efficient in supersampling. + attribListDefault[tmp++] = EGL_SAMPLE_BUFFERS; + attribListDefault[tmp++] = 1; + + attribListDefault[tmp++] = EGL_SAMPLES; + attribListDefault[tmp++] = 4; + } +#endif // __WINSCW__ +*/ + + // Terminate attribute list + attribListDefault[tmp++] = EGL_NONE; + + + + + // Define properties for the wanted EGLSurface. + EGLint attribListCustom[25]; // reserve enough space for configurations + tmp = 0; + + attribListCustom[tmp++] = EGL_BUFFER_SIZE; + attribListCustom[tmp++] = cmData.iBitCount; + + attribListCustom[tmp++] = EGL_RED_SIZE; + attribListCustom[tmp++] = cmData.iRed; + + attribListCustom[tmp++] = EGL_GREEN_SIZE; + attribListCustom[tmp++] = cmData.iGreen; + + attribListCustom[tmp++] = EGL_BLUE_SIZE; + attribListCustom[tmp++] = cmData.iBlue; + + attribListCustom[tmp++] = EGL_RENDERABLE_TYPE; + attribListCustom[tmp++] = EGL_OPENVG_BIT; + + attribListCustom[tmp++] = EGL_SURFACE_TYPE; + attribListCustom[tmp++] = iEglBufferType; + + attribListCustom[tmp++] = EGL_ALPHA_SIZE; + attribListCustom[tmp++] = cmData.iAlpha; + +/* + if( iIsHardwareAccelerated ) + { + // Emulator renders in software, so it does not antialias. + // MBX is efficient in supersampling. + attribListCustom[tmp++] = EGL_SAMPLE_BUFFERS; + attribListCustom[tmp++] = 1; + + attribListCustom[tmp++] = EGL_SAMPLES; + attribListCustom[tmp++] = 4; + } +*/ + // Terminate attribute list + attribListCustom[tmp++] = EGL_NONE; + + + // Choose an EGLConfig that best matches to the properties in attribList. + TInt numOfConfigs = 0; + if (iBufferColorMode == 0) + { + // No explicit color mode. Vg chooses the best mode. + numOfConfigs = iRenderer.EglChooseConfig(attribListDefault); + } + else + { + numOfConfigs = iRenderer.EglChooseConfig(attribListCustom); + } + + if(!numOfConfigs) + { +#ifdef _DEBUG + TInt eglerr = eglGetError(); + HUI_DEBUG2(_L("CHuiVg10PBufferSurface::DetermineConfig() - eglChooseConfig failed, no required EGL configuration found. Cause: %S (error %i). Panicking."), &CHuiVg10RenderSurface::EglErrorMessage(eglerr), eglerr); +#endif + HUI_PANIC(THuiPanic::ERenderSurfaceUnknownDisplayMode) + } + + HUI_DEBUG1(_L("CHuiVg10PBufferSurface::DetermineConfig() - Got %i configs."), numOfConfigs); + + // Print the attributes of the selected config to log file. + iRenderer.EglPrintConfig(0); + + if (iBufferColorMode == 0) + { + // Set color mode based on parameters + + // Update color mode struct + TInt cfg = iRenderer.EglConfig(0); + eglGetConfigAttrib(iEglDisplay, cfg, EGL_BUFFER_SIZE, &(cmData.iBitCount)); + eglGetConfigAttrib(iEglDisplay, cfg, EGL_RED_SIZE, &(cmData.iRed)); + eglGetConfigAttrib(iEglDisplay, cfg, EGL_GREEN_SIZE, &(cmData.iGreen)); + eglGetConfigAttrib(iEglDisplay, cfg, EGL_BLUE_SIZE, &(cmData.iBlue)); + eglGetConfigAttrib(iEglDisplay, cfg, EGL_ALPHA_SIZE, &(cmData.iAlpha)); + + // Find color mode from array + for (TInt colorModeIndex = 0; + colorModeIndex < (sizeof(KHuiColorModeData) / sizeof(THuiColorModeData)); + colorModeIndex++) + { + if ( + (cmData.iBitCount == KHuiColorModeData[colorModeIndex].iBitCount) && + (cmData.iRed == KHuiColorModeData[colorModeIndex].iRed) && + (cmData.iGreen == KHuiColorModeData[colorModeIndex].iGreen) && + (cmData.iBlue == KHuiColorModeData[colorModeIndex].iBlue) && + (cmData.iAlpha == KHuiColorModeData[colorModeIndex].iAlpha) ) + { + iBufferColorMode = KHuiColorModeData[colorModeIndex].iColorMode; + } + } + } + + // Choose the best EGLConfig. EGLConfigs returned by eglChooseConfig + // are sorted so that the best matching EGLConfig is first in the list. + return iRenderer.EglConfig(0); + } + + +EGLSurface CHuiVg10PBufferSurface::CreateSurface(EGLConfig aConfig) + { + EGLSurface surface = EGL_NO_SURFACE; + if (iEglBufferType == EGL_PBUFFER_BIT) + { + // Create a Pbuffer surface. + EGLint pbufferAttribList[] = + { + EGL_WIDTH, iSize.iWidth, + EGL_HEIGHT, iSize.iHeight, + EGL_NONE + }; + + HUI_DEBUG(_L("CHuiVg10PBufferSurface::CreateSurface() - Attempting to create a PBuffer surface.")); + surface = eglCreatePbufferSurface(iEglDisplay, aConfig, pbufferAttribList); + } + + else if (iEglBufferType == EGL_PIXMAP_BIT) + { + delete(iBuffer); + iBuffer = NULL; + iBuffer = new CWsBitmap( CHuiStatic::WsSession() ); + if (iBuffer && (iBufferColorMode > 0)) + { + iBuffer->Create( iSize, (TDisplayMode)iBufferColorMode); + HUI_DEBUG(_L("CHuiVg10PBufferSurface::CreateSurface() - Attempting to create a Pixmap surface.")); + surface = eglCreatePixmapSurface(iEglDisplay, aConfig, iBuffer, NULL); + } + } + else + { + // For PC-lint + } + + return surface; + } + + +TSize CHuiVg10PBufferSurface::Size() const + { + return iSize; + } + + +void CHuiVg10PBufferSurface::SetSizeL(const TSize& aSize) + { + iSize = aSize; + + // Recreate pbuffer surfaces. + eglMakeCurrent(EGL_NO_DISPLAY, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + + // Recreate the rendering surface. + eglDestroySurface(iEglDisplay, iEglSurface); + + iEglSurface = CreateSurface(DetermineConfig()); + if(iEglSurface == EGL_NO_SURFACE) + { + TInt eglerr = eglGetError(); + switch (eglerr) + { + case EGL_BAD_ALLOC: + HUI_DEBUG2(_L("CHuiVg10PBufferSurface::SetSizeL() - ERROR! Failed to (re)create surface having size (%ix%i). Out of memory."), + aSize.iWidth, aSize.iHeight); + User::Leave(KErrNoMemory); + default: + HUI_DEBUG4(_L("CHuiVg10PBufferSurface::SetSizeL() - ERROR! Failed to (re)create surface having size (%ix%i).Cause: %S (EGL error code: %i). Leaving."), + aSize.iWidth, aSize.iHeight, + &CHuiVg10RenderSurface::EglErrorMessage(eglerr), eglerr); + case EGL_SUCCESS: // indicates that no error was recorded, but still the CreateSurface call failed (=> unable to continue!) + User::Leave(KErrNotSupported); + } + } + + MakeCurrent(); + } + + +void CHuiVg10PBufferSurface::MakeCurrent() + { + if (iEglSurface == NULL || iEglContext == NULL) + { + // we can't makeCurrent on a released surface + return; + } + + // No need to change the current render surface if this render surface is current already. + if(CHuiStatic::CurrentRenderSurface() != ((MHuiRenderSurface*)this)) + { + eglMakeCurrent(iEglDisplay, iEglSurface, iEglSurface, iEglContext); + + TInt eglerr = eglGetError(); + if(eglerr != EGL_SUCCESS) + { + HUI_DEBUG2(_L("CHuiVg10PBufferSurface::MakeCurrent() - Could not switch this rendering surface on. Cause: %S (EGL error code: %i). Panicking."), + &CHuiVg10RenderSurface::EglErrorMessage(eglerr), eglerr); + HUI_PANIC(THuiPanic::ERenderSurfaceActivationFailed) + } + CHuiStatic::SetCurrentRenderSurface(this); + } + } + + +void CHuiVg10PBufferSurface::SwapBuffers() + { + // Pbuffers consist of a single buffer only (no front/back buffers to swap). + } + + +void CHuiVg10PBufferSurface::BindTexture(TInt aTextureUnit, + const MHuiSegmentedTexture& aTexture, + TInt aSegment) + { + (void)aTextureUnit; + (void)aTexture; + (void)aSegment; + } + +void CHuiVg10PBufferSurface::HandleVisibilityEvent(TBool /* aIsVisible */ ) + { + // dummy method, does not handle the events in any way.. + } + +void CHuiVg10PBufferSurface::Release() + { + + HUI_DEBUG( _L("CHuiVg10PBufferSurface::Release() - Releasing EGL surface and context..") ); + if (iEglSurface != NULL) + { + eglDestroySurface(iEglDisplay, iEglSurface); + TInt eglerr = eglGetError(); + if(eglerr != EGL_SUCCESS) + { + HUI_DEBUG2(_L("CHuiVg10PBufferSurface::Release() - WARNING! Could not destroy EGL surface. Cause: %S (EGL error code: %i)."), + &CHuiVg10RenderSurface::EglErrorMessage(eglerr), eglerr); + } + iEglSurface = NULL; + } + + // Delete pixmap if exists + delete(iBuffer); + iBuffer = NULL; + + if (iEglContext != NULL) + { + // Unshare this context if it was + // set as shared.. + if(iRenderer.EglSharedContext() == iEglContext) + { + HUI_DEBUG(_L("CHuiVg10PBufferSurface::Release() - Unsharing this render context.")); + iRenderer.EglSetSharedContext(EGL_NO_CONTEXT); + } + + eglDestroyContext(iEglDisplay, iEglContext); + TInt eglerr = eglGetError(); + if(eglerr != EGL_SUCCESS) + { + HUI_DEBUG2(_L("CHuiVg10PBufferSurface::Release() - WARNING! Could not destroy EGL context. Cause: %S (EGL error code: %i)."), + &CHuiVg10RenderSurface::EglErrorMessage(eglerr), eglerr); + } + iEglContext = NULL; + } + + } + +void CHuiVg10PBufferSurface::RestoreL() + { + + HUI_DEBUG( _L("CHuiVg10PBufferSurface::RestoreL() - Restoring render surface.") ); + + if((iEglSurface != NULL) && (iEglContext != NULL)) + { + HUI_DEBUG( _L("CHuiVg10RenderSurface::RestoreL() - Render surface and context already in place, no need to restore.") ); + } + iEglDisplay = iRenderer.EglDisplay(); + + // Create an EGL rendering surface. + EGLConfig config = DetermineConfig(); + iEglSurface = CreateSurface(config); + if(iEglSurface == EGL_NO_SURFACE) + { + TInt eglerr = eglGetError(); + switch (eglerr) + { + case EGL_BAD_ALLOC: + HUI_DEBUG2(_L("CHuiVg10PBufferSurface::RestoreL() - ERROR! Failed to create pbuffer surface having size (%ix%i). Out of memory."), + iSize.iWidth, iSize.iHeight); + User::Leave(KErrNoMemory); + default: + HUI_DEBUG4(_L("CHuiVg10PBufferSurface::RestoreL() - ERROR! Failed to create pbuffer surface having size (%ix%i). Cause: %S (EGL error code: %i)."), + iSize.iWidth, iSize.iHeight, + &CHuiVg10RenderSurface::EglErrorMessage(eglerr), eglerr); + case EGL_SUCCESS: // indicates that no error was recorded, but still the CreateSurface call failed (=> unable to continue!) + User::Leave(KErrNotSupported); + } + } + + // Create rendering context for PBuffer rendering. + // There is only a single texture manager in the environment, so textures + // need to shared between all contexts. + iEglContext = eglCreateContext(iEglDisplay, config, + iRenderer.EglSharedContext(), NULL); + if(iEglContext == EGL_NO_CONTEXT) + { + TInt eglerr = eglGetError(); + switch (eglerr) + { + case EGL_BAD_ALLOC: + HUI_DEBUG(_L("CHuiVg10PBufferSurface::RestoreL() - ERROR! Failed to create rendering context. Out of memory.")); + User::Leave(KErrNoMemory); + default: + HUI_DEBUG2(_L("CHuiVg10PBufferSurface::RestoreL() - ERROR! Failed to create rendering context. Cause: %S (EGL error code: %i)."), + &CHuiVg10RenderSurface::EglErrorMessage(eglerr), eglerr); + case EGL_SUCCESS: // indicates that no error was recorded, but still the CreateSurface call failed (=> unable to continue!) + User::Leave(KErrNotSupported); + } + } + + // Share this context if there was not already a shared context for texture + // management + if(iRenderer.EglSharedContext() == EGL_NO_CONTEXT) + { + HUI_DEBUG(_L("CHuiVg10PBufferSurface::ConstructL() - Making this surface shared.")); + // Now that there is a context, make sure the renderer knows of it. + iRenderer.EglSetSharedContext(iEglContext); + } + eglMakeCurrent(iEglDisplay, iEglSurface, iEglSurface, iEglContext); + } + +EGLSurface CHuiVg10PBufferSurface::EglSurface() + { + return iEglSurface; + } + +void CHuiVg10PBufferSurface::BindToM3G() + { + } + +void CHuiVg10PBufferSurface::ReleaseFromM3G() + { + } + +CFbsBitmap* CHuiVg10PBufferSurface::Buffer() + { + return iBuffer; + } + +TInt CHuiVg10PBufferSurface::BufferColorMode() const + { + return iBufferColorMode; + } + +TUint CHuiVg10PBufferSurface::Flags() const + { + // ToDo: Is some flag needed? + return MHuiRenderSurface::EFlagNone; + } + +void CHuiVg10PBufferSurface::HandleDisplayUsageChangeL() + { + // Nothing to do + } + +void CHuiVg10PBufferSurface::SetDirtyRect(const TRect& /*aRect*/) + { + // Nothing to do + } + +MHuiTargetBitmap* CHuiVg10PBufferSurface::BackBuffer() + { + // Nothing to do + return NULL; + } + +CFbsBitGc* CHuiVg10PBufferSurface::Gc() + { + // Nothing to do + return NULL; + } + +void CHuiVg10PBufferSurface::RenderSurfaceExtension(const TUid& /*aExtensionUid*/, TAny** aExtensionParams) + { + *aExtensionParams = NULL; + }