javauis/lcdui_akn/lcdgd/src/lcdgdrvi.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Tue, 27 Apr 2010 16:30:29 +0300
branchRCL_3
changeset 19 04becd199f91
permissions -rw-r--r--
Revision: v2.1.22 Kit: 201017

/*
* Copyright (c) 2005 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 <graphicsaccelerator.h>
#include <ecom/ecom.h>
#include <ecom/implementationproxy.h>
#include <lcdgdrv.h>
#include "lcdgdrvif.h"
#include "lcdtransform.h"
#include "calctransform.h"
#include "collision.h"
#include "lcdgdev.h"

#ifdef _DEBUG
TBool DbgValidateImageType(const TImageType& aType);
TBool DbgValidateRendererArray(const TImageRenderer aRendererArray[], TInt aCount);
#endif

/**
 * Used in blitter/renderer searches
 */
inline TBool operator == (const TImageType& aLhs, const TImageType& aRhs)
{
    return (aLhs.iTransparency == aRhs.iTransparency) &&
           (aLhs.iAlphaMode == aRhs.iAlphaMode) &&
           (aLhs.iColorMode == aRhs.iColorMode);
}

inline void Swap(TInt& aX, TInt& aY)
{
    TInt tmp = aX;
    aX = aY;
    aY = tmp;
}

#define ASCIITEXT(x) (const TUint8*)x
#define UCS16TEXT(x) (const TText*)L##x

struct TLcdDriverType
{
    TDisplayMode    iMode;
    const TUint8*   iDataType;      // ASCII/UTF8
    const TText*    iLibName;       // UNICODE
    TInt            iInterfaceUid;
};
const TLcdDriverType LcdDriverTypeTab[] =
{
    { EColor64K,  ASCIITEXT(LCDGD_COLOR64K_DRIVER_ID_STR),  UCS16TEXT("LCDC64K"),  LCDGD_COLOR64K_IMPLEMENTATION_UID },
    { EColor4K,   ASCIITEXT(LCDGD_COLOR4K_DRIVER_ID_STR),   UCS16TEXT("LCDC4K"),   LCDGD_COLOR4K_IMPLEMENTATION_UID  },
    { EColor16MU, ASCIITEXT(LCDGD_COLOR16MU_DRIVER_ID_STR), UCS16TEXT("LCDC16MU"), LCDGD_COLOR16MU_IMPLEMENTATION_UID },
    { EColor16MA, ASCIITEXT(LCDGD_COLOR16MA_DRIVER_ID_STR), UCS16TEXT("LCDC16MA"), LCDGD_COLOR16MA_IMPLEMENTATION_UID }
};
const TInt KLcdDriverTypeTabSize = sizeof(LcdDriverTypeTab)/sizeof(LcdDriverTypeTab[0]);

// *****************************************************************
// Driver implementation ECOM interface.
//
// *****************************************************************
EXPORT_C CLcdGraphicsDriverImpl* CLcdGraphicsDriverImpl::NewL(TDisplayMode aDisplayMode)
{
    const TLcdDriverType* type = &LcdDriverTypeTab[0];
    const TLcdDriverType* end  = type + KLcdDriverTypeTabSize;
    while (type < end)
    {
        if (type->iMode == aDisplayMode)
        {
            break;
        }
        type++;
    }

    if (type == end)
    {
        User::Leave(KErrNotSupported);
    }

    TEComResolverParams resolverParams;

    TPtrC8 dataType(type->iDataType);
    resolverParams.SetDataType(dataType);

    TUid    interfaceUid  = KLcdDriverInterfaceUid;
    TUint32 dtorKeyOffset = _FOFF(CLcdGraphicsDriverImpl, iDtor_ID_Key);

    //
    // Try to load via ECOM
    //
    CLcdGraphicsDriverImpl* impl = NULL;
    impl = (CLcdGraphicsDriverImpl*)REComSession::CreateImplementationL(interfaceUid, dtorKeyOffset, resolverParams);

    return impl;
}

