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