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 <assert.h>
+#include <e32base.h>
+#include <e32debug.h>
+#include <pixelformats.h>
+#include <hal.h>
+
+#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<RDisplayChannel::TDisplayInfo> 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;
+ }