EXPORT_C CLcdGraphicsDriverImpl::CLcdGraphicsDriverImpl
(
    const TDriverInfo& aDriverInfo,
    const TImageRenderer* aRendererArray,
    TInt aRendererCount,
    const TColorMap* aColorMapArray,
    TInt aColorMapCount,
    const TCollisionDetector* aCollisionDetectorArray,
    TInt aCollisionDetectorCount,
    const TDrawFunctions* aDrawFunctionsArray,
    TInt aDrawFunctionsCount
)
        : iDriverInfo(aDriverInfo)
        , iRendererArray(aRendererArray)
        , iRendererCount(aRendererCount)
        , iColorMapArray(aColorMapArray)
        , iColorMapCount(aColorMapCount)
        , iCollisionDetectorArray(aCollisionDetectorArray)
        , iCollisionDetectorCount(aCollisionDetectorCount)
        , iDrawFunctionsArray(aDrawFunctionsArray)
        , iDrawFunctionsCount(aDrawFunctionsCount)
{
}

EXPORT_C CLcdGraphicsDriverImpl::~CLcdGraphicsDriverImpl()
{
    if (iDtor_ID_Key != KNullUid)
    {
        REComSession::DestroyedImplementation(iDtor_ID_Key);
    }
}

EXPORT_C void CLcdGraphicsDriverImpl::GetDriverInfo(CLcdGraphicsDriver::TDriverInfo& aDriverInfo) const
{
    aDriverInfo=iDriverInfo;
}

EXPORT_C TInt CLcdGraphicsDriverImpl::DrawRegion
(
    const TAcceleratedBitmapInfo* aDstColorBitmap,
    const TRect&                  aDstRect,
    const TAcceleratedBitmapInfo* aSrcColorBitmap,
    const TAcceleratedBitmapInfo* aSrcAlphaBitmap,
    TTransparency                 aSrcTransparency,
    const TRect&                  aSrcRect,
    TTransformType                aSrcTransform,
    const TRect&                  aClipRect
)
{
    ASSERT(aDstColorBitmap);
    ASSERT(aSrcColorBitmap);

    TInt err = KErrNotSupported;

    TImageType dstType;
    dstType.iColorMode = aDstColorBitmap->iDisplayMode;
    dstType.iAlphaMode = ENone;
    dstType.iTransparency = ETransparencyNone;

    TImageType srcType;
    srcType.iColorMode = aSrcColorBitmap->iDisplayMode;
    srcType.iAlphaMode = aSrcAlphaBitmap ? aSrcAlphaBitmap->iDisplayMode : ENone;
    srcType.iTransparency = aSrcTransparency;

    const TImageRenderer* renderer = GetRenderer(dstType, srcType, aSrcTransform, ECompositeSrcOver);
    if (renderer)
    {
        TImageRenderFunction drawRegion = renderer->iFunction;

        // calc source to target transform
        TLcdTransform transform = CalcTransform(aDstRect, aSrcRect, aSrcTransform);

        TRect dstRect(aDstRect);
        TRect srcRect(aSrcRect);
        TRect srcClipRect(aSrcColorBitmap->iSize);
        TRect dstClipRect(aDstColorBitmap->iSize);

        // clip cliprect to device rect
        dstClipRect.Intersection(aClipRect);

        // calculate source and target rects clipped to src and target bounds.
        ClipTransformRect(dstRect, srcRect, dstClipRect, srcClipRect, transform);

        // clip dst rect to cliprect shouldn't be necessary if
        // ClipTransformRect works
        dstRect.Intersection(dstClipRect);

        if (!dstRect.IsEmpty())
        {
            // calc target to source transform.
            transform = transform.Inverse();

            ASSERT(CheckBounds(aDstColorBitmap->iSize, aSrcColorBitmap->iSize, dstRect, transform));

            (*drawRegion)(aDstColorBitmap, NULL, dstRect, aSrcColorBitmap, aSrcAlphaBitmap, transform);
        }

        err = KErrNone;
    }

    return err;
}

