os/graphics/graphicscomposition/openwfc_ri_displaychannel/src/openwfc_ri_displaychannel.cpp
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/graphics/graphicscomposition/openwfc_ri_displaychannel/src/openwfc_ri_displaychannel.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,466 @@
1.4 +// Copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
1.5 +//
1.6 +// Permission is hereby granted, free of charge, to any person obtaining a
1.7 +// copy of this software and/or associated documentation files (the
1.8 +// "Materials"), to deal in the Materials without restriction, including
1.9 +// without limitation the rights to use, copy, modify, merge, publish,
1.10 +// distribute, sublicense, and/or sell copies of the Materials, and to
1.11 +// permit persons to whom the Materials are furnished to do so, subject to
1.12 +// the following conditions:
1.13 +//
1.14 +// The above copyright notice and this permission notice shall be included
1.15 +// in all copies or substantial portions of the Materials.
1.16 +//
1.17 +// THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
1.18 +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
1.19 +// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
1.20 +// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
1.21 +// CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
1.22 +// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
1.23 +// MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
1.24 +//
1.25 +// Description:
1.26 +// Display Adaptation Interface Implementation for Display channel
1.27 +//
1.28 +//
1.29 +
1.30 +#include "openwfc_ri_displaychannel.h"
1.31 +#include <e32debug.h>
1.32 +#include <hal.h>
1.33 +
1.34 +_LIT(KDisplayChannelLdd, "display0.ldd");
1.35 +const TUint32 KDefaultScreenNumber = 0;
1.36 +
1.37 +#ifdef _DEBUG
1.38 +void Panic(TInt aPanic)
1.39 + {
1.40 + _LIT(KPanic, "DA-DC");
1.41 + User::Panic(KPanic, aPanic);
1.42 + }
1.43 +#endif
1.44 +
1.45 +EXPORT_C COpenWFC_RI_Display* COpenWFC_RI_Display::NewL(TUint aScreen)
1.46 + {
1.47 + return COpenWFC_RI_DisplayChannel::NewL(aScreen);
1.48 + }
1.49 +
1.50 +EXPORT_C TUint32 COpenWFC_RI_Display::DefaultScreenNumber()
1.51 + {
1.52 + return KDefaultScreenNumber;
1.53 + }
1.54 +
1.55 +COpenWFC_RI_DisplayChannel::COpenWFC_RI_DisplayChannel(TUint aScreen):
1.56 +iScreenNumber(aScreen),
1.57 +iCurrentSceneStream(SYMBIAN_INVALID_HANDLE)
1.58 + {
1.59 + }
1.60 +
1.61 +COpenWFC_RI_DisplayChannel* COpenWFC_RI_DisplayChannel::NewL(TUint aScreen)
1.62 + {
1.63 + COpenWFC_RI_DisplayChannel* screenContext = new(ELeave) COpenWFC_RI_DisplayChannel(aScreen);
1.64 + CleanupStack::PushL(screenContext);
1.65 + screenContext->ConstructL();
1.66 + CleanupStack::Pop(screenContext);
1.67 + return screenContext;
1.68 + }
1.69 +
1.70 +COpenWFC_RI_DisplayChannel::~COpenWFC_RI_DisplayChannel()
1.71 + {
1.72 + TInt count = iCompositionBuffer.Count();
1.73 + for(TInt ii = 0; ii < count; ++ii)
1.74 + {
1.75 + TBufferAddress* addr = iCompositionBuffer[ii];
1.76 + if (addr)
1.77 + {
1.78 + addr->iChunk.Close();
1.79 + delete addr;
1.80 + }
1.81 + }
1.82 + iCompositionBuffer.Close();
1.83 + // We do not need to use this boolean
1.84 + TBool unused;
1.85 + // Reset the initial rotation for next time.
1.86 + iDispChan.SetRotation(iDefaultRotation, unused);
1.87 + iDispChan.Close();
1.88 + }
1.89 +
1.90 +void COpenWFC_RI_DisplayChannel::ConstructL()
1.91 + {
1.92 + TInt err = User::LoadLogicalDevice(KDisplayChannelLdd);
1.93 + if (err != KErrNone && err != KErrAlreadyExists)
1.94 + {
1.95 + User::Leave(err);
1.96 + }
1.97 +
1.98 + User::LeaveIfError(iDispChan.Open(iScreenNumber));
1.99 +//#ifdef __WINS__
1.100 + iScreenInfo.iDefaultRotation = EScreenRotate0;
1.101 + iDefaultRotation = RDisplayChannel::ERotationNormal;
1.102 + iRotationOffset = 0;
1.103 +//#else
1.104 +// iScreenInfo.iDefaultRotation = EScreenRotate270;
1.105 +// iDefaultRotation = RDisplayChannel::ERotation270CW;
1.106 +// iRotationOffset = 3;
1.107 +//#endif
1.108 + RDisplayChannel::TDisplayRotation rotation = iDispChan.CurrentRotation();
1.109 + switch (rotation)
1.110 + {
1.111 + case RDisplayChannel::ERotationNormal:
1.112 + iScreenInfo.iCurrentRotation = EScreenRotate0;
1.113 + break;
1.114 + case RDisplayChannel::ERotation90CW:
1.115 + iScreenInfo.iCurrentRotation = EScreenRotate90;
1.116 + break;
1.117 + case RDisplayChannel::ERotation180:
1.118 + iScreenInfo.iCurrentRotation = EScreenRotate180;
1.119 + break;
1.120 + case RDisplayChannel::ERotation270CW:
1.121 + iScreenInfo.iCurrentRotation = EScreenRotate270;
1.122 + break;
1.123 + default:
1.124 + RDebug::Printf("COpenWFC_RI_DisplayChannel::ConstructL() unsupported rotation %d", rotation);
1.125 + User::Leave(KErrNotSupported);
1.126 + }
1.127 +
1.128 + iNewRotation = iScreenInfo.iCurrentRotation;
1.129 + TPckgBuf<RDisplayChannel::TDisplayInfo> pkgInfo;
1.130 + iDispChan.GetDisplayInfo(pkgInfo);
1.131 + RDisplayChannel::TDisplayInfo info = pkgInfo();
1.132 + /* Note that in theory other formats could be supported for composition
1.133 + * (eg EUidPixelFormatARGB_8888 | EUidPixelFormatARGB_8888_PRE )
1.134 + * So long as the background colour is opaque then the final composed image should end up opaque,
1.135 + * so compatible with alpha modes.
1.136 + * However, it would give problems for fastpathing, where alpha byte should be ignored,
1.137 + * probably fastpath would need to be disabled.
1.138 + * At present we only care about PlatSim,
1.139 + * and it is unlikely that any platform will NOT support xrgb32,
1.140 + * so it is better to assert the capabilities match than think about this hypothetical case too hard.
1.141 + */
1.142 + if (info.iPixelFormat != EUidPixelFormatXRGB_8888)
1.143 + {
1.144 + RDebug::Printf("COpenWFC_RI_DisplayChannel::ConstructL() unsupported pixel format 0x%08.8x", info.iPixelFormat);
1.145 + User::Leave(KErrNotSupported);
1.146 + }
1.147 +
1.148 + iScreenInfo.iPixelFormat = EUidPixelFormatXRGB_8888;
1.149 + iScreenInfo.iSupportedRotations = info.iAvailableRotations;
1.150 +
1.151 + TInt bytesPerPixel = 4;
1.152 + if((info.iBitsPerPixel != 24) && (info.iBitsPerPixel != 32))
1.153 + {
1.154 + RDebug::Printf("COpenWFC_RI_DisplayChannel::ConstructL()unexpected bpp value %d", info.iBitsPerPixel);
1.155 + }
1.156 +
1.157 + iScreenInfo.iBytesPerPixel = bytesPerPixel;
1.158 +
1.159 + if (iRotationOffset & 1)
1.160 + {
1.161 + // Either 90 or 270 degree rotation, so reverse the normal and flipped
1.162 + // sizes (which relate to zero degrees rotation).
1.163 + iScreenInfo.iNormalWidth = info.iFlipped.iWidth;
1.164 + iScreenInfo.iNormalHeight = info.iFlipped.iHeight;
1.165 + iScreenInfo.iNormalStride = info.iFlipped.iOffsetBetweenLines;
1.166 + iScreenInfo.iFlippedWidth = info.iNormal.iWidth;
1.167 + iScreenInfo.iFlippedHeight = info.iNormal.iHeight;
1.168 + iScreenInfo.iFlippedStride = info.iNormal.iOffsetBetweenLines;
1.169 + }
1.170 + else
1.171 + {
1.172 + iScreenInfo.iNormalWidth = info.iNormal.iWidth;
1.173 + iScreenInfo.iNormalHeight = info.iNormal.iHeight;
1.174 + iScreenInfo.iNormalStride = info.iNormal.iOffsetBetweenLines;
1.175 + iScreenInfo.iFlippedWidth = info.iFlipped.iWidth;
1.176 + iScreenInfo.iFlippedHeight = info.iFlipped.iHeight;
1.177 + iScreenInfo.iFlippedStride = info.iFlipped.iOffsetBetweenLines;
1.178 + }
1.179 +
1.180 + if (iScreenInfo.iNormalStride < 0)
1.181 + {
1.182 + iScreenInfo.iNormalStride = bytesPerPixel * iScreenInfo.iNormalWidth;
1.183 + }
1.184 + if (iScreenInfo.iFlippedStride < 0)
1.185 + {
1.186 + iScreenInfo.iFlippedStride = bytesPerPixel * iScreenInfo.iFlippedWidth;
1.187 + }
1.188 +
1.189 + for(TInt i = 0; i < info.iNumCompositionBuffers; ++i)
1.190 + {
1.191 + iCompositionBuffer.AppendL(NULL);
1.192 + TBufferAddress* address = new(ELeave) TBufferAddress;
1.193 + iCompositionBuffer[i] = address;
1.194 + User::LeaveIfError(iDispChan.GetCompositionBufferInfo(i, address->iChunk, address->iOffset));
1.195 + address->iAddress = address->iChunk.Base() + address->iOffset;
1.196 + }
1.197 + }
1.198 +
1.199 +TInt COpenWFC_RI_Display::GetAttributeSize(TUint aAttributeId)
1.200 + {
1.201 + switch (aAttributeId)
1.202 + {
1.203 + case EScreenAttributeImplementationVersion:
1.204 + case EScreenAttributePixelFormat:
1.205 + case EScreenAttributeBytesPerPixel:
1.206 + case EScreenAttributeSupportedRotation:
1.207 + case EScreenAttributeNormalWidth:
1.208 + case EScreenAttributeNormalHeight:
1.209 + case EScreenAttributeNormalStride:
1.210 + case EScreenAttributeFlippedWidth:
1.211 + case EScreenAttributeFlippedHeight:
1.212 + case EScreenAttributeFlippedStride:
1.213 + case EScreenAttributeDefaultRotation:
1.214 + case EScreenAttributeCurrentRotation:
1.215 + return sizeof(TUint32);
1.216 +
1.217 + case EScreenAttributeScreenGeometry:
1.218 + return sizeof(TScreenGeometryAttribute);
1.219 +
1.220 + default:
1.221 + return 0;
1.222 + }
1.223 + }
1.224 +
1.225 +TInt COpenWFC_RI_DisplayChannel::GetAttribute(TInt aAttributeId, TAny* aAttribute, TInt aAttributeSize)
1.226 + {
1.227 + TInt parameterSize = GetAttributeSize(aAttributeId);
1.228 +
1.229 + if (aAttribute == NULL)
1.230 + {
1.231 + return KErrArgument;
1.232 + }
1.233 +
1.234 + if (parameterSize == 0)
1.235 + {
1.236 + return KErrNotSupported;
1.237 + }
1.238 +
1.239 + if (aAttributeSize != parameterSize)
1.240 + {
1.241 + return KErrArgument;
1.242 + }
1.243 +
1.244 + switch (aAttributeId)
1.245 + {
1.246 + case EScreenAttributeImplementationVersion:
1.247 + *((TUint32*)aAttribute) = KImplementationVersion;
1.248 + break;
1.249 + case EScreenAttributePixelFormat:
1.250 + *((TUint32*)aAttribute) = iScreenInfo.iPixelFormat;
1.251 + break;
1.252 + case EScreenAttributeBytesPerPixel:
1.253 + *((TUint32*)aAttribute) = iScreenInfo.iBytesPerPixel;
1.254 + break;
1.255 + case EScreenAttributeSupportedRotation:
1.256 + *((TUint32*)aAttribute) = iScreenInfo.iSupportedRotations;
1.257 + break;
1.258 + case EScreenAttributeNormalWidth:
1.259 + *((TUint32*)aAttribute) = iScreenInfo.iNormalWidth;
1.260 + break;
1.261 + case EScreenAttributeNormalHeight:
1.262 + *((TUint32*)aAttribute) = iScreenInfo.iNormalHeight;
1.263 + break;
1.264 + case EScreenAttributeNormalStride:
1.265 + *((TUint32*)aAttribute) = iScreenInfo.iNormalStride;
1.266 + break;
1.267 + case EScreenAttributeFlippedWidth:
1.268 + *((TUint32*)aAttribute) = iScreenInfo.iFlippedWidth;
1.269 + break;
1.270 + case EScreenAttributeFlippedHeight:
1.271 + *((TUint32*)aAttribute) = iScreenInfo.iFlippedHeight;
1.272 + break;
1.273 + case EScreenAttributeFlippedStride:
1.274 + *((TUint32*)aAttribute) = iScreenInfo.iFlippedStride;
1.275 + break;
1.276 + case EScreenAttributeDefaultRotation:
1.277 + *((TUint32*)aAttribute) = iScreenInfo.iDefaultRotation;
1.278 + break;
1.279 + case EScreenAttributeCurrentRotation:
1.280 + *((TUint32*)aAttribute) = iScreenInfo.iCurrentRotation;
1.281 + break;
1.282 + case EScreenAttributeScreenGeometry:
1.283 + *((TScreenGeometryAttribute*)aAttribute) = iScreenInfo;
1.284 + break;
1.285 + default:
1.286 + return KErrNotSupported;
1.287 + }
1.288 +
1.289 + return KErrNone;
1.290 + }
1.291 +
1.292 +
1.293 +TInt COpenWFC_RI_DisplayChannel::SetAttribute(TInt aAttributeId, TAny* aAttribute, TInt aAttributeSize)
1.294 + {
1.295 + // the only parameter we can modify is the current rotation
1.296 + TInt parameterSize = GetAttributeSize(aAttributeId);
1.297 +
1.298 + if (aAttributeSize != parameterSize || aAttribute == NULL)
1.299 + {
1.300 + return KErrArgument;
1.301 + }
1.302 +
1.303 + switch (aAttributeId)
1.304 + {
1.305 + case EScreenAttributeCurrentRotation:
1.306 + iNewRotation = static_cast<TScreenRotation>(*((TUint32*)aAttribute));
1.307 + break;
1.308 + default:
1.309 + return KErrNotSupported;
1.310 + }
1.311 + return KErrNone;
1.312 + }
1.313 +
1.314 +
1.315 +TInt COpenWFC_RI_DisplayChannel::CommitAttribute()
1.316 + {
1.317 + // For DisplayChannel the new screen attributes must be applied
1.318 + // at the same time with the composition.
1.319 + if (iScreenInfo.iCurrentRotation != iNewRotation)
1.320 + {
1.321 + TInt totalRotation;
1.322 + RDisplayChannel::TDisplayRotation dcRotation;
1.323 +
1.324 + // Change the rotation to a numeric index from zero
1.325 + switch (iNewRotation)
1.326 + {
1.327 + case EScreenRotate90:
1.328 + totalRotation = 1;
1.329 + break;
1.330 + case EScreenRotate180:
1.331 + totalRotation = 2;
1.332 + break;
1.333 + case EScreenRotate270:
1.334 + totalRotation = 3;
1.335 + break;
1.336 + case EScreenRotate0:
1.337 + default:
1.338 + __ASSERT_DEBUG(iNewRotation == EScreenRotate0, Panic(__LINE__));
1.339 + totalRotation = 0;
1.340 + break;
1.341 + }
1.342 +
1.343 + // Add the initial rotation of the device and wrap to get final one.
1.344 + totalRotation = (totalRotation + iRotationOffset) % 4;
1.345 +
1.346 + // Now change the final rotation to the display channel rotation
1.347 + switch (totalRotation)
1.348 + {
1.349 + case 1:
1.350 + dcRotation = RDisplayChannel::ERotation90CW;
1.351 + break;
1.352 + case 2:
1.353 + dcRotation = RDisplayChannel::ERotation180;
1.354 + break;
1.355 + case 3:
1.356 + dcRotation = RDisplayChannel::ERotation270CW;
1.357 + break;
1.358 + case 0:
1.359 + default:
1.360 + __ASSERT_DEBUG(totalRotation == 0, Panic(__LINE__));
1.361 + dcRotation = RDisplayChannel::ERotationNormal;
1.362 + break;
1.363 + }
1.364 +
1.365 + if (!(iScreenInfo.iSupportedRotations & dcRotation))
1.366 + {
1.367 + return KErrNotSupported;
1.368 + }
1.369 +
1.370 + // We do not need to use this boolean
1.371 + TBool displayConfigChanged;
1.372 + TInt err = iDispChan.SetRotation(dcRotation, displayConfigChanged);
1.373 + __ASSERT_DEBUG(err == KErrNone, Panic(__LINE__));
1.374 + if (err == KErrNone)
1.375 + {
1.376 + iScreenInfo.iCurrentRotation = iNewRotation;
1.377 + }
1.378 + else
1.379 + {
1.380 + return err;
1.381 + }
1.382 + }
1.383 + return KErrNone;
1.384 + }
1.385 +
1.386 +TInt COpenWFC_RI_DisplayChannel::SetLayerSurface(TInt aLayer, SymbianStreamType aStream,TInt* aNonTrivialAttribs)
1.387 + {
1.388 + // display channel interface can be seen as mono-layered
1.389 + if (aLayer != 0)
1.390 + {
1.391 + return KErrArgument;
1.392 + }
1.393 + if (aNonTrivialAttribs && *aNonTrivialAttribs)
1.394 + {
1.395 + return KErrNotSupported;
1.396 + }
1.397 + TBool acceptable=ETrue;
1.398 + khronos_int32_t format,pixSize;
1.399 + SymbianStreamGetHeader(aStream,NULL,NULL,NULL,&format,&pixSize);
1.400 + if (format!=EUidPixelFormatARGB_8888 && format!=EUidPixelFormatARGB_8888_PRE && format!=EUidPixelFormatXRGB_8888)
1.401 + {
1.402 + acceptable=EFalse;
1.403 + }
1.404 +
1.405 + if (!acceptable)
1.406 + {
1.407 + return KErrNotSupported;
1.408 + }
1.409 +
1.410 + iCurrentSceneStream = aStream;
1.411 + return KErrNone;
1.412 + }
1.413 +
1.414 +TInt COpenWFC_RI_DisplayChannel::SetTopLayerSurface(SymbianStreamType aStream,TInt* aNonTrivialAttribs)
1.415 + {
1.416 + return SetLayerSurface(KTopMostLayer, aStream,aNonTrivialAttribs);
1.417 + }
1.418 +
1.419 +TInt COpenWFC_RI_DisplayChannel::UpdateDisplay()
1.420 + {
1.421 + // The solution is suboptimal because a blit is used insteat of posting a user buffer
1.422 + // The solution is more simpler and because the emulator is to be phased-out soon,
1.423 + // there is no much incentive in complicating the code
1.424 + TInt err;
1.425 +
1.426 + TUint bufferIndex;
1.427 + TRequestStatus status;
1.428 + iDispChan.GetCompositionBuffer(bufferIndex, status);
1.429 + User::WaitForRequest(status);
1.430 +
1.431 + err = status.Int();
1.432 + if (err != KErrNone || bufferIndex >= iCompositionBuffer.Count())
1.433 + {
1.434 + return KErrGeneral;
1.435 + }
1.436 +
1.437 + TUint8* firstPixelAddr = iCompositionBuffer[bufferIndex]->iAddress;
1.438 +
1.439 + // Only 32 or 16bpp supported and assume stride == width * pixel size
1.440 + TInt size = 0;
1.441 + if (iNewRotation == EScreenRotate0 || iNewRotation == EScreenRotate180)
1.442 + {
1.443 + size = iScreenInfo.iNormalHeight * iScreenInfo.iNormalStride;
1.444 + }
1.445 + else
1.446 + {
1.447 + size = iScreenInfo.iFlippedHeight * iScreenInfo.iFlippedStride;
1.448 + }
1.449 + SymbianStreamBuffer frontBuffer;
1.450 + SymbianStreamAcquireReadBuffer(iCurrentSceneStream, &frontBuffer);
1.451 + void* pixelDataPtr = NULL;
1.452 + SymbianStreamGetBufferPointer(iCurrentSceneStream, frontBuffer,&pixelDataPtr);
1.453 + Mem::Move(firstPixelAddr, pixelDataPtr, size);
1.454 + RDisplayChannel::TPostCount postCount;
1.455 + err = iDispChan.PostCompositionBuffer(NULL, postCount);
1.456 + if (err == KErrNone)
1.457 + {
1.458 + // This will throttle composition more than necessary,
1.459 + // since it will wait until buffer is being displayed
1.460 + iDispChan.WaitForPost(postCount, status);
1.461 + User::WaitForRequest(status);
1.462 + err = status.Int();
1.463 + }
1.464 +
1.465 + SymbianStreamReleaseReadBuffer(iCurrentSceneStream, frontBuffer);
1.466 +
1.467 + return err;
1.468 + }
1.469 +