graphicscomposition/surfaceupdate/tsrc/tcompositionbackend.cpp
changeset 0 5d03bc08d59c
equal deleted inserted replaced
-1:000000000000 0:5d03bc08d59c
       
     1 // Copyright (c) 2006-2009 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:
       
    14 //
       
    15 
       
    16 /**
       
    17  @file
       
    18  @test
       
    19  @internalComponent - Internal Symbian test code 
       
    20 */
       
    21 
       
    22 #include <e32std.h>
       
    23 #include "tcompositionbackend.h"
       
    24 #include <graphics/suerror.h>
       
    25 
       
    26 const TInt KNotificationsAtTime = 10; //how many notifications could be processed at a time, varies from 1...
       
    27 
       
    28 CTContentUpdateReceiver::CTContentUpdateReceiver(TInt aScreen) :
       
    29 	iScreen(aScreen), iVisible(ETrue)
       
    30 	{
       
    31 	RThread thread;
       
    32 	iReceiverThreadId = thread.Id();
       
    33 	}
       
    34 
       
    35 CTContentUpdateReceiver::~CTContentUpdateReceiver()
       
    36 	{
       
    37 	if(iPeriodic)
       
    38 		iPeriodic->Cancel();
       
    39 	delete iPeriodic;
       
    40 	iLock.Close();
       
    41 	iPriorityLock.Close();
       
    42 	}
       
    43 
       
    44 void CTContentUpdateReceiver::ConstructL()
       
    45 	{
       
    46 	TCallBack callback(CallBack);
       
    47 	callback.iPtr = this;
       
    48 	User::LeaveIfError(iLock.CreateLocal());
       
    49 	User::LeaveIfError(iPriorityLock.CreateLocal(0));
       
    50     iPeriodic= CPeriodic::NewL(CPeriodic::EPriorityStandard);
       
    51     iPeriodic->Start(TTimeIntervalMicroSeconds32(0),TTimeIntervalMicroSeconds32(KCompositionInterval), callback);
       
    52 	}
       
    53 
       
    54 CTContentUpdateReceiver* CTContentUpdateReceiver::NewL(TInt aScreen)
       
    55 	{
       
    56 	CTContentUpdateReceiver* receiver = new (ELeave) CTContentUpdateReceiver(aScreen);
       
    57 	CleanupStack::PushL(receiver);
       
    58 	receiver->ConstructL();
       
    59 	CleanupStack::Pop();
       
    60 	return receiver;  
       
    61 	}
       
    62 
       
    63 TInt    CTContentUpdateReceiver::Extension_(TUint aExtensionId, TAny*& aRetIface, TAny* a1)
       
    64     {
       
    65     switch (aExtensionId)
       
    66         {
       
    67         case MCompositionSurfaceUpdate::ETypeId:
       
    68             aRetIface= static_cast<MCompositionSurfaceUpdate*>(this);
       
    69             return KErrNone;
       
    70 
       
    71         default:    ;
       
    72         }
       
    73     return CExtensionContainer::Extension_(aExtensionId,aRetIface,a1);
       
    74     }
       
    75 
       
    76 TInt CTContentUpdateReceiver::CallBack(TAny *aAny)
       
    77 	{
       
    78 	return (static_cast <CTContentUpdateReceiver*> (aAny))->CheckNewNotifications();
       
    79 	}
       
    80 
       
    81 void CTContentUpdateReceiver::Stop()
       
    82 	{
       
    83     iLock.Wait();
       
    84 	iStop = ETrue;
       
    85     iLock.Signal();
       
    86 	}
       
    87 
       
    88 EXPORT_C void CTContentUpdateReceiver::SetVisible(TBool aVisible)
       
    89     {
       
    90     iLock.Wait();
       
    91     iVisible = aVisible;
       
    92     iLock.Signal();
       
    93     }
       
    94 
       
    95 TInt CTContentUpdateReceiver::CheckNewNotifications()
       
    96 	{
       
    97 	iLock.Wait();
       
    98  	if(iStop && (iNumberElements <= 0))
       
    99 		{
       
   100 	    iLock.Signal();
       
   101 		CActiveScheduler::Stop();
       
   102 		return 0;//the return value is irrelevant for CPeriodic function
       
   103 		}
       
   104 	if(iSetInternalPriority)
       
   105 		{
       
   106 		TRAPD(res, DoSetInternalPriorityL());
       
   107 	    iLock.Signal();
       
   108 		__ASSERT_ALWAYS(res ==KErrNone, User::Panic(_L("CheckNewNotifications"), KErrGeneral));
       
   109 		return 0;//the return value is irrelevant for CPeriodic function
       
   110 		}	
       
   111 	TInt index = 0;	
       
   112 	RThread thread;
       
   113 	TInt res = thread.Open(iThreadId);
       
   114 	__ASSERT_ALWAYS(res ==KErrNone, User::Panic(_L("CheckNewNotifications"), KErrGeneral));
       
   115 
       
   116 		//we will check only one limited amount of requests at the time
       
   117 	for(TInt iteration = 0; (iNumberElements > index) && (iteration < KNotificationsAtTime); iteration++)
       
   118 		{
       
   119 		if(iArray[index].iType == EReqDisplayed)
       
   120 			{
       
   121 			*(iArray[index].iTimeStamp) = User::FastCounter();
       
   122 			if(iCompositionOrder)
       
   123 				{
       
   124 				iCompositionOrder->SetOrder(EOrderComposition);
       
   125 				}
       
   126 			}
       
   127 		else if(iArray[index].iType == EReqDisplayedXTimes)
       
   128 			{
       
   129 			iArray[index].iDisplayedXTimes--;
       
   130 			if(iArray[index].iDisplayedXTimes > 0)
       
   131 				{
       
   132 				index++;
       
   133 				continue;
       
   134 				}
       
   135 			}
       
   136 		TRequestStatus* status = iArray[index].iStatus;
       
   137 		res = iVisible ? KErrNone : KErrNotVisible;
       
   138 		Remove(index);
       
   139 		thread.RequestComplete(status, res);
       
   140 		}
       
   141 	thread.Close();	
       
   142     iLock.Signal();
       
   143 	return 0;//the return value is irrelevant for CPeriodic function
       
   144 	}
       
   145 
       
   146 void CTContentUpdateReceiver::DoSetInternalPriorityL()
       
   147 	{
       
   148 	RThread thread;
       
   149 	User::LeaveIfError(thread.Open(iReceiverThreadId));
       
   150 	thread.SetPriority(iInternalPriority);
       
   151 	thread.Close();
       
   152 	TInt compositionInterval = KCompositionInterval;
       
   153 	CPeriodic::TPriority priority = CPeriodic::EPriorityStandard;
       
   154 	if(iInternalPriority < EPriorityNormal)
       
   155 		{
       
   156 		priority = CPeriodic::EPriorityIdle;
       
   157 		compositionInterval = KCompositionIntervalLong;
       
   158 		}
       
   159 	else if (iInternalPriority > EPriorityNormal)
       
   160 		{
       
   161 		priority = CPeriodic::EPriorityHigh;
       
   162 		compositionInterval = KCompositionIntervalShort;
       
   163 		}
       
   164 
       
   165 	TCallBack callback(CallBack);
       
   166 	callback.iPtr = this;
       
   167 	iPeriodic->Cancel();
       
   168 	delete iPeriodic;
       
   169 	iPeriodic= CPeriodic::NewL(priority);
       
   170 	iPeriodic->Start(TTimeIntervalMicroSeconds32(compositionInterval),TTimeIntervalMicroSeconds32(compositionInterval), callback);
       
   171 	iSetInternalPriority = EFalse;
       
   172 	iPriorityLock.Signal();
       
   173 	}
       
   174 
       
   175 EXPORT_C TInt CTContentUpdateReceiver::SetInternalPriority(TThreadPriority aInternalPriority)
       
   176 	{
       
   177 	iLock.Wait();
       
   178 	iInternalPriority = aInternalPriority;
       
   179 	iSetInternalPriority = ETrue;
       
   180     iLock.Signal();
       
   181 	
       
   182     //wait for the priority changes takes place
       
   183     iPriorityLock.Wait();
       
   184 	return KErrNone;
       
   185 	}
       
   186 
       
   187 void CTContentUpdateReceiver::ContentUpdated(const TSurfaceId& aId, 
       
   188 				TInt aBuffer, 
       
   189 				const TRegion* aRegion, 
       
   190 				TRequestStatus* aStatusAvailable, 
       
   191 				TRequestStatus* aStatusDisplayed, TUint32* aTimeStamp, 
       
   192 				TRequestStatus* aStatusDisplayedXTimes, TInt* aDisplayedXTimes)
       
   193 	{
       
   194 	(TAny)&aId;
       
   195 	(TAny)aBuffer;
       
   196 	(TAny)aRegion;
       
   197 	
       
   198 	iLock.Wait();
       
   199 	if(iStop)
       
   200 		{
       
   201 		if(aStatusAvailable)
       
   202 			{
       
   203 			User::RequestComplete(aStatusAvailable, KErrDied);
       
   204 			}
       
   205 		if(aStatusDisplayed)
       
   206 			{
       
   207 			User::RequestComplete(aStatusDisplayed, KErrDied);
       
   208 			}
       
   209 		if(aStatusDisplayedXTimes)
       
   210 			{
       
   211 			User::RequestComplete(aStatusDisplayedXTimes, KErrDied);
       
   212 			}
       
   213 	    iLock.Signal();
       
   214 		return;
       
   215 		}
       
   216 	
       
   217 	RThread thread;
       
   218 	iThreadId = thread.Id();
       
   219 	
       
   220 	if(aStatusAvailable)
       
   221 		{
       
   222 		Add(aStatusAvailable, EReqAvailable);
       
   223 		}
       
   224 	if(aStatusDisplayed)
       
   225 		{
       
   226 		Add(aStatusDisplayed, EReqDisplayed, 0, aTimeStamp);
       
   227 		}
       
   228 	if(aStatusDisplayedXTimes)
       
   229 		{
       
   230 		Add(aStatusDisplayedXTimes, EReqDisplayedXTimes, *aDisplayedXTimes);
       
   231 		}
       
   232     iLock.Signal();
       
   233 	}
       
   234 
       
   235 /** 
       
   236    Add notification to the list. The function is called from the SUS thread.
       
   237    The client of this API must use a lock mechanizm to preserve data integrity.
       
   238 */
       
   239 TInt CTContentUpdateReceiver::Add(TRequestStatus *aStatus, RequestType aType, 
       
   240 			TInt aDisplayedXTimes, TUint32* aTimeStamp)
       
   241 	{
       
   242  	TInt index = iNumberElements;
       
   243 	TInt max = sizeof(iArray) / sizeof(iArray[0]) - 1;
       
   244 	if(index >= max)
       
   245 		return KErrOverflow;
       
   246 	
       
   247 	iArray[index].iStatus = aStatus;
       
   248 	iArray[index].iType = aType;
       
   249 	iArray[index].iDisplayedXTimes = aDisplayedXTimes;
       
   250 	iArray[index].iTimeStamp = aTimeStamp;
       
   251 	
       
   252 	iNumberElements++;
       
   253 	return KErrNone;
       
   254 	}
       
   255 
       
   256 /** 
       
   257    Remove notification from the list.
       
   258    The function is called from the backend thread. 
       
   259    The client of this API must use a lock mechanizm to preserve data integrity.
       
   260 */
       
   261 void CTContentUpdateReceiver::Remove(TInt aIndex) 
       
   262 	{
       
   263 	TInt max = sizeof(iArray) / sizeof(iArray[0]) - 1;
       
   264 	if((aIndex < 0) || (aIndex >= max))
       
   265 			return;
       
   266 	
       
   267 	iNumberElements--;
       
   268 	if(aIndex < iNumberElements)
       
   269 		{
       
   270 		Mem::Move(&iArray[aIndex], &iArray[aIndex + 1], (iNumberElements - aIndex) * sizeof(RequestObject));
       
   271 		iArray[iNumberElements].iType= EReqEmpty;
       
   272 		}
       
   273 	else
       
   274 		{
       
   275 		iArray[aIndex].iType = EReqEmpty;
       
   276 		}	
       
   277 	}
       
   278 	
       
   279 TInt CTContentUpdateReceiver::ThreadFunction(TAny* aAny)
       
   280 	{
       
   281 	  // get clean-up stack
       
   282 	CTrapCleanup* cleanup=CTrapCleanup::New();
       
   283 	RThread thread;
       
   284 	_LIT(KTestReceiver, "TestReceiver");
       
   285 	__ASSERT_ALWAYS(cleanup!=NULL, thread.Panic( KTestReceiver, KErrNoMemory));
       
   286 	
       
   287 	  // create an active scheduler and server
       
   288 	CActiveScheduler *pA = new CActiveScheduler;
       
   289 	__ASSERT_ALWAYS(pA != NULL, thread.Panic( KTestReceiver, KErrNoMemory));
       
   290 
       
   291 	  //Install the active scheduler
       
   292 	CActiveScheduler::Install(pA);
       
   293 
       
   294 	CTContentUpdateReceiver *pCB = NULL;
       
   295 	TInt screen = * (static_cast <TInt*> (aAny));
       
   296 	TRAPD(err, pCB = CTContentUpdateReceiver::NewL(screen));
       
   297 	__ASSERT_ALWAYS(err == KErrNone, thread.Panic( KTestReceiver, err));
       
   298 	
       
   299  	*(static_cast <CTContentUpdateReceiver**> (aAny)) = pCB;
       
   300     
       
   301       // Let everyone know that we are ready to
       
   302       // deal with requests.
       
   303 	RThread::Rendezvous(KErrNone);
       
   304 	  // And start fielding requests from client(s).
       
   305 	CActiveScheduler::Start();
       
   306 
       
   307      // Tidy up... 	
       
   308 	delete pCB;
       
   309 	delete pA;
       
   310 	delete cleanup; 
       
   311 	
       
   312 	return KErrNone;
       
   313 	}
       
   314 
       
   315 _LIT(KMaskBackend, "CompositionBackend_%d");
       
   316 const TUint KDefaultHeapSize=0x10000;
       
   317 
       
   318 EXPORT_C TInt StartTestUpdateReceiver(CTContentUpdateReceiver*& aReceiver, TInt aScreen)
       
   319 	{
       
   320 	RThread compositionThread;
       
   321 	TInt res = KErrGeneral;
       
   322 	TBuf<64> contentUpdateReceiverThreadName;
       
   323 	TBuf<64> contentUpdateReceiverThreadMask;
       
   324 	
       
   325 	// Guarantee uniqueness of thread name by using timestamp
       
   326 	TTime tm;
       
   327 	TBuf<32> timeStamp;
       
   328 	tm.UniversalTime();
       
   329 	TRAP(res, tm.FormatL(timeStamp, _L("_%H%T%S%C")));
       
   330 	if(res != KErrNone)
       
   331 		{
       
   332 		return res;
       
   333 		}
       
   334 
       
   335 	contentUpdateReceiverThreadName.Format(KMaskBackend, aScreen);
       
   336 	contentUpdateReceiverThreadName.Append(timeStamp);
       
   337 	contentUpdateReceiverThreadMask = contentUpdateReceiverThreadName;
       
   338 	contentUpdateReceiverThreadMask.Insert(0, _L("*"));
       
   339 	TFindThread findThread(contentUpdateReceiverThreadMask);
       
   340 	TFullName name;
       
   341 	  // Need to check that the thread exists.
       
   342 	if (findThread.Next(name)!=KErrNone)
       
   343 		{
       
   344 		aReceiver = reinterpret_cast <CTContentUpdateReceiver*> (aScreen);
       
   345 		
       
   346 		  // Create the thread for the server.
       
   347 		res = compositionThread.Create(contentUpdateReceiverThreadName,
       
   348 			CTContentUpdateReceiver::ThreadFunction,
       
   349 			KDefaultStackSize,
       
   350 			KDefaultHeapSize,
       
   351 			KDefaultHeapSize,
       
   352 			(TAny*) &aReceiver
       
   353 			);
       
   354 			
       
   355           // The thread has been created OK so get it started - however
       
   356           // we need to make sure that it has started before we continue.
       
   357 		if (res==KErrNone)
       
   358 			{
       
   359 			TRequestStatus rendezvousStatus;
       
   360 			compositionThread.SetPriority(EPriorityNormal);
       
   361 			compositionThread.Rendezvous(rendezvousStatus);
       
   362 			compositionThread.Resume();
       
   363 			User::WaitForRequest(rendezvousStatus);
       
   364 			res = rendezvousStatus.Int();
       
   365 			}
       
   366 		}
       
   367 		compositionThread.Close();
       
   368 		return res;
       
   369 	}
       
   370 
       
   371 EXPORT_C void CloseTestUpdateReceiver(CTContentUpdateReceiver* aReceiver)
       
   372 	{
       
   373 	if(!aReceiver)
       
   374 		return;
       
   375 
       
   376 	TBuf<64> contentUpdateReceiverThreadName;
       
   377 	contentUpdateReceiverThreadName.Format(KMaskBackend, aReceiver->Screen());
       
   378 	TBuf<64> contentUpdateReceiverThreadMask;
       
   379 	contentUpdateReceiverThreadMask = contentUpdateReceiverThreadName;
       
   380 	contentUpdateReceiverThreadMask.Insert(0, _L("*"));
       
   381 	contentUpdateReceiverThreadMask.Append('*');
       
   382 	TFindThread findThread(contentUpdateReceiverThreadMask);
       
   383 	TFullName name;
       
   384 	RThread thread;
       
   385 	if((findThread.Next(name)!=KErrNone) ||
       
   386 		(thread.Open(findThread) != KErrNone))
       
   387 		{
       
   388 		thread.Close();
       
   389 		return;
       
   390 		}
       
   391 	TRequestStatus status; 
       
   392 	thread.Logon(status);
       
   393 	if(aReceiver)
       
   394 		aReceiver->Stop();
       
   395 	User::WaitForRequest(status);
       
   396 	thread.Close();
       
   397 	}