diff -r 000000000000 -r 5d03bc08d59c graphicscomposition/openwfcompositionengine/adaptation/src/Platform/Graphics/symbian/owfscreen_displaychannel.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/graphicscomposition/openwfcompositionengine/adaptation/src/Platform/Graphics/symbian/owfscreen_displaychannel.cpp Tue Feb 02 01:47:50 2010 +0200 @@ -0,0 +1,458 @@ +// 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: +// Display Channel adaptation for owfscreen +// +// + +#include "owfscreen.h" + +#include +#include +#include +#include +#include + +#include "owfimage.h" + +#include "owfdisplaycontext.h" + +static const int KDefaultScreenNum = 0; +_LIT(KDisplayChannelLdd, "display0.ldd"); + +COwfcDisplayDevice* COwfcDisplayDevice::gDisplayDeviceInstancePtr = NULL; + +static OWFboolean GetDisplayInfo(OWFint aScreenNumber, COWFScreenDisplayInfo * & aInfo) + { + if (!OWF_Screen_Valid(aScreenNumber)) + { + return OWF_FALSE; + } + COwfcDisplayDevice *pInstance = COwfcDisplayDevice::SingletonInstance(); + if (!pInstance) + { + return OWF_FALSE; + } + TInt index = pInstance->iScreenDisplayInfo.Find((TInt)aScreenNumber, COwfcDisplayDevice::ScreenCompare); + if (index == KErrNotFound) + { + return OWF_FALSE; + } + aInfo = pInstance->iScreenDisplayInfo[index]; + return OWF_TRUE; + } + +COwfcDisplayDevice* COwfcDisplayDevice::SingletonInstance() + { + if (!gDisplayDeviceInstancePtr) + { + TInt err = User::LoadLogicalDevice(KDisplayChannelLdd); + if (err != KErrNone && err != KErrAlreadyExists) + { + DPRINT(("COwfcDisplayDevice::SingletonInstance: Error in LoadLogicalDevice.")); + return NULL; + } + gDisplayDeviceInstancePtr = new COwfcDisplayDevice; + if (!gDisplayDeviceInstancePtr) + { + DPRINT(("Cannot create Display Device singleton instance.")); + return NULL; + } + } + return gDisplayDeviceInstancePtr; + } + +TInt COwfcDisplayDevice::CloseScreen(TInt aScreen, OWFboolean *aCanDelete) + { + TInt index = iScreenDisplayInfo.Find(aScreen, ScreenCompare); + if (index == KErrNotFound) + { + return KErrNotFound; + } + delete iScreenDisplayInfo[index]; + iScreenDisplayInfo.Remove(index); + if (iScreenDisplayInfo.Count() == 0) + { + *aCanDelete = OWF_TRUE; + } + return KErrNone; + } + +COWFScreenDisplayInfo::COWFScreenDisplayInfo(TInt aScreen):iScreenNumber(aScreen) + { + } + +COWFScreenDisplayInfo::~COWFScreenDisplayInfo() + { + TInt count = iCompositionBuffer.Count(); + for(TInt ii = 0; ii < count; ++ii) + { + TBufferAddress* addr = iCompositionBuffer[ii]; + if (addr) + { + addr->iChunk.Close(); + delete addr; + } + } + iCompositionBuffer.Close(); + // We do not need to use this boolean + TBool unused; + // Reset the initial rotation for next time. + iDispChan.SetRotation(iDefaultRotation, unused); + iDispChan.Close(); + } + +void COWFScreenDisplayInfo::ConstructL() + { + User::LeaveIfError(iDispChan.Open(iScreenNumber)); +#ifdef __WINS__ + iDefaultRotation = RDisplayChannel::ERotationNormal; +#else + iDefaultRotation = RDisplayChannel::ERotation270CW; +#endif + + switch (iDispChan.CurrentRotation()) + { + case RDisplayChannel::ERotationNormal: + iScreenInfo.currentRotation = OWF_ROTATION_0; + break; + case RDisplayChannel::ERotation90CW: + iScreenInfo.currentRotation = OWF_ROTATION_90; + break; + case RDisplayChannel::ERotation180: + iScreenInfo.currentRotation = OWF_ROTATION_180; + break; + case RDisplayChannel::ERotation270CW: + iScreenInfo.currentRotation = OWF_ROTATION_270; + break; + default: + DPRINT(("Unsupported rotation %d", rotation)); + User::Leave(KErrNotSupported); + } + + TPckgBuf pkgInfo; + iDispChan.GetDisplayInfo(pkgInfo); + RDisplayChannel::TDisplayInfo info = pkgInfo(); + switch(info.iPixelFormat) + { + case EUidPixelFormatXRGB_8888: + case EUidPixelFormatARGB_8888: + case EUidPixelFormatARGB_8888_PRE: + iScreenInfo.pixelFormat = OWF_IMAGE_XRGB8888; + break; +#ifdef SUPPORT_565_OUTPUT + case EUidPixelFormatRGB_565: + iScreenInfo.pixelFormat = OWF_IMAGE_RGB565; + break; +#endif + default: + DPRINT(("Unsupported pixel format 0x%08.8x", info.iPixelFormat)); + User::Leave(KErrNotSupported); + } + iScreenInfo.supportedRotations = info.iAvailableRotations; + TInt bytesPerPixel = 2; + if( info.iBitsPerPixel == 24 || info.iBitsPerPixel == 32) + { + bytesPerPixel = 4; + } + + switch (iDefaultRotation) + { + case RDisplayChannel::ERotation90CW: + iRotationOffset = 1; + break; + case RDisplayChannel::ERotation180: + iRotationOffset = 2; + break; + case RDisplayChannel::ERotation270CW: + iRotationOffset = 3; + break; + case RDisplayChannel::ERotationNormal: + default: + OWF_ASSERT(iDefaultRotation == RDisplayChannel::ERotationNormal); + iRotationOffset = 0; + } + + if (iRotationOffset & 1) + { + // Either 90 or 270 degree rotation, so reverse the normal and flipped + // sizes (which relate to zero degrees rotation). + iScreenInfo.normal.width = info.iFlipped.iWidth; + iScreenInfo.normal.height = info.iFlipped.iHeight; + iScreenInfo.normal.stride = info.iFlipped.iOffsetBetweenLines; + iScreenInfo.flipped.width = info.iNormal.iWidth; + iScreenInfo.flipped.height = info.iNormal.iHeight; + iScreenInfo.flipped.stride = info.iNormal.iOffsetBetweenLines; + } + else + { + iScreenInfo.normal.width = info.iNormal.iWidth; + iScreenInfo.normal.height = info.iNormal.iHeight; + iScreenInfo.normal.stride = info.iNormal.iOffsetBetweenLines; + iScreenInfo.flipped.width = info.iFlipped.iWidth; + iScreenInfo.flipped.height = info.iFlipped.iHeight; + iScreenInfo.flipped.stride = info.iFlipped.iOffsetBetweenLines; + } + + if (iScreenInfo.normal.stride < 0) + { + iScreenInfo.normal.stride = bytesPerPixel * iScreenInfo.normal.width; + } + if (iScreenInfo.flipped.stride < 0) + { + iScreenInfo.flipped.stride = bytesPerPixel * iScreenInfo.flipped.width; + } + + for(TInt ii = 0; ii < info.iNumCompositionBuffers; ++ii) + { + iCompositionBuffer.AppendL(NULL); + TBufferAddress* address = new(ELeave) TBufferAddress; + iCompositionBuffer[ii] = address; + User::LeaveIfError(iDispChan.GetCompositionBufferInfo(ii, address->iChunk, address->iOffset)); + address->iAddress = address->iChunk.Base() + address->iOffset; + } + } + +COWFScreenDisplayInfo* COWFScreenDisplayInfo::NewL(TInt aScreen) + { + COWFScreenDisplayInfo* sdi = new(ELeave) COWFScreenDisplayInfo(aScreen); + CleanupStack::PushL(sdi); + sdi->ConstructL(); + CleanupStack::Pop(sdi); + return sdi; + } + +COwfcDisplayDevice::~COwfcDisplayDevice() + { + COwfcDisplayDevice::gDisplayDeviceInstancePtr = NULL; + iScreenDisplayInfo.Close(); + } + +TInt COwfcDisplayDevice::OpenScreen(TInt aScreen) + { + if (!OWF_Screen_Valid(aScreen)) + { + return KErrNotSupported; + } + TInt err = iScreenDisplayInfo.Find(aScreen, ScreenCompare); + if (err != KErrNotFound) + { + return KErrInUse; + } + COWFScreenDisplayInfo *info = NULL; + TRAP(err, info = COWFScreenDisplayInfo::NewL(aScreen)); + if (err == KErrNone) + { + err = iScreenDisplayInfo.Append(info); + if (err != KErrNone) + { + delete info; + } + } + return err; + } + +OWFboolean COWFScreenDisplayInfo::Blit(void* buffer, OWF_ROTATION rotation) + { + TInt err; + + if (iScreenInfo.currentRotation != rotation) + { + TInt totalRotation; + RDisplayChannel::TDisplayRotation dcRotation; + + // Change the rotation to a numeric index from zero + switch (rotation) + { + case OWF_ROTATION_90: + totalRotation = 1; + break; + case OWF_ROTATION_180: + totalRotation = 2; + break; + case OWF_ROTATION_270: + totalRotation = 3; + break; + case OWF_ROTATION_0: + default: + OWF_ASSERT(rotation == OWF_ROTATION_0); + totalRotation = 0; + break; + } + + // Add the initial rotation of the device and wrap to get final one. + totalRotation = (totalRotation + iRotationOffset) % 4; + + // Now change the final rotation to the display channel rotation + switch (totalRotation) + { + case 1: + dcRotation = RDisplayChannel::ERotation90CW; + break; + case 2: + dcRotation = RDisplayChannel::ERotation180; + break; + case 3: + dcRotation = RDisplayChannel::ERotation270CW; + break; + case 0: + default: + OWF_ASSERT(totalRotation == 0); + dcRotation = RDisplayChannel::ERotationNormal; + break; + } + + if (!(iScreenInfo.supportedRotations & dcRotation)) + { + return OWF_FALSE; + } + // We do not need to use this boolean + TBool displayConfigChanged; + err = iDispChan.SetRotation(dcRotation, displayConfigChanged); + OWF_ASSERT(err == KErrNone); + iScreenInfo.currentRotation = rotation; + } + + TUint bufferIndex; + TRequestStatus status; + iDispChan.GetCompositionBuffer(bufferIndex, status); + User::WaitForRequest(status); + + err = status.Int(); + if (err != KErrNone || bufferIndex >= iCompositionBuffer.Count()) + { + return OWF_FALSE; + } + + TUint8* firstPixelAddr = iCompositionBuffer[bufferIndex]->iAddress; + + // Only 32 or 16bpp supported and assume stride == width * pixel size + TInt size = 0; + if (rotation == OWF_ROTATION_0 || rotation == OWF_ROTATION_180) + { + size = iScreenInfo.normal.height * iScreenInfo.normal.stride; + } + else + { + size = iScreenInfo.flipped.height * iScreenInfo.flipped.stride; + } + Mem::Move(firstPixelAddr, buffer, size); + RDisplayChannel::TPostCount postCount; + err = iDispChan.PostCompositionBuffer(NULL, postCount); + if (err == KErrNone) + { + // This will throttle composition more than necessary, + // since it will wait until buffer is being displayed + iDispChan.WaitForPost(postCount, status); + User::WaitForRequest(status); + err = status.Int(); + } + return (err == KErrNone) ? OWF_TRUE : OWF_FALSE; + } + +TInt COWFScreenDisplayInfo::ScreenNumber() const + { + return iScreenNumber; + } + +void COWFScreenDisplayInfo::GetScreenInfo(OWF_SCREEN *header) const + { + *header = iScreenInfo; + } + +// + +OWF_API_CALL OWFint OWF_Screen_GetDefaultNumber() + { + return KDefaultScreenNum; + } + +OWF_API_CALL OWFboolean OWF_Number_Of_Screens(OWFint *pNumberOfScreens) + { + TInt screens = 0; + TInt err = HAL::Get(HAL::EDisplayNumberOfScreens, screens); + if (err != KErrNone) + { + DPRINT(("Cannot get number of screens from HAL, error: %d", err)); + return OWF_FALSE; + } + *pNumberOfScreens = (OWFint)screens; + return OWF_TRUE; + } + +OWF_API_CALL OWFboolean OWF_Screen_Valid(OWFint screen) + { + OWFint numberOfScreens = 0; + if (!OWF_Number_Of_Screens(&numberOfScreens)) + { + return OWF_FALSE; + } + if (screen < 0 || screen >= numberOfScreens) + { + return OWF_FALSE; + } + return OWF_TRUE; + } + +OWF_API_CALL OWFboolean OWF_Screen_Valid_And_Available(OWFint screen) + { + if (!OWF_Screen_Valid(screen)) + { + return OWF_FALSE; + } + COwfcDisplayDevice *pInstance = COwfcDisplayDevice::SingletonInstance(); + if (!pInstance) + { + return OWF_TRUE; + } + TInt index = pInstance->iScreenDisplayInfo.Find((TInt)screen, COwfcDisplayDevice::ScreenCompare); + if (index != KErrNotFound) + { + return OWF_FALSE; + } + return OWF_TRUE; + } + +OWF_API_CALL OWFboolean OWF_Screen_GetHeader(OWFint screen, OWF_SCREEN* header) + { + COWFScreenDisplayInfo* info; + if (!GetDisplayInfo(screen, info)) + { + return OWF_FALSE; + } + info->GetScreenInfo(header); + return OWF_TRUE; + } + +OWF_API_CALL OWFboolean OWF_Screen_Blit(OWFint screenNumber, void* buffer, OWF_ROTATION rotation) + { + COWFScreenDisplayInfo* info; + if (!GetDisplayInfo(screenNumber, info)) + { + return OWF_FALSE; + } + return info->Blit(buffer, rotation); + } + +OWF_API_CALL OWFboolean +OWF_Screen_Rotation_Supported(OWFint screen) + { + COWFScreenDisplayInfo* info; + if (!GetDisplayInfo(screen, info)) + { + return OWF_FALSE; + } + OWF_SCREEN header; + info->GetScreenInfo(&header); + return (header.supportedRotations & 0xF == 0xF) ? OWF_TRUE : OWF_FALSE; + }