sl@0: // Copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies). sl@0: // sl@0: // Permission is hereby granted, free of charge, to any person obtaining a sl@0: // copy of this software and/or associated documentation files (the sl@0: // "Materials"), to deal in the Materials without restriction, including sl@0: // without limitation the rights to use, copy, modify, merge, publish, sl@0: // distribute, sublicense, and/or sell copies of the Materials, and to sl@0: // permit persons to whom the Materials are furnished to do so, subject to sl@0: // the following conditions: sl@0: // sl@0: // The above copyright notice and this permission notice shall be included sl@0: // in all copies or substantial portions of the Materials. sl@0: // sl@0: // THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, sl@0: // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF sl@0: // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. sl@0: // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY sl@0: // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, sl@0: // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE sl@0: // MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS. sl@0: // sl@0: // Description: sl@0: // Display Adaptation Interface Implementation for Display channel sl@0: // sl@0: // sl@0: sl@0: #include "openwfc_ri_displaychannel.h" sl@0: #include sl@0: #include sl@0: sl@0: _LIT(KDisplayChannelLdd, "display0.ldd"); sl@0: const TUint32 KDefaultScreenNumber = 0; sl@0: sl@0: #ifdef _DEBUG sl@0: void Panic(TInt aPanic) sl@0: { sl@0: _LIT(KPanic, "DA-DC"); sl@0: User::Panic(KPanic, aPanic); sl@0: } sl@0: #endif sl@0: sl@0: EXPORT_C COpenWFC_RI_Display* COpenWFC_RI_Display::NewL(TUint aScreen) sl@0: { sl@0: return COpenWFC_RI_DisplayChannel::NewL(aScreen); sl@0: } sl@0: sl@0: EXPORT_C TUint32 COpenWFC_RI_Display::DefaultScreenNumber() sl@0: { sl@0: return KDefaultScreenNumber; sl@0: } sl@0: sl@0: COpenWFC_RI_DisplayChannel::COpenWFC_RI_DisplayChannel(TUint aScreen): sl@0: iScreenNumber(aScreen), sl@0: iCurrentSceneStream(SYMBIAN_INVALID_HANDLE) sl@0: { sl@0: } sl@0: sl@0: COpenWFC_RI_DisplayChannel* COpenWFC_RI_DisplayChannel::NewL(TUint aScreen) sl@0: { sl@0: COpenWFC_RI_DisplayChannel* screenContext = new(ELeave) COpenWFC_RI_DisplayChannel(aScreen); sl@0: CleanupStack::PushL(screenContext); sl@0: screenContext->ConstructL(); sl@0: CleanupStack::Pop(screenContext); sl@0: return screenContext; sl@0: } sl@0: sl@0: COpenWFC_RI_DisplayChannel::~COpenWFC_RI_DisplayChannel() sl@0: { sl@0: TInt count = iCompositionBuffer.Count(); sl@0: for(TInt ii = 0; ii < count; ++ii) sl@0: { sl@0: TBufferAddress* addr = iCompositionBuffer[ii]; sl@0: if (addr) sl@0: { sl@0: addr->iChunk.Close(); sl@0: delete addr; sl@0: } sl@0: } sl@0: iCompositionBuffer.Close(); sl@0: // We do not need to use this boolean sl@0: TBool unused; sl@0: // Reset the initial rotation for next time. sl@0: iDispChan.SetRotation(iDefaultRotation, unused); sl@0: iDispChan.Close(); sl@0: } sl@0: sl@0: void COpenWFC_RI_DisplayChannel::ConstructL() sl@0: { sl@0: TInt err = User::LoadLogicalDevice(KDisplayChannelLdd); sl@0: if (err != KErrNone && err != KErrAlreadyExists) sl@0: { sl@0: User::Leave(err); sl@0: } sl@0: sl@0: User::LeaveIfError(iDispChan.Open(iScreenNumber)); sl@0: //#ifdef __WINS__ sl@0: iScreenInfo.iDefaultRotation = EScreenRotate0; sl@0: iDefaultRotation = RDisplayChannel::ERotationNormal; sl@0: iRotationOffset = 0; sl@0: //#else sl@0: // iScreenInfo.iDefaultRotation = EScreenRotate270; sl@0: // iDefaultRotation = RDisplayChannel::ERotation270CW; sl@0: // iRotationOffset = 3; sl@0: //#endif sl@0: RDisplayChannel::TDisplayRotation rotation = iDispChan.CurrentRotation(); sl@0: switch (rotation) sl@0: { sl@0: case RDisplayChannel::ERotationNormal: sl@0: iScreenInfo.iCurrentRotation = EScreenRotate0; sl@0: break; sl@0: case RDisplayChannel::ERotation90CW: sl@0: iScreenInfo.iCurrentRotation = EScreenRotate90; sl@0: break; sl@0: case RDisplayChannel::ERotation180: sl@0: iScreenInfo.iCurrentRotation = EScreenRotate180; sl@0: break; sl@0: case RDisplayChannel::ERotation270CW: sl@0: iScreenInfo.iCurrentRotation = EScreenRotate270; sl@0: break; sl@0: default: sl@0: RDebug::Printf("COpenWFC_RI_DisplayChannel::ConstructL() unsupported rotation %d", rotation); sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: sl@0: iNewRotation = iScreenInfo.iCurrentRotation; sl@0: TPckgBuf pkgInfo; sl@0: iDispChan.GetDisplayInfo(pkgInfo); sl@0: RDisplayChannel::TDisplayInfo info = pkgInfo(); sl@0: /* Note that in theory other formats could be supported for composition sl@0: * (eg EUidPixelFormatARGB_8888 | EUidPixelFormatARGB_8888_PRE ) sl@0: * So long as the background colour is opaque then the final composed image should end up opaque, sl@0: * so compatible with alpha modes. sl@0: * However, it would give problems for fastpathing, where alpha byte should be ignored, sl@0: * probably fastpath would need to be disabled. sl@0: * At present we only care about PlatSim, sl@0: * and it is unlikely that any platform will NOT support xrgb32, sl@0: * so it is better to assert the capabilities match than think about this hypothetical case too hard. sl@0: */ sl@0: if (info.iPixelFormat != EUidPixelFormatXRGB_8888) sl@0: { sl@0: RDebug::Printf("COpenWFC_RI_DisplayChannel::ConstructL() unsupported pixel format 0x%08.8x", info.iPixelFormat); sl@0: User::Leave(KErrNotSupported); sl@0: } sl@0: sl@0: iScreenInfo.iPixelFormat = EUidPixelFormatXRGB_8888; sl@0: iScreenInfo.iSupportedRotations = info.iAvailableRotations; sl@0: sl@0: TInt bytesPerPixel = 4; sl@0: if((info.iBitsPerPixel != 24) && (info.iBitsPerPixel != 32)) sl@0: { sl@0: RDebug::Printf("COpenWFC_RI_DisplayChannel::ConstructL()unexpected bpp value %d", info.iBitsPerPixel); sl@0: } sl@0: sl@0: iScreenInfo.iBytesPerPixel = bytesPerPixel; sl@0: sl@0: if (iRotationOffset & 1) sl@0: { sl@0: // Either 90 or 270 degree rotation, so reverse the normal and flipped sl@0: // sizes (which relate to zero degrees rotation). sl@0: iScreenInfo.iNormalWidth = info.iFlipped.iWidth; sl@0: iScreenInfo.iNormalHeight = info.iFlipped.iHeight; sl@0: iScreenInfo.iNormalStride = info.iFlipped.iOffsetBetweenLines; sl@0: iScreenInfo.iFlippedWidth = info.iNormal.iWidth; sl@0: iScreenInfo.iFlippedHeight = info.iNormal.iHeight; sl@0: iScreenInfo.iFlippedStride = info.iNormal.iOffsetBetweenLines; sl@0: } sl@0: else sl@0: { sl@0: iScreenInfo.iNormalWidth = info.iNormal.iWidth; sl@0: iScreenInfo.iNormalHeight = info.iNormal.iHeight; sl@0: iScreenInfo.iNormalStride = info.iNormal.iOffsetBetweenLines; sl@0: iScreenInfo.iFlippedWidth = info.iFlipped.iWidth; sl@0: iScreenInfo.iFlippedHeight = info.iFlipped.iHeight; sl@0: iScreenInfo.iFlippedStride = info.iFlipped.iOffsetBetweenLines; sl@0: } sl@0: sl@0: if (iScreenInfo.iNormalStride < 0) sl@0: { sl@0: iScreenInfo.iNormalStride = bytesPerPixel * iScreenInfo.iNormalWidth; sl@0: } sl@0: if (iScreenInfo.iFlippedStride < 0) sl@0: { sl@0: iScreenInfo.iFlippedStride = bytesPerPixel * iScreenInfo.iFlippedWidth; sl@0: } sl@0: sl@0: for(TInt i = 0; i < info.iNumCompositionBuffers; ++i) sl@0: { sl@0: iCompositionBuffer.AppendL(NULL); sl@0: TBufferAddress* address = new(ELeave) TBufferAddress; sl@0: iCompositionBuffer[i] = address; sl@0: User::LeaveIfError(iDispChan.GetCompositionBufferInfo(i, address->iChunk, address->iOffset)); sl@0: address->iAddress = address->iChunk.Base() + address->iOffset; sl@0: } sl@0: } sl@0: sl@0: TInt COpenWFC_RI_Display::GetAttributeSize(TUint aAttributeId) sl@0: { sl@0: switch (aAttributeId) sl@0: { sl@0: case EScreenAttributeImplementationVersion: sl@0: case EScreenAttributePixelFormat: sl@0: case EScreenAttributeBytesPerPixel: sl@0: case EScreenAttributeSupportedRotation: sl@0: case EScreenAttributeNormalWidth: sl@0: case EScreenAttributeNormalHeight: sl@0: case EScreenAttributeNormalStride: sl@0: case EScreenAttributeFlippedWidth: sl@0: case EScreenAttributeFlippedHeight: sl@0: case EScreenAttributeFlippedStride: sl@0: case EScreenAttributeDefaultRotation: sl@0: case EScreenAttributeCurrentRotation: sl@0: return sizeof(TUint32); sl@0: sl@0: case EScreenAttributeScreenGeometry: sl@0: return sizeof(TScreenGeometryAttribute); sl@0: sl@0: default: sl@0: return 0; sl@0: } sl@0: } sl@0: sl@0: TInt COpenWFC_RI_DisplayChannel::GetAttribute(TInt aAttributeId, TAny* aAttribute, TInt aAttributeSize) sl@0: { sl@0: TInt parameterSize = GetAttributeSize(aAttributeId); sl@0: sl@0: if (aAttribute == NULL) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: sl@0: if (parameterSize == 0) sl@0: { sl@0: return KErrNotSupported; sl@0: } sl@0: sl@0: if (aAttributeSize != parameterSize) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: sl@0: switch (aAttributeId) sl@0: { sl@0: case EScreenAttributeImplementationVersion: sl@0: *((TUint32*)aAttribute) = KImplementationVersion; sl@0: break; sl@0: case EScreenAttributePixelFormat: sl@0: *((TUint32*)aAttribute) = iScreenInfo.iPixelFormat; sl@0: break; sl@0: case EScreenAttributeBytesPerPixel: sl@0: *((TUint32*)aAttribute) = iScreenInfo.iBytesPerPixel; sl@0: break; sl@0: case EScreenAttributeSupportedRotation: sl@0: *((TUint32*)aAttribute) = iScreenInfo.iSupportedRotations; sl@0: break; sl@0: case EScreenAttributeNormalWidth: sl@0: *((TUint32*)aAttribute) = iScreenInfo.iNormalWidth; sl@0: break; sl@0: case EScreenAttributeNormalHeight: sl@0: *((TUint32*)aAttribute) = iScreenInfo.iNormalHeight; sl@0: break; sl@0: case EScreenAttributeNormalStride: sl@0: *((TUint32*)aAttribute) = iScreenInfo.iNormalStride; sl@0: break; sl@0: case EScreenAttributeFlippedWidth: sl@0: *((TUint32*)aAttribute) = iScreenInfo.iFlippedWidth; sl@0: break; sl@0: case EScreenAttributeFlippedHeight: sl@0: *((TUint32*)aAttribute) = iScreenInfo.iFlippedHeight; sl@0: break; sl@0: case EScreenAttributeFlippedStride: sl@0: *((TUint32*)aAttribute) = iScreenInfo.iFlippedStride; sl@0: break; sl@0: case EScreenAttributeDefaultRotation: sl@0: *((TUint32*)aAttribute) = iScreenInfo.iDefaultRotation; sl@0: break; sl@0: case EScreenAttributeCurrentRotation: sl@0: *((TUint32*)aAttribute) = iScreenInfo.iCurrentRotation; sl@0: break; sl@0: case EScreenAttributeScreenGeometry: sl@0: *((TScreenGeometryAttribute*)aAttribute) = iScreenInfo; sl@0: break; sl@0: default: sl@0: return KErrNotSupported; sl@0: } sl@0: sl@0: return KErrNone; sl@0: } sl@0: sl@0: sl@0: TInt COpenWFC_RI_DisplayChannel::SetAttribute(TInt aAttributeId, TAny* aAttribute, TInt aAttributeSize) sl@0: { sl@0: // the only parameter we can modify is the current rotation sl@0: TInt parameterSize = GetAttributeSize(aAttributeId); sl@0: sl@0: if (aAttributeSize != parameterSize || aAttribute == NULL) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: sl@0: switch (aAttributeId) sl@0: { sl@0: case EScreenAttributeCurrentRotation: sl@0: iNewRotation = static_cast(*((TUint32*)aAttribute)); sl@0: break; sl@0: default: sl@0: return KErrNotSupported; sl@0: } sl@0: return KErrNone; sl@0: } sl@0: sl@0: sl@0: TInt COpenWFC_RI_DisplayChannel::CommitAttribute() sl@0: { sl@0: // For DisplayChannel the new screen attributes must be applied sl@0: // at the same time with the composition. sl@0: if (iScreenInfo.iCurrentRotation != iNewRotation) sl@0: { sl@0: TInt totalRotation; sl@0: RDisplayChannel::TDisplayRotation dcRotation; sl@0: sl@0: // Change the rotation to a numeric index from zero sl@0: switch (iNewRotation) sl@0: { sl@0: case EScreenRotate90: sl@0: totalRotation = 1; sl@0: break; sl@0: case EScreenRotate180: sl@0: totalRotation = 2; sl@0: break; sl@0: case EScreenRotate270: sl@0: totalRotation = 3; sl@0: break; sl@0: case EScreenRotate0: sl@0: default: sl@0: __ASSERT_DEBUG(iNewRotation == EScreenRotate0, Panic(__LINE__)); sl@0: totalRotation = 0; sl@0: break; sl@0: } sl@0: sl@0: // Add the initial rotation of the device and wrap to get final one. sl@0: totalRotation = (totalRotation + iRotationOffset) % 4; sl@0: sl@0: // Now change the final rotation to the display channel rotation sl@0: switch (totalRotation) sl@0: { sl@0: case 1: sl@0: dcRotation = RDisplayChannel::ERotation90CW; sl@0: break; sl@0: case 2: sl@0: dcRotation = RDisplayChannel::ERotation180; sl@0: break; sl@0: case 3: sl@0: dcRotation = RDisplayChannel::ERotation270CW; sl@0: break; sl@0: case 0: sl@0: default: sl@0: __ASSERT_DEBUG(totalRotation == 0, Panic(__LINE__)); sl@0: dcRotation = RDisplayChannel::ERotationNormal; sl@0: break; sl@0: } sl@0: sl@0: if (!(iScreenInfo.iSupportedRotations & dcRotation)) sl@0: { sl@0: return KErrNotSupported; sl@0: } sl@0: sl@0: // We do not need to use this boolean sl@0: TBool displayConfigChanged; sl@0: TInt err = iDispChan.SetRotation(dcRotation, displayConfigChanged); sl@0: __ASSERT_DEBUG(err == KErrNone, Panic(__LINE__)); sl@0: if (err == KErrNone) sl@0: { sl@0: iScreenInfo.iCurrentRotation = iNewRotation; sl@0: } sl@0: else sl@0: { sl@0: return err; sl@0: } sl@0: } sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt COpenWFC_RI_DisplayChannel::SetLayerSurface(TInt aLayer, SymbianStreamType aStream,TInt* aNonTrivialAttribs) sl@0: { sl@0: // display channel interface can be seen as mono-layered sl@0: if (aLayer != 0) sl@0: { sl@0: return KErrArgument; sl@0: } sl@0: if (aNonTrivialAttribs && *aNonTrivialAttribs) sl@0: { sl@0: return KErrNotSupported; sl@0: } sl@0: TBool acceptable=ETrue; sl@0: khronos_int32_t format,pixSize; sl@0: SymbianStreamGetHeader(aStream,NULL,NULL,NULL,&format,&pixSize); sl@0: if (format!=EUidPixelFormatARGB_8888 && format!=EUidPixelFormatARGB_8888_PRE && format!=EUidPixelFormatXRGB_8888) sl@0: { sl@0: acceptable=EFalse; sl@0: } sl@0: sl@0: if (!acceptable) sl@0: { sl@0: return KErrNotSupported; sl@0: } sl@0: sl@0: iCurrentSceneStream = aStream; sl@0: return KErrNone; sl@0: } sl@0: sl@0: TInt COpenWFC_RI_DisplayChannel::SetTopLayerSurface(SymbianStreamType aStream,TInt* aNonTrivialAttribs) sl@0: { sl@0: return SetLayerSurface(KTopMostLayer, aStream,aNonTrivialAttribs); sl@0: } sl@0: sl@0: TInt COpenWFC_RI_DisplayChannel::UpdateDisplay() sl@0: { sl@0: // The solution is suboptimal because a blit is used insteat of posting a user buffer sl@0: // The solution is more simpler and because the emulator is to be phased-out soon, sl@0: // there is no much incentive in complicating the code sl@0: TInt err; sl@0: sl@0: TUint bufferIndex; sl@0: TRequestStatus status; sl@0: iDispChan.GetCompositionBuffer(bufferIndex, status); sl@0: User::WaitForRequest(status); sl@0: sl@0: err = status.Int(); sl@0: if (err != KErrNone || bufferIndex >= iCompositionBuffer.Count()) sl@0: { sl@0: return KErrGeneral; sl@0: } sl@0: sl@0: TUint8* firstPixelAddr = iCompositionBuffer[bufferIndex]->iAddress; sl@0: sl@0: // Only 32 or 16bpp supported and assume stride == width * pixel size sl@0: TInt size = 0; sl@0: if (iNewRotation == EScreenRotate0 || iNewRotation == EScreenRotate180) sl@0: { sl@0: size = iScreenInfo.iNormalHeight * iScreenInfo.iNormalStride; sl@0: } sl@0: else sl@0: { sl@0: size = iScreenInfo.iFlippedHeight * iScreenInfo.iFlippedStride; sl@0: } sl@0: SymbianStreamBuffer frontBuffer; sl@0: SymbianStreamAcquireReadBuffer(iCurrentSceneStream, &frontBuffer); sl@0: void* pixelDataPtr = NULL; sl@0: SymbianStreamGetBufferPointer(iCurrentSceneStream, frontBuffer,&pixelDataPtr); sl@0: Mem::Move(firstPixelAddr, pixelDataPtr, size); sl@0: RDisplayChannel::TPostCount postCount; sl@0: err = iDispChan.PostCompositionBuffer(NULL, postCount); sl@0: if (err == KErrNone) sl@0: { sl@0: // This will throttle composition more than necessary, sl@0: // since it will wait until buffer is being displayed sl@0: iDispChan.WaitForPost(postCount, status); sl@0: User::WaitForRequest(status); sl@0: err = status.Int(); sl@0: } sl@0: sl@0: SymbianStreamReleaseReadBuffer(iCurrentSceneStream, frontBuffer); sl@0: sl@0: return err; sl@0: } sl@0: