os/graphics/graphicscomposition/openwfc_ri_displaychannel/src/openwfc_ri_displaychannel.cpp
author sl@SLION-WIN7.fritz.box
Fri, 15 Jun 2012 03:10:57 +0200
changeset 0 bde4ae8d615e
permissions -rw-r--r--
First public contribution.
     1 // Copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
     2 //
     3 // Permission is hereby granted, free of charge, to any person obtaining a
     4 // copy of this software and/or associated documentation files (the
     5 // "Materials"), to deal in the Materials without restriction, including
     6 // without limitation the rights to use, copy, modify, merge, publish,
     7 // distribute, sublicense, and/or sell copies of the Materials, and to
     8 // permit persons to whom the Materials are furnished to do so, subject to
     9 // the following conditions:
    10 //
    11 // The above copyright notice and this permission notice shall be included
    12 // in all copies or substantial portions of the Materials.
    13 //
    14 // THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
    15 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
    16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
    17 // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
    18 // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
    19 // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
    20 // MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
    21 // 
    22 // Description:
    23 // Display Adaptation Interface Implementation for Display channel
    24 // 
    25 //
    26 
    27 #include "openwfc_ri_displaychannel.h"
    28 #include <e32debug.h>
    29 #include <hal.h>
    30 
    31 _LIT(KDisplayChannelLdd, "display0.ldd");
    32 const TUint32 KDefaultScreenNumber = 0;
    33 
    34 #ifdef _DEBUG
    35 void Panic(TInt aPanic)
    36     {
    37     _LIT(KPanic, "DA-DC");
    38     User::Panic(KPanic, aPanic);
    39     }
    40 #endif
    41 
    42 EXPORT_C COpenWFC_RI_Display* COpenWFC_RI_Display::NewL(TUint aScreen)
    43     {
    44     return COpenWFC_RI_DisplayChannel::NewL(aScreen);
    45     }
    46 
    47 EXPORT_C TUint32 COpenWFC_RI_Display::DefaultScreenNumber()
    48     {
    49     return KDefaultScreenNumber;
    50     }
    51     
    52 COpenWFC_RI_DisplayChannel::COpenWFC_RI_DisplayChannel(TUint aScreen):
    53 iScreenNumber(aScreen),
    54 iCurrentSceneStream(SYMBIAN_INVALID_HANDLE)
    55     {
    56     }
    57 
    58 COpenWFC_RI_DisplayChannel* COpenWFC_RI_DisplayChannel::NewL(TUint aScreen)
    59     {
    60     COpenWFC_RI_DisplayChannel* screenContext = new(ELeave) COpenWFC_RI_DisplayChannel(aScreen);
    61     CleanupStack::PushL(screenContext);
    62     screenContext->ConstructL();
    63     CleanupStack::Pop(screenContext);
    64     return screenContext;
    65     }
    66 
    67 COpenWFC_RI_DisplayChannel::~COpenWFC_RI_DisplayChannel()
    68     {
    69     TInt count = iCompositionBuffer.Count();
    70     for(TInt ii = 0; ii < count; ++ii)
    71         {
    72         TBufferAddress* addr = iCompositionBuffer[ii];
    73         if (addr)
    74             {
    75             addr->iChunk.Close();
    76             delete addr;
    77             }
    78         }
    79     iCompositionBuffer.Close();
    80     // We do not need to use this boolean
    81     TBool unused;
    82     // Reset the initial rotation for next time.
    83     iDispChan.SetRotation(iDefaultRotation, unused);
    84     iDispChan.Close();
    85     }
    86 
    87 void COpenWFC_RI_DisplayChannel::ConstructL()
    88     {
    89     TInt err = User::LoadLogicalDevice(KDisplayChannelLdd);
    90     if (err != KErrNone && err != KErrAlreadyExists)
    91         {
    92         User::Leave(err);
    93         }
    94     
    95     User::LeaveIfError(iDispChan.Open(iScreenNumber));
    96 //#ifdef __WINS__
    97     iScreenInfo.iDefaultRotation = EScreenRotate0;
    98     iDefaultRotation = RDisplayChannel::ERotationNormal;
    99     iRotationOffset = 0;
   100 //#else
   101 //    iScreenInfo.iDefaultRotation = EScreenRotate270;
   102 //    iDefaultRotation = RDisplayChannel::ERotation270CW;
   103 //    iRotationOffset = 3;
   104 //#endif
   105     RDisplayChannel::TDisplayRotation rotation = iDispChan.CurrentRotation();
   106     switch (rotation)
   107         {
   108         case RDisplayChannel::ERotationNormal:
   109             iScreenInfo.iCurrentRotation = EScreenRotate0;
   110             break;
   111         case RDisplayChannel::ERotation90CW:
   112             iScreenInfo.iCurrentRotation = EScreenRotate90;
   113             break;
   114         case RDisplayChannel::ERotation180:
   115             iScreenInfo.iCurrentRotation = EScreenRotate180;
   116             break;
   117         case RDisplayChannel::ERotation270CW:
   118             iScreenInfo.iCurrentRotation = EScreenRotate270;
   119             break;
   120         default:
   121             RDebug::Printf("COpenWFC_RI_DisplayChannel::ConstructL() unsupported rotation %d", rotation);
   122             User::Leave(KErrNotSupported);
   123         }
   124     
   125     iNewRotation = iScreenInfo.iCurrentRotation;
   126     TPckgBuf<RDisplayChannel::TDisplayInfo> pkgInfo;
   127     iDispChan.GetDisplayInfo(pkgInfo);
   128     RDisplayChannel::TDisplayInfo info = pkgInfo();
   129     /* Note that in theory other formats could be supported for composition 
   130      * (eg  EUidPixelFormatARGB_8888 | EUidPixelFormatARGB_8888_PRE )
   131      * So long as the background colour is opaque then the final composed image should end up opaque,
   132      * so compatible with alpha modes.
   133      * However, it would give problems for fastpathing, where alpha byte should be ignored,
   134      * probably fastpath would need to be disabled.
   135      * At present we only care about PlatSim, 
   136      * and it is unlikely that any platform will NOT support xrgb32,
   137      * so it is better to assert the capabilities match than think about this hypothetical case too hard.  
   138      */
   139     if (info.iPixelFormat != EUidPixelFormatXRGB_8888)
   140         {
   141         RDebug::Printf("COpenWFC_RI_DisplayChannel::ConstructL() unsupported pixel format 0x%08.8x", info.iPixelFormat);
   142         User::Leave(KErrNotSupported);
   143         }
   144 
   145     iScreenInfo.iPixelFormat = EUidPixelFormatXRGB_8888;
   146     iScreenInfo.iSupportedRotations = info.iAvailableRotations;
   147     
   148     TInt bytesPerPixel = 4;
   149     if((info.iBitsPerPixel != 24) && (info.iBitsPerPixel != 32))
   150         {
   151         RDebug::Printf("COpenWFC_RI_DisplayChannel::ConstructL()unexpected bpp value %d", info.iBitsPerPixel);
   152         }
   153     
   154     iScreenInfo.iBytesPerPixel = bytesPerPixel;
   155     
   156     if (iRotationOffset & 1)
   157         {
   158         // Either 90 or 270 degree rotation, so reverse the normal and flipped
   159         // sizes (which relate to zero degrees rotation).
   160         iScreenInfo.iNormalWidth = info.iFlipped.iWidth;
   161         iScreenInfo.iNormalHeight = info.iFlipped.iHeight;
   162         iScreenInfo.iNormalStride = info.iFlipped.iOffsetBetweenLines;
   163         iScreenInfo.iFlippedWidth = info.iNormal.iWidth;
   164         iScreenInfo.iFlippedHeight = info.iNormal.iHeight;
   165         iScreenInfo.iFlippedStride = info.iNormal.iOffsetBetweenLines;
   166         }
   167     else
   168         {
   169         iScreenInfo.iNormalWidth = info.iNormal.iWidth;
   170         iScreenInfo.iNormalHeight = info.iNormal.iHeight;
   171         iScreenInfo.iNormalStride = info.iNormal.iOffsetBetweenLines;
   172         iScreenInfo.iFlippedWidth = info.iFlipped.iWidth;
   173         iScreenInfo.iFlippedHeight = info.iFlipped.iHeight;
   174         iScreenInfo.iFlippedStride = info.iFlipped.iOffsetBetweenLines;
   175         }
   176         
   177     if (iScreenInfo.iNormalStride < 0)
   178         {
   179         iScreenInfo.iNormalStride = bytesPerPixel * iScreenInfo.iNormalWidth;
   180         }
   181     if (iScreenInfo.iFlippedStride < 0)
   182         {
   183         iScreenInfo.iFlippedStride = bytesPerPixel * iScreenInfo.iFlippedWidth;
   184         }
   185     
   186     for(TInt i = 0; i < info.iNumCompositionBuffers; ++i)
   187         {
   188         iCompositionBuffer.AppendL(NULL);
   189         TBufferAddress* address = new(ELeave) TBufferAddress;
   190         iCompositionBuffer[i] = address;
   191         User::LeaveIfError(iDispChan.GetCompositionBufferInfo(i, address->iChunk, address->iOffset));
   192         address->iAddress = address->iChunk.Base() + address->iOffset;
   193         }
   194     }
   195 
   196 TInt COpenWFC_RI_Display::GetAttributeSize(TUint aAttributeId)
   197     {
   198     switch (aAttributeId)
   199         {
   200         case EScreenAttributeImplementationVersion:
   201         case EScreenAttributePixelFormat:
   202         case EScreenAttributeBytesPerPixel:
   203         case EScreenAttributeSupportedRotation:
   204         case EScreenAttributeNormalWidth:
   205         case EScreenAttributeNormalHeight:
   206         case EScreenAttributeNormalStride:
   207         case EScreenAttributeFlippedWidth:
   208         case EScreenAttributeFlippedHeight:
   209         case EScreenAttributeFlippedStride:
   210         case EScreenAttributeDefaultRotation:
   211         case EScreenAttributeCurrentRotation:
   212             return sizeof(TUint32);
   213          
   214         case EScreenAttributeScreenGeometry:
   215             return sizeof(TScreenGeometryAttribute);
   216             
   217         default:
   218             return 0;
   219         }
   220     }
   221 
   222 TInt COpenWFC_RI_DisplayChannel::GetAttribute(TInt aAttributeId, TAny* aAttribute, TInt aAttributeSize)
   223     {
   224     TInt parameterSize = GetAttributeSize(aAttributeId);
   225 
   226     if (aAttribute == NULL)
   227         {
   228         return KErrArgument;
   229         }
   230     
   231     if (parameterSize == 0) 
   232         {
   233         return KErrNotSupported;
   234         }
   235     
   236     if (aAttributeSize != parameterSize)
   237         {
   238         return KErrArgument;
   239         }
   240     
   241     switch (aAttributeId)
   242         {
   243         case EScreenAttributeImplementationVersion:
   244             *((TUint32*)aAttribute) = KImplementationVersion;
   245             break;
   246         case EScreenAttributePixelFormat:
   247             *((TUint32*)aAttribute) = iScreenInfo.iPixelFormat;
   248             break;            
   249         case EScreenAttributeBytesPerPixel:
   250             *((TUint32*)aAttribute) = iScreenInfo.iBytesPerPixel;
   251             break;
   252         case EScreenAttributeSupportedRotation:
   253             *((TUint32*)aAttribute) = iScreenInfo.iSupportedRotations;
   254             break;
   255         case EScreenAttributeNormalWidth:
   256             *((TUint32*)aAttribute) = iScreenInfo.iNormalWidth;
   257             break;
   258         case EScreenAttributeNormalHeight:
   259             *((TUint32*)aAttribute) = iScreenInfo.iNormalHeight;
   260             break;
   261         case EScreenAttributeNormalStride:
   262             *((TUint32*)aAttribute) = iScreenInfo.iNormalStride;
   263             break;
   264         case EScreenAttributeFlippedWidth:
   265             *((TUint32*)aAttribute) = iScreenInfo.iFlippedWidth;
   266             break;
   267         case EScreenAttributeFlippedHeight:
   268             *((TUint32*)aAttribute) = iScreenInfo.iFlippedHeight;
   269             break;
   270         case EScreenAttributeFlippedStride:
   271             *((TUint32*)aAttribute) = iScreenInfo.iFlippedStride;
   272             break;
   273         case EScreenAttributeDefaultRotation:
   274             *((TUint32*)aAttribute) = iScreenInfo.iDefaultRotation;
   275             break;
   276         case EScreenAttributeCurrentRotation:
   277             *((TUint32*)aAttribute) = iScreenInfo.iCurrentRotation;
   278             break;
   279         case EScreenAttributeScreenGeometry:
   280             *((TScreenGeometryAttribute*)aAttribute) = iScreenInfo;
   281             break;
   282         default:
   283             return KErrNotSupported;
   284         }
   285     
   286     return KErrNone;
   287     }
   288 
   289 
   290 TInt COpenWFC_RI_DisplayChannel::SetAttribute(TInt aAttributeId, TAny* aAttribute, TInt aAttributeSize)
   291     {
   292     // the only parameter we can modify is the current rotation
   293     TInt parameterSize = GetAttributeSize(aAttributeId);
   294 
   295     if (aAttributeSize != parameterSize || aAttribute == NULL)
   296         {
   297         return KErrArgument;
   298         }
   299     
   300     switch (aAttributeId)
   301         {
   302         case EScreenAttributeCurrentRotation:
   303             iNewRotation = static_cast<TScreenRotation>(*((TUint32*)aAttribute));
   304             break;
   305         default:
   306             return KErrNotSupported;
   307         }
   308     return KErrNone;
   309     }
   310 
   311 
   312 TInt COpenWFC_RI_DisplayChannel::CommitAttribute()
   313     {
   314     // For DisplayChannel the new screen attributes must be applied
   315     // at the same time with the composition.
   316     if (iScreenInfo.iCurrentRotation != iNewRotation)
   317         {
   318         TInt totalRotation;
   319         RDisplayChannel::TDisplayRotation dcRotation;
   320 
   321         // Change the rotation to a numeric index from zero
   322         switch (iNewRotation)
   323             {
   324             case EScreenRotate90:
   325                 totalRotation = 1;
   326                 break;
   327             case EScreenRotate180:
   328                 totalRotation = 2;
   329                 break;
   330             case EScreenRotate270:
   331                 totalRotation = 3;
   332                 break;
   333             case EScreenRotate0:
   334             default:
   335                 __ASSERT_DEBUG(iNewRotation == EScreenRotate0, Panic(__LINE__));
   336                 totalRotation = 0;
   337                 break;
   338             }
   339 
   340         // Add the initial rotation of the device and wrap to get final one.
   341         totalRotation = (totalRotation + iRotationOffset) % 4;
   342 
   343         // Now change the final rotation to the display channel rotation
   344         switch (totalRotation)
   345             {
   346             case 1:
   347                 dcRotation = RDisplayChannel::ERotation90CW;
   348                 break;
   349             case 2:
   350                 dcRotation = RDisplayChannel::ERotation180;
   351                 break;
   352             case 3:
   353                 dcRotation = RDisplayChannel::ERotation270CW;
   354                 break;
   355             case 0:
   356             default:
   357                 __ASSERT_DEBUG(totalRotation == 0, Panic(__LINE__));
   358                 dcRotation = RDisplayChannel::ERotationNormal;
   359                 break;
   360             }
   361 
   362         if (!(iScreenInfo.iSupportedRotations & dcRotation))
   363             {
   364             return KErrNotSupported;
   365             }
   366         
   367         // We do not need to use this boolean
   368         TBool displayConfigChanged;
   369         TInt err = iDispChan.SetRotation(dcRotation, displayConfigChanged);
   370         __ASSERT_DEBUG(err == KErrNone, Panic(__LINE__));
   371         if (err == KErrNone)
   372             {
   373             iScreenInfo.iCurrentRotation = iNewRotation;
   374             }
   375         else
   376             {
   377             return err;
   378             }
   379         }
   380     return KErrNone;
   381     }
   382 
   383 TInt COpenWFC_RI_DisplayChannel::SetLayerSurface(TInt aLayer, SymbianStreamType aStream,TInt* aNonTrivialAttribs)
   384     {
   385     // display channel interface can be seen as mono-layered
   386     if (aLayer != 0)
   387         {
   388         return KErrArgument;
   389         }
   390     if (aNonTrivialAttribs && *aNonTrivialAttribs)
   391         {
   392         return KErrNotSupported;
   393         }
   394     TBool acceptable=ETrue;
   395     khronos_int32_t format,pixSize;
   396     SymbianStreamGetHeader(aStream,NULL,NULL,NULL,&format,&pixSize);
   397     if (format!=EUidPixelFormatARGB_8888 && format!=EUidPixelFormatARGB_8888_PRE && format!=EUidPixelFormatXRGB_8888)
   398         {
   399         acceptable=EFalse;
   400         }
   401             
   402     if (!acceptable)
   403         {
   404         return KErrNotSupported;
   405         }
   406     
   407     iCurrentSceneStream = aStream;
   408     return KErrNone;
   409     }
   410 
   411 TInt COpenWFC_RI_DisplayChannel::SetTopLayerSurface(SymbianStreamType aStream,TInt* aNonTrivialAttribs)
   412     {
   413     return SetLayerSurface(KTopMostLayer, aStream,aNonTrivialAttribs);
   414     }
   415 
   416 TInt COpenWFC_RI_DisplayChannel::UpdateDisplay()
   417     {
   418     // The solution is suboptimal because a blit is used insteat of posting a user buffer
   419     // The solution is more simpler and because the emulator is to be phased-out soon,
   420     // there is no much incentive in complicating the code
   421     TInt err;
   422     
   423     TUint bufferIndex;
   424     TRequestStatus status;
   425     iDispChan.GetCompositionBuffer(bufferIndex, status);
   426     User::WaitForRequest(status);
   427     
   428     err = status.Int();
   429     if (err != KErrNone || bufferIndex >= iCompositionBuffer.Count()) 
   430         {
   431         return KErrGeneral;
   432         }
   433     
   434     TUint8* firstPixelAddr = iCompositionBuffer[bufferIndex]->iAddress;
   435     
   436     // Only 32 or 16bpp supported and assume stride == width * pixel size
   437     TInt size = 0;
   438     if (iNewRotation == EScreenRotate0 || iNewRotation == EScreenRotate180)
   439         {
   440         size = iScreenInfo.iNormalHeight * iScreenInfo.iNormalStride; 
   441         }
   442     else
   443         {
   444         size = iScreenInfo.iFlippedHeight * iScreenInfo.iFlippedStride; 
   445         }
   446     SymbianStreamBuffer frontBuffer;
   447     SymbianStreamAcquireReadBuffer(iCurrentSceneStream, &frontBuffer);
   448     void* pixelDataPtr = NULL;
   449     SymbianStreamGetBufferPointer(iCurrentSceneStream, frontBuffer,&pixelDataPtr);
   450     Mem::Move(firstPixelAddr, pixelDataPtr, size);
   451     RDisplayChannel::TPostCount postCount;
   452     err = iDispChan.PostCompositionBuffer(NULL, postCount);
   453     if (err == KErrNone)
   454         {
   455         // This will throttle composition more than necessary,
   456         // since it will wait until buffer is being displayed
   457         iDispChan.WaitForPost(postCount, status);
   458         User::WaitForRequest(status);
   459         err = status.Int();
   460         }
   461     
   462     SymbianStreamReleaseReadBuffer(iCurrentSceneStream, frontBuffer);
   463 
   464     return err;
   465     }
   466