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".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
13 // Description: Owns, hides, and provides an interface to the OpenWFC compositor for use by the final (display) render stage.
15 #include "openwfcwrapper.h"
20 #include "elementwrapper.h"
21 #include <graphics/compositionsurfaceupdate.h>
22 #include <graphics/symbianstream.h>
23 #include "openwfcpanics.h"
24 #include "openwfcjobmanager.h"
26 #include <graphics/eglsynchelper.h>
28 #define KRgbaBlack 0x000000FF
30 void Panic(TOpenWfcPanic aPanic)
32 _LIT(KPanic, "OpenWFC");
33 User::Panic(KPanic, aPanic);
36 class COpenWfcWrapper::OffScreenComposeGuard
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);
45 void LogRequestStatusError(TInt aRequestStatusError);
47 TRequestStatus*& iRequestStatus;
49 EGLDisplay iEGLDisplay;
52 TInt iRequestStatusError;
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)
64 void COpenWfcWrapper::OffScreenComposeGuard::SetSync(EGLSyncKHR aSync, EGLDisplay aDpy)
70 void COpenWfcWrapper::OffScreenComposeGuard::SetDeviceAndContext(WFCDevice aDevice, WFCContext aContext)
76 void COpenWfcWrapper::OffScreenComposeGuard::LogRequestStatusError(TInt aRequestStatusError)
78 iRequestStatusError=aRequestStatusError;
81 void COpenWfcWrapper::OffScreenComposeGuard::Close()
83 if (iContext != WFC_INVALID_HANDLE)
85 DestroyAllContextElements(iDevice, iContext);
86 wfcDestroyContext(iDevice, iContext);
89 if (iSync != EGL_NO_SYNC_KHR)
91 eglDestroySyncKHR(iEGLDisplay, iSync);
96 User::RequestComplete(iRequestStatus, iRequestStatusError);
100 TEMPLATE_SPECIALIZATION class RHashTableBase::Defaults<TSurfaceId, RHashTableBase::EDefaultSpecifier_Normal>
103 inline static TGeneralHashFunction32 Hash();
104 inline static TGeneralIdentityRelation Id();
107 inline TGeneralHashFunction32 RHashTableBase::Defaults<TSurfaceId, RHashTableBase::EDefaultSpecifier_Normal>::Hash()
108 {return (TGeneralHashFunction32)&DefaultHash::Integer;}
110 inline TGeneralIdentityRelation RHashTableBase::Defaults<TSurfaceId, RHashTableBase::EDefaultSpecifier_Normal>::Id()
111 {return (TGeneralIdentityRelation)&DefaultIdentity::Integer;}
113 TUint32 COpenWfcWrapper::HashFunction(const TSurfaceId& aHashKey)
115 TPckgC<TSurfaceId> pckg(aHashKey);
116 return DefaultHash::Des8(pckg);
118 COpenWfcWrapper* COpenWfcWrapper::NewL(TInt aScreenNo, CDisplayPolicy* aDisplayPolicy)
120 COpenWfcWrapper* wrapper = new (ELeave) COpenWfcWrapper(aDisplayPolicy);
121 CleanupStack::PushL(wrapper);
122 wrapper->ConstructL(aScreenNo);
123 CleanupStack::Pop(wrapper);
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),
134 iRotation(MWsScene::ESceneAntiClockwise0),
135 iAutonomousCompositionInitiated(EFalse)
139 void COpenWfcWrapper::ConstructL(TInt aScreenId)
142 _LIT(KOpenWfcLog, "+ COpenWfcWrapper::ConstructL");
143 RDebug::Print(KOpenWfcLog);
146 iScreenNumber = aScreenId;
147 WFCint filterList[] = { WFC_DEVICE_FILTER_SCREEN_NUMBER, iScreenNumber, WFC_NONE};
149 iEGLDisplay = eglGetDisplay(EGL_DEFAULT_DISPLAY);
150 eglInitialize(iEGLDisplay, NULL, NULL);
153 if ((wfcEnumerateDevices(&dev, 1, filterList) == 1) &&
154 (dev != WFC_INVALID_HANDLE))
156 // clean previous errors
157 wfcGetError(iDevice);
159 // Let's get the device handle, opening in the same time the device
160 iDevice = wfcCreateDevice(dev, NULL);
163 //Not enough information to deduce why the device could not be created. Report as memory failure
164 User::Leave(KErrNoMemory);
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);
169 iOnScreenContext = wfcCreateOnScreenContext(iDevice, iScreenNumber, NULL);
170 if (iOnScreenContext==NULL)
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);
177 wfcSetContextAttribi(iDevice, iOnScreenContext, WFC_CONTEXT_ROTATION, WFC_ROTATION_0);
178 wfcSetContextAttribi(iDevice, iOnScreenContext, WFC_CONTEXT_BG_COLOR, KRgbaBlack);
180 iContextDisplayControl = NULL;
182 User::LeaveIfNull(iJobManager = COpenWfcJobManger::NewL(*this, iDevice, iOnScreenContext, iScreenNumber));
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);
190 iSurfaceManager.Open();
192 iSourceMap.Reserve(iInitialSourceMapSize);
195 COpenWfcWrapper::~COpenWfcWrapper()
199 if(!iUiSurface.IsNull())
200 UnregisterSurface(iUiSurface);
208 //destroy all the elements, which should remove all the element references.
209 while (iCleanupElementList)
211 CElementWrapper* cleanupElement = iCleanupElementList;
212 delete cleanupElement;
213 OPENWFC_ASSERT_DEBUG(cleanupElement != iCleanupElementList,EPanicWfcElementNotRemovedOnShutdown);
214 if (cleanupElement == iCleanupElementList)
216 break; //can't keep cleaning up the same front item
219 THashMapIter<TSurfaceId, SourceAndRef> iter(iSourceMap);
220 const TSurfaceId* nextKey = iter.NextKey();
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();
232 iSurfaceManager.Close();
233 eglTerminate(iEGLDisplay);
235 // Destroying the context should take care of any sources or masks
236 wfcDestroyContext(iDevice, iOnScreenContext);
237 wfcDestroyDevice(iDevice);
240 class CBaseExtension: public CBase
243 virtual TInt Extension_(TUint aExtensionId, TAny*& a0, TAny* a1)
244 { return CBase::Extension_(aExtensionId,a0,a1); }
246 TInt COpenWfcWrapper::Extension_(TUint aExtensionId, TAny*& aRetPtr, TAny* aExtra)
252 switch (aExtensionId)
255 case EExtensionDebugBackendGuid:
256 return KErrNotSupported;
257 case EExtensionDebugContextGuid:
258 aRetPtr=(TAny*)OnScreenContext();
260 case EExtensionDebugDeviceGuid:
261 aRetPtr=(TAny*)Device();
263 case EExtensionDebugElementGuid:
266 CElementWrapper* newElement=static_cast<CElementWrapper*>(aExtra);
267 aRetPtr=(TAny*)newElement->Element();
272 return KErrBadHandle;
274 case EExtensionDebugSourceGuid:
277 TSurfaceId* surfId=static_cast<TSurfaceId*>(aExtra);
278 SourceAndRef* foundSourceAndRef=iSourceMap.Find(*surfId);
279 if (foundSourceAndRef)
281 aRetPtr=(TAny*)foundSourceAndRef->source;
291 return KErrBadHandle;
294 case MCompositionSurfaceUpdate::ETypeId:
296 CBaseExtension* basePtr = NULL;
297 SymbianStreamHasRegisteredScreenNotifications(iScreenNumber,reinterpret_cast<void**>(&basePtr));
300 return basePtr->Extension_(MCompositionSurfaceUpdate::KUidCompositionSurfaceUpdate,aRetPtr,aExtra);
304 return KErrNotSupported;
307 case MWsDisplayControl::ETypeId:
308 if (iContextDisplayControl)
310 aRetPtr= static_cast<MWsDisplayControl*>(this);
315 return KErrNotSupported;
317 case MDisplayControlBase::ETypeId:
318 if (iContextDisplayControl)
320 aRetPtr= static_cast<MDisplayControlBase*>(this);
325 return KErrNotSupported;
328 return KErrNotSupported;
331 MWsElement* COpenWfcWrapper::CreateElementL()
333 CElementWrapper* element = CElementWrapper::NewL(*this,iCleanupElementList);
337 void COpenWfcWrapper::DestroyElement(MWsElement* aElement)
341 CElementWrapper* element=static_cast<CElementWrapper*>(aElement);
342 RemoveElementFromSceneList(element);
347 void COpenWfcWrapper::Compose(TRequestStatus* aCompleted)
349 STD_ASSERT_DEBUG(CompositionDue(), EPluginPanicCompositionSequenceError);
351 OPENWFC_ASSERT_DEBUG(iJobManager, EPanicWfcThreadManagerNotInitialised);
352 if (!iAutonomousCompositionInitiated)
356 iJobManager->ComposeRequest(aCompleted);
358 iCompositionModified = EFalse;
359 ResumeCompositorIfPaused();
362 TSize COpenWfcWrapper::ScreenSize() const
364 // clean previous errors
366 (void)wfcGetError(iDevice);
369 TInt height = wfcGetContextAttribi(iDevice, iOnScreenContext, WFC_CONTEXT_TARGET_HEIGHT);
370 OPENWFC_ASSERT_DEBUG(TranslateOpenWfcError(wfcGetError(iDevice)) == KErrNone, EPanicWfcBadAttribute);
372 TInt width = wfcGetContextAttribi(iDevice, iOnScreenContext, WFC_CONTEXT_TARGET_WIDTH);
373 OPENWFC_ASSERT_DEBUG(TranslateOpenWfcError(wfcGetError(iDevice)) == KErrNone, EPanicWfcBadAttribute);
375 WFCint rotation = wfcGetContextAttribi(iDevice, iOnScreenContext, WFC_CONTEXT_ROTATION);
376 OPENWFC_ASSERT_DEBUG(TranslateOpenWfcError(wfcGetError(iDevice)) == KErrNone, EPanicWfcBadAttribute);
378 return rotation == WFC_ROTATION_0 || rotation == WFC_ROTATION_180 ? TSize(width, height) : TSize(height, width);
381 TInt COpenWfcWrapper::RegisterSurface (const TSurfaceId& aSurface)
383 // clean previous errors
384 wfcGetError(iDevice);
385 //check surface id not null
386 if (aSurface.IsNull())
391 if (!IsValidSurface(aSurface))
393 return KErrBadHandle;
396 //look for surface being registered
397 SourceAndRef* sourceAndRef = iSourceMap.Find(aSurface);
400 //if registered increase ref count and return
401 sourceAndRef->sourceRef++;
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
412 //No need to acquire stream as public NativeStream handle is TSurfaceId
413 WFCNativeStreamType stream = reinterpret_cast<WFCNativeStreamType>(&aSurface);
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)
420 return TranslateOpenWfcError(wfcGetError(iDevice));
423 TInt err = iSourceMap.Insert(aSurface,newSourceAndRef);
426 wfcDestroySource(iDevice,newSourceAndRef.source);
433 TInt COpenWfcWrapper::UnregisterSurface (const TSurfaceId& aSurface)
435 //check surface id not null
436 if (aSurface.IsNull())
441 if (!IsValidSurface(aSurface))
446 SourceAndRef* sourceAndRef = iSourceMap.Find(aSurface);
448 if (sourceAndRef && sourceAndRef->sourceRef == 0)
454 if (sourceAndRef->sourceRef <= 1)
456 sourceAndRef->sourceRef = 0;
458 if (sourceAndRef->elementRef > 0)
460 //if elements are currently in use
463 wfcDestroySource(iDevice,sourceAndRef->source); //removing source reference on the stream
466 iSourceMap.Remove(aSurface);
469 sourceAndRef->sourceRef--;
472 return KErrBadHandle;
475 TBool COpenWfcWrapper::IsValidSurface(const TSurfaceId& aSurface)
477 if (aSurface.Type() != TSurfaceId::EScreenSurface)
479 RSurfaceManager::TInfoBuf buff;
480 TInt err = SurfaceManager().SurfaceInfo(aSurface, buff);
482 if (err == KErrArgument)
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
494 WFCSource COpenWfcWrapper::IncEltRefRegSource(const TSurfaceId& aHashKey)
496 SourceAndRef* foundSourceAndRef=iSourceMap.Find(aHashKey);
497 if (foundSourceAndRef && foundSourceAndRef->sourceRef)
499 foundSourceAndRef->elementRef++;
500 return foundSourceAndRef->source;
502 return WFC_INVALID_HANDLE;
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
512 TInt COpenWfcWrapper::DecEltRefRegSource(const TSurfaceId& aHashKey)
514 SourceAndRef* foundSourceAndRef=iSourceMap.Find(aHashKey);
515 if (foundSourceAndRef && foundSourceAndRef->elementRef>0)
517 TInt retRefs=((--foundSourceAndRef->elementRef)+foundSourceAndRef->sourceRef);
520 wfcDestroySource(iDevice,foundSourceAndRef->source);
521 iSourceMap.Remove(aHashKey);
525 return KErrBadHandle;
528 void COpenWfcWrapper::RemoveElement(MWsElement* aElement)
535 CElementWrapper* removeElement = static_cast<CElementWrapper*>(aElement);
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)
543 if(removeElement == iUiElement1)
545 else if(removeElement == iUiElement2)
548 STD_ASSERT_DEBUG(EFalse, EPluginPanicNonMatchingRemovalOfUiElement);
551 RemoveElementFromSceneList(removeElement);
552 removeElement->InsertAfter(iRemoveElementList,NULL,CElementWrapper::EUpdate_Remove); //insert into remove element list!!!
553 SetCompositionModified();
556 void COpenWfcWrapper::RemoveElementFromSceneList(CElementWrapper* aElement)
558 CElementWrapper** refFromElementBelow=NULL;
559 if (iSceneElementList==aElement)
561 refFromElementBelow=&iSceneElementList; //remove from bottom of scene
563 else if (iRemoveElementList==aElement)
565 refFromElementBelow=&iRemoveElementList;
569 refFromElementBelow=aElement->RefsMyElementBelow(); //remove from current mid-list position
572 aElement->RemoveAfter(refFromElementBelow);
575 TInt COpenWfcWrapper::SetUiSurface(const TSurfaceId& aNewUiSurface)
577 TInt err = RegisterSurface(aNewUiSurface);
582 err = iUiElement1->ConnectSurface(aNewUiSurface);
583 STD_ASSERT_DEBUG(!err, EPluginPanicNewUiSurfaceUnsettable);
587 err = iUiElement2->ConnectSurface(aNewUiSurface);
588 STD_ASSERT_DEBUG(!err, EPluginPanicNewUiSurfaceUnsettable);
594 if(!iUiSurface.IsNull())
596 // This should not fail as the surface will no longer be used by any element
597 err = UnregisterSurface(iUiSurface);
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.
605 STD_ASSERT_DEBUG(!err, EPluginPanicPreviousUiSurfaceUnregisterable);
608 iUiSurface = aNewUiSurface;
613 TInt COpenWfcWrapper::AddElement(MWsElement* aElement, MWsElement* aAbove)
616 CElementWrapper* addedElement = static_cast<CElementWrapper*>(aElement);
617 CElementWrapper* insertAboveThisElement = static_cast<CElementWrapper*>(aAbove);
619 if (aElement == aAbove)
624 if (addedElement == NULL || &addedElement->Owner()!=this ||
625 (insertAboveThisElement && &insertAboveThisElement->Owner()!=this) ||
626 (addedElement->UpdateFlags() & CElementWrapper::EUpdate_Destroy))
631 if (insertAboveThisElement &&
632 ((!insertAboveThisElement->RefsMyElementBelow() && iSceneElementList != insertAboveThisElement) ||
633 (insertAboveThisElement->UpdateFlags() & (CElementWrapper::EUpdate_Remove | CElementWrapper::EUpdate_Destroy))))
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)
644 err = AttachSurfaceToUiElement(addedElement);
649 //figure out which element to add the element above
650 const TSurfaceId& newSurf = addedElement->ConnectedSurface();
651 if (!addedElement->ConnectedSurface().IsNull())
653 //is surface registered
654 WFCSource newSource = IncEltRefRegSource(newSurf);
655 if (newSource == WFC_INVALID_HANDLE)
656 { //suggests the surface was not registered
659 DecEltRefRegSource(newSurf); //only need to decrement if it found a source
662 RemoveElementFromSceneList(addedElement);
664 // figure out which element to add it below
665 CElementWrapper** insertBelowThisElement = NULL;
666 if (insertAboveThisElement)
668 insertBelowThisElement=&insertAboveThisElement->MyElementAbove();
672 insertBelowThisElement=&iSceneElementList;
675 addedElement->InsertAfter(*insertBelowThisElement,insertAboveThisElement,CElementWrapper::EUpdate_Insert);
677 SetCompositionModified();
683 void COpenWfcWrapper::Compose(const TSurfaceId& aOffScreenTarget, TRequestStatus* aCompleted)
685 if (aOffScreenTarget.IsNull())
689 User::RequestComplete(aCompleted, KErrNone);
693 ComposeInternal(aOffScreenTarget,TPoint(0,0),iSceneElementList,NULL,aCompleted);
696 void COpenWfcWrapper::Compose(const TSurfaceId& aOffScreenTarget, const TPoint& aOrigin,
697 MWsElement* aStart, MWsElement* aEnd, TRequestStatus* aCompleted)
699 if (aOffScreenTarget.IsNull())
703 User::RequestComplete(aCompleted, KErrNone);
708 CElementWrapper* startElement=static_cast<CElementWrapper*>(aStart);
709 CElementWrapper* endElement=static_cast<CElementWrapper*>(aEnd);
713 if ( &startElement->Owner()!=this
714 || (startElement!=iSceneElementList && !startElement->ElementBelow())
715 || (startElement->UpdateFlags() & (startElement->EUpdate_Remove|startElement->EUpdate_Destroy))
720 RThread().RequestComplete(aCompleted, KErrArgument);
725 { //If endElement is NULL then draw to end else draw including the specified endElement
727 if ( &endElement->Owner()!=this
728 || (endElement->UpdateFlags() & (endElement->EUpdate_Remove|endElement->EUpdate_Destroy))
735 for (CElementWrapper* sceneElement=startElement;sceneElement!=endElement;sceneElement=sceneElement->MyElementAbove())
737 if (sceneElement==NULL)
748 RThread().RequestComplete(aCompleted, KErrArgument);
752 aEnd=aEnd->ElementAbove(); //now scene does NOT include endElement. May now be NULL!
759 ComposeInternal(aOffScreenTarget,aOrigin,aStart,aEnd,aCompleted);
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.
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.
775 void COpenWfcWrapper::ComposeInternal (const TSurfaceId& aOffScreenTarget,
776 const TPoint& aOrigin,
779 TRequestStatus* aCompleted)
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);
787 // clean previous errors
788 wfcGetError(iDevice);
793 *aCompleted = KRequestPending;
796 OffScreenComposeGuard composeGuard(aCompleted);
798 WFCNativeStreamType stream=reinterpret_cast<WFCNativeStreamType>(&aOffScreenTarget);
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)
805 composeGuard.LogRequestStatusError(KErrArgument);
806 composeGuard.Close();
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__);
815 targetSurfaceId = aOffScreenTarget;
816 targetStream = stream;
818 EGLint attrib_list[1] = {EGL_NONE };
820 EGLSyncKHR sync = eglCreateSyncKHR(iEGLDisplay,
821 EGL_SYNC_REUSABLE_KHR,
824 if (sync == EGL_NO_SYNC_KHR)
826 composeGuard.LogRequestStatusError(KErrNoMemory);
827 composeGuard.Close();
830 composeGuard.SetSync(sync, iEGLDisplay);
832 // Now, that we have the target surface stream we can create the temporary context
833 WFCContext offScreenContext = wfcCreateOffScreenContext(iDevice, targetStream, NULL);
835 if (offScreenContext == WFC_INVALID_HANDLE)
837 composeGuard.LogRequestStatusError(TranslateOpenWfcError(wfcGetError(iDevice)));
838 composeGuard.Close();
842 composeGuard.SetDeviceAndContext(iDevice, offScreenContext);
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);
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())
853 if (!(elementScene->UpdateFlags()&(elementScene->EUpdate_Destroy|elementScene->EUpdate_Remove)))
855 // we do our best to replicate the elements
856 TInt err=elementScene->ReplicateElements(offScreenContext, previousTargetElement,elementOffset);
859 composeGuard.LogRequestStatusError(err);
860 composeGuard.Close();
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);
874 composeGuard.Close();
877 void COpenWfcWrapper::PauseComposition (void)
880 OPENWFC_ASSERT_DEBUG(iJobManager, EPanicWfcThreadManagerNotInitialised);
881 iAutonomousCompositionInitiated = ETrue;
882 iJobManager->CompositionPauseRequest();
885 void COpenWfcWrapper::ResumeComposition (void)
887 OPENWFC_ASSERT_DEBUG(iJobManager, EPanicWfcThreadManagerNotInitialised);
888 iAutonomousCompositionInitiated = ETrue;
889 iJobManager->CompositionResumeRequest();
892 TBitFlags32 COpenWfcWrapper::SupportedScreenRotations() const
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);
903 void COpenWfcWrapper::SetScreenRotation(MWsScene::TSceneRotation aRotation)
906 // clean previous errors
907 (void)wfcGetError(iDevice);
910 if (aRotation != iRotation)
912 WFCRotation wfcRotation = WFC_ROTATION_0;
915 case MWsScene::ESceneAntiClockwise90:
916 wfcRotation = WFC_ROTATION_90;
918 case MWsScene::ESceneAntiClockwise180:
919 wfcRotation = WFC_ROTATION_180;
921 case MWsScene::ESceneAntiClockwise270:
922 wfcRotation = WFC_ROTATION_270;
925 wfcRotation = WFC_ROTATION_0;
928 iRotation = aRotation;
929 wfcSetContextAttribi(iDevice, iOnScreenContext, WFC_CONTEXT_ROTATION, wfcRotation);
930 OPENWFC_ASSERT_DEBUG(TranslateOpenWfcError(wfcGetError(iDevice)) == KErrNone, EPanicWfcBadAttribute);
933 SetCompositionModified();
936 TInt COpenWfcWrapper::SetConfiguration(const TDisplayConfiguration& aConfig)
938 return iContextDisplayControl->SetConfiguration (aConfig);
941 MWsScene::TSceneRotation COpenWfcWrapper::ScreenRotation() const
944 // clean previous errors
945 (void)wfcGetError(iDevice);
947 WFCint result = wfcGetContextAttribi(iDevice, iOnScreenContext, WFC_CONTEXT_ROTATION);
948 OPENWFC_ASSERT_DEBUG(TranslateOpenWfcError(wfcGetError(iDevice)) == KErrNone, EPanicWfcBadAttribute);
949 MWsScene::TSceneRotation rotation = MWsScene::ESceneAntiClockwise0;
952 case WFC_ROTATION_90:
953 rotation = MWsScene::ESceneAntiClockwise90;
955 case WFC_ROTATION_180:
956 rotation = MWsScene::ESceneAntiClockwise180;
958 case WFC_ROTATION_270:
959 rotation = MWsScene::ESceneAntiClockwise270;
963 OPENWFC_ASSERT_DEBUG(result==WFC_ROTATION_0,(TOpenWfcPanic)__LINE__);
964 rotation = MWsScene::ESceneAntiClockwise0;
971 TInt COpenWfcWrapper::NumberOfResolutions()const
973 if (iContextDisplayControl)
975 return iContextDisplayControl->NumberOfResolutions();
977 return KErrNotSupported;
980 TInt COpenWfcWrapper::GetResolutions(RArray<TResolution>& aResolutions)const
982 if (iContextDisplayControl)
984 return iContextDisplayControl->GetResolutions(aResolutions);
986 return KErrNotSupported;
989 void COpenWfcWrapper::GetConfiguration(TDisplayConfiguration& aConfig)const
991 if (iContextDisplayControl)
993 iContextDisplayControl->GetConfiguration (aConfig);
997 TInt COpenWfcWrapper::PreferredDisplayVersion() const
999 if (iContextDisplayControl)
1001 return iContextDisplayControl->PreferredDisplayVersion();
1003 return KErrNotSupported;
1006 void COpenWfcWrapper::NotifyOnDisplayChange(TRequestStatus& aStatus)
1008 // Stub for future implementation.
1009 TRequestStatus *status = &aStatus;
1010 RThread().RequestComplete(status, KErrNotSupported);
1013 void COpenWfcWrapper::NotifyOnDisplayChangeCancel()
1015 // Stub for future implementation.
1018 void COpenWfcWrapper::NotifyOnConfigChange(TRequestStatus& aStatus)
1020 // Stub for future implementation.
1021 TRequestStatus *status = &aStatus;
1022 RThread().RequestComplete(status, KErrNotSupported);
1025 void COpenWfcWrapper::NotifyOnConfigChangeCancel()
1027 // Stub for future implementation.
1031 void COpenWfcWrapper::FlushSceneElementChanges()
1033 while (CElementWrapper* curr = iRemoveElementList)
1035 curr->FlushSceneChanges();
1036 RemoveElementFromSceneList(curr);
1037 if (curr->UpdateFlags() & CElementWrapper::EUpdate_Destroy)
1042 iRemoveElementList=NULL;
1043 if (CElementWrapper* curr=iSceneElementList)
1045 for (CElementWrapper*next=curr->MyElementAbove(); curr; curr=next,next=curr?curr->MyElementAbove():NULL)
1047 curr->FlushSceneChanges();
1052 TInt COpenWfcWrapper::TranslateOpenWfcError(WFCErrorCode error)
1056 case WFC_ERROR_NONE:
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:
1070 case WFC_ERROR_BUSY:
1071 return KErrServerBusy;
1072 case WFC_ERROR_BAD_HANDLE:
1073 return KErrBadHandle;
1074 case WFC_ERROR_INCONSISTENCY:
1076 case WFC_ERROR_FORCE_32BIT:
1077 // intentional fall through
1083 void COpenWfcWrapper::DestroyAllContextElements(WFCDevice dev, WFCContext ctx)
1085 // we try our best to destroy all elements of the specified context
1086 if (dev != WFC_INVALID_HANDLE && ctx != WFC_INVALID_HANDLE)
1088 WFCElement element = wfcGetContextAttribi(dev, ctx, WFC_CONTEXT_LOWEST_ELEMENT);
1089 if (element != WFC_INVALID_HANDLE)
1091 wfcDestroyElement(dev, element);
1096 void COpenWfcWrapper::PauseCompositorIfNeeded()
1098 if (!iPaused && iAllowCompositorPause && iWithinBeginEnd)
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.
1111 void COpenWfcWrapper::SetCompositionModified()
1113 PauseCompositorIfNeeded();
1114 iCompositionModified = ETrue;
1117 void COpenWfcWrapper::ResumeCompositorIfPaused()
1120 ResumeComposition();
1124 void COpenWfcWrapper::Begin(const TRegion* aRegion)
1126 iWithinBeginEnd = ETrue;
1127 iAllowCompositorPause = (aRegion && !aRegion->IsEmpty());
1129 if (iCompositionModified)
1130 PauseCompositorIfNeeded();
1133 TBool COpenWfcWrapper::CompositionDue()
1135 return (iWithinBeginEnd && iCompositionModified);
1138 void COpenWfcWrapper::End()
1140 iWithinBeginEnd = EFalse;
1143 TInt COpenWfcWrapper::FlushedSetConfiguration(const TDisplayConfiguration& /*aConfig*/)
1145 OPENWFC_ASSERT_DEBUG(0, EPanicMethodNotImplemented);
1146 TInt retval=KErrNone;
1147 if (retval<=KErrNone)
1149 SetCompositionModified();
1154 CDisplayPolicy* COpenWfcWrapper::DisplayPolicy()
1156 return iDisplayPolicy;
1159 TInt COpenWfcWrapper::AttachSurfaceToUiElement(CElementWrapper* aNewUiElement)
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;
1167 STD_ASSERT_DEBUG(EFalse, EPluginPanicDuplicateUiElement);
1169 return aNewUiElement->ConnectSurface(iUiSurface);