diff -r 000000000000 -r bde4ae8d615e os/graphics/graphicstest/uibench/s60/src/openvgengine.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/os/graphics/graphicstest/uibench/s60/src/openvgengine.cpp Fri Jun 15 03:10:57 2012 +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 +#include + + +_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(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; + }