--- /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 <coecntrl.h>
+
+
+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