uiacceltk/hitchcock/Client/src/alfdrawer.cpp
changeset 64 9f8c0686fb49
--- /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());
+    }
+