os/graphics/graphicstest/uibench/s60/src/openvgengine.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1  // Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
     2  // All rights reserved.
     3  // This component and the accompanying materials are made available
     4  // under the terms of "Eclipse Public License v1.0"
     5  // which accompanies this distribution, and is available
     6  // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7  //
     8  // Initial Contributors:
     9  // Nokia Corporation - initial contribution.
    10  //
    11  // Contributors:
    12  //
    13  // Description:
    14  //
    15 
    16 
    17 #include "openvgengine.h"
    18 #include "eglrendering.h"
    19 
    20 #include <eikenv.h>
    21 #include <e32math.h>
    22 
    23 
    24 _LIT(KCoverBitmaps, "z:\\resource\\apps\\covers.mbm");
    25 
    26 
    27 GLDEF_D VGUErrorCode vguComputeWarpQuadToQuadProxy(VGfloat dx0, VGfloat dy0,
    28                                                    VGfloat dx1, VGfloat dy1,
    29                                                    VGfloat dx2, VGfloat dy2,
    30                                                    VGfloat dx3, VGfloat dy3,
    31                                                    VGfloat sx0, VGfloat sy0,
    32                                                    VGfloat sx1, VGfloat sy1,
    33                                                    VGfloat sx2, VGfloat sy2,
    34                                                    VGfloat sx3, VGfloat sy3,
    35                                                    VGfloat * matrix)
    36 	{
    37 	vguComputeWarpQuadToQuad(
    38                                                    sx0, sy0,
    39                                                    sx1, sy1,
    40                                                    sx2, sy2,
    41                                                    sx3, sy3,
    42                                                    dx0, dy0,
    43                                                    dx1, dy1,
    44                                                    dx2, dy2,
    45                                                    dx3, dy3,
    46                                                    matrix);
    47 	return VGU_NO_ERROR;
    48 	}
    49 
    50 COpenVGEngine* COpenVGEngine::NewL(RWindow& aWindow,EGLDisplay& aDisplay, EGLSurface& aSurface, EGLContext& aContext)
    51 	{
    52 	COpenVGEngine* self = new(ELeave) COpenVGEngine(aWindow, aDisplay, aSurface, aContext);
    53 	return self;
    54 	}
    55 
    56 COpenVGEngine::COpenVGEngine(RWindow& aWindow,EGLDisplay& aDisplay, EGLSurface& aSurface, EGLContext& aContext) :
    57         iWindow(aWindow), iDisplay(aDisplay), iSurface(aSurface), iContext(aContext), iWantedCover(20),
    58         iHasPendingDraw(EFalse), iShowCoverImage(EFalse), iSpeedOffset(0), iShowMirror(ETrue), iSpeed(0),
    59         iCurrentImageIndex(0)
    60     {
    61 #ifdef PORTRAIT_MODE
    62     iSurfaceSize.iWidth = iWindow.Size().iHeight;
    63     iSurfaceSize.iHeight = iWindow.Size().iWidth;
    64 #else
    65     iSurfaceSize = iWindow.Size();
    66 #endif  
    67     // initiate the location of each cover & make the wanted one the cover at the opposite end
    68     for(TInt i = 0; i < KMaxCoversExample3; ++i)
    69         {
    70         iCoverLocation[i] = i;
    71         }
    72     }
    73 
    74 COpenVGEngine::~COpenVGEngine()
    75 	{
    76 	Deactivate();
    77 	}
    78 
    79 TInt COpenVGEngine::GetSpeed()
    80 	{
    81 	return static_cast<TInt>(iSpeed * 100000);
    82 	}
    83 
    84 TBool COpenVGEngine::IsPending()
    85 	{
    86 	return iHasPendingDraw;
    87 	}
    88 
    89 void COpenVGEngine::ActivateL()
    90 	{
    91 	CEGLRendering::EGLCheckReturnError(eglMakeCurrent(iDisplay, iSurface, iSurface, iContext));
    92 	
    93 	// Setup initial OpenVG context state
    94 	VGfloat clearColour[] = { 0.1f, 0.1f, 0.2f, 1.0f };
    95 	vgSetfv(VG_CLEAR_COLOR, 4, clearColour);
    96 	vgSeti(VG_IMAGE_QUALITY, VG_IMAGE_QUALITY_NONANTIALIASED);
    97 	vgSeti(VG_RENDERING_QUALITY, VG_RENDERING_QUALITY_NONANTIALIASED);	
    98 	vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE);
    99 
   100 	CFbsBitmap* bitmap = new(ELeave) CFbsBitmap();
   101 	CleanupStack::PushL(bitmap);
   102 	TInt idx = 0;
   103 	while(bitmap->Load(KCoverBitmaps, idx++) == KErrNone)
   104 		{
   105 		VGint width = bitmap->SizeInPixels().iWidth;
   106 		VGint height = bitmap->SizeInPixels().iHeight;
   107 		// Crate VGImage
   108 		VGImage image = vgCreateImage(VG_sRGB_565, width, height, VG_IMAGE_QUALITY_NONANTIALIASED);
   109 		CEGLRendering::VGCheckError();
   110 		//Load Symbian bitmap into VGImage
   111 		vgImageSubData(image, bitmap->DataAddress(), bitmap->DataStride(), VG_sRGB_565, 0, 0, width, height);
   112 		CEGLRendering::VGCheckError();
   113 		iImages.AppendL(image);		
   114 		}
   115 	CleanupStack::PopAndDestroy(bitmap);
   116 	iHasPendingDraw = ETrue;
   117 	
   118 	//Checks if any images were loaded
   119 	if(iImages.Count() == 0)
   120 		{
   121 		User::Leave(KErrNotFound);
   122 		}
   123 	
   124 	iShadowPaint = vgCreatePaint();
   125 	CEGLRendering::VGCheckError();
   126 	if (iShadowPaint != VG_INVALID_HANDLE)
   127 		{
   128 		VGfloat paintColour[4] = { 0.4f, 0.4f, 0.6f, 1.0f };
   129 		vgSetParameterfv(iShadowPaint, VG_PAINT_COLOR, 4, paintColour); 
   130 		CEGLRendering::VGCheckError();
   131 		}
   132 	}
   133 
   134 void COpenVGEngine::Deactivate()
   135 	{
   136 	CEGLRendering::EGLCheckReturnError(eglMakeCurrent(iDisplay, iSurface, iSurface, iContext));
   137 	for (TInt i = iImages.Count() - 1; i >= 0; --i)
   138 		{
   139 		vgDestroyImage(iImages[i]);
   140 		}
   141 	vgDestroyPaint(iShadowPaint);
   142 	eglWaitClient();
   143 	iImages.Reset();
   144 	iHasPendingDraw = EFalse;
   145 	}
   146 
   147 void COpenVGEngine::Step()
   148 	{
   149 	CEGLRendering::EGLCheckReturnError(eglMakeCurrent(iDisplay, iSurface, iSurface, iContext));
   150 		
   151 #ifdef PORTRAIT_MODE	
   152 	vgClear(0, 0, iSurfaceSize.iHeight, iSurfaceSize.iWidth);
   153 #else
   154 	vgClear(0, 0, iSurfaceSize.iWidth, iSurfaceSize.iHeight);
   155 #endif
   156 	
   157 	if (Abs(iCoverLocation[iWantedCover]) < 0.03)
   158 		{
   159 		iSpeed = 0.0f;
   160 		iHasPendingDraw = EFalse;
   161 		}
   162 	else if (Abs(iCoverLocation[iWantedCover]) < 0.5)
   163 		{
   164 		iSpeed *= 0.7;
   165 		}
   166 	else
   167 		{
   168 		iSpeed = 0.05 * (2 + Abs(iCoverLocation[iWantedCover]) + (Abs(iCoverLocation[iWantedCover]) + 1)
   169                     * (Abs(iCoverLocation[iWantedCover]) + 1) / 2);
   170 		}
   171 	// For each Cover, update its location in the correct direction
   172 	// Check if the wanted cover is already at the CenterStage point
   173 
   174 	VGfloat moveEachCover = iSpeed;
   175 	if (iCoverLocation[iWantedCover] > 0.0)
   176 		{
   177 		moveEachCover *= -1;
   178 		}	
   179 	
   180 	for (TInt i = 0; i < KMaxCoversExample3; ++i)
   181 		{
   182 		iCoverLocation[i] += moveEachCover;
   183 		}
   184 	
   185 	TInt coverClippingCount = 10;
   186 	TInt middleCoverPos = 0;
   187 	VGfloat threshold = 0.50f;
   188 
   189 	while(Abs(iCoverLocation[middleCoverPos]) > threshold)
   190 		{
   191 		++middleCoverPos;
   192 		}
   193 	
   194 	
   195 	//left
   196 	TInt cutOff = middleCoverPos - coverClippingCount;
   197 	if (cutOff <0 )
   198 		{
   199 		cutOff = 0;
   200 		}
   201 	for (TInt i = cutOff; i < middleCoverPos; ++i)
   202 		{
   203 		DrawCover(i);
   204 		}
   205 	
   206 	//right
   207 	cutOff = coverClippingCount + middleCoverPos;
   208 	if (cutOff >= KMaxCoversExample3)
   209 		{
   210 		cutOff = KMaxCoversExample3-1;
   211 		}
   212 	
   213 	for (TInt j = cutOff; j >= middleCoverPos; --j)
   214 	    {
   215 		DrawCover(j);
   216         }
   217 
   218 	static TInt dir = 1;
   219 	if (iWantedCover == (KMaxCoversExample3 - 1))
   220 		{
   221 		dir = -1;
   222 		}
   223 	else if (iWantedCover == 0)
   224 		{
   225 		dir = 1;
   226 		}
   227 
   228 	iWantedCover += dir;
   229 	iHasPendingDraw = ETrue;
   230 	}
   231 
   232 void COpenVGEngine::DrawCover(TInt coverIndex)
   233 	{ 	
   234 		VGImage image = iImages[coverIndex % iImages.Count()];
   235 		// Starting at the outside, render each visible (+/-  KMaxDisplayCoversExample3/2) Cover
   236 		// Calculate its path
   237 		vgLoadIdentity();
   238 #ifdef PORTRAIT_MODE
   239 		vgTranslate(iSurfaceSize.iHeight, 0);
   240 		vgRotate(90);
   241 #endif
   242 		VGfloat coverPosition = iCoverLocation[coverIndex];
   243 		VGfloat tempMatrix[3][3];
   244 
   245 		//flip coords
   246 		VGfloat flipmatrix[] = 
   247 			{
   248 			1.0f, 0.0f, 0.0f, 
   249 			0.0f, -1.0f, 0.0f,
   250 			0.0f, 0.0f, 1.0f
   251 			};
   252 		vgMultMatrix(flipmatrix);		
   253 		VGint imageWidth = vgGetParameteri(image, VG_IMAGE_WIDTH);
   254 		VGint imageHeight = vgGetParameteri(image, VG_IMAGE_HEIGHT);
   255 
   256 		//VGint yTrans = -200;	
   257 		
   258 		//factors which must be multiplied with side of image which will be projected towards back
   259 		//valid if projecting right image side to back
   260 		//opposite is (1 - factor) for projecting left image side.
   261 
   262 		VGfloat bottomProjectXFactor= (0.75f);
   263 		VGfloat bottomProjectYFactor = (0.20f);
   264 		
   265 		VGfloat topProjectXFactor = (0.75f);
   266 		VGfloat topProjectYFactor = (0.90f);
   267 				
   268 		VGfloat imageSpacingFactor = 0.16;
   269 		
   270 		VGfloat translationOffset = 0.0;
   271 		
   272 
   273 		//float yscale = 1.7;
   274 		//float xscale = 4.4;
   275 		//imageHeight = Min(iSurfaceSize.iWidth/xscale, iSurfaceSize.iHeight/yscale);
   276 		//imageWidth = imageHeight;
   277 		//TInt KImageSize = imageHeight/1.125;
   278 		//VGint yTrans = iSurfaceSize.iHeight/-1.2;	
   279 		
   280 		TInt KImageSize = (imageHeight * 8) / 9; //KImageSize - secondary covers should be 8/9 of the size of the middle cover
   281 		//VGint yTrans = -200;	
   282 		VGint yTrans = - (iWindow.Size().iHeight * 5) / 6;	
   283 		
   284 		
   285 		VGfloat middleTranslationOffset = KImageSize / 2;		
   286 		VGfloat coverProjectionLimit = 10;
   287 		
   288 		if (coverPosition >= 1)
   289 			{
   290 			//if considering an image on the right side, this is offset from middle to place image on screen			
   291 			translationOffset = middleTranslationOffset- KImageSize/2 + KImageSize*imageSpacingFactor * (coverPosition -1);
   292 						
   293 			//left side of image goes back.
   294 			vguComputeWarpQuadToQuadProxy(0.0f, 0.0f, 
   295 					   imageWidth, 0.0f, 
   296 					   0.0f, imageHeight, 
   297 					   imageWidth, imageHeight,					   
   298 					   KImageSize * (1 - bottomProjectXFactor*(1-Abs(coverPosition)/coverProjectionLimit)),KImageSize * bottomProjectYFactor,//left vertex
   299 					   KImageSize, 0.0f,
   300 					   KImageSize * (1 - topProjectXFactor*(1-Abs(coverPosition)/coverProjectionLimit)), KImageSize * topProjectYFactor,//left vertex
   301 					   KImageSize, KImageSize,			   
   302 					   &tempMatrix[0][0]);
   303 			}
   304 		else if (coverPosition < -1)
   305 			{			
   306 			//must move an extra image width from center , as coordinates from bottom left corner of image. 
   307 			translationOffset = - (middleTranslationOffset + (KImageSize * imageSpacingFactor) * ( -coverPosition - 1) + KImageSize/2) ;
   308 			
   309 			vguComputeWarpQuadToQuadProxy(  0.0f, 0.0f, 
   310 					   imageWidth, 0.0f, 
   311 					   0.0f, imageHeight, 
   312 					   imageWidth, imageHeight,
   313 					   
   314 					   0.0f, 0.0f,
   315 					   (bottomProjectXFactor*(1-Abs(coverPosition)/coverProjectionLimit))* KImageSize, bottomProjectYFactor * KImageSize, //Right Vertex
   316 					   0.0f, (KImageSize),
   317 					   (topProjectXFactor*(1-Abs(coverPosition)/coverProjectionLimit)) * KImageSize, topProjectYFactor * KImageSize, //Right Vertex
   318 					   
   319 					   &tempMatrix[0][0]);			
   320 			}
   321 		else if((coverPosition > -1) && (coverPosition <= 0))// -0.07))
   322 			{			
   323 			translationOffset = -middleTranslationOffset * Abs(coverPosition) - KImageSize/2 ;
   324 						
   325 			vguComputeWarpQuadToQuadProxy(  0.0f, 0.0f, 
   326 	    						   imageWidth, 0.0f, 
   327 	    						   0.0f, imageHeight, 
   328 	    						   imageWidth, imageHeight,	    						   
   329 	    						   0.0f, 0.0f,
   330 	    						   KImageSize * (1 - (1-bottomProjectXFactor) * Abs(coverPosition)), KImageSize * bottomProjectYFactor * Abs(coverPosition),
   331 	    						   0.0f, KImageSize,
   332 	    						   (KImageSize * (1 - ( 1 - topProjectXFactor) * Abs(coverPosition))) , KImageSize * (1 - (1 - topProjectYFactor) * Abs(coverPosition)),	    						   
   333 	    						   &tempMatrix[0][0]);		
   334 			}				
   335 		else if ((coverPosition >=0) && (coverPosition <= 1))
   336 			{
   337 			translationOffset = middleTranslationOffset * Abs(coverPosition) - KImageSize / 2;				    						   			
   338 			vguComputeWarpQuadToQuadProxy( 0.0f, 0.0f, 
   339 	    						   imageWidth, 0.0f, 
   340 	    						   0.0f, imageHeight, 
   341 	    						   imageWidth, imageHeight,	    						   
   342 	    						   KImageSize * (1-bottomProjectXFactor)* (coverPosition), KImageSize * (bottomProjectYFactor) * (coverPosition),
   343 	    						   KImageSize, 0,
   344 	    						   KImageSize * ( 1 - topProjectXFactor) * (coverPosition) , KImageSize * (1 - (1 - topProjectYFactor) * Abs(coverPosition)),
   345 	    						   KImageSize, KImageSize,	    						   
   346 	    						   &tempMatrix[0][0]);
   347 			}
   348 		iSpeedOffset = 140*(iSpeed)*(iSpeed);		
   349         if (iCoverLocation[iWantedCover] < 0)
   350             {
   351             iSpeedOffset *= -1;
   352             }
   353 		vgTranslate(iWindow.Size().iWidth/2 + translationOffset + iSpeedOffset, yTrans);
   354 						
   355 		vgMultMatrix(&tempMatrix[0][0]);
   356 		if (Abs(coverPosition) <= 1)
   357 			{
   358 			VGfloat scale = GetMiddleCoverScalingFactor(coverPosition);
   359 			vgScale(scale,scale);
   360 			vgTranslate(-(scale-1)/2 * KImageSize,-(scale-1)/2 * KImageSize);
   361 			}
   362 		vgDrawImage(image);
   363 		CEGLRendering::VGCheckError();
   364 		if (iShowMirror)
   365 			{
   366 			vgScale(1,-1);
   367 			vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_MULTIPLY);
   368 			vgTranslate(0,-4*KImageSize+226); 
   369 			//vgTranslate(0,iSurfaceSize.iHeight/-.839); 
   370 					
   371 			vgSetPaint(iShadowPaint, VG_FILL_PATH);
   372 			vgDrawImage(image);
   373 			CEGLRendering::VGCheckError();
   374 				
   375 			vgSeti(VG_IMAGE_MODE,VG_DRAW_IMAGE_NORMAL);
   376 			}
   377 	}
   378 
   379 TKeyResponse COpenVGEngine::HandleKeyEventL(const TKeyEvent& aKeyEvent)
   380 	{
   381 	TKeyResponse response = EKeyWasConsumed;
   382 	switch (aKeyEvent.iCode)
   383 		{
   384 	case EKeyRightArrow:
   385 		NextCover();
   386 		break;	
   387 	case EKeyLeftArrow:
   388 		PreviousCover();
   389 		break;		
   390 	case EKeyBackspace: 
   391 		ToggleCoverReflection();
   392 		break;		
   393 	default:
   394 		response = EKeyWasNotConsumed;
   395 		break;
   396 		};
   397 	return response;
   398 	}
   399 
   400 void COpenVGEngine::NextCover()
   401 	{
   402 	if (iWantedCover < (KMaxCoversExample3 - 1))
   403 	    {
   404 	    ++iWantedCover;
   405 	    iHasPendingDraw = ETrue;
   406 	    }		
   407 	}
   408 
   409 void COpenVGEngine::PreviousCover()
   410 	{
   411 	if (iWantedCover > 0)
   412 	    {
   413 	    --iWantedCover;
   414 	    iHasPendingDraw = ETrue;
   415 	    }
   416 	}
   417 
   418 void COpenVGEngine::ToggleCoverReflection()
   419 	{
   420 	iShowMirror = !iShowMirror;
   421 	}
   422 
   423 VGfloat COpenVGEngine::GetMiddleCoverScalingFactor(VGfloat aCoverPosition)
   424 	{
   425 	if(Abs(aCoverPosition) > 1)
   426 	    {
   427 	    return 0.0f;
   428 	    }
   429 	return (-0.125 * Abs(aCoverPosition) + 1.125);	
   430 	}
   431 
   432 void COpenVGEngine::Refresh()
   433 	{
   434 	iHasPendingDraw = ETrue;
   435 	}