os/graphics/windowing/windowserverplugins/openwfc/src/openwfcwrapper.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 2008-2010 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description: Owns, hides, and provides an interface to the OpenWFC compositor for use by the final (display) render stage.
    14 
    15 #include "openwfcwrapper.h"
    16 #include "panic.h"
    17 #include "utils.h"
    18 
    19 #include <WF/wfc.h>
    20 #include "elementwrapper.h"
    21 #include <graphics/compositionsurfaceupdate.h>
    22 #include <graphics/symbianstream.h>
    23 #include "openwfcpanics.h"
    24 #include "openwfcjobmanager.h"
    25 
    26 #include <graphics/eglsynchelper.h>
    27 
    28 #define KRgbaBlack       0x000000FF
    29 
    30 void Panic(TOpenWfcPanic aPanic)
    31     {
    32     _LIT(KPanic, "OpenWFC");
    33     User::Panic(KPanic, aPanic);
    34     }
    35 
    36 class COpenWfcWrapper::OffScreenComposeGuard
    37     {
    38     public:
    39         OffScreenComposeGuard(TRequestStatus*& aRequestStatus);
    40         void SetOffScreenNativeStream(WFCNativeStreamType aNativeStream);
    41         void SetTargetNativeStream(WFCNativeStreamType aNativeStream);
    42         void SetSync(EGLSyncKHR aSync, EGLDisplay aDpy);
    43         void SetDeviceAndContext(WFCDevice aDevice, WFCContext aContext);
    44         void Close();
    45         void LogRequestStatusError(TInt aRequestStatusError);
    46     private:
    47         TRequestStatus*& iRequestStatus;
    48         EGLSyncKHR iSync;
    49         EGLDisplay iEGLDisplay;
    50         WFCDevice iDevice;
    51         WFCContext iContext;
    52         TInt    iRequestStatusError;
    53     };
    54 
    55 COpenWfcWrapper::OffScreenComposeGuard::OffScreenComposeGuard(TRequestStatus*& aRequestStatus):
    56 iRequestStatus(aRequestStatus),
    57 iSync(EGL_NO_SYNC_KHR),
    58 iDevice(WFC_INVALID_HANDLE),
    59 iContext(WFC_INVALID_HANDLE),
    60 iRequestStatusError(KErrNone)
    61     {}
    62 
    63 
    64 void COpenWfcWrapper::OffScreenComposeGuard::SetSync(EGLSyncKHR aSync, EGLDisplay aDpy)
    65     {
    66     iSync = aSync;
    67     iEGLDisplay = aDpy;
    68     }
    69 
    70 void COpenWfcWrapper::OffScreenComposeGuard::SetDeviceAndContext(WFCDevice aDevice, WFCContext aContext)
    71     {
    72     iContext = aContext; 
    73     iDevice = aDevice;
    74     }
    75 
    76 void COpenWfcWrapper::OffScreenComposeGuard::LogRequestStatusError(TInt aRequestStatusError)
    77     {
    78     iRequestStatusError=aRequestStatusError;
    79     }
    80 
    81 void COpenWfcWrapper::OffScreenComposeGuard::Close()
    82     {
    83     if (iContext != WFC_INVALID_HANDLE)
    84         {
    85         DestroyAllContextElements(iDevice, iContext);
    86         wfcDestroyContext(iDevice, iContext);
    87         }
    88   
    89     if (iSync != EGL_NO_SYNC_KHR)
    90         {
    91         eglDestroySyncKHR(iEGLDisplay, iSync);
    92         }
    93 
    94     if (iRequestStatus)
    95         {
    96         User::RequestComplete(iRequestStatus, iRequestStatusError);
    97         }
    98     }
    99 
   100 TEMPLATE_SPECIALIZATION class RHashTableBase::Defaults<TSurfaceId, RHashTableBase::EDefaultSpecifier_Normal>
   101     {
   102 public:
   103     inline static TGeneralHashFunction32 Hash();
   104     inline static TGeneralIdentityRelation Id();
   105     };
   106 
   107 inline TGeneralHashFunction32 RHashTableBase::Defaults<TSurfaceId, RHashTableBase::EDefaultSpecifier_Normal>::Hash()
   108     {return (TGeneralHashFunction32)&DefaultHash::Integer;}
   109 
   110 inline TGeneralIdentityRelation RHashTableBase::Defaults<TSurfaceId, RHashTableBase::EDefaultSpecifier_Normal>::Id()
   111     {return (TGeneralIdentityRelation)&DefaultIdentity::Integer;}
   112 
   113 TUint32 COpenWfcWrapper::HashFunction(const TSurfaceId& aHashKey)
   114     {
   115     TPckgC<TSurfaceId> pckg(aHashKey);
   116     return DefaultHash::Des8(pckg);
   117     }
   118 COpenWfcWrapper* COpenWfcWrapper::NewL(TInt aScreenNo, CDisplayPolicy* aDisplayPolicy)
   119 	{
   120 	COpenWfcWrapper* wrapper = new (ELeave) COpenWfcWrapper(aDisplayPolicy);
   121 	CleanupStack::PushL(wrapper);
   122 	wrapper->ConstructL(aScreenNo);
   123 	CleanupStack::Pop(wrapper);
   124 	return wrapper;
   125 	}
   126 
   127 COpenWfcWrapper::COpenWfcWrapper(CDisplayPolicy* aDisplayPolicy)
   128 	: iUiSurface(TSurfaceId::CreateNullId()), iDisplayPolicy(aDisplayPolicy),
   129 	iSourceMap(THashFunction32<TSurfaceId>(COpenWfcWrapper::HashFunction), TIdentityRelation<TSurfaceId>()),
   130 	iDevice(WFC_INVALID_HANDLE),
   131 	iOnScreenContext(WFC_INVALID_HANDLE),
   132 	iScreenNumber(-1),
   133 	iJobManager(NULL),
   134 	iRotation(MWsScene::ESceneAntiClockwise0),
   135 	iAutonomousCompositionInitiated(EFalse)
   136 	{
   137 	}
   138 
   139 void COpenWfcWrapper::ConstructL(TInt aScreenId)
   140 	{
   141 #ifdef _DEBUG
   142     _LIT(KOpenWfcLog, "+ COpenWfcWrapper::ConstructL");
   143     RDebug::Print(KOpenWfcLog);
   144 #endif
   145 
   146     iScreenNumber = aScreenId;
   147     WFCint filterList[] = { WFC_DEVICE_FILTER_SCREEN_NUMBER, iScreenNumber, WFC_NONE};
   148 
   149     iEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
   150     eglInitialize(iEGLDisplay, NULL, NULL);
   151         
   152     WFCint dev = 0;
   153     if ((wfcEnumerateDevices(&dev, 1, filterList) == 1) &&
   154         (dev != WFC_INVALID_HANDLE))
   155         {
   156         // clean previous errors
   157         wfcGetError(iDevice);
   158     
   159         // Let's get the device handle, opening in the same time the device
   160         iDevice = wfcCreateDevice(dev, NULL);
   161         if (iDevice==NULL)
   162             {
   163             //Not enough information to deduce why the device could not be created. Report as memory failure
   164             User::Leave(KErrNoMemory);
   165             }
   166         //Can't clean previous errors until we have a device, and the errors should be none if it created successfully.
   167         OPENWFC_ASSERT_DEBUG(!wfcGetError(iDevice),EPanicWfcStartupErrorUnexpected);
   168         
   169         iOnScreenContext = wfcCreateOnScreenContext(iDevice, iScreenNumber, NULL);
   170         if (iOnScreenContext==NULL)
   171             {
   172             TInt err = wfcGetError(iDevice);
   173             OPENWFC_ASSERT_DEBUG(err==WFC_ERROR_OUT_OF_MEMORY,EPanicWfcContextNotCreated);
   174             User::Leave((err==WFC_ERROR_OUT_OF_MEMORY)?KErrNoMemory:KErrUnknown);
   175             }
   176 
   177         wfcSetContextAttribi(iDevice, iOnScreenContext, WFC_CONTEXT_ROTATION, WFC_ROTATION_0);
   178         wfcSetContextAttribi(iDevice, iOnScreenContext, WFC_CONTEXT_BG_COLOR, KRgbaBlack);
   179         
   180         iContextDisplayControl = NULL;
   181         
   182         User::LeaveIfNull(iJobManager = COpenWfcJobManger::NewL(*this, iDevice, iOnScreenContext, iScreenNumber));
   183         }
   184     else
   185         {
   186         // we cannot continue because we cannot find a device for the given screenId
   187         // Not enough information to get detailed error! Report as parameter not accepted.
   188         User::Leave(KErrArgument);
   189         }
   190     iSurfaceManager.Open();
   191 
   192     iSourceMap.Reserve(iInitialSourceMapSize);
   193     }
   194 
   195 COpenWfcWrapper::~COpenWfcWrapper()
   196 	{
   197 	iUiElement1 = NULL;
   198 	iUiElement2 = NULL;
   199     if(!iUiSurface.IsNull())
   200         UnregisterSurface(iUiSurface);
   201     
   202     if (iJobManager)
   203         {
   204         PauseComposition();
   205         delete iJobManager;
   206         }
   207     
   208     //destroy all the elements, which should remove all the element references.
   209     while (iCleanupElementList)
   210         {
   211         CElementWrapper* cleanupElement = iCleanupElementList;
   212         delete cleanupElement;
   213         OPENWFC_ASSERT_DEBUG(cleanupElement != iCleanupElementList,EPanicWfcElementNotRemovedOnShutdown);
   214         if (cleanupElement == iCleanupElementList)
   215             {
   216             break;  //can't keep cleaning up the same front item
   217             }
   218         }
   219     THashMapIter<TSurfaceId, SourceAndRef> iter(iSourceMap);
   220     const TSurfaceId* nextKey = iter.NextKey();
   221     while (nextKey)
   222         {
   223         const SourceAndRef* pSource = NULL;
   224         //destroy any remaining registered surfaces
   225         pSource = iter.CurrentValue();
   226         OPENWFC_ASSERT_DEBUG(pSource && pSource->elementRef == 0,EPanicWfcElementNotRemovedOnShutdown);
   227         wfcDestroySource(iDevice,pSource->source);
   228         nextKey = iter.NextKey();
   229         }
   230 
   231     iSourceMap.Close();
   232     iSurfaceManager.Close();
   233     eglTerminate(iEGLDisplay);
   234 
   235     // Destroying the context should take care of any sources or masks
   236     wfcDestroyContext(iDevice, iOnScreenContext);
   237     wfcDestroyDevice(iDevice);
   238 	}
   239 
   240 class CBaseExtension: public CBase
   241     {
   242     public:
   243         virtual TInt Extension_(TUint aExtensionId, TAny*& a0, TAny* a1)
   244             {   return CBase::Extension_(aExtensionId,a0,a1);   }
   245     };
   246 TInt COpenWfcWrapper::Extension_(TUint aExtensionId, TAny*& aRetPtr, TAny* aExtra)
   247     {
   248 #ifndef _DEBUG
   249     (void) aExtra;
   250 #endif
   251     
   252     switch (aExtensionId)
   253         {
   254 #ifdef _DEBUG
   255         case EExtensionDebugBackendGuid:
   256             return KErrNotSupported;
   257         case EExtensionDebugContextGuid:
   258             aRetPtr=(TAny*)OnScreenContext();
   259             return KErrNone;
   260         case EExtensionDebugDeviceGuid:
   261             aRetPtr=(TAny*)Device();
   262             return KErrNone;
   263         case EExtensionDebugElementGuid:
   264             if (aExtra)
   265                 {
   266                 CElementWrapper* newElement=static_cast<CElementWrapper*>(aExtra);
   267                 aRetPtr=(TAny*)newElement->Element();
   268                 return KErrNone;
   269                 }
   270             else
   271                 {
   272                 return KErrBadHandle;
   273                 }
   274         case EExtensionDebugSourceGuid:
   275             if (aExtra)
   276                 {
   277                 TSurfaceId* surfId=static_cast<TSurfaceId*>(aExtra);
   278                 SourceAndRef* foundSourceAndRef=iSourceMap.Find(*surfId);
   279                 if (foundSourceAndRef)
   280                     {
   281                     aRetPtr=(TAny*)foundSourceAndRef->source;
   282                     return KErrNone;
   283                     }
   284                 else
   285                     {
   286                     return KErrNotFound;
   287                     }
   288                 }
   289             else
   290                 {
   291                 return KErrBadHandle;
   292                 }
   293 #endif
   294         case MCompositionSurfaceUpdate::ETypeId:
   295              {
   296              CBaseExtension* basePtr = NULL;
   297              SymbianStreamHasRegisteredScreenNotifications(iScreenNumber,reinterpret_cast<void**>(&basePtr));
   298              if (basePtr)
   299                  {
   300                  return basePtr->Extension_(MCompositionSurfaceUpdate::KUidCompositionSurfaceUpdate,aRetPtr,aExtra);
   301                  }
   302              else
   303                  {
   304                  return KErrNotSupported;
   305                  }
   306              }
   307         case MWsDisplayControl::ETypeId:
   308             if (iContextDisplayControl)
   309                 {
   310                 aRetPtr= static_cast<MWsDisplayControl*>(this);
   311                 return KErrNone;
   312                 }
   313             else
   314                 {
   315                 return KErrNotSupported;
   316                 }
   317         case MDisplayControlBase::ETypeId:
   318             if (iContextDisplayControl)
   319                 {
   320                 aRetPtr= static_cast<MDisplayControlBase*>(this);
   321                 return KErrNone;
   322                 }
   323             else
   324                 {
   325                 return KErrNotSupported;
   326                 }
   327         default:
   328             return KErrNotSupported;
   329         }
   330     }
   331 MWsElement* COpenWfcWrapper::CreateElementL()
   332 	{
   333 	CElementWrapper* element = CElementWrapper::NewL(*this,iCleanupElementList);
   334 	return element;
   335 	}
   336 
   337 void COpenWfcWrapper::DestroyElement(MWsElement* aElement)
   338 	{		
   339 	if(aElement)
   340 	    {	    
   341 	    CElementWrapper* element=static_cast<CElementWrapper*>(aElement);
   342 	    RemoveElementFromSceneList(element);
   343 	    delete element;
   344 	    }
   345 	}
   346 
   347 void COpenWfcWrapper::Compose(TRequestStatus* aCompleted)
   348 	{
   349 	STD_ASSERT_DEBUG(CompositionDue(), EPluginPanicCompositionSequenceError);
   350 
   351 	OPENWFC_ASSERT_DEBUG(iJobManager, EPanicWfcThreadManagerNotInitialised);
   352     if (!iAutonomousCompositionInitiated)
   353         {
   354         ResumeComposition();
   355         }
   356     iJobManager->ComposeRequest(aCompleted);
   357     
   358 	iCompositionModified = EFalse;
   359 	ResumeCompositorIfPaused();
   360 	}
   361 
   362 TSize COpenWfcWrapper::ScreenSize() const
   363 	{
   364     // clean previous errors
   365     #ifdef _DEBUG
   366     (void)wfcGetError(iDevice);
   367     #endif
   368     
   369     TInt height = wfcGetContextAttribi(iDevice, iOnScreenContext, WFC_CONTEXT_TARGET_HEIGHT);
   370     OPENWFC_ASSERT_DEBUG(TranslateOpenWfcError(wfcGetError(iDevice)) == KErrNone, EPanicWfcBadAttribute);
   371 
   372     TInt width = wfcGetContextAttribi(iDevice, iOnScreenContext, WFC_CONTEXT_TARGET_WIDTH);
   373     OPENWFC_ASSERT_DEBUG(TranslateOpenWfcError(wfcGetError(iDevice)) == KErrNone, EPanicWfcBadAttribute);
   374     
   375     WFCint rotation = wfcGetContextAttribi(iDevice, iOnScreenContext, WFC_CONTEXT_ROTATION);
   376     OPENWFC_ASSERT_DEBUG(TranslateOpenWfcError(wfcGetError(iDevice)) == KErrNone, EPanicWfcBadAttribute);
   377     
   378     return rotation == WFC_ROTATION_0 || rotation == WFC_ROTATION_180 ? TSize(width, height) : TSize(height, width);
   379 	}
   380 
   381 TInt COpenWfcWrapper::RegisterSurface (const TSurfaceId& aSurface)
   382     {
   383     // clean previous errors
   384     wfcGetError(iDevice);
   385     //check surface id not null
   386     if (aSurface.IsNull())
   387         {
   388         return KErrArgument;
   389         }
   390     
   391     if (!IsValidSurface(aSurface))
   392         {
   393         return KErrBadHandle;
   394         } 
   395     
   396     //look for surface being registered
   397     SourceAndRef* sourceAndRef = iSourceMap.Find(aSurface);
   398     if (sourceAndRef)
   399         {
   400         //if registered increase ref count and return
   401         sourceAndRef->sourceRef++;
   402         return KErrNone;
   403         }
   404 
   405     // Surface not currently registered so do so now.
   406     // Initialise struct. Could be handled via. constructor.
   407     SourceAndRef newSourceAndRef;
   408     newSourceAndRef.source = NULL;
   409     newSourceAndRef.sourceRef = 1;    //Surface reference count
   410     newSourceAndRef.elementRef = 0;   //Element reference count
   411 
   412     //No need to acquire stream as public NativeStream handle is TSurfaceId
   413     WFCNativeStreamType stream = reinterpret_cast<WFCNativeStreamType>(&aSurface);
   414 
   415     //create source
   416     newSourceAndRef.source = wfcCreateSourceFromStream(iDevice,iOnScreenContext,stream,NULL);
   417     //check for valid surface size should be performed by compositor in CreateSource.
   418     if (newSourceAndRef.source == WFC_INVALID_HANDLE)
   419         {
   420         return TranslateOpenWfcError(wfcGetError(iDevice));
   421         }
   422     //add to list
   423     TInt err = iSourceMap.Insert(aSurface,newSourceAndRef);
   424     if (err != KErrNone)
   425         {
   426         wfcDestroySource(iDevice,newSourceAndRef.source);
   427         return KErrNoMemory;
   428         }
   429 
   430     return KErrNone;
   431     }
   432 
   433 TInt COpenWfcWrapper::UnregisterSurface (const TSurfaceId& aSurface)
   434     {
   435     //check surface id not null
   436     if (aSurface.IsNull())
   437         {
   438         return KErrArgument;
   439         }
   440 
   441     if (!IsValidSurface(aSurface))
   442         {
   443         return KErrArgument;
   444         }   
   445     
   446     SourceAndRef* sourceAndRef = iSourceMap.Find(aSurface);
   447 
   448     if (sourceAndRef && sourceAndRef->sourceRef == 0)
   449         {
   450         sourceAndRef = NULL;
   451         }
   452     if (sourceAndRef)
   453         {
   454         if (sourceAndRef->sourceRef <= 1)
   455             {
   456             sourceAndRef->sourceRef = 0;
   457 
   458             if (sourceAndRef->elementRef > 0)
   459                 {
   460                 //if elements are currently in use
   461                 return KErrInUse;
   462                 }
   463             wfcDestroySource(iDevice,sourceAndRef->source); //removing source reference on the stream
   464 
   465             //destroy entry
   466             iSourceMap.Remove(aSurface);
   467             return KErrNone;
   468             }
   469         sourceAndRef->sourceRef--;
   470         return KErrNone;
   471         }
   472     return KErrBadHandle;
   473     }
   474 
   475 TBool COpenWfcWrapper::IsValidSurface(const TSurfaceId& aSurface)
   476     {
   477     if (aSurface.Type() != TSurfaceId::EScreenSurface)
   478         {
   479         RSurfaceManager::TInfoBuf buff;
   480         TInt err = SurfaceManager().SurfaceInfo(aSurface, buff);
   481     
   482         if (err == KErrArgument)
   483             {
   484             return EFalse;
   485             }     
   486         } 
   487     return ETrue;
   488     }
   489 
   490 /** 
   491  * Finds the source for a registered surface ID and increments its "element" reference count
   492  * @return registered source handle or WFC_INVALID_HANDLE if not registered
   493  **/
   494 WFCSource COpenWfcWrapper::IncEltRefRegSource(const TSurfaceId& aHashKey)
   495     {
   496     SourceAndRef* foundSourceAndRef=iSourceMap.Find(aHashKey);
   497     if (foundSourceAndRef && foundSourceAndRef->sourceRef)
   498         {   //still registered
   499         foundSourceAndRef->elementRef++;
   500         return foundSourceAndRef->source;
   501         }
   502     return WFC_INVALID_HANDLE;
   503     }
   504 
   505 
   506 /** 
   507  * Finds the source for a registered surface ID and decrements the "element" reference count.
   508  * If all counts are zero then the source is unregistered and the mapping removed   
   509  * @return positive if not destroyed, 0 if destroyed
   510  *         or KErrBadHandle if bad surface id or surface has no element reference count
   511  **/
   512 TInt COpenWfcWrapper::DecEltRefRegSource(const TSurfaceId& aHashKey)
   513     {
   514     SourceAndRef* foundSourceAndRef=iSourceMap.Find(aHashKey);
   515     if (foundSourceAndRef && foundSourceAndRef->elementRef>0)
   516         {
   517         TInt retRefs=((--foundSourceAndRef->elementRef)+foundSourceAndRef->sourceRef);
   518         if (retRefs==0)
   519             {
   520             wfcDestroySource(iDevice,foundSourceAndRef->source);
   521             iSourceMap.Remove(aHashKey);
   522             }
   523         return retRefs;
   524         }
   525     return KErrBadHandle;
   526     }
   527 
   528 void COpenWfcWrapper::RemoveElement(MWsElement* aElement)
   529 	{
   530     if (!aElement)
   531         {
   532         return;
   533         }
   534 	
   535 	CElementWrapper* removeElement = static_cast<CElementWrapper*>(aElement);
   536 	
   537 	//the UI element is a special case since we set and maintain the surface
   538 	TUint32 renderStageFlags;
   539 	removeElement->GetRenderStageFlags(renderStageFlags);
   540 	if (renderStageFlags & MWsElement::EElementIsIndirectlyRenderedUserInterface || 
   541 	    renderStageFlags & MWsElement::EElementIsDirectlyRenderedUserInterface)
   542 		{
   543 		if(removeElement == iUiElement1)
   544 		    iUiElement1 = NULL;
   545 		else if(removeElement == iUiElement2)
   546 		    iUiElement2 = NULL;
   547 		else
   548 			STD_ASSERT_DEBUG(EFalse, EPluginPanicNonMatchingRemovalOfUiElement);
   549 		}
   550 
   551 	RemoveElementFromSceneList(removeElement);
   552 	removeElement->InsertAfter(iRemoveElementList,NULL,CElementWrapper::EUpdate_Remove);  //insert into remove element list!!!
   553 	SetCompositionModified();
   554 	}
   555 
   556 void COpenWfcWrapper::RemoveElementFromSceneList(CElementWrapper* aElement)
   557     {
   558     CElementWrapper** refFromElementBelow=NULL;
   559     if (iSceneElementList==aElement)
   560         {
   561         refFromElementBelow=&iSceneElementList;  //remove from bottom of scene
   562         }
   563     else if (iRemoveElementList==aElement)
   564         {
   565         refFromElementBelow=&iRemoveElementList;
   566         }
   567     else
   568         {
   569         refFromElementBelow=aElement->RefsMyElementBelow();   //remove from current mid-list position
   570         }
   571     
   572     aElement->RemoveAfter(refFromElementBelow);
   573     }
   574 
   575 TInt COpenWfcWrapper::SetUiSurface(const TSurfaceId& aNewUiSurface)
   576 	{
   577 	TInt err = RegisterSurface(aNewUiSurface);
   578 	if (!err)
   579 		{
   580 		if(iUiElement1)
   581 			{
   582 			err = iUiElement1->ConnectSurface(aNewUiSurface);
   583 			STD_ASSERT_DEBUG(!err, EPluginPanicNewUiSurfaceUnsettable);
   584 			}
   585 		if(iUiElement2)
   586 			{
   587 			err = iUiElement2->ConnectSurface(aNewUiSurface);
   588 			STD_ASSERT_DEBUG(!err, EPluginPanicNewUiSurfaceUnsettable);
   589 			}
   590 		}
   591 
   592 	if(!err)
   593 		{
   594 		if(!iUiSurface.IsNull())
   595 			{
   596 			// This should not fail as the surface will no longer be used by any element
   597 			err = UnregisterSurface(iUiSurface);
   598 
   599       if (err == KErrInUse)	// This is not needed once openwf implementation is corrected:
   600 									          // It should not return KErrInUse if it is only the backend holding onto it.
   601 			    {
   602 			    err = KErrNone;
   603 			    }
   604 
   605 			STD_ASSERT_DEBUG(!err, EPluginPanicPreviousUiSurfaceUnregisterable);
   606 			}
   607 
   608 		iUiSurface = aNewUiSurface;
   609 		}
   610 	return err;
   611 	}
   612 
   613 TInt COpenWfcWrapper::AddElement(MWsElement* aElement, MWsElement* aAbove)
   614     {
   615     TInt err = KErrNone;
   616     CElementWrapper* addedElement = static_cast<CElementWrapper*>(aElement);
   617     CElementWrapper* insertAboveThisElement = static_cast<CElementWrapper*>(aAbove);
   618 
   619     if (aElement == aAbove)
   620         {
   621         return KErrArgument;
   622         }
   623     
   624     if (addedElement == NULL || &addedElement->Owner()!=this || 
   625         (insertAboveThisElement && &insertAboveThisElement->Owner()!=this) || 
   626         (addedElement->UpdateFlags() & CElementWrapper::EUpdate_Destroy))
   627         {
   628         return KErrArgument;
   629         }
   630     
   631     if (insertAboveThisElement && 
   632         ((!insertAboveThisElement->RefsMyElementBelow() && iSceneElementList != insertAboveThisElement) || 
   633         (insertAboveThisElement->UpdateFlags() & (CElementWrapper::EUpdate_Remove | CElementWrapper::EUpdate_Destroy))))
   634         {
   635         return KErrArgument;
   636         }
   637     
   638     //the UI element is a special case since we set and maintain the surface
   639     TUint32 renderStageFlags;
   640     addedElement->GetRenderStageFlags(renderStageFlags);
   641     if (renderStageFlags & MWsElement::EElementIsIndirectlyRenderedUserInterface || 
   642         renderStageFlags & MWsElement::EElementIsDirectlyRenderedUserInterface)
   643         {
   644         err = AttachSurfaceToUiElement(addedElement);
   645         }
   646     
   647     if(!err)
   648         {
   649         //figure out which element to add the element above           
   650         const TSurfaceId& newSurf = addedElement->ConnectedSurface();
   651         if (!addedElement->ConnectedSurface().IsNull())
   652             {
   653             //is surface registered
   654             WFCSource newSource = IncEltRefRegSource(newSurf);
   655             if (newSource == WFC_INVALID_HANDLE)
   656                 { //suggests the surface was not registered
   657                 return KErrArgument;
   658                 }
   659             DecEltRefRegSource(newSurf);    //only need to decrement if it found a source
   660             }
   661         
   662         RemoveElementFromSceneList(addedElement);
   663        
   664         // figure out which element to add it below
   665         CElementWrapper** insertBelowThisElement = NULL;
   666         if (insertAboveThisElement)
   667             {
   668             insertBelowThisElement=&insertAboveThisElement->MyElementAbove();
   669             }
   670         else
   671             {
   672             insertBelowThisElement=&iSceneElementList;
   673             }
   674         
   675         addedElement->InsertAfter(*insertBelowThisElement,insertAboveThisElement,CElementWrapper::EUpdate_Insert);
   676         
   677         SetCompositionModified();
   678         }
   679     
   680     return err;
   681     }
   682 
   683 void COpenWfcWrapper::Compose(const TSurfaceId& aOffScreenTarget, TRequestStatus* aCompleted)
   684 	{
   685     if (aOffScreenTarget.IsNull())
   686         {
   687         if (aCompleted)
   688             {
   689             User::RequestComplete(aCompleted, KErrNone);
   690             return;
   691             }
   692         }
   693     ComposeInternal(aOffScreenTarget,TPoint(0,0),iSceneElementList,NULL,aCompleted);
   694 	}
   695 
   696 void COpenWfcWrapper::Compose(const TSurfaceId& aOffScreenTarget, const TPoint& aOrigin,
   697 	         MWsElement* aStart, MWsElement* aEnd, TRequestStatus* aCompleted)
   698 	{
   699     if (aOffScreenTarget.IsNull())
   700         {
   701         if (aCompleted)
   702             {
   703             User::RequestComplete(aCompleted, KErrNone);
   704             return;
   705             }
   706         }
   707     
   708     CElementWrapper* startElement=static_cast<CElementWrapper*>(aStart);
   709     CElementWrapper* endElement=static_cast<CElementWrapper*>(aEnd);
   710     
   711     if (startElement)
   712         {
   713         if (    &startElement->Owner()!=this
   714             ||  (startElement!=iSceneElementList && !startElement->ElementBelow())
   715             ||  (startElement->UpdateFlags() & (startElement->EUpdate_Remove|startElement->EUpdate_Destroy))
   716             )
   717             {
   718             if (aCompleted)
   719                 {
   720                 RThread().RequestComplete(aCompleted, KErrArgument);
   721                 }
   722             return;
   723             }
   724         if (endElement)
   725             {   //If endElement is NULL then draw to end else draw including the specified endElement
   726             TBool fail=EFalse;
   727             if (    &endElement->Owner()!=this
   728                 ||  (endElement->UpdateFlags() & (endElement->EUpdate_Remove|endElement->EUpdate_Destroy))
   729                 )
   730                 {
   731                 fail=ETrue;
   732                 }
   733             else
   734                 {
   735                 for (CElementWrapper* sceneElement=startElement;sceneElement!=endElement;sceneElement=sceneElement->MyElementAbove())
   736                     {
   737                     if (sceneElement==NULL)
   738                         {
   739                         fail=ETrue;
   740                         break;
   741                         }
   742                     }
   743                 }
   744             if (fail)
   745                 {
   746                 if (aCompleted)
   747                     {
   748                     RThread().RequestComplete(aCompleted, KErrArgument);
   749                     }
   750                 return;
   751                 }
   752             aEnd=aEnd->ElementAbove();   //now scene does NOT include endElement. May now be NULL!
   753             }
   754         }
   755     else
   756         {
   757         aEnd=NULL;
   758         }
   759     ComposeInternal(aOffScreenTarget,aOrigin,aStart,aEnd,aCompleted);
   760 	}
   761 
   762 /** Internal compose does not check some errors. 
   763  *  They should have already been checked by the public API caller.
   764  *  NOTE element aEnd is NOT composed by this internal method!
   765  *  Any elements pending removal will not be displayed (including aStart and aEnd.
   766  * 
   767  * @param   aOffScreenTarget    A valid surface for offscreen composition.
   768  * @param   aOrigin             The origin sets where the top-left corner of the
   769  *                              surface is within the element coordinate system.
   770  * @param   aStart              The starting element of the elements to be composed.
   771  * @param   aEnd                The element above the last element to be composed (or NULL).
   772  * @param   aCompleted          NULL or request status that will be set to KErrNone when
   773  *                              the composition finishes.
   774  **/
   775 void COpenWfcWrapper::ComposeInternal (const TSurfaceId&   aOffScreenTarget,
   776                         const TPoint&       aOrigin,
   777                         MWsElement*       aStart,
   778                         MWsElement*       aEnd,
   779                         TRequestStatus*     aCompleted)
   780     {
   781     // Initial approach reuses the device but it may be more safer to create, and destroy, its own device
   782     CElementWrapper* startElement=static_cast<CElementWrapper*>(aStart);
   783     CElementWrapper* endElement=static_cast<CElementWrapper*>(aEnd);
   784     
   785     TInt err = KErrNone;
   786 #ifdef _DEBUG
   787     // clean previous errors
   788     wfcGetError(iDevice);
   789 #endif    
   790     
   791     if (aCompleted)
   792         {
   793         *aCompleted = KRequestPending;
   794         }
   795     
   796     OffScreenComposeGuard composeGuard(aCompleted);
   797     
   798     WFCNativeStreamType stream=reinterpret_cast<WFCNativeStreamType>(&aOffScreenTarget);
   799     
   800     RSurfaceManager::TInfoBuf buff;
   801     err=SurfaceManager().SurfaceInfo(aOffScreenTarget,buff);
   802     OPENWFC_ASSERT_DEBUG(err==KErrNone,TOpenWfcPanic(__LINE__));
   803     if (err!=KErrNone || buff().iSize.iWidth ==0 || buff().iSize.iHeight == 0)
   804         {
   805         composeGuard.LogRequestStatusError(KErrArgument);
   806         composeGuard.Close();
   807         return;
   808         }
   809     
   810     // Create the native stream target
   811     TSurfaceId targetSurfaceId = TSurfaceId::CreateNullId();
   812     WFCNativeStreamType targetStream = WFC_INVALID_HANDLE;
   813     OPENWFC_ASSERT_DEBUG(wfcGetError(iDevice)==WFC_ERROR_NONE,(TOpenWfcPanic)__LINE__);
   814 
   815     targetSurfaceId = aOffScreenTarget;
   816     targetStream = stream;
   817      
   818     EGLint attrib_list[1] = {EGL_NONE };
   819     
   820     EGLSyncKHR sync = eglCreateSyncKHR(iEGLDisplay,
   821                                                 EGL_SYNC_REUSABLE_KHR,
   822                                                 attrib_list);
   823     
   824     if (sync == EGL_NO_SYNC_KHR)
   825         {
   826         composeGuard.LogRequestStatusError(KErrNoMemory);
   827         composeGuard.Close();
   828         return;
   829         }
   830     composeGuard.SetSync(sync, iEGLDisplay);
   831     
   832     // Now, that we have the target surface stream we can create the temporary context
   833     WFCContext offScreenContext = wfcCreateOffScreenContext(iDevice, targetStream, NULL);
   834 
   835     if (offScreenContext == WFC_INVALID_HANDLE)
   836         {
   837         composeGuard.LogRequestStatusError(TranslateOpenWfcError(wfcGetError(iDevice)));
   838         composeGuard.Close();
   839         return;
   840         }
   841 
   842     composeGuard.SetDeviceAndContext(iDevice, offScreenContext);
   843 
   844     TInt contextBackGroundColour = wfcGetContextAttribi(iDevice, iOnScreenContext, WFC_CONTEXT_BG_COLOR);
   845     wfcSetContextAttribi(iDevice, offScreenContext, WFC_CONTEXT_BG_COLOR, contextBackGroundColour);
   846     OPENWFC_ASSERT_DEBUG(TranslateOpenWfcError(wfcGetError(iDevice)) == KErrNone, EPanicWfcBadAttribute);
   847     
   848     TPoint elementOffset(-aOrigin.iX,-aOrigin.iY);
   849     // let's replicate the scene to the offscreen context
   850     WFCElement previousTargetElement = WFC_INVALID_HANDLE;
   851     for (CElementWrapper* elementScene = startElement; elementScene !=endElement; elementScene = elementScene->MyElementAbove())
   852         {
   853         if (!(elementScene->UpdateFlags()&(elementScene->EUpdate_Destroy|elementScene->EUpdate_Remove)))
   854             {
   855             // we do our best to replicate the elements
   856             TInt err=elementScene->ReplicateElements(offScreenContext, previousTargetElement,elementOffset);
   857             if (err)
   858                 {
   859                 composeGuard.LogRequestStatusError(err);
   860                 composeGuard.Close();
   861                 return;
   862                 }
   863             }
   864         }
   865 
   866     // let's compose
   867     wfcCommit(iDevice, offScreenContext, WFC_TRUE);
   868     wfcCompose(iDevice, offScreenContext, WFC_TRUE);
   869     wfcFence(iDevice, offScreenContext, iEGLDisplay, sync);
   870     EGLTimeKHR timeout = (EGLTimeKHR) EGL_FOREVER_KHR;
   871     OPENWFC_ASSERT_DEBUG(TranslateOpenWfcError(wfcGetError(iDevice)) == KErrNone, EPanicWfcBadAttribute);
   872     eglClientWaitSyncKHR(iEGLDisplay, sync, 0, timeout);
   873     
   874     composeGuard.Close();
   875     }
   876 
   877 void COpenWfcWrapper::PauseComposition (void)
   878     {
   879     
   880     OPENWFC_ASSERT_DEBUG(iJobManager, EPanicWfcThreadManagerNotInitialised);
   881     iAutonomousCompositionInitiated = ETrue;
   882     iJobManager->CompositionPauseRequest();
   883     }
   884 
   885 void COpenWfcWrapper::ResumeComposition (void)
   886     {
   887     OPENWFC_ASSERT_DEBUG(iJobManager, EPanicWfcThreadManagerNotInitialised);
   888     iAutonomousCompositionInitiated = ETrue;
   889     iJobManager->CompositionResumeRequest();
   890     }
   891 
   892 TBitFlags32 COpenWfcWrapper::SupportedScreenRotations() const
   893     {
   894     TBitFlags32 result;
   895     // we DO support, by default, all these rotations
   896     result.Set(MWsScene::ESceneAntiClockwise0);
   897     result.Set(MWsScene::ESceneAntiClockwise90);
   898     result.Set(MWsScene::ESceneAntiClockwise180);
   899     result.Set(MWsScene::ESceneAntiClockwise270);
   900     return result;
   901     }
   902 
   903 void COpenWfcWrapper::SetScreenRotation(MWsScene::TSceneRotation aRotation)
   904 	{
   905 #ifdef _DEBUG
   906     // clean previous errors
   907     (void)wfcGetError(iDevice);
   908 #endif
   909 
   910     if (aRotation != iRotation)
   911         {
   912         WFCRotation wfcRotation = WFC_ROTATION_0;
   913         switch (aRotation)
   914             {
   915             case MWsScene::ESceneAntiClockwise90:
   916                 wfcRotation = WFC_ROTATION_90;
   917                 break;
   918             case MWsScene::ESceneAntiClockwise180:
   919                 wfcRotation = WFC_ROTATION_180;
   920                 break;
   921             case MWsScene::ESceneAntiClockwise270:
   922                 wfcRotation = WFC_ROTATION_270;
   923                 break;
   924             default:
   925                 wfcRotation = WFC_ROTATION_0;
   926                 break;
   927             }
   928         iRotation = aRotation;
   929         wfcSetContextAttribi(iDevice, iOnScreenContext, WFC_CONTEXT_ROTATION, wfcRotation);
   930         OPENWFC_ASSERT_DEBUG(TranslateOpenWfcError(wfcGetError(iDevice)) == KErrNone, EPanicWfcBadAttribute);
   931         }
   932 	
   933 	SetCompositionModified();
   934 	}
   935 
   936 TInt COpenWfcWrapper::SetConfiguration(const TDisplayConfiguration& aConfig)
   937     {
   938     return iContextDisplayControl->SetConfiguration (aConfig);
   939     }
   940 
   941 MWsScene::TSceneRotation COpenWfcWrapper::ScreenRotation() const
   942 	{
   943 #ifdef _DEBUG
   944     // clean previous errors
   945     (void)wfcGetError(iDevice);
   946 #endif
   947     WFCint result = wfcGetContextAttribi(iDevice, iOnScreenContext, WFC_CONTEXT_ROTATION);
   948     OPENWFC_ASSERT_DEBUG(TranslateOpenWfcError(wfcGetError(iDevice)) == KErrNone, EPanicWfcBadAttribute);
   949     MWsScene::TSceneRotation rotation = MWsScene::ESceneAntiClockwise0;
   950     switch (result)
   951         {
   952         case WFC_ROTATION_90:
   953             rotation = MWsScene::ESceneAntiClockwise90;
   954             break;
   955         case WFC_ROTATION_180:
   956             rotation = MWsScene::ESceneAntiClockwise180;
   957             break;
   958         case WFC_ROTATION_270:
   959             rotation = MWsScene::ESceneAntiClockwise270;
   960             break;
   961         case WFC_ROTATION_0:
   962         default:
   963             OPENWFC_ASSERT_DEBUG(result==WFC_ROTATION_0,(TOpenWfcPanic)__LINE__);
   964             rotation = MWsScene::ESceneAntiClockwise0;
   965             break;
   966         }
   967     
   968 	return rotation;
   969 	}
   970 
   971 TInt COpenWfcWrapper::NumberOfResolutions()const
   972     {
   973     if (iContextDisplayControl)
   974         {
   975         return iContextDisplayControl->NumberOfResolutions();
   976         }
   977     return KErrNotSupported;
   978     }
   979 
   980 TInt COpenWfcWrapper::GetResolutions(RArray<TResolution>& aResolutions)const
   981     {
   982     if (iContextDisplayControl)
   983         {
   984         return iContextDisplayControl->GetResolutions(aResolutions);
   985         }
   986     return KErrNotSupported;
   987     }
   988 
   989 void COpenWfcWrapper::GetConfiguration(TDisplayConfiguration& aConfig)const
   990     {
   991     if (iContextDisplayControl)
   992         {
   993         iContextDisplayControl->GetConfiguration (aConfig);
   994         }
   995     }
   996 
   997 TInt COpenWfcWrapper::PreferredDisplayVersion() const
   998     {
   999     if (iContextDisplayControl)
  1000         {
  1001         return iContextDisplayControl->PreferredDisplayVersion();
  1002         }
  1003     return KErrNotSupported;
  1004     }
  1005 
  1006 void COpenWfcWrapper::NotifyOnDisplayChange(TRequestStatus& aStatus)
  1007     {
  1008     // Stub for future implementation. 
  1009     TRequestStatus *status = &aStatus;
  1010     RThread().RequestComplete(status, KErrNotSupported);
  1011     }
  1012 
  1013 void COpenWfcWrapper::NotifyOnDisplayChangeCancel()
  1014     {
  1015     // Stub for future implementation. 
  1016     }
  1017 
  1018 void COpenWfcWrapper::NotifyOnConfigChange(TRequestStatus& aStatus)
  1019     {
  1020     // Stub for future implementation. 
  1021     TRequestStatus *status = &aStatus;
  1022     RThread().RequestComplete(status, KErrNotSupported);
  1023     }
  1024 
  1025 void COpenWfcWrapper::NotifyOnConfigChangeCancel()
  1026     {
  1027     // Stub for future implementation. 
  1028     }
  1029 
  1030 
  1031 void COpenWfcWrapper::FlushSceneElementChanges()
  1032     {
  1033     while (CElementWrapper* curr = iRemoveElementList)
  1034         {
  1035         curr->FlushSceneChanges();
  1036         RemoveElementFromSceneList(curr);
  1037         if (curr->UpdateFlags() & CElementWrapper::EUpdate_Destroy)
  1038             {
  1039             delete curr;
  1040             }
  1041         }
  1042     iRemoveElementList=NULL;
  1043     if (CElementWrapper* curr=iSceneElementList)
  1044         {
  1045         for (CElementWrapper*next=curr->MyElementAbove(); curr;   curr=next,next=curr?curr->MyElementAbove():NULL)
  1046             {
  1047             curr->FlushSceneChanges();
  1048             }
  1049         }
  1050     }
  1051 
  1052 TInt COpenWfcWrapper::TranslateOpenWfcError(WFCErrorCode error)
  1053     {
  1054     switch (error)
  1055         {
  1056         case WFC_ERROR_NONE:
  1057             return KErrNone;
  1058         case WFC_ERROR_OUT_OF_MEMORY:
  1059             return KErrNoMemory;
  1060         case WFC_ERROR_ILLEGAL_ARGUMENT:
  1061             return KErrArgument;
  1062         case WFC_ERROR_BAD_ATTRIBUTE:
  1063             return KErrArgument;
  1064         case WFC_ERROR_BAD_DEVICE:
  1065             return KErrArgument;
  1066         case WFC_ERROR_UNSUPPORTED:
  1067             return KErrNotSupported;
  1068         case WFC_ERROR_IN_USE:
  1069             return KErrInUse;
  1070         case WFC_ERROR_BUSY:
  1071             return KErrServerBusy;
  1072         case WFC_ERROR_BAD_HANDLE:
  1073             return KErrBadHandle;
  1074         case WFC_ERROR_INCONSISTENCY:
  1075             return KErrGeneral;
  1076         case WFC_ERROR_FORCE_32BIT:
  1077             // intentional fall through
  1078         default:
  1079             return KErrUnknown;
  1080         }
  1081     }
  1082 
  1083 void COpenWfcWrapper::DestroyAllContextElements(WFCDevice dev, WFCContext ctx)
  1084     {
  1085     // we try our best to destroy all elements of the specified context
  1086     if (dev != WFC_INVALID_HANDLE && ctx != WFC_INVALID_HANDLE)
  1087         {
  1088         WFCElement element = wfcGetContextAttribi(dev, ctx, WFC_CONTEXT_LOWEST_ELEMENT);
  1089         if (element != WFC_INVALID_HANDLE)
  1090             {
  1091             wfcDestroyElement(dev, element);
  1092             }
  1093         }
  1094     }
  1095 
  1096 void COpenWfcWrapper::PauseCompositorIfNeeded()
  1097 	{
  1098 	if (!iPaused && iAllowCompositorPause && iWithinBeginEnd)
  1099 		{
  1100 		PauseComposition();
  1101 		iPaused = ETrue;
  1102 		}
  1103 	}
  1104 
  1105 /**
  1106 Sets the system state for modified scene composition.
  1107 	- Pause OpenWF composition if the standard render stage is within a begin/end block.
  1108 	- If not within a pause/end block then set a flag to indicate that the scene composition 
  1109 		has been modified. On entering the begin/end block composition will be paused appropriatly.
  1110 */
  1111 void COpenWfcWrapper::SetCompositionModified()
  1112 	{
  1113 	PauseCompositorIfNeeded();
  1114 	iCompositionModified = ETrue;
  1115 	}
  1116 
  1117 void COpenWfcWrapper::ResumeCompositorIfPaused()
  1118 	{
  1119 	if (iPaused)
  1120 		ResumeComposition();
  1121 	iPaused = EFalse;
  1122 	}
  1123 
  1124 void COpenWfcWrapper::Begin(const TRegion* aRegion)
  1125 	{
  1126 	iWithinBeginEnd = ETrue;
  1127 	iAllowCompositorPause = (aRegion && !aRegion->IsEmpty());
  1128 	
  1129 	if (iCompositionModified)
  1130 		PauseCompositorIfNeeded();
  1131 	}
  1132 
  1133 TBool COpenWfcWrapper::CompositionDue()
  1134 	{
  1135 	return (iWithinBeginEnd && iCompositionModified);
  1136 	}
  1137 
  1138 void COpenWfcWrapper::End()
  1139 	{
  1140 	iWithinBeginEnd = EFalse;
  1141 	}
  1142 
  1143 TInt COpenWfcWrapper::FlushedSetConfiguration(const TDisplayConfiguration& /*aConfig*/)
  1144 	{
  1145 	OPENWFC_ASSERT_DEBUG(0, EPanicMethodNotImplemented);
  1146 	TInt retval=KErrNone;
  1147 	if (retval<=KErrNone)
  1148 		{
  1149 		SetCompositionModified();
  1150 		}
  1151 	return retval;
  1152 	}
  1153 
  1154 CDisplayPolicy* COpenWfcWrapper::DisplayPolicy()
  1155 	{
  1156 	return iDisplayPolicy;
  1157 	}
  1158 
  1159 TInt COpenWfcWrapper::AttachSurfaceToUiElement(CElementWrapper* aNewUiElement)
  1160 	{
  1161 	STD_ASSERT_DEBUG(!iUiSurface.IsNull(), EPluginPanicUiSurfaceIsNull);
  1162 	if(iUiElement1 == NULL || iUiElement1 == aNewUiElement)
  1163 	    iUiElement1 = aNewUiElement;
  1164 	else if(iUiElement2 == NULL || iUiElement2 == aNewUiElement)
  1165 	    iUiElement2 = aNewUiElement;
  1166 	else
  1167 		STD_ASSERT_DEBUG(EFalse, EPluginPanicDuplicateUiElement);
  1168 
  1169 	return aNewUiElement->ConnectSurface(iUiSurface);
  1170 	}