diff -r aecbbf00d063 -r d48ab3b357f1 uifw/ganes/src/HgVgEGL.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/uifw/ganes/src/HgVgEGL.cpp Wed Sep 01 12:16:19 2010 +0100 @@ -0,0 +1,360 @@ +/* +* Copyright (c) 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: +* +*/ + + +// INCLUDE FILES +#include "HgVgEGL.h" +#include "HgVgConstants.h" +#include + + +using namespace HgVgConstants; + +// ============================ MEMBER FUNCTIONS =============================== +// ----------------------------------------------------------------------------- +// CHgVgEGL::NewL() +// Two-phased constructor. +// ----------------------------------------------------------------------------- +// +CHgVgEGL* CHgVgEGL::NewL(RWindow& aWindow) + { + CHgVgEGL* self = new ( ELeave ) CHgVgEGL(); + CleanupStack::PushL (self ); + self->ConstructL(aWindow); + CleanupStack::Pop (self ); + return self; + } + +// ----------------------------------------------------------------------------- +// CHgVgEGL::ConstructL() +// Symbian 2nd phase constructor can leave. +// ----------------------------------------------------------------------------- +// +void CHgVgEGL::ConstructL (RWindow& aWindow) + { + InitEGL(aWindow); + } + +// ----------------------------------------------------------------------------- +// CHgVgEGL::CHgVgEGL() +// C++ default constructor can NOT contain any code, that might leave. +// ----------------------------------------------------------------------------- +// +CHgVgEGL::CHgVgEGL() + { + } + +// ----------------------------------------------------------------------------- +// CHgVgEGL::~CHgVgEGL() +// Destructor. +// ----------------------------------------------------------------------------- +// +CHgVgEGL::~CHgVgEGL ( ) + { + DestroyEGL(); + } + +// --------------------------------------------------------------------------- +// CHgVgEGL::InitWindowSurfaceL() +// --------------------------------------------------------------------------- +// +void CHgVgEGL::InitWindowSurfaceL(RWindow& aWindow) + { + //RDebug::Print(_L("CHgVgEGL::InitWindowSurface")); + + InitEGL(aWindow); + } + +// --------------------------------------------------------------------------- +// CHgVgEGL::FreeWindowSurface() +// --------------------------------------------------------------------------- +// +void CHgVgEGL::FreeWindowSurface() + { + //RDebug::Print(_L("CHgVgEGL::FreeWindowSurface")); + + // make sure there is nothing pending. + vgFinish(); + + // unbind current surface. + eglMakeCurrent(iDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, iContextVg); + + // destroy surface + eglDestroySurface(iDisplay, iSurface); + iSurface = VG_INVALID_HANDLE; + } + +// --------------------------------------------------------------------------- +// CHgVgEGL::ReadyToRender() +// --------------------------------------------------------------------------- +// +TBool CHgVgEGL::ReadyToRender() const + { + return iSurface && iDisplay && iContextVg; + } + +// --------------------------------------------------------------------------- +// CHgVgEGL::SwapBuffers() +// --------------------------------------------------------------------------- +// +void CHgVgEGL::SwapBuffers() + { + eglSwapBuffers(iDisplay, iSurface); + } + +// --------------------------------------------------------------------------- +// CHgVgEGL::Display() +// --------------------------------------------------------------------------- +// +EGLDisplay CHgVgEGL::Display() const + { + return iDisplay; + } + +// --------------------------------------------------------------------------- +// CHgVgEGL::Surface +// --------------------------------------------------------------------------- +// +EGLSurface CHgVgEGL::Surface() const + { + return iSurface; + } + +// --------------------------------------------------------------------------- +// CHgVgEGL::Context() +// --------------------------------------------------------------------------- +// +EGLContext CHgVgEGL::Context() const + { + return iContextVg; + } + +// --------------------------------------------------------------------------- +// CHgVgEGL::CurrentConfig() +// --------------------------------------------------------------------------- +// +EGLConfig CHgVgEGL::CurrentConfig() const + { + return iChosenConfig; + } + +// --------------------------------------------------------------------------- +// CHgVgEGL::InitEGL() +// --------------------------------------------------------------------------- +// +void CHgVgEGL::InitEGL(RWindow& aWindow) + { + + // if we are just resizing or recreating + if (iContextVg != VG_INVALID_HANDLE) + { + + + // save old surface + EGLSurface oldSurface = VG_INVALID_HANDLE; + if (iSurface != VG_INVALID_HANDLE) + { + // make sure there is nothing pending. + vgFinish(); + + oldSurface = iSurface; + + // unbind current surface. + eglMakeCurrent(iDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, iContextVg); + } + + // create new surface + InitEGLWindowSurfaceL(aWindow); + + // bind new surface + eglMakeCurrent(iDisplay, iSurface, iSurface, iContextVg); + + if (oldSurface != VG_INVALID_HANDLE) + { + // free old surface + eglDestroySurface(iDisplay,oldSurface); + } + + } + else + { + + // get display + iDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY); + + // intialize egl + eglInitialize(iDisplay, NULL, NULL); + + // find suitable display config + EGLint numConfigs; + iChosenConfig = 0; + + const EGLint KColorAttribList[] = + { + EGL_RED_SIZE, KSurfaceRedBits, + EGL_GREEN_SIZE, KSurfaceGreenBits, + EGL_BLUE_SIZE, KSurfaceBlueBits, + EGL_ALPHA_SIZE, KSurfaceAlphaBits, + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT, + EGL_NONE + }; + + eglChooseConfig(iDisplay, KColorAttribList, &iChosenConfig, 1, &numConfigs); + + // we need openvg + eglBindAPI(EGL_OPENVG_API); + + InitEGLWindowSurfaceL(aWindow); + + // Create context for our thread. + iContextVg = eglCreateContext(iDisplay, iChosenConfig, EGL_NO_CONTEXT, NULL); + + // bind surface to context + eglMakeCurrent(iDisplay, iSurface, iSurface, iContextVg); + + } + + } + +// --------------------------------------------------------------------------- +// CHgVgEGL::InitEGLWindowSurfaceL() +// --------------------------------------------------------------------------- +// +void CHgVgEGL::InitEGLWindowSurfaceL(RWindow& aWindow) + { + + + // Create surface with premodulated alpha. + const EGLint KAttriblist[] = + { + EGL_VG_ALPHA_FORMAT, EGL_VG_ALPHA_FORMAT_PRE, + EGL_NONE + }; + iSurface = eglCreateWindowSurface(iDisplay, iChosenConfig, &aWindow, KAttriblist); + EGLint error = eglGetError(); + if (error == EGL_BAD_ALLOC) + { + //RDebug::Print(_L("CHgVgEGL:: Can't create surface! (out of memory)")); + User::Leave(KErrNoMemory); + } + else if (error == EGL_BAD_SURFACE || iSurface == EGL_NO_SURFACE) + { + //RDebug::Print(_L("CHgVgEGL:: Can't create surface! (general)")); + User::Leave(KErrGeneral); + } + + eglSurfaceAttrib(iDisplay, iSurface, EGL_SWAP_BEHAVIOR, EGL_BUFFER_DESTROYED); + + } + +// --------------------------------------------------------------------------- +// CHgVgEGL::DestroyEGL() +// --------------------------------------------------------------------------- +// +void CHgVgEGL::DestroyEGL() + { + // deinitialize egl + eglMakeCurrent(iDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + eglDestroySurface(iDisplay,iSurface); + eglDestroyContext( iDisplay, iContextVg ); + eglTerminate(iDisplay); + eglReleaseThread(); + } + + +// --------------------------------------------------------------------------- +// CHgVgEGL::GetSurfaceToBitmap() +// --------------------------------------------------------------------------- +// +CFbsBitmap* CHgVgEGL::GetSurfaceToBitmap(const TRect& aRect, TBool aLandscape) const + { + // make sure every thing is in back buffer + vgFinish(); + + + CFbsBitmap* bitmap = new CFbsBitmap(); + + if (bitmap) + { + // create temporary buffer for data + RBuf8 buf; + TInt bufCreateErr = buf.Create(aRect.Width() * aRect.Height() * 4); + if(bufCreateErr != KErrNone) { + buf.Close(); //just in case + delete bitmap; + bitmap = NULL; + return NULL; + } + buf.Fill(0xFF); + + // read data back from vg (this is sloooww) + VGint dataStride = 0; + if (aLandscape) + { + dataStride = 4 * aRect.Height(); + vgReadPixels((void*)buf.Ptr(), + dataStride, VG_sARGB_8888, 0, 0, aRect.Height(), aRect.Width()); + } + else + { + dataStride = 4 * aRect.Width(); + vgReadPixels((void*)buf.Ptr(), + dataStride, VG_sARGB_8888, 0, 0, aRect.Width(), aRect.Height()); + } + + // because of bug in vg driver we need to swap memory using for loop, because + // negative datastrides cause crash + TInt bitmapCreateErr = bitmap->Create(TSize(aRect.Width(), aRect.Height()), EColor16MA); + if(bitmapCreateErr != KErrNone) { + buf.Close(); + delete bitmap; + bitmap = NULL; + return NULL; + } + + bitmap->BeginDataAccess(); + if (!aLandscape) + { + TUint8* ptrTrg = (TUint8*)bitmap->DataAddress(); + TUint8* ptrSrc = (TUint8*)buf.Ptr(); + for (TInt i = 0; i < aRect.Height(); i++) + { + Mem::Copy(ptrTrg + dataStride * i, + ptrSrc + dataStride * (aRect.Height() - i - 1), dataStride); + } + } + else + { + TUint32* ptrTrg = (TUint32*)bitmap->DataAddress(); + TUint32* ptrSrc = (TUint32*)buf.Ptr(); + for (TInt i = 0; i < aRect.Height(); i++) + { + for (TInt j = 0; j < aRect.Width(); j++) + { + ptrTrg[(aRect.Height() - i - 1)*aRect.Width()+(aRect.Width()-j-1)] = ptrSrc[j*aRect.Height()+i]; + } + } + } + bitmap->EndDataAccess(); + buf.Close(); + } + + return bitmap; + } + +// End of File