EXPORT_C TInt CLcdGraphicsDriverImpl::CopyRegion
(
    const TAcceleratedBitmapInfo*   aDstColorBitmap,
    const TAcceleratedBitmapInfo*   aDstAlphaBitmap,
    TTransparency                   aDstTransparency,
    const TRect&                    aDstRect,
    const TAcceleratedBitmapInfo*   aSrcColorBitmap,
    const TAcceleratedBitmapInfo*   aSrcAlphaBitmap,
    TTransparency                   aSrcTransparency,
    const TRect&                    aSrcRect,
    TTransformType                  aSrcTransform,
    const TRect&                    aClipRect
)
{
    ASSERT(aDstColorBitmap);
    ASSERT(aSrcColorBitmap);

    TInt err = KErrNotSupported;
    TImageType dstType;
    TImageType srcType;

    dstType.iColorMode = aDstColorBitmap->iDisplayMode;
    dstType.iAlphaMode = aDstAlphaBitmap ? aDstAlphaBitmap->iDisplayMode : ENone;
    dstType.iTransparency = aDstTransparency;

    srcType.iColorMode = aSrcColorBitmap->iDisplayMode;
    srcType.iAlphaMode = aSrcAlphaBitmap ? aSrcAlphaBitmap->iDisplayMode : ENone;
    srcType.iTransparency = aSrcTransparency;

    const TImageRenderer* renderer = GetRenderer(dstType, srcType, aSrcTransform, ECompositeSrcCopy);
    if (renderer)
    {
        TImageRenderFunction copyRegion = renderer->iFunction;

        // calc source to target transform
        TLcdTransform transform = CalcTransform(aDstRect, aSrcRect, aSrcTransform);

        TRect dstRect(aDstRect);
        TRect srcRect(aSrcRect);
        TRect srcClipRect(aSrcColorBitmap->iSize);
        TRect dstClipRect(aDstColorBitmap->iSize);

        // clip cliprect to device rect
        dstClipRect.Intersection(aClipRect);

        // clip source and target rects
        ClipTransformRect(dstRect, srcRect, dstClipRect, srcClipRect, transform);

        // check src and dst rects still correspond
        ASSERT(CheckTransform(dstRect, srcRect, transform));

        // clip dst rect to cliprect shouldn't be necessary if
        // ClipTransformRect works
        dstRect.Intersection(dstClipRect);

        if (!dstRect.IsEmpty())
        {
            // calc target to source transform.
            transform = transform.Inverse();

            // check source and dst rects lie within bounds
            ASSERT(CheckBounds(aDstColorBitmap->iSize, aSrcColorBitmap->iSize, dstRect, transform));

            (*copyRegion)(aDstColorBitmap, aDstAlphaBitmap, dstRect, aSrcColorBitmap, aSrcAlphaBitmap, transform);
        }

        err = KErrNone;
    }

    return err;
}

