uiacceltk/hitchcock/coretoolkit/rendervg10/src/HuiVg10PBufferSurface.cpp
changeset 0 15bf7259bb7c
child 3 d8a3531bc6b8
--- /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 <EGL/egl.h>
+
+#include <coemain.h>
+
+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;
+    }