diff -r 000000000000 -r 15bf7259bb7c uiacceltk/hitchcock/coretoolkit/rendervg10/src/HuiVg10RenderSurface.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uiacceltk/hitchcock/coretoolkit/rendervg10/src/HuiVg10RenderSurface.cpp Tue Feb 02 07:56:43 2010 +0200 @@ -0,0 +1,481 @@ +/* +* 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: OpenVG 1.0 render surface implementation. +* +*/ + + + +#include "HuiVg10RenderSurface.h" +#include "HuiVg10RenderPlugin.h" +#include "uiacceltk/HuiSegmentedTexture.h" +#include "uiacceltk/HuiDisplay.h" +#include "uiacceltk/HuiStatic.h" +#include "uiacceltk/HuiUtil.h" +#include +#include +#include +#include "uiacceltk/HuiProbe.h" +#include "uiacceltk/HuiEnv.h" + +#include + + +CHuiVg10RenderSurface* CHuiVg10RenderSurface::NewL(CHuiDisplay& aDisplay) + { + CHuiVg10RenderSurface* self = CHuiVg10RenderSurface::NewLC(aDisplay); + CleanupStack::Pop(self); + return self; + } + + +CHuiVg10RenderSurface* CHuiVg10RenderSurface::NewLC(CHuiDisplay& aDisplay) + { + CHuiVg10RenderSurface* self = new (ELeave) CHuiVg10RenderSurface(aDisplay); + CleanupStack::PushL(self); + self->ConstructL(); + return self; + } + + +CHuiVg10RenderSurface::CHuiVg10RenderSurface(CHuiDisplay& aDisplay) + : iDisplay(&aDisplay) + { + HUI_PROBE_ASSOCIATE_WITH_CURRENT_SESSION + HUI_PROBE_REPORT_CONSTRUCTED + } + + +void CHuiVg10RenderSurface::ConstructL() + { + HUI_DEBUG(_L("CHuiVg10RenderSurface::ConstructL() - Constructing OpenVG 1.0 Rendering surface.")); + + // Size of the surface. + iSize = iDisplay->Size(); + + // Create egl context and rendering surface + iEglContext = iEglSurface = NULL; + iBoundTexture = NULL; + RestoreL(); + + HUI_DEBUG(_L("CHuiVg10RenderSurface::ConstructL() - Construction succeeded.")); +} + + +CHuiVg10RenderSurface::~CHuiVg10RenderSurface() + { + Release(); + iDisplay = NULL; + HUI_PROBE_REPORT_DESTRUCTED + } + + +CHuiDisplay& CHuiVg10RenderSurface::Display() const + { + return *iDisplay; + } + + +TUint CHuiVg10RenderSurface::Flags() const + { + TBool useDirtyAreas = CHuiStatic::Renderer().Allows(EHuiRenderPluginAllowSwapBufferPreserve); + if (useDirtyAreas) + { + return MHuiRenderSurface::EFlagUseDirtyRects; + } + else + { + return MHuiRenderSurface::EFlagNone; + } + } + + +TBool CHuiVg10RenderSurface::GetScreenOrigin(TPoint& aOrigin) const + { + if(iDisplay && iDisplay->NativeControl()) + { + aOrigin = iDisplay->NativeControl()->PositionRelativeToScreen(); + return ETrue; + } + return EFalse; + } + +static void CreateConstEglAttribs(int& i, EGLint* attribList) + { + const TInt BITS_PER_CHANNEL = 8; + + attribList[i++] = EGL_RED_SIZE; + attribList[i++] = BITS_PER_CHANNEL; + + attribList[i++] = EGL_GREEN_SIZE; + attribList[i++] = BITS_PER_CHANNEL; + + attribList[i++] = EGL_BLUE_SIZE; + attribList[i++] = BITS_PER_CHANNEL; + + attribList[i++] = EGL_ALPHA_SIZE; + attribList[i++] = BITS_PER_CHANNEL; + + attribList[i++] = EGL_SURFACE_TYPE; + + TBool useDirtyAreas = CHuiStatic::Renderer().Allows(EHuiRenderPluginAllowSwapBufferPreserve); + if (useDirtyAreas) + { + attribList[i++] = EGL_WINDOW_BIT | EGL_PBUFFER_BIT | EGL_SWAP_BEHAVIOR_PRESERVED_BIT; + } + else + { + attribList[i++] = EGL_WINDOW_BIT | EGL_PBUFFER_BIT; + } + + attribList[i++] = EGL_RENDERABLE_TYPE; + attribList[i++] = EGL_OPENVG_BIT; + } + +EGLConfig CHuiVg10RenderSurface::DetermineConfig() + { + EGLint attribList[20]; // reserve enough space for configurations + int i = 0; + + // Get default properties for the wanted EGLSurface. + CreateConstEglAttribs(i, attribList); + + // Terminate attribute list + attribList[i++] = EGL_NONE; + + CHuiVg10RenderPlugin& render = CHuiStatic::Vg10Renderer(); + + // Choose an EGLConfig that best matches to the properties in attribList. + TInt numOfConfigs = render.EglChooseConfig(attribList); + + if(!numOfConfigs) + { + TInt eglerr = eglGetError(); + HUI_DEBUG2(_L("CHuiVg10RenderSurface::DetermineConfig() - eglChooseConfig failed, no required EGL configuration found. Cause: %S (error %i). Panicking."), &CHuiVg10RenderSurface::EglErrorMessage(eglerr), eglerr); + HUI_PANIC(THuiPanic::ERenderSurfaceUnknownDisplayMode); + } + + HUI_DEBUG1(_L("CHuiVg10RenderSurface::DetermineConfig() - Got %i configs."), numOfConfigs); + + // Print the attributes of the selected config to log file. + render.EglPrintConfig(0); + + // Choose the best EGLConfig. EGLConfigs returned by eglChooseConfig + // are sorted so that the best matching EGLConfig is first in the list. + return render.EglConfig(0); + } + + +EGLSurface CHuiVg10RenderSurface::CreateSurface(EGLConfig aConfig) + { + EGLint* attriblistPtr = NULL; +#ifndef __WINS__ // \todo instead of "#ifndef" should make a check if alpha mode is supported + // Create a rendering surface. + EGLint attriblist[] = + { + EGL_VG_ALPHA_FORMAT, EGL_VG_ALPHA_FORMAT_PRE, + EGL_NONE + }; + attriblistPtr = &attriblist[0]; +#endif + + if(iDisplay->NativeWindow()) + { + HUI_DEBUG(_L("CHuiVg10RenderSurface::CreateSurface() - Attempting to create a real window surface.")); + EGLSurface surf = eglCreateWindowSurface(iEglDisplay, aConfig, + iDisplay->NativeWindow(), attriblistPtr); + + TBool useDirtyAreas = CHuiStatic::Renderer().Allows(EHuiRenderPluginAllowSwapBufferPreserve); + if (useDirtyAreas) + { + eglSurfaceAttrib(iEglDisplay, surf, EGL_SWAP_BEHAVIOR, EGL_BUFFER_PRESERVED ); + } + return surf; + } + else + { + // Pbuffer attributes. + EGLint pbufferAttribList[] = + { + EGL_WIDTH, iSize.iWidth, + EGL_HEIGHT, iSize.iHeight, + EGL_NONE + }; + + HUI_DEBUG(_L("CHuiVg10RenderSurface::CreateSurface() - Attempting to create a pbuffer surface.")); + return eglCreatePbufferSurface(iEglDisplay, aConfig, pbufferAttribList); + } + } + + +TSize CHuiVg10RenderSurface::Size() const + { + return iSize; + } + + +void CHuiVg10RenderSurface::SetSizeL(const TSize& aSize) + { + iSize = aSize; + + if(!iDisplay->NativeWindow()) + { + // 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("CHuiVg10RenderSurface::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("CHuiVg10RenderSurface::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); + } + } + } + } + + +void CHuiVg10RenderSurface::MakeCurrent() + { + // No need to change the current render surface if this render surface is current already. + if(CHuiStatic::CurrentRenderSurface() != ((MHuiRenderSurface*)this)) + { + CHuiEnv* env = CHuiEnv::Static(); + if (env && env->iSwapObserver) + { + env->iSwapObserver->ReleaseWindowServer(); + } + + eglMakeCurrent(iEglDisplay, iEglSurface, iEglSurface, iEglContext); + + if (env && env->iSwapObserver) + { + env->iSwapObserver->ReleaseWindowServer(EFalse); + } + + TInt eglerr = eglGetError(); + if(eglerr != EGL_SUCCESS) + { + HUI_DEBUG3(_L("CHuiVg10RenderSurface::MakeCurrent() - Error in switching on the render surface, EGLDisplay: %i, EGLSurface: %i, EGLContext: %i."), + iEglDisplay, iEglSurface, iEglContext); + HUI_DEBUG2(_L("CHuiVg10RenderSurface::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 CHuiVg10RenderSurface::SwapBuffers() + { + eglSwapBuffers(iEglDisplay, iEglSurface); + } + + +void CHuiVg10RenderSurface::BindTexture(TInt /*aTextureUnit*/, + const MHuiSegmentedTexture& aTexture, + TInt /*aSegment*/) + { + iBoundTexture = &aTexture; + } + + +const MHuiSegmentedTexture* CHuiVg10RenderSurface::BoundTexture() const + { + return iBoundTexture; + } + +void CHuiVg10RenderSurface::HandleVisibilityEvent(TBool /* aIsVisible */ ) + { + // Dummy method, does not handle the events in any way... + } + +void CHuiVg10RenderSurface::Release() + { + HUI_DEBUG( _L("CHuiVg10RenderSurface::Release() - Releasing EGL surface and context..") ); + if (iEglSurface != NULL) + { + eglDestroySurface(iEglDisplay, iEglSurface); + TInt eglerr = eglGetError(); + if(eglerr != EGL_SUCCESS) + { + HUI_DEBUG2(_L("CHuiVg10RenderSurface::Release() - WARNING! Could not destroy EGL surface. Cause: %S (EGL error code: %i)."), + &CHuiVg10RenderSurface::EglErrorMessage(eglerr), eglerr); + } + iEglSurface = NULL; + } + if (iEglContext != NULL) + { + // Unshare this context if it was + // set as shared.. + CHuiVg10RenderPlugin& renderer = CHuiStatic::Vg10Renderer(); + if(renderer.EglSharedContext() == iEglContext) + { + HUI_DEBUG(_L("CHuiVg10RenderSurface::Release() - Unsharing this render context.")); + renderer.EglSetSharedContext(EGL_NO_CONTEXT); + } + + eglDestroyContext(iEglDisplay, iEglContext); + TInt eglerr = eglGetError(); + if(eglerr != EGL_SUCCESS) + { + HUI_DEBUG2(_L("CHuiVg10RenderSurface::Release() - WARNING! Could not destroy EGL context. Cause: %S (EGL error code: %i)."), + &CHuiVg10RenderSurface::EglErrorMessage(eglerr), eglerr); + } + iEglContext = NULL; + } + } + +void CHuiVg10RenderSurface::RestoreL() + { + HUI_DEBUG( _L("CHuiVg10RenderSurface::RestoreL() - Recreating render surface.") ); + + if((iEglSurface != NULL) && (iEglContext != NULL)) + { + HUI_DEBUG( _L("CHuiVg10RenderSurface::RestoreL() - Render surface and context already in place, no need to restore.") ); + } + + CHuiVg10RenderPlugin& render = CHuiStatic::Vg10Renderer(); + iEglDisplay = render.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("CHuiVg10RenderSurface::RestoreL() - ERROR! Failed to create rendering surface having size (%ix%i). Out of memory."), + iSize.iWidth, iSize.iHeight); + User::Leave(KErrNoMemory); + default: + HUI_DEBUG4(_L("CHuiVg10RenderSurface::RestoreL() - ERROR! Failed to create rendering surface having size (%ix%i). Cause: %S (EGL error code: %i)."), + iSize.iWidth, iSize.iHeight, + &CHuiVg10RenderSurface::EglErrorMessage(eglerr), eglerr); + User::Leave(KErrNotSupported); + } + } + + // There is only a single texture manager in the environment, so textures + // need to shared between all contexts. + iEglContext = eglCreateContext(iEglDisplay, config, + render.EglSharedContext(), NULL); + if(iEglContext == EGL_NO_CONTEXT) + { + TInt eglerr = eglGetError(); + switch (eglerr) + { + case EGL_BAD_ALLOC: + HUI_DEBUG(_L("CHuiVg10RenderSurface::RestoreL() - ERROR! Failed to create rendering context. Out of memory.")); + User::Leave(KErrNoMemory); + default: + HUI_DEBUG2(_L("CHuiVg10RenderSurface::RestoreL() - ERROR! Failed to create rendering context. Cause: %S (EGL error code: %i)."), + &CHuiVg10RenderSurface::EglErrorMessage(eglerr), eglerr); + User::Leave(KErrNotSupported); + } + } + + // Share the created context for texture management. + if(render.EglSharedContext() == EGL_NO_CONTEXT) + { + // Now that there is a context, make sure the renderer knows of it. + render.EglSetSharedContext(iEglContext); + } + } + +const TDesC& CHuiVg10RenderSurface::EglErrorMessage(TInt aErrorCode) + { + // EGL Error messages. + _LIT(KEglErrorSUCCESS, "The last function succeeded without error."); + _LIT(KEglErrorNOT_INITIALIZED, "EGL is not initialized, or could not be initialized, for the specified EGL display connection."); + _LIT(KEglErrorBAD_ACCESS, "EGL cannot access a requested resource (for example a context is bound in another thread)."); + _LIT(KEglErrorBAD_ALLOC, "EGL failed to allocate resources for the requested operation."); + _LIT(KEglErrorBAD_ATTRIBUTE, "An unrecognized attribute or attribute value was passed in the attribute list."); + _LIT(KEglErrorBAD_CONTEXT, "An EGLContext argument does not name a valid EGL rendering context."); + _LIT(KEglErrorBAD_CONFIG, "An EGLConfig argument does not name a valid EGL frame buffer configuration."); + _LIT(KEglErrorBAD_CURRENT_SURFACE, "The current surface of the calling thread is a window, pixel buffer or pixmap that is no longer valid."); + _LIT(KEglErrorBAD_DISPLAY, "An EGLDisplay argument does not name a valid EGL display connection."); + _LIT(KEglErrorBAD_SURFACE, "An EGLSurface argument does not name a valid surface (window, pixel buffer or pixmap) configured for GL rendering."); + _LIT(KEglErrorBAD_MATCH, "Arguments are inconsistent (for example, a valid context requires buffers not supplied by a valid surface)."); + _LIT(KEglErrorBAD_PARAMETER, "One or more argument values are invalid."); + _LIT(KEglErrorBAD_NATIVE_PIXMAP, "A NativePixmapType argument does not refer to a valid native pixmap."); + _LIT(KEglErrorBAD_NATIVE_WINDOW, "A NativeWindowType argument does not refer to a valid native window."); + _LIT(KEglErrorUNKNOWN, "Unknown EGL Error."); + + // Define literals for the errors + switch(aErrorCode) + { + case EGL_SUCCESS: return KEglErrorSUCCESS; + case EGL_NOT_INITIALIZED: return KEglErrorNOT_INITIALIZED; + case EGL_BAD_ACCESS: return KEglErrorBAD_ACCESS; + case EGL_BAD_ALLOC: return KEglErrorBAD_ALLOC; + case EGL_BAD_ATTRIBUTE: return KEglErrorBAD_ATTRIBUTE; + case EGL_BAD_CONTEXT: return KEglErrorBAD_CONTEXT; + case EGL_BAD_CONFIG: return KEglErrorBAD_CONFIG; + case EGL_BAD_CURRENT_SURFACE: return KEglErrorBAD_CURRENT_SURFACE; + case EGL_BAD_DISPLAY: return KEglErrorBAD_DISPLAY; + case EGL_BAD_SURFACE: return KEglErrorBAD_SURFACE; + case EGL_BAD_MATCH: return KEglErrorBAD_MATCH; + case EGL_BAD_PARAMETER: return KEglErrorBAD_PARAMETER; + case EGL_BAD_NATIVE_PIXMAP: return KEglErrorBAD_NATIVE_PIXMAP; + case EGL_BAD_NATIVE_WINDOW: return KEglErrorBAD_NATIVE_WINDOW; + default: return KEglErrorUNKNOWN; + } + } + +void CHuiVg10RenderSurface::HandleDisplayUsageChangeL() + { + // Nothing to do + } + +void CHuiVg10RenderSurface::SetDirtyRect(const TRect& /*aRect*/) + { + // Nothing to do + } + +MHuiTargetBitmap* CHuiVg10RenderSurface::BackBuffer() + { + // Nothing to do + return NULL; + } + +CFbsBitGc* CHuiVg10RenderSurface::Gc() + { + // Nothing to do + return NULL; + } + +void CHuiVg10RenderSurface::RenderSurfaceExtension(const TUid& /*aExtensionUid*/, TAny** aExtensionParams) + { + *aExtensionParams = NULL; + } + +HUI_SESSION_OBJECT_IMPL(CHuiVg10RenderSurface, ETypeRenderSurface)