/**
Detect collision between images. Returns ETrue if the overlapping
region contains corresponding opaque pixels.
*/
EXPORT_C TBool CLcdGraphicsDriverImpl::DetectCollision
(
    const TAcceleratedBitmapInfo* aMask1,
    TTransparency       aTransparency1,
    const TSize&        aSize1,
    const TRect&        aRect1,
    TInt                aTransform1,
    const TPoint&       aPoint1,

    const TAcceleratedBitmapInfo* aMask2,
    TTransparency       aTransparency2,
    const TSize&        aSize2,
    const TRect&        aRect2,
    TInt                aTransform2,
    const TPoint&       aPoint2
)
{
    if ((aMask1 == NULL) && (aMask2 == NULL))
    {
        // if neither have mask all pixels opaque, so collide
        return ETrue;
    }

    ASSERT(aRect1.Intersects(TRect(aSize1)));
    ASSERT(aRect2.Intersects(TRect(aSize2)));

    TDisplayMode displayMode1 = aMask1 ? aMask1->iDisplayMode : ENone;
    TDisplayMode displayMode2 = aMask2 ? aMask2->iDisplayMode : ENone;
    const TCollisionDetector* detector = GetCollisionDetector(displayMode1,aTransparency1,displayMode2,aTransparency2);
    ASSERT(detector != NULL);

    TSize dstSize1=aRect1.Size();
    if (aTransform1 & EReflectDiag)
    {
        Swap(dstSize1.iWidth, dstSize1.iHeight);
    }
    TSize dstSize2=aRect2.Size();
    if (aTransform2 & EReflectDiag)
    {
        Swap(dstSize2.iWidth, dstSize2.iHeight);
    }
    TRect dstRect1(aPoint1, dstSize1);
    TRect dstRect2(aPoint2, dstSize2);

    TLcdTransform forward1 = CalcTransform(dstRect1, aRect1, (TTransformType)aTransform1);
    const TRect srcClipRect1(aSize1);
    TRect srcRect1 = aRect1;
    ClipTransformRect(dstRect1, srcRect1, dstRect2, srcClipRect1, forward1);
    TLcdTransform transform1 = forward1.Inverse();

    TLcdTransform forward2 = CalcTransform(dstRect2, aRect2, (TTransformType)aTransform2);
    const TRect srcClipRect2(aSize2);
    TRect srcRect2 = aRect2;
    ClipTransformRect(dstRect2, srcRect2, dstRect1, srcClipRect2, forward2);
    TLcdTransform transform2 = forward2.Inverse();

    return (*detector->iFunction)(aMask1, aMask2, srcRect1, srcRect2, transform1, transform2);
}

CLcdGraphicsDevice* CLcdGraphicsDriverImpl::CreateDeviceL(const TImageType& aType)
{
    const TDrawFunctions* drawFunctions = GetDrawFunctions(aType.iColorMode);
    const TColorMap* colorMap = GetColorMap(aType.iColorMode);

    if (!drawFunctions || !colorMap)
    {
        User::Leave(KErrNotSupported);
    }

    CRenderFunctions* renderers = new(ELeave) CRenderFunctions;
    CleanupStack::PushL(renderers);

    const TImageRenderer* ptr = iRendererArray;
    const TImageRenderer* end = iRendererArray + iRendererCount;
    while (ptr < end)
    {
        //
        // extract only the drawRegion renderers
        //
        if ((ptr->iTargetType == aType) && (ptr->iCompositeRule == ECompositeSrcOver))
        {
            renderers->AppendL(*ptr);
        }
        ++ptr;
    }

    //
    // We need to find all renderers targeting aType
    //
    CLcdGraphicsDeviceImpl* impl = new(ELeave) CLcdGraphicsDeviceImpl
    (
        *this,
        aType,
        renderers,
        *colorMap,
        *drawFunctions
    );
    CleanupStack::Pop(renderers);
    return impl;
}

const TImageRenderer* CLcdGraphicsDriverImpl::GetRenderer
(
    const TImageType& aTargetType,
    const TImageType& aSourceType,
    TTransformType aTransform,
    TCompositRule aCompositeRule
)
const
{
    const TInt transformBit = 1<<aTransform;

    const TInt            count = iRendererCount;
    const TImageRenderer* array = iRendererArray;

    const TImageRenderer* ptr = array;
    const TImageRenderer* end = array + count;

    while (ptr < end)
    {
        if ((ptr->iCompositeRule == aCompositeRule) &&
                (ptr->iTransformMask & transformBit)  &&
                (ptr->iSourceType == aSourceType)     &&
                (ptr->iTargetType == aTargetType))
        {
            return ptr;
        }
        ++ptr;
    }

    return NULL;
}

/**
 *
 */
const TColorMap* CLcdGraphicsDriverImpl::GetColorMap(TDisplayMode aMode)
{
    const TColorMap* ptr = iColorMapArray;
    const TColorMap* end = iColorMapArray + iColorMapCount;

    while (ptr < end)
    {
        if (ptr->iTargetMode == aMode)
        {
            return ptr;
        }
        ++ptr;
    }

    return NULL;
}


