graphicstest/uibench/s60/src/openvgengine.cpp
changeset 0 5d03bc08d59c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/graphicstest/uibench/s60/src/openvgengine.cpp	Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,435 @@
+ // 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 "openvgengine.h"
+#include "eglrendering.h"
+
+#include <eikenv.h>
+#include <e32math.h>
+
+
+_LIT(KCoverBitmaps, "z:\\resource\\apps\\covers.mbm");
+
+
+GLDEF_D VGUErrorCode vguComputeWarpQuadToQuadProxy(VGfloat dx0, VGfloat dy0,
+                                                   VGfloat dx1, VGfloat dy1,
+                                                   VGfloat dx2, VGfloat dy2,
+                                                   VGfloat dx3, VGfloat dy3,
+                                                   VGfloat sx0, VGfloat sy0,
+                                                   VGfloat sx1, VGfloat sy1,
+                                                   VGfloat sx2, VGfloat sy2,
+                                                   VGfloat sx3, VGfloat sy3,
+                                                   VGfloat * matrix)
+	{
+	vguComputeWarpQuadToQuad(
+                                                   sx0, sy0,
+                                                   sx1, sy1,
+                                                   sx2, sy2,
+                                                   sx3, sy3,
+                                                   dx0, dy0,
+                                                   dx1, dy1,
+                                                   dx2, dy2,
+                                                   dx3, dy3,
+                                                   matrix);
+	return VGU_NO_ERROR;
+	}
+
+COpenVGEngine* COpenVGEngine::NewL(RWindow& aWindow,EGLDisplay& aDisplay, EGLSurface& aSurface, EGLContext& aContext)
+	{
+	COpenVGEngine* self = new(ELeave) COpenVGEngine(aWindow, aDisplay, aSurface, aContext);
+	return self;
+	}
+
+COpenVGEngine::COpenVGEngine(RWindow& aWindow,EGLDisplay& aDisplay, EGLSurface& aSurface, EGLContext& aContext) :
+        iWindow(aWindow), iDisplay(aDisplay), iSurface(aSurface), iContext(aContext), iWantedCover(20),
+        iHasPendingDraw(EFalse), iShowCoverImage(EFalse), iSpeedOffset(0), iShowMirror(ETrue), iSpeed(0),
+        iCurrentImageIndex(0)
+    {
+#ifdef PORTRAIT_MODE
+    iSurfaceSize.iWidth = iWindow.Size().iHeight;
+    iSurfaceSize.iHeight = iWindow.Size().iWidth;
+#else
+    iSurfaceSize = iWindow.Size();
+#endif  
+    // initiate the location of each cover & make the wanted one the cover at the opposite end
+    for(TInt i = 0; i < KMaxCoversExample3; ++i)
+        {
+        iCoverLocation[i] = i;
+        }
+    }
+
+COpenVGEngine::~COpenVGEngine()
+	{
+	Deactivate();
+	}
+
+TInt COpenVGEngine::GetSpeed()
+	{
+	return static_cast<TInt>(iSpeed * 100000);
+	}
+
+TBool COpenVGEngine::IsPending()
+	{
+	return iHasPendingDraw;
+	}
+
+void COpenVGEngine::ActivateL()
+	{
+	CEGLRendering::EGLCheckReturnError(eglMakeCurrent(iDisplay, iSurface, iSurface, iContext));
+	
+	// Setup initial OpenVG context state
+	VGfloat clearColour[] = { 0.1f, 0.1f, 0.2f, 1.0f };
+	vgSetfv(VG_CLEAR_COLOR, 4, clearColour);
+	vgSeti(VG_IMAGE_QUALITY, VG_IMAGE_QUALITY_NONANTIALIASED);
+	vgSeti(VG_RENDERING_QUALITY, VG_RENDERING_QUALITY_NONANTIALIASED);	
+	vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
+
+	CFbsBitmap* bitmap = new(ELeave) CFbsBitmap();
+	CleanupStack::PushL(bitmap);
+	TInt idx = 0;
+	while(bitmap->Load(KCoverBitmaps, idx++) == KErrNone)
+		{
+		VGint width = bitmap->SizeInPixels().iWidth;
+		VGint height = bitmap->SizeInPixels().iHeight;
+		// Crate VGImage
+		VGImage image = vgCreateImage(VG_sRGB_565, width, height, VG_IMAGE_QUALITY_NONANTIALIASED);
+		CEGLRendering::VGCheckError();
+		//Load Symbian bitmap into VGImage
+		vgImageSubData(image, bitmap->DataAddress(), bitmap->DataStride(), VG_sRGB_565, 0, 0, width, height);
+		CEGLRendering::VGCheckError();
+		iImages.AppendL(image);		
+		}
+	CleanupStack::PopAndDestroy(bitmap);
+	iHasPendingDraw = ETrue;
+	
+	//Checks if any images were loaded
+	if(iImages.Count() == 0)
+		{
+		User::Leave(KErrNotFound);
+		}
+	
+	iShadowPaint = vgCreatePaint();
+	CEGLRendering::VGCheckError();
+	if (iShadowPaint != VG_INVALID_HANDLE)
+		{
+		VGfloat paintColour[4] = { 0.4f, 0.4f, 0.6f, 1.0f };
+		vgSetParameterfv(iShadowPaint, VG_PAINT_COLOR, 4, paintColour); 
+		CEGLRendering::VGCheckError();
+		}
+	}
+
+void COpenVGEngine::Deactivate()
+	{
+	CEGLRendering::EGLCheckReturnError(eglMakeCurrent(iDisplay, iSurface, iSurface, iContext));
+	for (TInt i = iImages.Count() - 1; i >= 0; --i)
+		{
+		vgDestroyImage(iImages[i]);
+		}
+	vgDestroyPaint(iShadowPaint);
+	eglWaitClient();
+	iImages.Reset();
+	iHasPendingDraw = EFalse;
+	}
+
+void COpenVGEngine::Step()
+	{
+	CEGLRendering::EGLCheckReturnError(eglMakeCurrent(iDisplay, iSurface, iSurface, iContext));
+		
+#ifdef PORTRAIT_MODE	
+	vgClear(0, 0, iSurfaceSize.iHeight, iSurfaceSize.iWidth);
+#else
+	vgClear(0, 0, iSurfaceSize.iWidth, iSurfaceSize.iHeight);
+#endif
+	
+	if (Abs(iCoverLocation[iWantedCover]) < 0.03)
+		{
+		iSpeed = 0.0f;
+		iHasPendingDraw = EFalse;
+		}
+	else if (Abs(iCoverLocation[iWantedCover]) < 0.5)
+		{
+		iSpeed *= 0.7;
+		}
+	else
+		{
+		iSpeed = 0.05 * (2 + Abs(iCoverLocation[iWantedCover]) + (Abs(iCoverLocation[iWantedCover]) + 1)
+                    * (Abs(iCoverLocation[iWantedCover]) + 1) / 2);
+		}
+	// For each Cover, update its location in the correct direction
+	// Check if the wanted cover is already at the CenterStage point
+
+	VGfloat moveEachCover = iSpeed;
+	if (iCoverLocation[iWantedCover] > 0.0)
+		{
+		moveEachCover *= -1;
+		}	
+	
+	for (TInt i = 0; i < KMaxCoversExample3; ++i)
+		{
+		iCoverLocation[i] += moveEachCover;
+		}
+	
+	TInt coverClippingCount = 10;
+	TInt middleCoverPos = 0;
+	VGfloat threshold = 0.50f;
+
+	while(Abs(iCoverLocation[middleCoverPos]) > threshold)
+		{
+		++middleCoverPos;
+		}
+	
+	
+	//left
+	TInt cutOff = middleCoverPos - coverClippingCount;
+	if (cutOff <0 )
+		{
+		cutOff = 0;
+		}
+	for (TInt i = cutOff; i < middleCoverPos; ++i)
+		{
+		DrawCover(i);
+		}
+	
+	//right
+	cutOff = coverClippingCount + middleCoverPos;
+	if (cutOff >= KMaxCoversExample3)
+		{
+		cutOff = KMaxCoversExample3-1;
+		}
+	
+	for (TInt j = cutOff; j >= middleCoverPos; --j)
+	    {
+		DrawCover(j);
+        }
+
+	static TInt dir = 1;
+	if (iWantedCover == (KMaxCoversExample3 - 1))
+		{
+		dir = -1;
+		}
+	else if (iWantedCover == 0)
+		{
+		dir = 1;
+		}
+
+	iWantedCover += dir;
+	iHasPendingDraw = ETrue;
+	}
+
+void COpenVGEngine::DrawCover(TInt coverIndex)
+	{ 	
+		VGImage image = iImages[coverIndex % iImages.Count()];
+		// Starting at the outside, render each visible (+/-  KMaxDisplayCoversExample3/2) Cover
+		// Calculate its path
+		vgLoadIdentity();
+#ifdef PORTRAIT_MODE
+		vgTranslate(iSurfaceSize.iHeight, 0);
+		vgRotate(90);
+#endif
+		VGfloat coverPosition = iCoverLocation[coverIndex];
+		VGfloat tempMatrix[3][3];
+
+		//flip coords
+		VGfloat flipmatrix[] = 
+			{
+			1.0f, 0.0f, 0.0f, 
+			0.0f, -1.0f, 0.0f,
+			0.0f, 0.0f, 1.0f
+			};
+		vgMultMatrix(flipmatrix);		
+		VGint imageWidth = vgGetParameteri(image, VG_IMAGE_WIDTH);
+		VGint imageHeight = vgGetParameteri(image, VG_IMAGE_HEIGHT);
+
+		//VGint yTrans = -200;	
+		
+		//factors which must be multiplied with side of image which will be projected towards back
+		//valid if projecting right image side to back
+		//opposite is (1 - factor) for projecting left image side.
+
+		VGfloat bottomProjectXFactor= (0.75f);
+		VGfloat bottomProjectYFactor = (0.20f);
+		
+		VGfloat topProjectXFactor = (0.75f);
+		VGfloat topProjectYFactor = (0.90f);
+				
+		VGfloat imageSpacingFactor = 0.16;
+		
+		VGfloat translationOffset = 0.0;
+		
+
+		//float yscale = 1.7;
+		//float xscale = 4.4;
+		//imageHeight = Min(iSurfaceSize.iWidth/xscale, iSurfaceSize.iHeight/yscale);
+		//imageWidth = imageHeight;
+		//TInt KImageSize = imageHeight/1.125;
+		//VGint yTrans = iSurfaceSize.iHeight/-1.2;	
+		
+		TInt KImageSize = (imageHeight * 8) / 9; //KImageSize - secondary covers should be 8/9 of the size of the middle cover
+		//VGint yTrans = -200;	
+		VGint yTrans = - (iWindow.Size().iHeight * 5) / 6;	
+		
+		
+		VGfloat middleTranslationOffset = KImageSize / 2;		
+		VGfloat coverProjectionLimit = 10;
+		
+		if (coverPosition >= 1)
+			{
+			//if considering an image on the right side, this is offset from middle to place image on screen			
+			translationOffset = middleTranslationOffset- KImageSize/2 + KImageSize*imageSpacingFactor * (coverPosition -1);
+						
+			//left side of image goes back.
+			vguComputeWarpQuadToQuadProxy(0.0f, 0.0f, 
+					   imageWidth, 0.0f, 
+					   0.0f, imageHeight, 
+					   imageWidth, imageHeight,					   
+					   KImageSize * (1 - bottomProjectXFactor*(1-Abs(coverPosition)/coverProjectionLimit)),KImageSize * bottomProjectYFactor,//left vertex
+					   KImageSize, 0.0f,
+					   KImageSize * (1 - topProjectXFactor*(1-Abs(coverPosition)/coverProjectionLimit)), KImageSize * topProjectYFactor,//left vertex
+					   KImageSize, KImageSize,			   
+					   &tempMatrix[0][0]);
+			}
+		else if (coverPosition < -1)
+			{			
+			//must move an extra image width from center , as coordinates from bottom left corner of image. 
+			translationOffset = - (middleTranslationOffset + (KImageSize * imageSpacingFactor) * ( -coverPosition - 1) + KImageSize/2) ;
+			
+			vguComputeWarpQuadToQuadProxy(  0.0f, 0.0f, 
+					   imageWidth, 0.0f, 
+					   0.0f, imageHeight, 
+					   imageWidth, imageHeight,
+					   
+					   0.0f, 0.0f,
+					   (bottomProjectXFactor*(1-Abs(coverPosition)/coverProjectionLimit))* KImageSize, bottomProjectYFactor * KImageSize, //Right Vertex
+					   0.0f, (KImageSize),
+					   (topProjectXFactor*(1-Abs(coverPosition)/coverProjectionLimit)) * KImageSize, topProjectYFactor * KImageSize, //Right Vertex
+					   
+					   &tempMatrix[0][0]);			
+			}
+		else if((coverPosition > -1) && (coverPosition <= 0))// -0.07))
+			{			
+			translationOffset = -middleTranslationOffset * Abs(coverPosition) - KImageSize/2 ;
+						
+			vguComputeWarpQuadToQuadProxy(  0.0f, 0.0f, 
+	    						   imageWidth, 0.0f, 
+	    						   0.0f, imageHeight, 
+	    						   imageWidth, imageHeight,	    						   
+	    						   0.0f, 0.0f,
+	    						   KImageSize * (1 - (1-bottomProjectXFactor) * Abs(coverPosition)), KImageSize * bottomProjectYFactor * Abs(coverPosition),
+	    						   0.0f, KImageSize,
+	    						   (KImageSize * (1 - ( 1 - topProjectXFactor) * Abs(coverPosition))) , KImageSize * (1 - (1 - topProjectYFactor) * Abs(coverPosition)),	    						   
+	    						   &tempMatrix[0][0]);		
+			}				
+		else if ((coverPosition >=0) && (coverPosition <= 1))
+			{
+			translationOffset = middleTranslationOffset * Abs(coverPosition) - KImageSize / 2;				    						   			
+			vguComputeWarpQuadToQuadProxy( 0.0f, 0.0f, 
+	    						   imageWidth, 0.0f, 
+	    						   0.0f, imageHeight, 
+	    						   imageWidth, imageHeight,	    						   
+	    						   KImageSize * (1-bottomProjectXFactor)* (coverPosition), KImageSize * (bottomProjectYFactor) * (coverPosition),
+	    						   KImageSize, 0,
+	    						   KImageSize * ( 1 - topProjectXFactor) * (coverPosition) , KImageSize * (1 - (1 - topProjectYFactor) * Abs(coverPosition)),
+	    						   KImageSize, KImageSize,	    						   
+	    						   &tempMatrix[0][0]);
+			}
+		iSpeedOffset = 140*(iSpeed)*(iSpeed);		
+        if (iCoverLocation[iWantedCover] < 0)
+            {
+            iSpeedOffset *= -1;
+            }
+		vgTranslate(iWindow.Size().iWidth/2 + translationOffset + iSpeedOffset, yTrans);
+						
+		vgMultMatrix(&tempMatrix[0][0]);
+		if (Abs(coverPosition) <= 1)
+			{
+			VGfloat scale = GetMiddleCoverScalingFactor(coverPosition);
+			vgScale(scale,scale);
+			vgTranslate(-(scale-1)/2 * KImageSize,-(scale-1)/2 * KImageSize);
+			}
+		vgDrawImage(image);
+		CEGLRendering::VGCheckError();
+		if (iShowMirror)
+			{
+			vgScale(1,-1);
+			vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_MULTIPLY);
+			vgTranslate(0,-4*KImageSize+226); 
+			//vgTranslate(0,iSurfaceSize.iHeight/-.839); 
+					
+			vgSetPaint(iShadowPaint, VG_FILL_PATH);
+			vgDrawImage(image);
+			CEGLRendering::VGCheckError();
+				
+			vgSeti(VG_IMAGE_MODE,VG_DRAW_IMAGE_NORMAL);
+			}
+	}
+
+TKeyResponse COpenVGEngine::HandleKeyEventL(const TKeyEvent& aKeyEvent)
+	{
+	TKeyResponse response = EKeyWasConsumed;
+	switch (aKeyEvent.iCode)
+		{
+	case EKeyRightArrow:
+		NextCover();
+		break;	
+	case EKeyLeftArrow:
+		PreviousCover();
+		break;		
+	case EKeyBackspace: 
+		ToggleCoverReflection();
+		break;		
+	default:
+		response = EKeyWasNotConsumed;
+		break;
+		};
+	return response;
+	}
+
+void COpenVGEngine::NextCover()
+	{
+	if (iWantedCover < (KMaxCoversExample3 - 1))
+	    {
+	    ++iWantedCover;
+	    iHasPendingDraw = ETrue;
+	    }		
+	}
+
+void COpenVGEngine::PreviousCover()
+	{
+	if (iWantedCover > 0)
+	    {
+	    --iWantedCover;
+	    iHasPendingDraw = ETrue;
+	    }
+	}
+
+void COpenVGEngine::ToggleCoverReflection()
+	{
+	iShowMirror = !iShowMirror;
+	}
+
+VGfloat COpenVGEngine::GetMiddleCoverScalingFactor(VGfloat aCoverPosition)
+	{
+	if(Abs(aCoverPosition) > 1)
+	    {
+	    return 0.0f;
+	    }
+	return (-0.125 * Abs(aCoverPosition) + 1.125);	
+	}
+
+void COpenVGEngine::Refresh()
+	{
+	iHasPendingDraw = ETrue;
+	}