diff -r e1e28b0273b0 -r 93fff7023be8 AppSrc/TextureLoader.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/AppSrc/TextureLoader.cpp Fri Oct 15 10:18:29 2010 +0900 @@ -0,0 +1,789 @@ +/* +* 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: Juha Kauppinen, Mika Hokkanen +* +* Description: Photo Browser +* +*/ + +// INCLUDE FILES +#include "TextureLoader.h" +#include +#include "ImagicContainerBrowser.h" +#include "ImagicViewBrowser.h" +#include + +// INCLUDES +#include +#include +#include "ImagicAppUi.h" + +/*----------------------------------------------------------------------*/ +// Constructor and destructor +// +CTextureLoader::CTextureLoader(CImagicAppUi* aImagicAppUi, CImagicContainerBrowser* aContainer, CImagicViewBrowser* aView, + RCriticalSection* aDrawLock) : + //CActive(CActive::EPriorityStandard), + CActive(CActive::EPriorityLow), + //CActive(CActive::EPriorityStandard), + //CActive(CActive::EPriorityUserInput), + //CActive(CActive::EPriorityHigh), + iImagicAppUi(aImagicAppUi), + iContainer(aContainer), + iView(aView), + iDrawLock(aDrawLock), + iData(NULL) + + { + DP0_IMAGIC(_L("CTextureLoader::CTextureLoader++")); + + // Add loader to active scheduler + CActiveScheduler::Add(this); + + DP0_IMAGIC(_L("CTextureLoader::CTextureLoader--")); + } + +void CTextureLoader::ConstructL() + { + DP0_IMAGIC(_L("CTextureLoader::ConstructL++")); + + // Create small default bitmap + iBitmap = new (ELeave) CFbsBitmap(); + iSmileBitmap = new (ELeave) CFbsBitmap(); + iZoomBitmap = new (ELeave) CFbsBitmap(); +#ifdef USE_RGBA + iBitmap->Create(TSize(10, 10), EColor16MU); +#else + iBitmap->Create(TSize(10, 10), EColor16M); +#endif + + // Create bitmap scaler + iBitmapScaler = CBitmapScaler::NewL(); + iBitmapScaler->UseLowMemoryAlgorithm(ETrue); + + iRGB2BGRDone = EFalse; + +#ifdef ICONS_ENABLAD + LoadIcons(); +#endif + + DP0_IMAGIC(_L("CTextureLoader::ConstructL--")); + } + +CTextureLoader::~CTextureLoader() + { + DP0_IMAGIC(_L("CTextureLoader::~CTextureLoader++")); + + // Cancel ongoing process + Cancel(); + + // Free memory + delete iBitmapScaler; + delete iBitmap; + delete iSmileBitmap; + delete iZoomBitmap; + + iBitmapArray.Close(); + + DP0_IMAGIC(_L("CTextureLoader::~CTextureLoader--")); + } + +void CTextureLoader::GetPngL(TFileName& afilepath, CFbsBitmap* aBitmap) + { + DP0_IMAGIC(_L("CTextureLoader::GetPngL++")); + + CImageDecoder* idecoder = CImageDecoder::FileNewL(CEikonEnv::Static()->FsSession(), + afilepath, _L8("image/png")/*, CImageDecoder::EOptionAlwaysThread*/); + + TFrameInfo iFrameInfo = idecoder->FrameInfo(0); + aBitmap->Create(iFrameInfo.iOverallSizeInPixels, EColor16MA ); + + TRequestStatus aStatus = KRequestPending; + + TRAPD(err1, idecoder->Convert( &aStatus, *aBitmap, 0 )); + if(err1 == KErrNone) + User::WaitForRequest( aStatus ); + + delete idecoder; + + DP0_IMAGIC(_L("CTextureLoader::GetPngL--")); + } + + +void CTextureLoader::LoadIcons() + { + TInt err = KErrNone; + + TFileName filename; + filename = KSmileFileName; + TRAP(err, GetPngL(filename, iSmileBitmap)); + if(err == KErrNone) + iBitmapArray.Append(iSmileBitmap); + + err = KErrNone; + + filename = KZoomFileName; + TRAP(err, GetPngL(filename, iZoomBitmap)); + if(err == KErrNone) + iBitmapArray.Append(iZoomBitmap); + + + } + + +/*----------------------------------------------------------------------*/ +// Returns loader loading status +// +TBool CTextureLoader::IsActiveAndRunning() + { + // Make sure that loader is not active + if (IsRunning()) + return ETrue; + else + return EFalse; + } + + +/*----------------------------------------------------------------------*/ +// Loads picture and stores the OpenGL index into specified variable +// +void CTextureLoader::LoadL(CImageData* aData, TThumbSize aResolution) + { + DP1_IMAGIC(_L("CTextureLoader::LoadL++ - resolution: %d"), aResolution); + + // Make sure that loader is not active + if (IsRunning()) + { + DP0_IMAGIC(_L("CTextureLoader::LoadL - already running, KErrInUse")); + User::Leave(KErrInUse); + } + // Check that image is not already loaded + else if (aData->iGridData.iGlSuperHQTextIndex && aResolution == EFullSize) + { + DP0_IMAGIC(_L("CTextureLoader::LoadL - EFullRes KErrAlreadyExists")); + iData = NULL; + User::Leave(KErrAlreadyExists); + } + else if (aData->iGridData.iGlHQ512TextIndex && aResolution == ESize512x512) + { + DP0_IMAGIC(_L("CTextureLoader::LoadL - ESize512x512 KErrAlreadyExists")); + iData = NULL; + User::Leave(KErrAlreadyExists); + } + else if (aData->iGridData.iGlLQ128TextIndex && aResolution == ESize128x128) + { + DP0_IMAGIC(_L("CTextureLoader::LoadL - ESize128x128 KErrAlreadyExists")); + iData = NULL; + User::Leave(KErrAlreadyExists); + } + else if (aData->iGridData.iGlLQ32TextIndex && aResolution == ESize32x32) + { + DP0_IMAGIC(_L("CTextureLoader::LoadL - ESize32x32 KErrAlreadyExists")); + iData = NULL; + User::Leave(KErrAlreadyExists); + } + + iContainer->DynamicUnLoading(); + + // Store image data + iData = aData; + iResolution = aResolution; + iHighQuality = EFalse; + if(aResolution == EFullSize || aResolution == ESize512x512) + { + iHighQuality = ETrue; + //iContainer->DynamicUnLoading(); + } + + // Call engine to load picture + TRAPD(err, iView->LoadBitmapsToBrowserL(iData, aResolution)); + if (err != KErrNone) + { + //if (err == KErrNotFound || err == KErrPathNotFound) + iData->SetImageReady(aResolution, EFalse); + iData = NULL; + User::Leave(err); + } + + DP0_IMAGIC(_L("CTextureLoader::LoadL--")); + } + +/*----------------------------------------------------------------------*/ +// Releases 512x512 and Max resolution textures +// +void CTextureLoader::ReleaseSuperHResTexture(CImageData* aGridData) + { + DP0_IMAGIC(_L("CTextureLoader::ReleaseHResTextures++")); + + if(aGridData->iGridData.iGlSuperHQTextIndex != 0) + { + glDeleteTextures(1, &(aGridData->iGridData.iGlSuperHQTextIndex)); + aGridData->iGridData.iGlSuperHQTextIndex=0; + DP0_IMAGIC(_L("CTextureLoader::ReleaseHResTextures - glSuperHQTextIndex released")); + } + + DP0_IMAGIC(_L("CTextureLoader::ReleaseHResTextures--")); + } + +/*----------------------------------------------------------------------*/ +// Unloads picture from specified index +// +void CTextureLoader::ReleaseHQ512Textures() + { + DP0_IMAGIC(_L("CTextureLoader::ReleaseQ512Textures++")); + + TInt mem = 0; + TInt ret = HAL::Get(HALData::EMemoryRAMFree, mem); + DP1_IMAGIC(_L("CTextureLoader::ReleaseQ512Textures - Free RAM: %d"), mem); + + for(TInt i=0; iiIEngine->GetTotalNumOfImages(); i++) + { + if(i >= iContainer->GetCurrentIndex() + CImagicContainerBrowser::K512TNImageBuffer || + i <= iContainer->GetCurrentIndex() - CImagicContainerBrowser::K512TNImageBuffer) + { + CImageData* imageData = iImagicAppUi->GetEngine()->GetImageData(i); + + if(imageData->iGridData.iGlSuperHQTextIndex!=0) + { + glDeleteTextures(1, &(imageData->iGridData.iGlSuperHQTextIndex)); + imageData->iGridData.iGlSuperHQTextIndex=0; + } + + if(i != iContainer->GetCurrentIndex()) + { + if (imageData->iGridData.iGlHQ512TextIndex!=0) + { + glDeleteTextures(1, &(imageData->iGridData.iGlHQ512TextIndex)); + imageData->iGridData.iGlHQ512TextIndex=0; + } + } + } + } + + ret = HAL::Get(HALData::EMemoryRAMFree, mem); + DP1_IMAGIC(_L("CTextureLoader::ReleaseQ512Textures - Free RAM: %d"), mem); + + DP0_IMAGIC(_L("CTextureLoader::ReleaseQ512Textures--")); + } + + +/*----------------------------------------------------------------------*/ +// Unloads picture from specified index +// +void CTextureLoader::UnloadLQ512Tex(CImageData* aData) const + { + DP0_IMAGIC(_L("CTextureLoader::UnloadLQ512Tex++")); + + /*TInt mem = 0; + TInt ret = HAL::Get(HALData::EMemoryRAMFree, mem); + DP1_IMAGIC(_L("CTextureLoader::UnloadLQ512Tex - Free RAM: %d"), mem);*/ + + // Delete the picture + if (aData->iGridData.iGlHQ512TextIndex!=0) + { + glDeleteTextures(1, &(aData->iGridData.iGlHQ512TextIndex)); + aData->iGridData.iGlHQ512TextIndex=0; + } + + /*ret = HAL::Get(HALData::EMemoryRAMFree, mem); + DP1_IMAGIC(_L("CTextureLoader::UnloadLQ512Tex - Free RAM: %d"), mem);*/ + + DP0_IMAGIC(_L("CTextureLoader::UnloadLQ512Tex--")); + } + +/*----------------------------------------------------------------------*/ +// Unloads picture from specified index +// +void CTextureLoader::UnloadLQ128Tex(CImageData* aData) const + { + DP0_IMAGIC(_L("CTextureLoader::UnloadLQ128Tex++")); + + // Delete the picture + if (aData->iGridData.iGlLQ128TextIndex!=0) + { + glDeleteTextures(1, &(aData->iGridData.iGlLQ128TextIndex)); + aData->iGridData.iGlLQ128TextIndex=0; + } + + DP0_IMAGIC(_L("CTextureLoader::UnloadLQ128Tex--")); + } + +/*----------------------------------------------------------------------*/ +// Unloads picture from specified index +// +void CTextureLoader::UnloadLQ32Tex(CImageData* aData) const + { + DP0_IMAGIC(_L("CTextureLoader::UnloadLQ32Tex++")); + + if (aData->iGridData.iGlLQ32TextIndex!=0) + { + glDeleteTextures(1, &(aData->iGridData.iGlLQ32TextIndex)); + aData->iGridData.iGlLQ32TextIndex=0; + } + + DP0_IMAGIC(_L("CTextureLoader::UnloadLQ32Tex--")); + } + + +/*----------------------------------------------------------------------*/ +// Image is loaded by engine, iScale it for OpenGL if needed +// +void CTextureLoader::ImageLoadedL(TInt aError, CFbsBitmap* aBitmap, TInt aGLMaxRes) + { + DP0_IMAGIC(_L("CTextureLoader::ImageLoadedL++")); + + if(aError == KErrNotFound || aError == KErrPathNotFound) + { + DP0_IMAGIC(_L("CTextureLoader::ImageLoadedL - Error: KErrNotFound/KErrPathNotFound")); + iData->SetImageReady(iResolution, EFalse); + iData = NULL; + return; + } + else if(aError == KErrCorrupt) + { + DP0_IMAGIC(_L("CTextureLoader::ImageLoadedL - Error: KErrCorrupt")); + iData->SetImageReady(iResolution, EFalse); + iData->iGridData.iCorrupted = ETrue; + iData = NULL; + return; + } + else if(aError == KErrCancel) + { + //Image loading is cancelled only for superzoom iage loading + DP1_IMAGIC(_L("CTextureLoader::ImageLoadedL - Error: %d"), aError); + //iData->SetImageReady(iResolution, EFalse); + iData = NULL; + return; + } + else if(aError != KErrNone) + { + DP1_IMAGIC(_L("CTextureLoader::ImageLoadedL - Error: %d"), aError); + iData->SetImageReady(iResolution, EFalse); + iData = NULL; + return; + } + + // Set image ready to database + //iData->SetImageReady(iResolution, ETrue); + + iGLMaxRes = aGLMaxRes; + iImageSize = aBitmap->SizeInPixels(); + + //Check loaded image real size and check if scaling is needed + iScalingNeeded = IsScalingNeeded(iImageSize); + + TSize size; + // Check does image need to be scaled + if(!iScalingNeeded) + { //Image is already proper size, just create texture + CreateThumbnailTexture(aBitmap); + } + //Calculate new image size if scaling is needed(in case size is not pow^2) + else + { + size.iWidth = ScaleDown( iImageSize.iWidth ); + size.iHeight = ScaleDown( iImageSize.iHeight ); + + // Setup target bitmap to be large enough + iBitmap->Reset(); +#ifdef USE_RGBA + iBitmap->Create(size, EColor16MU); +#else + iBitmap->Create(size, EColor16M); +#endif + + // Setup image quality + CBitmapScaler::TQualityAlgorithm quality = CBitmapScaler::EMinimumQuality; + /*if(iHighQuality)*/ + quality=CBitmapScaler::EMaximumQuality; + + iBitmapScaler->SetQualityAlgorithm(quality); + + // Start scaling the bitmap, RunL will be called when complete + iBitmapScaler->Scale(&iStatus, *aBitmap, *iBitmap, EFalse); + if(!IsActive()) + SetActive(); + } + + DP0_IMAGIC(_L("CTextureLoader::ImageLoadedL--")); + } + +/*----------------------------------------------------------------------*/ +// Creates OpenGL texture of given bitmap +// +TInt CTextureLoader::CreateTexture(CFbsBitmap* aBitmap, TBool aHighQuality) + { + DP0_IMAGIC(_L("CTextureLoader::CreateTexture++")); + + // Get image data size + TInt width = aBitmap->SizeInPixels().iWidth; + TInt height = aBitmap->SizeInPixels().iHeight; + TInt dataSize = width * height; + + // Lock bitmap before modifying its data + aBitmap->LockHeap( EFalse ); + + // The data in the texture are in RGBA order but is read in BGRA order. + // So we have to swap the 1st and 3rd bytes. + TUint8* data = (TUint8 *)aBitmap->DataAddress(); + +#ifdef USE_RGBA + dataSize*=4; + for (TInt i=0; iUnlockHeap( EFalse ); + + return index; + } + +void CTextureLoader::CreateThumbnailTexture(CFbsBitmap* aBitmap) + { + DP0_IMAGIC(_L("CTextureLoader::CreateThumbnailTexture++")); + + TInt index = CreateTexture(aBitmap, iHighQuality); + iContainer->SetTextIndex(index); + + //Image has been loaded, store index + if(iResolution == ESize512x512) + { + //Check that we really have high resolution image + if((aBitmap->SizeInPixels().iHeight == 512 && aBitmap->SizeInPixels().iWidth == 1024) || + (aBitmap->SizeInPixels().iHeight == 1024 && aBitmap->SizeInPixels().iWidth == 512) || + (aBitmap->SizeInPixels().iHeight == 512 && aBitmap->SizeInPixels().iWidth == 512)) + { + iData->iGridData.iGlHQ512TextIndex = index; + } + else + {//if no high resolution image, delete existing texture from 128x128 slot and bind newly created texture there + if(aBitmap->SizeInPixels().iHeight == 128) + { + if(iData->iGridData.iGlLQ128TextIndex != 0) + glDeleteTextures(1, &(iData->iGridData.iGlLQ128TextIndex)); + iData->iGridData.iGlLQ128TextIndex = index; + } + if(aBitmap->SizeInPixels().iHeight == 32) + { + if(iData->iGridData.iGlLQ32TextIndex != 0) + glDeleteTextures(1, &(iData->iGridData.iGlLQ32TextIndex)); + iData->iGridData.iGlLQ32TextIndex = index; + } + } + iPreviousData = iData; + } + else if(iResolution == ESize128x128) + { + //Check if we had exif tn already binded and delete it + if(iData->iGridData.iGlLQ128TextIndex != 0) + { + glDeleteTextures(1, &(iData->iGridData.iGlLQ128TextIndex)); + } + iData->iGridData.iGlLQ128TextIndex = index; + } + else if(iResolution == ESize32x32) + { + //Check if we had exif tn already binded and delete it + if(iData->iGridData.iGlLQ32TextIndex != 0) + { + glDeleteTextures(1, &(iData->iGridData.iGlLQ32TextIndex)); + } + iData->iGridData.iGlLQ32TextIndex = index; + } +#ifdef SUPERZOOM + else if(iResolution == EFullSize) + { + iData->iGridData.iGlSuperHQTextIndex = index; + } +#endif + + //Order container to draw scaled image + /*if(iContainer->GetDrawMode() == EOneByOne) + { + //Check if loaded image is current one and draw it + CImageData* imageData = iImagicAppUi->GetEngineL()->GetImageData(iContainer->GetCurrentIndex(), iImagicAppUi->GetUIDrawMode()); + if(imageData->iGridData.iGlSuperHQTextIndex != 0) + iContainer->DrawNow(); + else if(imageData->iGridData.iGlHQ512TextIndex == iData->iGridData.iGlHQ512TextIndex ) + iContainer->DrawNow(); + else if(imageData->iGridData.iGlLQ128TextIndex == iData->iGridData.iGlLQ128TextIndex ) + iContainer->DrawNow(); + } + else*/ + { + iContainer->DrawNow(); + DP0_IMAGIC(_L("<----------- CTextureLoader DrawNow ----------->")); + } + + //Loader is finished + iData = NULL; + aBitmap->Reset(); + + //Set loader back on + //iContainer->SetLoadingOn(ETrue); + + DP0_IMAGIC(_L("CTextureLoader::CreateThumbnailTexture--")); + } + +/*----------------------------------------------------------------------*/ +// Active object's RunL +// +void CTextureLoader::RunL() + { + ASSERT(iBitmap); + CreateThumbnailTexture(iBitmap); + } + +/*----------------------------------------------------------------------*/ +// Active object's DoCancel +// +void CTextureLoader::DoCancel() + { + DP0_IMAGIC(_L("CTextureLoader::DoCancel++")); + + // Reset bitmap and cancel scaler + if (IsActive()) + { + iBitmap->Reset(); + iBitmapScaler->Cancel(); + } + + DP0_IMAGIC(_L("CTextureLoader::DoCancel--")); + } + +/*----------------------------------------------------------------------*/ +// Active object's RunError +// +void CTextureLoader::RunError() + { + // Nothing here + } + +/*----------------------------------------------------------------------*/ +// Scales given value to power of two +// +TInt CTextureLoader::ScaleDown(TInt aSize) + { + DP0_IMAGIC(_L("CTextureLoader::ScaleDown++")); + + if(iResolution == ESize32x32) + { + return 32; + } + else if(iResolution == ESize128x128 || iResolution == ESize512x512) + { + return 128; + } + + // Find new size for picture + TInt newSize; + for (newSize=1; newSize aSize) + newSize/=2; + + // Limit size to some maximum value + TInt maxSize=256; + TInt minSize = 32; + + + if(iHighQuality) // High quality pictures are lot bigger + { +/*#ifdef __WINS__ + maxSize=512; +#endif*/ + +#ifdef SUPERZOOM + //maxSize=iGLMaxRes; + if(iGLMaxRes >= 1024) + maxSize=1024; + else + maxSize=iGLMaxRes; + +#else + maxSize=512; +#endif + + } + // Check that size is below maximum and min size + if(newSize > maxSize) + newSize=maxSize; + if(newSize < minSize) + newSize=minSize; + + DP0_IMAGIC(_L("CTextureLoader::ScaleDown--")); + return newSize; + } + +/*----------------------------------------------------------------------*/ +// Creates OpenGL texture of given bitmap +// +void CTextureLoader::CreateIconTextures() + { + DP0_IMAGIC(_L("CTextureLoader::CreateIconTextures++")); + + for(TInt i=0; iSizeInPixels().iWidth; + TInt height = iBitmapArray[i]->SizeInPixels().iHeight; + TInt dataSize = width * height; + + // Lock bitmap before modifying its data + iBitmapArray[i]->LockHeap( EFalse ); + + // The data in the texture are in RGBA order but is read in BGRA order. + // So we have to swap the 1st and 3rd bytes. + TUint8* data = (TUint8 *)iBitmapArray[i]->DataAddress(); + + if(!iRGB2BGRDone) + { +//#ifdef USE_RGBA + dataSize*=4; + for (TInt i=0; iSetTextIndex(index); + + // Set texture parameters + //GL_NEAREST is faster than GL_LINEAR but quality is better in linear + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + + //#ifdef USE_RGBA + // Load texture into OpenGL memory + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data ); + /*#else + glTexImage2D( GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data ); + #endif*/ + + // Unlock bitmap + iBitmapArray[i]->UnlockHeap( EFalse ); + } + + iRGB2BGRDone = ETrue; + + iContainer->IconTexturesLoaded(iIconTextureIndexes); + + DP0_IMAGIC(_L("CTextureLoader::CreateIconTextures--")); + } + + +/*----------------------------------------------------------------------*/ +// Check if scaling is needed +// +TBool CTextureLoader::IsScalingNeeded(TSize aImageSize) + { +//Check loaded image real size and over write high quality flag + if((aImageSize.iHeight == 1024 && aImageSize.iWidth == 1024) || + (aImageSize.iHeight == 512 && aImageSize.iWidth == 1024) || + (aImageSize.iHeight == 1024 && aImageSize.iWidth == 512) || + (aImageSize.iHeight == 512 && aImageSize.iWidth == 512)) + { + // Set image ready to database, only if resolution was maching with Imagic TN size + iData->SetImageReady(ESize512x512, ETrue); + return EFalse; + } + if((aImageSize.iHeight == 128 && aImageSize.iWidth == 128)) + { + // Set image ready to database, only if resolution was maching with Imagic TN size + iData->SetImageReady(ESize128x128, ETrue); + return EFalse; + } + if((aImageSize.iHeight == 32 && aImageSize.iWidth == 32)) + { + // Set image ready to database, only if resolution was maching with Imagic TN size + iData->SetImageReady(ESize32x32, ETrue); + return EFalse; + } + + return ETrue; + }