os/graphics/graphicsdeviceinterface/directgdi/test/tmultithread.cpp
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     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