--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/uiacceltk/hitchcock/coretoolkit/rendervg10/src/huivg10canvasrenderbuffer.cpp Tue Feb 02 07:56:43 2010 +0200
@@ -0,0 +1,452 @@
+/*
+* 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: Class canvas renderering target
+*
+*/
+
+
+
+#include "huivg10canvasrenderbuffer.h"
+#include "HuiVg10RenderPlugin.h"
+#include "uiacceltk/HuiUtil.h"
+#include "uiacceltk/HuiEnv.h"
+#include "HuiVg10RenderPlugin.h"
+#include "uiacceltk/HuiDisplay.h"
+
+//#define HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL
+
+
+CHuiVg10CanvasRenderBuffer::CHuiVg10CanvasRenderBuffer()
+ {
+ }
+
+CHuiVg10CanvasRenderBuffer::~CHuiVg10CanvasRenderBuffer()
+ {
+ UnInitialize();
+ }
+
+void CHuiVg10CanvasRenderBuffer::UnInitialize()
+ {
+ CHuiVg10RenderPlugin& renderer = CHuiStatic::Vg10Renderer();
+
+ UnBind();
+
+ if (iGc)
+ {
+ delete iGc;
+ iGc = 0;
+ }
+
+ if (iRotatedImage)
+ {
+ vgDestroyImage(iRotatedImage);
+ iRotatedImage = VG_INVALID_HANDLE;
+ }
+
+ if (iImage)
+ {
+ vgDestroyImage(iImage);
+ iImage = VG_INVALID_HANDLE;
+ }
+
+ if (iSurface)
+ {
+ eglDestroySurface(renderer.EglDisplay(), iSurface);
+ iSurface = 0;
+ }
+
+ if (iContext)
+ {
+ eglDestroyContext(renderer.EglDisplay(), iContext);
+ iContext = 0;
+ }
+
+ iInitialized = EFalse;
+ }
+
+void CHuiVg10CanvasRenderBuffer::InitializeL(const TSize& aSize)
+ {
+ if (iSize == aSize && iImage && iContext && iSurface)
+ {
+ // Already initalized
+ return;
+ }
+
+ CHuiVg10RenderPlugin& renderer = CHuiStatic::Vg10Renderer();
+
+ // Just in case...
+ UnInitialize();
+
+ PushEGLContext();
+
+#ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL
+ TTime startTime;
+ startTime.UniversalTime();
+#endif
+
+ iSize = aSize;
+
+#ifndef __WINS__ // Should possibly query the supported mode instead?
+ VGImageFormat imageInternalFormat = VG_sARGB_8888_PRE;
+#else
+ VGImageFormat imageInternalFormat = VG_sARGB_8888;
+#endif
+
+ iImage = vgCreateImage(imageInternalFormat, iSize.iWidth, iSize.iHeight,
+ VG_IMAGE_QUALITY_NONANTIALIASED);
+
+ if (iImage == VG_INVALID_HANDLE)
+ {
+ PopEGLContext();
+
+ VGErrorCode err = vgGetError();
+ RDebug::Print(_L("CHuiVg10CanvasRenderBuffer::InitializeL() - vgCreateImage failed: VgError -- %04x"), err);
+ User::Leave(KErrGeneral);
+ }
+
+ const TInt BITS_PER_CHANNEL = 8;
+
+ // Choose an EGL config
+ const EGLint attrs[] =
+ {
+ EGL_SURFACE_TYPE, EGL_PBUFFER_BIT | EGL_VG_ALPHA_FORMAT_PRE_BIT,
+ EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT,
+ EGL_RED_SIZE, BITS_PER_CHANNEL,
+ EGL_GREEN_SIZE, BITS_PER_CHANNEL,
+ EGL_BLUE_SIZE, BITS_PER_CHANNEL,
+ EGL_ALPHA_SIZE, BITS_PER_CHANNEL,
+ EGL_NONE
+ };
+ TInt configCount = renderer.EglChooseConfig(attrs);
+ ASSERT(configCount > 0);
+
+ if (configCount <= 0)
+ {
+ PopEGLContext();
+
+ RDebug::Print(_L("CHuiVg10CanvasRenderBuffer::InitializeL() - no EGL config found !"));
+ User::Leave(KErrGeneral);
+ }
+
+ EGLConfig config = renderer.EglConfig(0);
+
+ // Create a context
+ iContext = eglCreateContext(renderer.EglDisplay(), config,
+ renderer.EglSharedContext(), NULL);
+
+ if(!iContext)
+ {
+ PopEGLContext();
+
+ EGLint err = eglGetError();
+ RDebug::Print(_L("CHuiVg10CanvasRenderBuffer::InitializeL() - EGLContext creation failed: EglError -- %04x"), err);
+ User::Leave(KErrGeneral);
+ }
+
+ // Create a pbuffer surface
+ iSurface = eglCreatePbufferFromClientBuffer(renderer.EglDisplay(), EGL_OPENVG_IMAGE,
+ iImage, config, NULL);
+ if(!iSurface)
+ {
+ PopEGLContext();
+
+ EGLint err = eglGetError();
+ RDebug::Print(_L("CHuiVg10CanvasRenderBuffer::InitializeL() - EGLSurface creation failed: EglError -- %04x"), err);
+ User::Leave(KErrGeneral);
+ }
+
+ // Initialize the context (TODO: We perhaps do not really need to do this by creating Cg
+ iGc = renderer.CreateGcL();
+ Bind();
+ iGc->InitState();
+
+ VGfloat color[] =
+ {
+ 0.f, 0.f, 0.f, 0.f
+ };
+ vgSetfv(VG_CLEAR_COLOR, sizeof(color) / sizeof(VGfloat), color);
+ vgClear(0, 0, iSize.iWidth, iSize.iHeight);
+ UnBind();
+
+ // Let renderer know that we have been fiddlling with OpenVg state directly
+ // "iGc->InitState" confuses scissoring setting, so lets notify it.
+ renderer.AddRestoreStateFlags(EHuiVg10GcStateFlagDirtyScissor);
+ renderer.AddRestoreStateFlags(EHuiVg10GcStateFlagDirtyBlendMode);
+
+ #ifdef HUI_DEBUG_PRINT_PERFORMANCE_INTERVAL
+ TTime endTime;
+ endTime.UniversalTime();
+ TInt timeInMs = endTime.MicroSecondsFrom( startTime ).Int64()/1000;
+ RDebug::Print(_L("> CHuiVg10CanvasRenderBuffer::InitializeL took %i ms"), timeInMs);
+#endif
+
+ iInitialized = ETrue;
+
+ PopEGLContext();
+ }
+
+void CHuiVg10CanvasRenderBuffer::Bind()
+ {
+ // Make sure it is safe to call even if "UnBind" has not been called or this function
+ // has already been called.
+ if (!iSurface || !iContext || iSavedContext || iSavedDrawSurface || iSavedReadSurface)
+ {
+ return;
+ }
+
+ // Save current context and surfaces
+ iSavedContext = eglGetCurrentContext();
+ iSavedDrawSurface = eglGetCurrentSurface(EGL_DRAW);
+ iSavedReadSurface = eglGetCurrentSurface(EGL_READ);
+
+ // Bind our own surface
+ CHuiVg10RenderPlugin& renderer = CHuiStatic::Vg10Renderer();
+ eglMakeCurrent(renderer.EglDisplay(), iSurface, iSurface, iContext);
+ }
+
+void CHuiVg10CanvasRenderBuffer::UnBind()
+ {
+ // Make sure it is safe to call even if "Bind" has not been called or this
+ // function has already been called.
+ if (!iSavedDrawSurface || !iSavedReadSurface || !iSavedContext)
+ {
+ return;
+ }
+
+ // Restore original surface & context
+ CHuiVg10RenderPlugin& renderer = CHuiStatic::Vg10Renderer();
+
+ // Todo: Should check whether the saved surface was UI surface
+ // and call CHuiVg10RenderSurface::MakeCurrent() for that instead
+ CHuiEnv* env = CHuiEnv::Static();
+ if (env && env->iSwapObserver)
+ {
+ env->iSwapObserver->ReleaseWindowServer();
+ }
+
+ eglMakeCurrent(renderer.EglDisplay(), iSavedDrawSurface, iSavedReadSurface,
+ iSavedContext);
+
+ if (env && env->iSwapObserver)
+ {
+ env->iSwapObserver->ReleaseWindowServer(EFalse);
+ }
+
+ iSavedDrawSurface = 0;
+ iSavedReadSurface = 0;
+ iSavedContext = 0;
+ }
+
+VGImage CHuiVg10CanvasRenderBuffer::Image() const
+ {
+ return iImage;
+ }
+
+
+void CHuiVg10CanvasRenderBuffer::PushEGLContext()
+ {
+ CHuiVg10RenderPlugin& renderer = CHuiStatic::Vg10Renderer();
+ iPreviousEGLState.iContext= eglGetCurrentContext();
+ TEGLState& state = renderer.GetUploadState();
+ if (state.iContext == KErrNotFound)
+ {
+ TEGLState& state = renderer.GetUploadState();
+ // the first context used for uploading will be used for all texture uploads
+ state.iContext = iPreviousEGLState.iContext;
+ state.iDrawSurface = eglGetCurrentSurface(EGL_DRAW);
+ state.iReadSurface = eglGetCurrentSurface(EGL_READ);
+ state.iDisplay = eglGetCurrentDisplay();
+ }
+ else
+ {
+ // change context only if necessary
+ if (iPreviousEGLState.iContext != state.iContext)
+ {
+ iPreviousEGLState.iDrawSurface = eglGetCurrentSurface(EGL_DRAW);
+ iPreviousEGLState.iReadSurface = eglGetCurrentSurface(EGL_READ);
+ iPreviousEGLState.iDisplay = eglGetCurrentDisplay();
+ eglMakeCurrent(state.iDisplay, state.iDrawSurface, state.iReadSurface, state.iContext);
+ }
+ }
+ }
+
+void CHuiVg10CanvasRenderBuffer::PopEGLContext()
+ {
+ CHuiVg10RenderPlugin& renderer = CHuiStatic::Vg10Renderer();
+ if (iPreviousEGLState.iContext != renderer.GetUploadState().iContext)
+ {
+ eglMakeCurrent(iPreviousEGLState.iDisplay, iPreviousEGLState.iDrawSurface, iPreviousEGLState.iReadSurface,iPreviousEGLState.iContext);
+ }
+ }
+
+void CHuiVg10CanvasRenderBuffer::Copy(const CHuiCanvasRenderBuffer& aSourceBuffer)
+ {
+ if (iSize != aSourceBuffer.Size())
+ {
+ return;
+ }
+
+ CHuiVg10CanvasRenderBuffer* sourcebuffer = (CHuiVg10CanvasRenderBuffer*) &aSourceBuffer;
+ vgCopyImage(iImage, 0, 0,
+ sourcebuffer->Image(), 0, 0,
+ iSize.iWidth, iSize.iHeight, VG_FALSE);
+ }
+
+void CHuiVg10CanvasRenderBuffer::Copy(TPoint aPoint)
+ {
+ ReadBackground(aPoint);
+ }
+
+void CHuiVg10CanvasRenderBuffer::ReadBackground(TPoint aPosition)
+ {
+ CHuiDisplay& display = CHuiStatic::Env().PrimaryDisplay();
+ TBool rotatedDisplay = display.Orientation() == CHuiGc::EOrientationCCW90 || display.Orientation() == CHuiGc::EOrientationCW90;
+ TRect renderBufferLocation = TRect(aPosition, iSize);
+
+ TRect displayArea = display.VisibleArea();
+
+ TInt displayHeight = displayArea.Height();
+ TInt displayWidth = displayArea.Width();
+
+ TSize rotatedSize = iSize;
+ TPoint rotatedPos = aPosition;
+
+ // Read pixels from surface
+ if (rotatedDisplay)
+ {
+ if (iRotatedImage == VG_INVALID_HANDLE)
+ {
+ PushEGLContext();
+
+ #ifndef __WINS__ // Should possibly query the supported mode instead?
+ VGImageFormat imageInternalFormat = VG_sARGB_8888_PRE;
+ #else
+ VGImageFormat imageInternalFormat = VG_sARGB_8888;
+ #endif
+
+ TSize rotatedImageSize = TSize(iSize.iHeight, iSize.iWidth);
+ iRotatedImage = vgCreateImage(imageInternalFormat, rotatedImageSize.iWidth, rotatedImageSize.iHeight,
+ VG_IMAGE_QUALITY_NONANTIALIASED);
+
+ PopEGLContext();
+ }
+
+
+ // If we have rotation on CHuiGc level, we must manually take that into account when
+ // accessing pixels directly
+ if(display.Orientation() == CHuiGc::EOrientationCCW90)
+ {
+ // Rotate the buffer location relative to real surface coordinates
+ rotatedSize = TSize(iSize.iHeight, iSize.iWidth);
+ rotatedPos = TPoint(displayHeight - aPosition.iY - iSize.iHeight, aPosition.iX);
+ renderBufferLocation = TRect(rotatedPos, rotatedSize);
+ }
+ else if(display.Orientation() == CHuiGc::EOrientationCW90)
+ {
+ // Rotate the buffer location relative to real surface coordinates
+ rotatedSize = TSize(iSize.iHeight, iSize.iWidth);
+ rotatedPos = TPoint(aPosition.iY, displayWidth - aPosition.iX - iSize.iWidth);
+ renderBufferLocation = TRect(rotatedPos, rotatedSize);
+ }
+ else
+ {
+ // nothing
+ }
+
+ // If screen is rotated but surface is not in native orientation, this gets difficult
+ // because vgGetPixels is not affected by transformations.
+
+ // Swap h and w so that those are the "real" values from surface point of view.
+ displayHeight = displayWidth;
+
+ #ifdef HUIFX_TRACE
+ RDebug::Print(_L("CHuiFxVg10OffscreenRenderbuffer::PrepareForReuse - renderBufferLocation: %i,%i, %i,%i "),
+ renderBufferLocation.iTl.iX,
+ renderBufferLocation.iTl.iY,
+ renderBufferLocation.iBr.iX,
+ renderBufferLocation.iBr.iY);
+
+ TRect vgRect(TPoint(renderBufferLocation.iTl.iX, displayHeight - renderBufferLocation.iTl.iY - rotatedSize.iHeight), rotatedSize);
+
+ RDebug::Print(_L("CHuiFxVg10OffscreenRenderbuffer::PrepareForReuse - vgRect: %i,%i, %i,%i "),
+ vgRect.iTl.iX,
+ vgRect.iTl.iY,
+ vgRect.iBr.iX,
+ vgRect.iBr.iY);
+ #endif
+
+ // So...first get pixels from surface into rotated image
+ vgGetPixels(iRotatedImage, 0, 0, renderBufferLocation.iTl.iX, displayHeight - renderBufferLocation.iTl.iY - rotatedSize.iHeight, rotatedSize.iWidth, rotatedSize.iHeight);
+
+ // Draw rotated image into real buffer image, first bind it as render target...
+ Bind();
+
+ // ...store some states...
+ const TInt VG_MATRIX_SIZE = 9;
+ VGfloat oldMatrix[VG_MATRIX_SIZE];
+ vgGetMatrix(oldMatrix);
+
+ // ...set some vg states...
+ vgLoadIdentity();
+ vgSeti(VG_BLEND_MODE, VG_BLEND_SRC);
+ vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_NORMAL);
+ vgSeti(VG_SCISSORING, VG_FALSE);
+
+ TInt w = iSize.iWidth;
+ TInt h = iSize.iHeight;
+
+ // ...select right rotation...
+ if (display.Orientation() == CHuiGc::EOrientationCW90)
+ {
+ // Rotate around origo and move back to displayarea
+ vgRotate(-90);
+ vgTranslate(-h, 0);
+ }
+ else if (display.Orientation() == CHuiGc::EOrientationCCW90)
+ {
+ // Rotate around origo and move back to displayarea
+ vgRotate(90);
+ vgTranslate(0, -w);
+ }
+ else if (display.Orientation() == CHuiGc::EOrientation180)
+ {
+ // Rotate around origo and move back to displayarea
+ vgRotate(180);
+ vgTranslate(-w, -h);
+ }
+ else
+ {
+ }
+
+ // ...Draw...
+ if (iRotatedImage != VG_INVALID_HANDLE)
+ {
+ vgDrawImage(iRotatedImage);
+ }
+
+ // ..and restore default VG states
+ vgSeti(VG_SCISSORING, VG_TRUE);
+ vgSeti(VG_BLEND_MODE, VG_BLEND_SRC_OVER);
+ vgLoadMatrix(oldMatrix);
+
+ // ...finally unbind image and we should have the content correctly.
+ UnBind();
+ }
+ else
+ {
+ // Much easier if no rotation !
+ vgGetPixels(iImage, 0, 0, renderBufferLocation.iTl.iX, displayHeight - renderBufferLocation.iTl.iY - rotatedSize.iHeight, rotatedSize.iWidth, rotatedSize.iHeight);
+ }
+ }
+