graphicsdeviceinterface/directgdi/test/tmultithread.cpp
changeset 0 5d03bc08d59c
equal deleted inserted replaced
-1:000000000000 0:5d03bc08d59c
       
     1 // Copyright (c) 2008-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  @internalComponent 
       
    19  @test
       
    20 */
       
    21 
       
    22 #include "tmultithread.h"
       
    23 #include <graphics/directgdicontext.h>
       
    24 
       
    25 const TUint KMinTestThreadHeapSize = 0x00000100;
       
    26 const TUint KMaxTestThreadheapSize = 0x00100000;
       
    27 
       
    28 CTMultiThread::CTMultiThread()
       
    29 	{
       
    30 	SetTestStepName(KTMultiThreadStep);
       
    31 	}
       
    32 
       
    33 CTMultiThread::~CTMultiThread()
       
    34 	{
       
    35 	iThread1.Close();
       
    36 	iThread2.Close();
       
    37 	}
       
    38 
       
    39 /**
       
    40 Override of base class virtual
       
    41 @leave Gets system wide error code
       
    42 @return - TVerdict code
       
    43 */
       
    44 TVerdict CTMultiThread::doTestStepPreambleL()
       
    45 	{			
       
    46 	CTDirectGdiStepBase::doTestStepPreambleL();	
       
    47 	return TestStepResult();
       
    48 	}
       
    49 
       
    50 /** 
       
    51 Override of base class pure virtual
       
    52 Our implementation only gets called if the base class doTestStepPreambleL() did
       
    53 not leave. That being the case, the current test result value will be EPass.
       
    54 @leave Gets system wide error code
       
    55 @return TVerdict code
       
    56 */	
       
    57 TVerdict CTMultiThread::doTestStepL()
       
    58 	{
       
    59 	if (iUseDirectGdi)
       
    60 		{
       
    61 		RunTestsL();
       
    62 		// No framework OOM tests are run for the multithreaded tests as OOM testing only checks the 
       
    63 		// heap in the current thread and these tests use multiple threads. Some heap checking is
       
    64 		// performed within the tests themselves.
       
    65 		}
       
    66 	else
       
    67 		{
       
    68 		INFO_PRINTF1(_L("Test skipped under BitGDI.\n"));	
       
    69 		}	
       
    70 	CloseTMSGraphicsStep();
       
    71 	return TestStepResult();
       
    72 	}
       
    73 
       
    74 /**
       
    75 Override of base class pure virtual
       
    76 Lists the tests to be run
       
    77 */
       
    78 void CTMultiThread::RunTestsL()
       
    79 	{
       
    80 	SetTestStepID(_L("GRAPHICS-DIRECTGDI-MULTITHREAD-0001"));
       
    81 	TestDirectGdiMultipleThreadIndependenceL();
       
    82 	RecordTestResultL();
       
    83 	SetTestStepID(_L("GRAPHICS-DIRECTGDI-MULTITHREAD-0002"));
       
    84 	TestShareEGLImageBetweenSources_MultithreadedL();
       
    85 	RecordTestResultL();
       
    86 	}
       
    87 
       
    88 /**
       
    89 @SYMTestCaseID  
       
    90 	GRAPHICS-DIRECTGDI-MULTITHREAD-0001
       
    91 	
       
    92 @SYMPREQ 
       
    93 	PREQ39
       
    94 
       
    95 @SYMREQ
       
    96 	REQ9195
       
    97 	REQ9201 
       
    98 	REQ9202 
       
    99 	REQ9222 
       
   100 	REQ9223 
       
   101 	REQ9236 
       
   102 	REQ9237
       
   103 	
       
   104 @SYMTestCaseDesc  
       
   105 	Ensure multi-threaded use of DirectGDI is truly independent.
       
   106 	
       
   107 @SYMTestPriority  
       
   108 	High
       
   109 	
       
   110 @SYMTestStatus 
       
   111 	Implemented
       
   112 	
       
   113 @SYMTestActions 
       
   114 	The following sequence should be legal:
       
   115 		1: (thread 1) initialise DirectGDI by calling ThreadOneStart()
       
   116 		2: (thread 2) initialise DirectGDI by calling ThreadTwoStart()
       
   117 		3: (thread 1) close DirectGDI
       
   118 		4: (thread 2) render using DirectGDI
       
   119 		
       
   120 @SYMTestExpectedResults 
       
   121 	There should be no panics.
       
   122 */
       
   123 void CTMultiThread::TestDirectGdiMultipleThreadIndependenceL()
       
   124 	{
       
   125 	INFO_PRINTF1(_L("Multithread_MultipleThreadIndependence"));	
       
   126 	// Create a semaphore
       
   127 	RSemaphore sem;
       
   128 	TEST(KErrNone == sem.CreateGlobal(KMultiThreadSemaphore, 0));
       
   129    	CleanupClosePushL(sem);	
       
   130    	
       
   131    	//create threads
       
   132 	User::LeaveIfError(iThread1.Create(KNameThreadOne, ThreadOneStart, KDefaultStackSize, KMinTestThreadHeapSize, KMaxTestThreadheapSize, NULL));
       
   133 	User::LeaveIfError(iThread2.Create(KNameThreadTwo, ThreadTwoStart, KDefaultStackSize, KMinTestThreadHeapSize, KMaxTestThreadheapSize, NULL));
       
   134 	
       
   135 	//launch thread1
       
   136 	TRequestStatus thread1Status;
       
   137 	iThread1.Logon(thread1Status);
       
   138 	iThread1.SetPriority(EPriorityLess);
       
   139 	iThread1.Resume();
       
   140 	sem.Wait();
       
   141 	iThread1.Suspend();
       
   142 	
       
   143 	//launch thread2
       
   144 	TRequestStatus thread2Status;
       
   145 	iThread2.Logon(thread2Status);
       
   146 	iThread2.SetPriority(EPriorityLess);
       
   147 	iThread2.Resume();
       
   148 	sem.Wait();
       
   149 	iThread2.Suspend();
       
   150 	
       
   151 	//resume thread1
       
   152 	iThread1.Resume();
       
   153 	User::WaitForRequest(thread1Status);
       
   154 	
       
   155 	//resume thread2
       
   156 	iThread2.Resume();
       
   157 	User::WaitForRequest(thread2Status);	
       
   158 	
       
   159 	TESTNOERROR(iThread1.ExitReason());
       
   160 	TESTNOERROR(iThread2.ExitReason());
       
   161 			
       
   162 	iThread1.Close();
       
   163 	iThread2.Close();
       
   164 	CleanupStack::PopAndDestroy(&sem);
       
   165 	}
       
   166 
       
   167 /**
       
   168 Function for initializing DirectGdi, used by TestDirectGdiMultipleThreadIndependenceL().
       
   169 @see TestDirectGdiMultipleThreadIndependenceL() 
       
   170 @param aInfo Not used
       
   171 @return KErrNone if successful, one of the system wide error codes otherwise
       
   172  */
       
   173 TInt CTMultiThread::ThreadOneStart(TAny* /*aInfo*/)
       
   174 	{	
       
   175 	TInt procHandles1  =0;
       
   176 	TInt threadHandles1=0;
       
   177 	RThread().HandleCount(procHandles1, threadHandles1);
       
   178 	__UHEAP_MARK;
       
   179 	
       
   180 	RSemaphore sem;
       
   181 	TInt ret = sem.OpenGlobal(KMultiThreadSemaphore);
       
   182 	if (ret!=KErrNone)
       
   183 		{
       
   184 		return ret;
       
   185 		}		
       
   186 	
       
   187 	//initialize graphics resource driver
       
   188 	ret = SgDriver::Open();
       
   189 	if (ret!=KErrNone)
       
   190 		{
       
   191 		return ret;
       
   192 		}		
       
   193 	
       
   194 	//initialise DirectGDI
       
   195 	ret = CDirectGdiDriver::Open();
       
   196 	if (ret!=KErrNone)
       
   197 		{
       
   198 		return ret;
       
   199 		}		
       
   200 
       
   201 	CDirectGdiDriver* dgdiDriver = CDirectGdiDriver::Static();
       
   202 	if(dgdiDriver == NULL)
       
   203 		{
       
   204 		return KErrGeneral;	
       
   205 		}
       
   206 	
       
   207 	sem.Signal();
       
   208 
       
   209 	//close DirectGDI
       
   210 	dgdiDriver->Close();
       
   211 	SgDriver::Close();	
       
   212 	sem.Close();
       
   213 	__UHEAP_MARKEND;
       
   214 	TInt procHandles2  =0;
       
   215 	TInt threadHandles2=0;
       
   216 	RThread().HandleCount(procHandles2,threadHandles2);
       
   217 	if (threadHandles1 != threadHandles2)
       
   218 		{
       
   219 		ret = KErrGeneral;  // Thread-owned handles not closed
       
   220 		}
       
   221 	return ret;
       
   222 	}
       
   223 
       
   224 /**
       
   225 Function for initializing DirectGdi then activating a target and drawing on it,
       
   226 used by TestDirectGdiMultipleThreadIndependenceL().
       
   227 @see TestDirectGdiMultipleThreadIndependenceL()
       
   228 @param aInfo Not used
       
   229 @return KErrNone if successful, one of the system wide error codes otherwise 
       
   230  */
       
   231 TInt CTMultiThread::ThreadTwoStart(TAny* /*aInfo*/)
       
   232 	{
       
   233 	TInt procHandles1  =0;
       
   234 	TInt threadHandles1=0;
       
   235 	RThread().HandleCount(procHandles1, threadHandles1);
       
   236 	__UHEAP_MARK;
       
   237 	CTrapCleanup* cleanupStack=CTrapCleanup::New();
       
   238 	if (cleanupStack==NULL)
       
   239 		{
       
   240 		return KErrNoMemory;
       
   241 		}
       
   242 	
       
   243 	RSemaphore sem;
       
   244 	TInt ret = sem.OpenGlobal(KMultiThreadSemaphore);
       
   245 	if (ret!=KErrNone)
       
   246 		{
       
   247 		return ret;
       
   248 		}		
       
   249 	
       
   250 	//initialize graphics resource driver
       
   251 	ret = SgDriver::Open();
       
   252 	if (ret!=KErrNone)
       
   253 		{
       
   254 		return ret;
       
   255 		}		
       
   256 	
       
   257 	//initialise DirectGDI
       
   258 	ret = CDirectGdiDriver::Open();
       
   259 	if (ret!=KErrNone)
       
   260 		{
       
   261 		return ret;
       
   262 		}		
       
   263 
       
   264 	CDirectGdiDriver* dgdiDriver = CDirectGdiDriver::Static();
       
   265 	if(dgdiDriver == NULL)
       
   266 		{
       
   267 		return KErrGeneral;	
       
   268 		}
       
   269 	
       
   270 	sem.Signal();
       
   271 	
       
   272 	//render using DirectGDI
       
   273 	CDirectGdiContext* gc = NULL;
       
   274 	TRAPD(err, gc=CDirectGdiContext::NewL(*dgdiDriver));
       
   275 	if(err != KErrNone)
       
   276 		{
       
   277 		return err;
       
   278 		}
       
   279 	
       
   280 	RSgImage rsgImage;	
       
   281 	TSgImageInfo imageInfo;
       
   282 	imageInfo.iSizeInPixels = TSize (320, 240);
       
   283 	imageInfo.iPixelFormat = EUidPixelFormatRGB_565;
       
   284 	imageInfo.iUsage = ESgUsageDirectGdiTarget;
       
   285 	ret = rsgImage.Create(imageInfo, NULL,0);
       
   286 	if(ret != KErrNone)
       
   287 		{
       
   288 		return ret;
       
   289 		}
       
   290 	RDirectGdiImageTarget dgdiImageTarget(*dgdiDriver);	
       
   291 	ret = dgdiImageTarget.Create(rsgImage);
       
   292 	if(ret != KErrNone)
       
   293 		{
       
   294 		return ret;
       
   295 		}
       
   296 	gc->Activate(dgdiImageTarget);
       
   297 	gc->SetPenColor(TRgb(100,100,100));
       
   298 	gc->DrawRect(TRect(0,0,30,30));
       
   299 	
       
   300 	rsgImage.Close();
       
   301 	dgdiImageTarget.Close();
       
   302 	delete gc;
       
   303 	dgdiDriver->Close();
       
   304 	SgDriver::Close();
       
   305 	delete cleanupStack;
       
   306 	__UHEAP_MARKEND;
       
   307 	sem.Close();	
       
   308 	TInt procHandles2  =0;
       
   309 	TInt threadHandles2=0;
       
   310 	RThread().HandleCount(procHandles2,threadHandles2);
       
   311 	if (threadHandles1 != threadHandles2)
       
   312 		{
       
   313 		ret = KErrGeneral;  // Thread-owned handles not closed
       
   314 		}
       
   315 	return ret;
       
   316 	}
       
   317 
       
   318 /**
       
   319 @SYMTestCaseID		
       
   320 	GRAPHICS-DIRECTGDI-MULTITHREAD-0002
       
   321 
       
   322 @SYMTestPriority
       
   323 	Critical
       
   324 
       
   325 @SYMPREQ
       
   326 	PREQ39
       
   327 
       
   328 @SYMREQ
       
   329 	REQ9195
       
   330 	REQ9201 
       
   331 	REQ9202 
       
   332 	REQ9222 
       
   333 	REQ9223 
       
   334 	REQ9236 
       
   335 	REQ9237
       
   336 
       
   337 @SYMTestStatus
       
   338 	Implemented
       
   339 
       
   340 @SYMTestCaseDesc
       
   341 	Create two CDirectGdiImageSource objects from the same RSgImage, but in different threads.
       
   342 
       
   343 @SYMTestActions	
       
   344 	Test the use case where we:
       
   345 	Create an RSgImage
       
   346 	Create two CDirectGdiImageSource objects, one in the current thread, and one in a new thread.
       
   347 	The CDirectGdiImageSource objects should share the EGL image created from the RSgImage in the 
       
   348 	current thread as only one EGL image can be created per RSgImage per process.
       
   349 	If the EGL image sharing is not working an error will occur when creating the
       
   350 	second CDirectGdiImageSource object in the new thread.
       
   351 */
       
   352 void CTMultiThread::TestShareEGLImageBetweenSources_MultithreadedL()
       
   353 	{
       
   354 	INFO_PRINTF1(_L("Multithread_ShareEGLImageBetweenSources"));
       
   355 	
       
   356 	TUidPixelFormat pixelFormat = EUidPixelFormatXRGB_8888;
       
   357 	SetTargetL(pixelFormat);
       
   358 	
       
   359 	// Initialize graphics resource driver
       
   360 	TInt res = SgDriver::Open();
       
   361 	TESTNOERRORL(res);
       
   362 	
       
   363 	res = CDirectGdiDriver::Open();
       
   364 	TESTNOERRORL(res);		
       
   365 	
       
   366 	CDirectGdiDriver* dgdiDriver = CDirectGdiDriver::Static();
       
   367 	TESTL(dgdiDriver != NULL);	
       
   368 	CleanupClosePushL(*dgdiDriver);	
       
   369 	
       
   370 	// Create a context
       
   371 	CDirectGdiContext* gc = CDirectGdiContext::NewL(*dgdiDriver);
       
   372 	TESTL(gc != NULL);	
       
   373 	CleanupStack::PushL(gc);	
       
   374 	
       
   375 	// Create a CFbsBitmap	
       
   376 	TSize patternSize(90,50);
       
   377 	TRect rect(0,0,90,50);
       
   378 	CFbsBitmap* bitmap = CreateCheckedBoardBitmapL(pixelFormat, patternSize);
       
   379 	TESTL(NULL != bitmap);
       
   380 	CleanupStack::PushL(bitmap);	
       
   381 	
       
   382 	// Create an RSgImage from the CFbsBitmap
       
   383 	TSgImageInfo imageInfo;
       
   384 	imageInfo.iSizeInPixels = patternSize;
       
   385 	imageInfo.iPixelFormat = pixelFormat;
       
   386 	imageInfo.iUsage = ESgUsageDirectGdiSource;
       
   387 	RSgImage sgImage;	
       
   388 	res = sgImage.Create(imageInfo, bitmap->DataAddress(), bitmap->DataStride());	
       
   389 	TESTNOERRORL(res);	
       
   390 	CleanupClosePushL(sgImage);
       
   391 	
       
   392 	// Create a RDirectGdiDrawableSource from the RSgImage
       
   393 	RDirectGdiDrawableSource dgdiImageSource(*dgdiDriver);	
       
   394 	res = dgdiImageSource.Create(sgImage);		
       
   395 	TESTNOERRORL(res);
       
   396 	CleanupClosePushL(dgdiImageSource);	
       
   397 	
       
   398 	// Create a semaphore
       
   399 	RSemaphore sem;
       
   400 	TEST(KErrNone == sem.CreateGlobal(KMultiThreadSemaphore, 0));
       
   401    	CleanupClosePushL(sem);	
       
   402    	
       
   403    	// Create the thread that will create a source from the RSgImage above   	
       
   404    	TSgDrawableId sgImageId = sgImage.Id();
       
   405 	User::LeaveIfError(iThread1.Create(KNameThreadOne, ThreadEGLImageStart, KDefaultStackSize, KMinTestThreadHeapSize, KMaxTestThreadheapSize, &sgImageId));	
       
   406 	
       
   407 	// Launch the thread
       
   408 	TRequestStatus threadStatus;
       
   409 	iThread1.Logon(threadStatus);
       
   410 	iThread1.SetPriority(EPriorityLess);
       
   411 	iThread1.Resume();
       
   412 	sem.Wait();
       
   413 	iThread1.Suspend();
       
   414 		
       
   415 	// Resume the thread
       
   416 	iThread1.Resume();
       
   417 	User::WaitForRequest(threadStatus);
       
   418 	
       
   419 	TESTNOERROR(iThread1.ExitReason());	
       
   420 			
       
   421 	iThread1.Close();	
       
   422 	SgDriver::Close();
       
   423 	CleanupStack::PopAndDestroy(6, dgdiDriver);
       
   424 	}
       
   425 
       
   426 /**
       
   427 Function use by TestShareEGLImageBetweenSources_MultithreadedL() when testing
       
   428 creation of a target in a separate thread.
       
   429 @see TestShareEGLImageBetweenSources_MultithreadedL()
       
   430 @param aInfo Not used
       
   431 @return KErrNone if successful, one of the system wide error codes otherwise
       
   432  */
       
   433 TInt CTMultiThread::ThreadEGLImageStart(TAny* aInfo)
       
   434 	{	
       
   435 	TInt procHandles1 = 0;
       
   436 	TInt threadHandles1 = 0;
       
   437 	RThread().HandleCount(procHandles1, threadHandles1);
       
   438 	__UHEAP_MARK;
       
   439 	CTrapCleanup* cleanupStack=CTrapCleanup::New();
       
   440 	if (cleanupStack==NULL)
       
   441 		{
       
   442 		return KErrNoMemory;
       
   443 		}		
       
   444 	
       
   445 	RSemaphore sem;
       
   446 	TInt ret = sem.OpenGlobal(KMultiThreadSemaphore);
       
   447 	if (ret!=KErrNone)
       
   448 		return ret;
       
   449 	
       
   450 	// Initialize graphics resource driver
       
   451 	ret = SgDriver::Open();
       
   452 	if (ret!=KErrNone)
       
   453 		return ret;
       
   454 	
       
   455 	// Initialise DirectGDI
       
   456 	ret = CDirectGdiDriver::Open();
       
   457 	if (ret!=KErrNone)
       
   458 		return ret;
       
   459 
       
   460 	CDirectGdiDriver* dgdiDriver = CDirectGdiDriver::Static();
       
   461 	if(dgdiDriver == NULL)
       
   462 		{
       
   463 		return KErrGeneral;	
       
   464 		}
       
   465 	
       
   466 	TSgDrawableId* sgImageId = reinterpret_cast<TSgDrawableId*>(aInfo);
       
   467 	RSgImage sgImageSource;
       
   468 	ret = sgImageSource.Open(*sgImageId);
       
   469 	if (ret!=KErrNone)
       
   470 		return ret;
       
   471 	
       
   472 	// Create a RDirectGdiDrawableSource from the RSgImage
       
   473 	RDirectGdiDrawableSource dgdiImageSource(*dgdiDriver);	
       
   474 	ret = dgdiImageSource.Create(sgImageSource);		
       
   475 	if (ret!=KErrNone)
       
   476 		return ret;
       
   477 	
       
   478 	sem.Signal();
       
   479 	
       
   480 	// Render using DirectGDI
       
   481 	CDirectGdiContext* gc = NULL;
       
   482 	TRAPD(err, gc=CDirectGdiContext::NewL(*dgdiDriver));
       
   483 	if(err != KErrNone)
       
   484 		{
       
   485 		return err;
       
   486 		}
       
   487 	
       
   488 	RSgImage rsgImage;	
       
   489 	TSgImageInfo imageInfo;
       
   490 	imageInfo.iSizeInPixels = TSize (320, 240);
       
   491 	imageInfo.iPixelFormat = EUidPixelFormatRGB_565;
       
   492 	imageInfo.iUsage = ESgUsageDirectGdiTarget;
       
   493 	ret = rsgImage.Create(imageInfo, NULL,0);
       
   494 	if(ret != KErrNone)
       
   495 		{
       
   496 		return ret;
       
   497 		}
       
   498 	RDirectGdiImageTarget dgdiImageTarget(*dgdiDriver);	
       
   499 	ret = dgdiImageTarget.Create(rsgImage);
       
   500 	if(ret != KErrNone)
       
   501 		{
       
   502 		return ret;
       
   503 		}
       
   504 	gc->Activate(dgdiImageTarget);
       
   505 	gc->SetPenColor(TRgb(100,100,100));
       
   506 	gc->DrawRect(TRect(0,0,30,30));
       
   507 	
       
   508 	dgdiImageSource.Close();
       
   509 	sgImageSource.Close();
       
   510 	rsgImage.Close();
       
   511 	dgdiImageTarget.Close();
       
   512 	delete gc;
       
   513 	dgdiDriver->Close();
       
   514 	SgDriver::Close();
       
   515 	delete cleanupStack;
       
   516 	__UHEAP_MARKEND;
       
   517 	sem.Close();	
       
   518 	TInt procHandles2  =0;
       
   519 	TInt threadHandles2=0;
       
   520 	RThread().HandleCount(procHandles2,threadHandles2);
       
   521 	if (threadHandles1 != threadHandles2)
       
   522 		{
       
   523 		ret = KErrGeneral;  // Thread-owned handles not closed
       
   524 		}
       
   525 	return ret;
       
   526 	}
       
   527