--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/uiacceltk/hitchcock/Client/src/alfdrawer.cpp Wed Nov 03 19:29:22 2010 +0200
@@ -0,0 +1,569 @@
+/*
+* Copyright (c) 2010 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: CAlfDrawer implementation.
+*
+*/
+
+
+
+
+#include <alf/alfdrawer.h>
+#include <alf/alfdirectclient.h>
+#include "alfcrppluginclient.h"
+#include "alflogger.h"
+#include "alfdrawerinternal.h"
+
+#include <coemain.h>
+#include <w32std.h>
+#include <fbs.h>
+
+// Class to hold internal alf drawer data.
+NONSHARABLE_CLASS( CAlfDrawer::TAlfDrawerData )
+ {
+public:
+ TAlfDrawerData();
+
+public:
+ CAlfCrpPluginClient* iClient;
+ };
+
+// Creates CAlfCrpPluginClient instance, returns error code.
+static TInt CreateAlfCrpClient(CAlfCrpPluginClient*& aClient);
+// Creates CAlfCrpPluginClient instance.
+static CAlfCrpPluginClient* CreateAlfCrpClientL();
+
+NONSHARABLE_CLASS( TAlfDrawerDirectClient ) : public MAlfDrawerScreenInterface
+ {
+public:
+ TAlfDrawerDirectClient( RAlfDirectClient& aClient );
+ TInt GetSizeAndRotation(TSize& aSize, TInt& aRotation);
+ TInt ReadPixels(CFbsBitmap* aBitmap);
+
+private:
+ RAlfDirectClient& iClient;
+ };
+
+/**
+ * Misc utility methods for CAlfDrawer.
+ */
+NONSHARABLE_CLASS(AlfDrawerUtils)
+ {
+public:
+
+ enum TRotation
+ {
+ ERotationNone,
+ ERotation90,
+ ERotation180,
+ ERotation270
+ };
+
+ /**
+ * Inverse rotate.
+ */
+ static void RotateBack(TInt aVirtualRotation, TRect& aRect, TSize aScreenSize)
+ {
+ if( aVirtualRotation == ERotation90 || aVirtualRotation == ERotation270 )
+ {
+ RotateRect( aVirtualRotation, aRect, aScreenSize, ETrue );
+ }
+ else if( aVirtualRotation == ERotation180 )
+ {
+ RotateRect( aVirtualRotation, aRect, aScreenSize, EFalse );
+ }
+ }
+
+ /**
+ * Rotate rect
+ */
+ static void RotateRect(TInt aDirection, TRect& aRect, TSize aScreenSize, TBool aMirror)
+ {
+ if (aMirror) aDirection = (aDirection+2)%4; // magic
+ for (;aDirection > 0; aDirection--)
+ {
+ TSize rotatedSize(aRect.Size().iHeight, aRect.Size().iWidth);
+ aRect = TRect(TPoint(aRect.iTl.iY, aScreenSize.iWidth - aRect.iTl.iX - rotatedSize.iHeight ), rotatedSize);
+ aScreenSize = TSize(aScreenSize.iHeight, aScreenSize.iWidth);
+ }
+ }
+
+ /**
+ * Copies screen to bitmap using 'read pixels' operation.
+ */
+ static void DoCopyScreenToBitmapL(
+ CWsScreenDevice& aDevice,
+ CFbsBitmap* aBitmap,
+ const TRect& aRect );
+
+ /**
+ * Copies screen to bitmap using 'read pixels' operation.
+ */
+ static void DoCopyScreenToBitmap2L(
+ MAlfDrawerScreenInterface* aInterface,
+ CFbsBitmap* aBitmap,
+ const TRect& aRect );
+
+ };
+
+// ---------------------------------------------------------------------------
+// NewL
+// ---------------------------------------------------------------------------
+//
+EXPORT_C CAlfDrawer* CAlfDrawer::NewL()
+ {
+ CAlfDrawer* self = new (ELeave) CAlfDrawer;
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+// ---------------------------------------------------------------------------
+// Destructor
+// ---------------------------------------------------------------------------
+//
+EXPORT_C CAlfDrawer::~CAlfDrawer()
+ {
+ if ( iData )
+ {
+ delete iData->iClient;
+ delete iData;
+ }
+ }
+
+// ---------------------------------------------------------------------------
+// Finish
+// ---------------------------------------------------------------------------
+//
+EXPORT_C TInt CAlfDrawer::Finish()
+ {
+ // First perform RWsSession finish operation to ensure
+ // that all drawing commands have been issued to renderstage.
+ TInt err = CCoeEnv::Static()->WsSession().Finish();
+
+ // Then create CRP instance (if needed).
+ if ( err == KErrNone && !iData->iClient )
+ {
+ err = CreateAlfCrpClient( iData->iClient );
+ }
+
+ // Finally, wait until alf side has finished rendering.
+ if ( err == KErrNone && iData->iClient )
+ {
+ iData->iClient->Synchronize();
+ }
+
+ return err;
+ }
+
+// ---------------------------------------------------------------------------
+// FallbackCopyScreenToBitmap
+// ---------------------------------------------------------------------------
+//
+EXPORT_C TInt CAlfDrawer::FallbackCopyScreenToBitmap(
+ CWsScreenDevice& aDevice,
+ CFbsBitmap* aBitmap,
+ const TRect& aRect)
+ {
+ TRAPD(err, AlfDrawerUtils::DoCopyScreenToBitmapL(aDevice, aBitmap, aRect));
+ return err;
+ }
+
+// ---------------------------------------------------------------------------
+// DoCopyScreenToBitmapL
+// ---------------------------------------------------------------------------
+//
+void AlfDrawerUtils::DoCopyScreenToBitmapL(
+ CWsScreenDevice& aDevice,
+ CFbsBitmap* aBitmap,
+ const TRect& aRect )
+ {
+ if (aDevice.GetScreenNumber() != 0) // only screen 0 supported for now
+ {
+ User::Leave(KErrNotSupported);
+ }
+
+ if ( !aBitmap ||
+ !aBitmap->Handle() ||
+ aBitmap->IsCompressedInRAM() ||
+ aBitmap->ExtendedBitmapType() != KNullUid )
+ {
+ User::Leave(KErrArgument);
+ }
+
+ __ALFLOGSTRING("DoCopyScreenToBitmapL begin");
+
+ RAlfDirectClient client;
+ CleanupClosePushL(client);
+
+ TAlfDrawerDirectClient clientWrapper(client);
+ DoCopyScreenToBitmap2L(&clientWrapper, aBitmap, aRect);
+
+ CleanupStack::PopAndDestroy(); // CleanupClosePushL
+
+ __ALFLOGSTRING("DoCopyScreenToBitmapL - Done");
+ }
+
+// ---------------------------------------------------------------------------
+// DoCopyScreenToBitmapL
+// ---------------------------------------------------------------------------
+//
+void AlfDrawerUtils::DoCopyScreenToBitmap2L(
+ MAlfDrawerScreenInterface* aInterface,
+ CFbsBitmap* aBitmap,
+ const TRect& aRect )
+ {
+ // Get size & virtual rotation from ALF side.
+ // GetSizeAndRotation will also create session to server.
+
+ TInt rotation = 0;
+ TSize size;
+ User::LeaveIfError(aInterface->GetSizeAndRotation(size, rotation));
+
+ // Calculate device size in pixels (same as aDevice.SizeInPixels())
+ TSize deviceSize = size;
+ if (rotation == AlfDrawerUtils::ERotation90 ||
+ rotation == AlfDrawerUtils::ERotation270 )
+ {
+ deviceSize.iWidth = size.iHeight;
+ deviceSize.iHeight = size.iWidth;
+ }
+
+ // Clip aRect to screen boundaries
+ TRect actualRect(deviceSize);
+ actualRect.Intersection(aRect);
+
+ __ALFLOGSTRING2("DoCopyScreenToBitmapL - requested rect origin %d x %d", actualRect.iTl.iX, actualRect.iTl.iY ) ;
+ __ALFLOGSTRING2("DoCopyScreenToBitmapL - requested rect %d x %d", actualRect.Size().iWidth, actualRect.Size().iHeight ) ;
+ __ALFLOGSTRING2("DoCopyScreenToBitmapL - bitmap rect %d x %d", aBitmap->SizeInPixels().iWidth, aBitmap->SizeInPixels().iHeight );
+ __ALFLOGSTRING1("DoCopyScreenToBitmapL - bitmap mode %d", aBitmap->DisplayMode() );
+
+ if ( TRect( aBitmap->SizeInPixels() ).IsEmpty() ||
+ actualRect.IsEmpty() )
+ {
+ __ALFLOGSTRING("DoCopyScreenToBitmapL - empty rect or zero bitmap size");
+ return;
+ }
+
+ // Select display mode.
+
+ TDisplayMode surfaceDisplayMode = EColor64K;
+ TDisplayMode bitmapDisplayMode = aBitmap->DisplayMode();
+ if ( bitmapDisplayMode == EColor16MU ||
+ bitmapDisplayMode == EColor16MA ||
+ bitmapDisplayMode == EColor16MAP )
+ {
+ surfaceDisplayMode = bitmapDisplayMode;
+ }
+
+ __ALFLOGSTRING3("DoCopyScreenToBitmapL - surface size %d x %d, mode %d",
+ size.iWidth, size.iHeight, surfaceDisplayMode ) ;
+
+ // Read pixels to temporary bitmap
+ CFbsBitmap* surfaceBitmap = new (ELeave) CFbsBitmap;
+ CleanupStack::PushL( surfaceBitmap );
+ User::LeaveIfError( surfaceBitmap->Create( size, surfaceDisplayMode ) );
+
+ TInt err = aInterface->ReadPixels( surfaceBitmap );
+ __ALFLOGSTRING1("DoCopyScreenToBitmapL - ReadPixels returned %d", err);
+ User::LeaveIfError( err );
+
+ // Copy data
+ TInt surfaceStride = CFbsBitmap::ScanLineLength(size.iWidth, surfaceDisplayMode);
+ __ALFLOGSTRING2("DoCopyScreenToBitmapL - DisplayMode %d, Stride %d", surfaceDisplayMode, surfaceStride);
+
+ TDisplayMode displayMode = surfaceDisplayMode;
+
+ TInt8 bytesPerPixel = 2;
+ switch( displayMode )
+ {
+ case EColor64K:
+ {
+ bytesPerPixel = 2;
+ break;
+ }
+ case EColor16MU:
+ case EColor16MA:
+ case EColor16MAP:
+ {
+ bytesPerPixel = 4;
+ break;
+ }
+
+ default:
+ {
+ __ALFLOGSTRING1("DoCopyScreenToBitmapL - display mode not supported %d", displayMode);
+ User::Leave( KErrNotSupported );
+ }
+ }
+
+ // actualRect (/aRect) must be converted to correct coordinate system.
+ TRect surfaceRect(actualRect);
+ AlfDrawerUtils::RotateBack(rotation, surfaceRect, deviceSize);
+ surfaceRect.Intersection(TRect(size));
+
+ __ALFLOGSTRING2("DoCopyScreenToBitmapL - surface rect tl %d x %d", surfaceRect.iTl.iX, surfaceRect.iTl.iY ) ;
+ __ALFLOGSTRING2("DoCopyScreenToBitmapL - surface rect size %d x %d", surfaceRect.Size().iWidth, surfaceRect.Size().iHeight ) ;
+
+ CFbsBitmap* bitmap = NULL;
+ TBool needTempBitmap = ETrue;
+
+ if( aBitmap->DisplayMode() == displayMode && actualRect == aRect && aBitmap->SizeInPixels() == aRect.Size() )
+ {
+ // Copy data direcly to given bitmap
+ bitmap = aBitmap;
+ needTempBitmap = EFalse;
+ }
+ else
+ {
+ // Create temporary bitmap which maches the sufrace's pixel format and source rect size
+ bitmap = new (ELeave) CFbsBitmap;
+ CleanupStack::PushL( bitmap );
+ TInt err = bitmap->Create( actualRect.Size(), displayMode );
+ __ALFLOGSTRING1("DoCopyScreenToBitmapL - Create returned %d", err );
+ User::LeaveIfError( err );
+ __ALFLOGSTRING("DoCopyScreenToBitmapL - display mode or size don't mach -> using temp bitmap" );
+ }
+
+ surfaceBitmap->BeginDataAccess();
+ bitmap->BeginDataAccess();
+
+ TUint8* surfacePtr = (TUint8*)surfaceBitmap->DataAddress() + surfaceStride * surfaceRect.iTl.iY;
+
+ TUint8* bitmapPtr = (TUint8*)bitmap->DataAddress();
+ TInt rowBegin = surfaceRect.iTl.iX * bytesPerPixel;
+ TInt captureBitmapWidth = surfaceRect.Width() * bytesPerPixel;
+
+ const TSize bitmapSize = bitmap->SizeInPixels();
+
+ // Initialize with direct copy case parameters
+ TInt bitmapPtrColumnDelta = bytesPerPixel;
+ TInt bitmapPtrRowDelta = bitmap->DataStride();
+
+ const TSize surfaceRectSize(surfaceRect.Size());
+ if ( rotation == AlfDrawerUtils::ERotationNone )
+ {
+ __ALFLOGSTRING("DoCopyScreenToBitmapL - direct copy") ;
+
+ // Direct copy case
+ for ( TInt row = surfaceRectSize.iHeight - 1 ; row >= 0 ; --row )
+ {
+ // Copy only the desired part of the bitmap
+ memcpy( bitmapPtr,
+ surfacePtr + rowBegin,
+ captureBitmapWidth );
+ surfacePtr += surfaceStride;
+ bitmapPtr += bitmap->DataStride();
+ }
+ }
+ else
+ {
+ // Handle rotation cases
+ //
+ // 0 degree case
+ // A B C
+ // 1 2 3
+ // 90 degrees anti-clockwise
+ // C 3
+ // B 2
+ // A 1
+ // 180 degrees anti-clockwise
+ // 3 2 1
+ // C B A
+ // 270 degrees anti-clockwise
+ // 1 A
+ // 2 B
+ // 3 C
+ //
+ switch (rotation)
+ {
+ case AlfDrawerUtils::ERotation90:
+ bitmapPtrColumnDelta = -bitmap->DataStride();
+ bitmapPtrRowDelta = bytesPerPixel;
+ bitmapPtr += ( bitmapSize.iHeight - 1 ) * bitmap->DataStride();
+ break;
+ case AlfDrawerUtils::ERotation180:
+ bitmapPtrColumnDelta = -bytesPerPixel;
+ bitmapPtrRowDelta = -bitmap->DataStride();
+ bitmapPtr += ( bitmapSize.iHeight - 1 ) * bitmap->DataStride() + ( bitmapSize.iWidth - 1 ) * bytesPerPixel;
+ break;
+ case AlfDrawerUtils::ERotation270:
+ bitmapPtrColumnDelta = bitmap->DataStride();
+ bitmapPtrRowDelta = -bytesPerPixel;
+ bitmapPtr += ( bitmapSize.iWidth - 1 ) * bytesPerPixel;
+ break;
+ default:
+ break;
+ }
+
+ // We go through surface row by row, column by column and
+ // copy pixel data to appropriate place to bitmap
+ if ( bytesPerPixel == 4 )
+ {
+ __ALFLOGSTRING("DoCopyScreenToBitmapL - four bytes per pixel, rotated copy") ;
+
+ for ( TInt row = surfaceRectSize.iHeight - 1 ; row >= 0 ; --row )
+ {
+ TUint8* rowBitmapPtr = bitmapPtr;
+ TUint8* rowSurfacePtr = surfacePtr + rowBegin;
+ for ( TInt column = surfaceRectSize.iWidth - 1 ; column >= 0 ; --column )
+ {
+ *((TUint32*)rowBitmapPtr) = *((TUint32*)rowSurfacePtr);
+
+ rowBitmapPtr += bitmapPtrColumnDelta;
+ rowSurfacePtr += bytesPerPixel;
+ }
+
+ surfacePtr += surfaceStride;
+ bitmapPtr += bitmapPtrRowDelta;
+ }
+ }
+ else
+ {
+ // Now bytesPerPixel == 2
+ __ALFLOGSTRING("DoCopyScreenToBitmapL - two bytes per pixel, rotated copy") ;
+ for ( TInt row = surfaceRectSize.iHeight - 1 ; row >= 0 ; --row )
+ {
+ TUint8* rowBitmapPtr = bitmapPtr;
+ TUint8* rowSurfacePtr = surfacePtr + rowBegin;
+ for ( TInt column = surfaceRectSize.iWidth - 1 ; column >= 0 ; --column )
+ {
+ *((TUint16*)rowBitmapPtr) = *((TUint16*)rowSurfacePtr);
+
+ rowBitmapPtr += bitmapPtrColumnDelta;
+ rowSurfacePtr += bytesPerPixel;
+ }
+
+ surfacePtr += surfaceStride;
+ bitmapPtr += bitmapPtrRowDelta;
+ }
+ }
+ }
+ __ALFLOGSTRING("DoCopyScreenToBitmapL - copy finished" );
+ surfaceBitmap->EndDataAccess(ETrue);
+ bitmap->EndDataAccess();
+
+ if( !needTempBitmap )
+ {
+ bitmap = NULL;
+ }
+ else // bitblit the temporary bitmap to given bitmap
+ {
+ CFbsBitmapDevice* tempBitmapDevice = CFbsBitmapDevice::NewL( aBitmap );
+ CleanupStack::PushL( tempBitmapDevice );
+ CFbsBitGc* tempBitmapGc = NULL;
+ User::LeaveIfError( tempBitmapDevice->CreateContext( tempBitmapGc ) );
+ CleanupStack::PushL( tempBitmapGc );
+
+ tempBitmapGc->SetDrawMode( CGraphicsContext::EDrawModeWriteAlpha );
+ tempBitmapGc->BitBlt( TPoint(), bitmap );
+
+ CleanupStack::PopAndDestroy( tempBitmapGc );
+ CleanupStack::PopAndDestroy( tempBitmapDevice );
+ CleanupStack::PopAndDestroy( bitmap );
+ }
+
+ CleanupStack::PopAndDestroy( surfaceBitmap );
+ }
+
+// ---------------------------------------------------------------------------
+// Constructor
+// ---------------------------------------------------------------------------
+//
+CAlfDrawer::CAlfDrawer()
+ {
+ }
+
+// ---------------------------------------------------------------------------
+// ConstructL
+// ---------------------------------------------------------------------------
+//
+void CAlfDrawer::ConstructL()
+ {
+ iData = new (ELeave) TAlfDrawerData;
+ CreateAlfCrpClient( iData->iClient );
+ }
+
+// ---------------------------------------------------------------------------
+// Constructor
+// ---------------------------------------------------------------------------
+//
+CAlfDrawer::TAlfDrawerData::TAlfDrawerData()
+ : iClient( NULL )
+ {
+ }
+
+// ---------------------------------------------------------------------------
+// CopyScreenToBitmap
+// ---------------------------------------------------------------------------
+//
+EXPORT_C TInt AlfDrawerInternal::CopyScreenToBitmap(
+ MAlfDrawerScreenInterface* aInterface,
+ CFbsBitmap* aBitmap,
+ const TRect& aRect )
+ {
+ TRAPD(err, AlfDrawerUtils::DoCopyScreenToBitmap2L(aInterface, aBitmap, aRect));
+ return err;
+ }
+
+// ---------------------------------------------------------------------------
+// CreateAlfCrpClient
+// ---------------------------------------------------------------------------
+//
+static TInt CreateAlfCrpClient(CAlfCrpPluginClient*& aClient)
+ {
+ TRAPD(err, aClient = CreateAlfCrpClientL());
+ return err;
+ }
+
+// ---------------------------------------------------------------------------
+// CreateAlfCrpClientL
+// ---------------------------------------------------------------------------
+//
+static CAlfCrpPluginClient* CreateAlfCrpClientL()
+ {
+ CAlfCrpPluginClient* client = new (ELeave) CAlfCrpPluginClient;
+ CleanupStack::PushL( client );
+ client->ConstructL();
+ CleanupStack::Pop( client );
+ return client;
+ }
+
+// ---------------------------------------------------------------------------
+// TAlfDrawerDirectClient
+// ---------------------------------------------------------------------------
+//
+TAlfDrawerDirectClient::TAlfDrawerDirectClient( RAlfDirectClient& aClient )
+ : iClient( aClient )
+ {
+ }
+
+// ---------------------------------------------------------------------------
+// GetSizeAndRotation
+// ---------------------------------------------------------------------------
+//
+TInt TAlfDrawerDirectClient::GetSizeAndRotation(TSize& aSize, TInt& aRotation)
+ {
+ return iClient.GetSizeAndRotation(aSize, aRotation);
+ }
+
+// ---------------------------------------------------------------------------
+// ReadPixels
+// ---------------------------------------------------------------------------
+//
+TInt TAlfDrawerDirectClient::ReadPixels(CFbsBitmap* aBitmap)
+ {
+ return iClient.ReadPixels(aBitmap->Handle());
+ }
+