const TCollisionDetector* CLcdGraphicsDriverImpl::GetCollisionDetector
(
    TDisplayMode    aDisplayMode1,
    TTransparency   aTransparency1,
    TDisplayMode    aDisplayMode2,
    TTransparency   aTransparency2
)
const
{
    const TCollisionDetector* ptr = iCollisionDetectorArray;
    const TCollisionDetector* end = iCollisionDetectorArray + iCollisionDetectorCount;

    TUint displayMode1Bit   = 1<<aDisplayMode1;
    TUint transparency1Bit  = 1<<aTransparency1;
    TUint displayMode2Bit   = 1<<aDisplayMode2;
    TUint transparency2Bit  = 1<<aTransparency2;

    while (ptr < end)
    {
        if ((ptr->iDisplayMode1 & displayMode1Bit) &&
                (ptr->iTransparency1 & transparency1Bit) &&
                (ptr->iDisplayMode2 & displayMode2Bit) &&
                (ptr->iTransparency2 & transparency2Bit))
        {
            return ptr;
        }
        ++ptr;
    }

    return NULL;
}


EXPORT_C const TDrawFunctions* CLcdGraphicsDriverImpl::GetDrawFunctions(TDisplayMode aMode) const
{
    const TDrawFunctions* ptr = iDrawFunctionsArray;
    const TDrawFunctions* end = iDrawFunctionsArray + iDrawFunctionsCount;
    while (ptr < end)
    {
        if (ptr->iDisplayMode == aMode)
        {
            return ptr;
        }
        ++ptr;
    }
    return NULL;
}

#ifdef _DEBUG
TBool DbgValidateRendererArray(const TImageRenderer aRendererArray[], TInt aCount)
{
    for (TInt i=0; i<aCount; i++)
    {
        const TImageRenderer& renderer = aRendererArray[i];

        if (!DbgValidateImageType(renderer.iTargetType))
        {
            return EFalse;
        }

        if (!DbgValidateImageType(renderer.iSourceType))
        {
            return EFalse;
        }

        if (NULL == renderer.iFunction)
        {
            return EFalse;
        }
    }
    return ETrue;
}

TBool DbgValidateImageType(const TImageType& aType)
{
    //
    // Validate displaymodes against transparency type.
    //
    switch (aType.iTransparency)
    {
    case ETransparencyNone:
        //
        // Must be none.
        //
        if (aType.iAlphaMode != ENone)
        {
            return EFalse;
        }
        break;

    case ETransparencyMaskBitmap:
        //
        // Must be one of EGray2 or matching display mode
        //
        if ((aType.iAlphaMode != EGray2) && (aType.iAlphaMode != aType.iColorMode))
        {
            return EFalse;
        }
        break;

    case ETransparencyAlphaBitmap:
        //
        // Must be EGray256 - the only supported alpha bitmap type.
        //
        if (aType.iAlphaMode != EGray256)
        {
            return EFalse;
        }
        break;

    case ETransparencyAlphaChannel:
        //
        // Alpha mode must be none
        // Color mode must be the Java ARGB8888 mode (build dependent)
        //
        if ((aType.iAlphaMode != ENone) || (aType.iColorMode != EColorARGB8888))
        {
            return EFalse;
        }
        break;

    case ETransparencyMaskChannel:
        if ((aType.iAlphaMode != ENone) || (aType.iColorMode != EColorARGB8888))
        {
            return EFalse;
        }
        break;

#ifdef RD_JAVA_NGA_ENABLED
    case ETransparencyAlphaChannelPre:
    case ETransparencyMaskChannelPre:
        if ((aType.iAlphaMode != ENone) || (aType.iColorMode != EColorARGB8888))
        {
            return EFalse;
        }
        break;
#endif // RD_JAVA_NGA_ENABLED

    case ETransparencyIgnoreChannel:
        if ((aType.iAlphaMode != ENone) || (aType.iColorMode != EColorARGB8888))
        {
            return EFalse;
        }
        break;
    }

    return ETrue;
}
#endif