--- /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;
+ }