os/graphics/egl/egltest/src/egltest_image_multithread.cpp
changeset 0 bde4ae8d615e
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/os/graphics/egl/egltest/src/egltest_image_multithread.cpp	Fri Jun 15 03:10:57 2012 +0200
     1.3 @@ -0,0 +1,864 @@
     1.4 +
     1.5 +// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
     1.6 +// All rights reserved.
     1.7 +// This component and the accompanying materials are made available
     1.8 +// under the terms of "Eclipse Public License v1.0"
     1.9 +// which accompanies this distribution, and is available
    1.10 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
    1.11 +//
    1.12 +// Initial Contributors:
    1.13 +// Nokia Corporation - initial contribution.
    1.14 +//
    1.15 +// Contributors:
    1.16 +//
    1.17 +// Description:
    1.18 +//
    1.19 +
    1.20 +/**
    1.21 + @file
    1.22 + @test
    1.23 +*/
    1.24 +
    1.25 +#include <test/tefunit.h> // for ASSERT macros
    1.26 +#include "egltest_image_multithread.h"
    1.27 +
    1.28 +#include <test/egltestcommonconversion.h>
    1.29 +#include <test/egltestcommonsgimageinfo.h>
    1.30 +
    1.31 +
    1.32 +CEglTest_MThread_Image_Base::CEglTest_MThread_Image_Base()
    1.33 +	{
    1.34 +	}
    1.35 +
    1.36 +CEglTest_MThread_Image_Base::~CEglTest_MThread_Image_Base()
    1.37 +	{
    1.38 +	iSgImageShared.Close();
    1.39 +	}
    1.40 +
    1.41 +/**
    1.42 +@SYMTestCaseID GRAPHICS-EGL-0155
    1.43 +
    1.44 +@SYMTestPriority 1
    1.45 +
    1.46 +@SYMPREQ 39
    1.47 +
    1.48 +@SYMREQ See SGL.GT0386.401 document
    1.49 +
    1.50 +@SYMTestCaseDesc
    1.51 +Check if EGL Implementation allows two threads to work in parallel.
    1.52 +
    1.53 +@SYMTestActions
    1.54 +Run two threads that independently perform the same actions detailed below.
    1.55 +This test will check for the “VG_KHR_EGL_image” extension, if it is not 
    1.56 +supported on this platform then the test will return immediately without failure.
    1.57 +Create and fully construct an RSgImage object
    1.58 +•	Set the iUsage bits to ESgUsageBitOpenVgImage
    1.59 +Pass the RSgImage object into eglCreateImageKHR() with
    1.60 +•	The target parameter set to EGL_NATIVE_PIXMAP_KHR
    1.61 +•	Use the current display and EGL_NO_CONTEXT
    1.62 +•	Use a NULL attr_list
    1.63 +Check that eglCreateImageKHR() does NOT return EGL_NO_IMAGE_KHR
    1.64 +Use vgCreateEGLImageTargetKHR() to construct a VGImage object from the EGLImage.
    1.65 +•	Check for errors (VGInvalidHandle is not returned)
    1.66 +Create a second RSgImage, and use it to create a pixmap surface that is 
    1.67 +compatible as a target for the VGImage to be drawn to.
    1.68 +•	Set the iUsage bit to ESgUsageBitOpenVgSurface
    1.69 +•	Use the same pixel format as the RSgImage above.
    1.70 +Now that a eglContext and an OpenVG context have been created, use the 
    1.71 +OpenVG API vgClearImage to clear to a chosen colour the VGImage previously 
    1.72 +returned by eglCreateImageKHR.
    1.73 +Use OpenVG to draw the just drawn VGImage to the pixmap surface currently 
    1.74 +linked to the context.
    1.75 +Call eglWaitClient() to finish the above drawing instructions synchronously.
    1.76 +Destroy the original image data
    1.77 +•	Pass the VGImage into vgDestroyImage()
    1.78 +•	Pass the EGLImage into eglDestroyImageKHR()
    1.79 +•	Close the first RSgImage
    1.80 +•	Check that the pixmap surface contains expected pixel values using 
    1.81 +OpenVG APIs, vgReadPixels.
    1.82 +Close the second RSgImage and destroy the pixmap surface
    1.83 +Check for memory and handle leaks
    1.84 +
    1.85 +@SYMTestExpectedResults
    1.86 +Pixmap surface has the expected contents in both threads (within tolerance).
    1.87 +No memory or handle leaks.
    1.88 +*/
    1.89 +TVerdict CEglTest_EGL_Image_Multi_Thread_Parallel::doTestStepL()
    1.90 +	{
    1.91 +	SetTestStepID(_L("GRAPHICS-EGL-0155"));
    1.92 +	INFO_PRINTF1(_L("Enter: CEglTest_EGL_Image_Multi_Thread_Parallel::doTestStepL"));
    1.93 +
    1.94 +	TBool ret = CheckForExtensionL(KEGL_RSgimage | KEGL_KHR_image_base | KEGL_KHR_image_pixmap | KVG_KHR_EGL_image);
    1.95 +	if(!ret)
    1.96 +		{
    1.97 +		// The extension is not supported
    1.98 +		RecordTestResultL();
    1.99 +		CloseTMSGraphicsStep();
   1.100 +		return TestStepResult();
   1.101 +		}
   1.102 +
   1.103 +	Test_MultiThreadL(2, ETrue);
   1.104 +	TerminateDisplayL();
   1.105 +
   1.106 +	INFO_PRINTF1(_L("Exit: CEglTest_EGL_Image_Multi_Thread_Parallel::doTestStepL"));
   1.107 +	RecordTestResultL();	
   1.108 +	CloseTMSGraphicsStep();
   1.109 +	return TestStepResult();
   1.110 +	}
   1.111 +
   1.112 +void CEglTest_EGL_Image_Multi_Thread_Parallel::doThreadFunctionL(TInt aIdx)
   1.113 +	{
   1.114 +	INFO_PRINTF2(_L("CEglTest_EGL_Image_Multi_Thread_Parallel::doThreadFunctionL, Thread %d"),aIdx);
   1.115 +	GetDisplayL();
   1.116 +	CTestEglSession* eglSess = CTestEglSession::NewLC(Logger(), iDisplay, aIdx);
   1.117 +	eglSess->InitializeL();	
   1.118 +	eglSess->OpenSgDriverL();
   1.119 +	
   1.120 +	// create a reference bitmap (we give index 7, as there's only 1 image in this test case)
   1.121 +	TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(KDefaultSourceFormat);
   1.122 +	CFbsBitmap* bitmap = eglSess->CreateReferenceBitmapL(bitmapMode, KPixmapSize, 7);
   1.123 +	CleanupStack::PushL(bitmap);
   1.124 +
   1.125 +	// Create an RSgImage
   1.126 +	INFO_PRINTF2(_L("Thread %d, Creating a RSgImage having the reference bitmap's content"),aIdx);
   1.127 +	TSgImageInfoOpenVgImage imageInfo = TSgImageInfoOpenVgImage(KDefaultSourceFormat, KPixmapSize);
   1.128 +    RSgImage rSgImageLocal;
   1.129 +	CleanupClosePushL(rSgImageLocal);
   1.130 +	ASSERT_EQUALS(rSgImageLocal.Create(imageInfo,bitmap->DataAddress(),bitmap->DataStride()), KErrNone);
   1.131 +
   1.132 +	INFO_PRINTF2(_L("Thread %d, Creating an EGLImage from the shared RSgImage"),aIdx);
   1.133 +	EGLImageKHR eglImageLocal = eglSess->eglCreateImageKhrL(iDisplay, EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, &rSgImageLocal, KEglImageAttribsPreservedTrue);
   1.134 +	ASSERT_EGL_TRUE(eglImageLocal != EGL_NO_IMAGE_KHR);
   1.135 +	CleanupStack::PopAndDestroy(&rSgImageLocal); 	//transferring ownership of the buffer to the EGLImage
   1.136 +	CleanupStack::PopAndDestroy(bitmap);
   1.137 +
   1.138 +	INFO_PRINTF2(_L("Thread %d, Creating a Surface and a Context bound to OpenVG"),aIdx);
   1.139 +	TUidPixelFormat pixelFormat = EglTestConversion::VgFormatToSgPixelFormat(KDefaultSurfaceFormat);
   1.140 +	TSgImageInfoOpenVgTarget imageInfo2 = TSgImageInfoOpenVgTarget(pixelFormat, KPixmapSize);
   1.141 +	// Create a pixmap surface matching the native image pixel format
   1.142 +	eglSess->CreatePixmapSurfaceAndMakeCurrentAndMatchL(imageInfo2,CTestEglSession::EResourceCloseSgImageEarly);
   1.143 +	
   1.144 +	INFO_PRINTF2(_L("Thread %d, Creating one VGImage from the EGLImage"),aIdx);
   1.145 +	VGImage vgImageLocal = eglSess->vgCreateImageTargetKHR((VGeglImageKHR)eglImageLocal);	
   1.146 +	ASSERT_VG_TRUE(vgImageLocal != VG_INVALID_HANDLE);
   1.147 +	ASSERT_EGL_TRUE(eglSess->DestroyEGLImage(iDisplay, eglImageLocal));
   1.148 +		
   1.149 +	// Copy the source VGImage to the surface
   1.150 +	vgSetPixels(0, 0, vgImageLocal, 0, 0, KPixmapSize.iWidth, KPixmapSize.iHeight);
   1.151 +	ASSERT_TRUE(vgGetError()==VG_NO_ERROR);
   1.152 +	eglWaitClient();
   1.153 +
   1.154 +	// destroy VGImage
   1.155 +	vgDestroyImage(vgImageLocal);
   1.156 +	ASSERT_TRUE(vgGetError()==VG_NO_ERROR);
   1.157 +
   1.158 +	// we can now compare the VgImage to the one we would expect for this particular thread
   1.159 +	CFbsBitmap* refBitmap = eglSess->CreateReferenceBitmapL(bitmapMode, KPixmapSize, 7);
   1.160 +	CleanupStack::PushL(refBitmap);
   1.161 +	eglSess->CheckVgDrawingL(KDefaultSurfaceFormat, refBitmap);
   1.162 +	CleanupStack::PopAndDestroy(refBitmap);
   1.163 +	INFO_PRINTF2(_L("Drawing successful, Thread %d"),aIdx);
   1.164 +
   1.165 +	// cleanup
   1.166 +	eglSess->CloseSgDriver();
   1.167 +  	CleanupStack::PopAndDestroy(eglSess);	
   1.168 +	}
   1.169 +
   1.170 +/**
   1.171 +@SYMTestCaseID GRAPHICS-EGL-0156
   1.172 +
   1.173 +@SYMTestPriority 1
   1.174 +
   1.175 +@SYMPREQ 39
   1.176 +
   1.177 +@SYMREQ See SGL.GT0386.401 document
   1.178 +
   1.179 +@SYMTestCaseDesc
   1.180 +Check if EGL Implementation allows two threads to work in parallel.
   1.181 +EGLImage can’t be created from an RSgImage that already has been linked to an EGLImage by another thread.
   1.182 +
   1.183 +@SYMTestActions
   1.184 +Main Thread: creates an RSgImage and starts thread1 and thread2.
   1.185 +Thread1: Creates an EGLImage from the RSgImage previous mentioned
   1.186 +--------
   1.187 +Thread2: Creates an EGLImage from the RSgImage previous mentioned and check that eglCreateImageKHR() does return EGL_NO_IMAGE_KHR
   1.188 +--------
   1.189 +Thread1: Closes the EGLImage
   1.190 +Main Thread: Closes the RSgImage.
   1.191 +
   1.192 +@SYMTestExpectedResults
   1.193 +eglCreateImageKHR() does return EGL_NO_IMAGE_KHR in the 2nd thread and EGL_BAD_ACCESS error is generated.
   1.194 +No memory or handle leaks
   1.195 +*/
   1.196 +TVerdict CEglTest_EGL_Image_Multi_Thread_Sibling_Basic::doTestStepL()
   1.197 +	{
   1.198 +	SetTestStepID(_L("GRAPHICS-EGL-0156"));
   1.199 +	INFO_PRINTF1(_L("Enter: CEglTest_EGL_Image_Multi_Thread_Sibling_Basic::doTestStepL"));
   1.200 +
   1.201 +	TBool ret = CheckForExtensionL(KEGL_RSgimage | KEGL_KHR_image_base | KEGL_KHR_image_pixmap | KVG_KHR_EGL_image);
   1.202 +	if(!ret)
   1.203 +		{
   1.204 +		// The extension is not supported
   1.205 +		RecordTestResultL();
   1.206 +		CloseTMSGraphicsStep();
   1.207 +		return TestStepResult();
   1.208 +		}
   1.209 +
   1.210 +	// Create display object
   1.211 +	ASSERT_TRUE(iDisplay == EGL_NO_DISPLAY);
   1.212 +    GetDisplayL();
   1.213 +    CTestEglSession* eglSess = CTestEglSession::NewLC(Logger(), iDisplay, 0);
   1.214 +	eglSess->InitializeL();
   1.215 +
   1.216 +	// Make sure the driver is ready
   1.217 +	eglSess->OpenSgDriverL();
   1.218 +
   1.219 +	// create a reference bitmap (we give index 0, as there's only 1 image in this test case)
   1.220 +	TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(KDefaultSourceFormat);
   1.221 +	CFbsBitmap* bitmap = eglSess->CreateReferenceBitmapL(bitmapMode, KPixmapSize, 0);
   1.222 +	CleanupStack::PushL(bitmap);
   1.223 +	
   1.224 +	// Create an RSgImage (member variable as it is 'shared' in the thread funtion...) 
   1.225 +	TSgImageInfoOpenVgImage imageInfo = TSgImageInfoOpenVgImage(KDefaultSourceFormat, KPixmapSize);
   1.226 +	ASSERT_EQUALS(iSgImageShared.Create(imageInfo,bitmap->DataAddress(),bitmap->DataStride()), KErrNone);
   1.227 +	CleanupStack::PopAndDestroy(bitmap);
   1.228 +
   1.229 +	// launch 2 threads
   1.230 +	Test_MultiThreadL(2, ETrue);
   1.231 +	
   1.232 +	// clean everything
   1.233 +	iSgImageShared.Close();
   1.234 +	CleanupStack::PopAndDestroy(eglSess);
   1.235 +	TerminateDisplayL();
   1.236 +	INFO_PRINTF1(_L("Exit: CEglTest_EGL_Image_Multi_Thread_Sibling_Basic::doTestStepL"));
   1.237 +	RecordTestResultL();
   1.238 +	CloseTMSGraphicsStep();
   1.239 +	return TestStepResult();
   1.240 +	}
   1.241 +
   1.242 +void CEglTest_EGL_Image_Multi_Thread_Sibling_Basic::doThreadFunctionL(TInt aIdx)
   1.243 +	{
   1.244 +	INFO_PRINTF2(_L("CEglTest_EGL_Image_Multi_Thread_Sibling_Basic::doThreadFunctionL, Thread %d"),aIdx);
   1.245 +	CTestEglSession* eglSess = CTestEglSession::NewLC(Logger(), iDisplay, aIdx);
   1.246 +	eglSess->InitializeL();
   1.247 +	eglSess->OpenSgDriverL();
   1.248 +			
   1.249 +	EGLImageKHR eglImageLocal = EGL_NO_IMAGE_KHR;
   1.250 +	if(aIdx == 0)
   1.251 +		{
   1.252 +		INFO_PRINTF2(_L("Thread %d, Creating an EGLImage from the shared RSgImage"),aIdx);
   1.253 +		eglImageLocal = eglSess->eglCreateImageKhrL(iDisplay,EGL_NO_CONTEXT,EGL_NATIVE_PIXMAP_KHR,&iSgImageShared,KEglImageAttribsPreservedTrue);
   1.254 +		ASSERT_EGL_TRUE(eglImageLocal != EGL_NO_IMAGE_KHR);
   1.255 +		}
   1.256 +	
   1.257 +	Rendezvous(aIdx);
   1.258 +	
   1.259 +	if(aIdx == 1)
   1.260 +		{
   1.261 +		INFO_PRINTF2(_L("Thread %d, Creating an EGLImage from the shared RSgImage"),aIdx);
   1.262 +		eglImageLocal = eglSess->eglCreateImageKhrL(iDisplay,EGL_NO_CONTEXT,EGL_NATIVE_PIXMAP_KHR,&iSgImageShared,KEglImageAttribsPreservedTrue);
   1.263 +		ASSERT_EGL_TRUE(eglImageLocal == EGL_NO_IMAGE_KHR);
   1.264 +		ASSERT_EGL_ERROR(EGL_BAD_ACCESS);
   1.265 +		}
   1.266 +	
   1.267 +	Rendezvous(aIdx);
   1.268 +	
   1.269 +	// cleanup
   1.270 +	if(aIdx == 0)
   1.271 +		{
   1.272 +		ASSERT_EGL_TRUE(eglSess->DestroyEGLImage(iDisplay, eglImageLocal));
   1.273 +		}
   1.274 +	eglSess->CloseSgDriver();
   1.275 +	CleanupStack::PopAndDestroy(eglSess);
   1.276 +	}
   1.277 +
   1.278 +/**
   1.279 +@SYMTestCaseID GRAPHICS-EGL-0157
   1.280 +
   1.281 +@SYMTestPriority 1
   1.282 +
   1.283 +@SYMPREQ 39
   1.284 +
   1.285 +@SYMREQ See SGL.GT0386.401 document
   1.286 +
   1.287 +@SYMTestCaseDesc
   1.288 +Check if EGL Implementation allows two threads to work in parallel.
   1.289 +Each thread is allowed to create a VGImage from the same EGLImage
   1.290 +
   1.291 +@SYMTestActions
   1.292 +Main Thread: creates an RSgImage with the same content as the reference bitmap and creates an EGLImage from it; starts thread1 and thread2.
   1.293 +Thread1: Creates an egl context and a pixmap surface linked to it. Creates an VGImage from the EGLImage previous mentioned
   1.294 +Thread2: Creates an egl context and a pixmap surface linked to it. Creates an VGImage from the EGLImage previous mentioned
   1.295 +--------
   1.296 +Thread 1: Changes the content of the RSgImage by using the VGImage that has a reference to it.
   1.297 +--------
   1.298 +Thread1: Passes the VGImage into vgDestroyImage()
   1.299 +Thread2: Copies the VGImage to the pixmap surface and checks the contents
   1.300 +Thread2: Passes the VGImage into vgDestroyImage()
   1.301 +Main Thread: Closes the EGLImage
   1.302 +Main Thread: Closes the RSgImage
   1.303 +
   1.304 +@SYMTestExpectedResults
   1.305 +No error is generated within both threads. The changes apported by the first thread affects the second thread. The content the pixmap surface will matches the one of the reference bitmap changed by the first thread.
   1.306 +No memory or handle leaks
   1.307 +*/
   1.308 +TVerdict CEglTest_EGL_Image_Multi_Thread_Sibling_VGImage::doTestStepL()
   1.309 +	{
   1.310 +	SetTestStepID(_L("GRAPHICS-EGL-0157"));
   1.311 +	INFO_PRINTF1(_L("Enter: CEglTest_EGL_Image_Multi_Thread_Sibling_VGImage::doTestStepL"));
   1.312 +
   1.313 +	TBool ret = CheckForExtensionL(KEGL_RSgimage | KEGL_KHR_image_base | KEGL_KHR_image_pixmap | KVG_KHR_EGL_image);
   1.314 +	if(!ret)
   1.315 +		{
   1.316 +		// The extension is not supported
   1.317 +		RecordTestResultL();
   1.318 +		CloseTMSGraphicsStep();
   1.319 +		return TestStepResult();
   1.320 +		}
   1.321 +
   1.322 +	// Create display object
   1.323 +	ASSERT_TRUE(iDisplay == EGL_NO_DISPLAY);
   1.324 +    GetDisplayL();
   1.325 +    CTestEglSession* eglSess = CTestEglSession::NewLC(Logger(), iDisplay, 0);
   1.326 +	eglSess->InitializeL();
   1.327 +
   1.328 +	// Make sure the driver is ready
   1.329 +	eglSess->OpenSgDriverL();
   1.330 +
   1.331 +	// create a reference bitmap (we give index 3, as there's only 1 image in this test case)
   1.332 +	TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(KDefaultSourceFormat);
   1.333 +	CFbsBitmap* bitmap = eglSess->CreateReferenceBitmapL(bitmapMode, KPixmapSize, 3);
   1.334 +	CleanupStack::PushL(bitmap);
   1.335 +	
   1.336 +	// Create an RSgImage (member variable as it is 'shared' in the thread funtion...) 
   1.337 +	INFO_PRINTF1(_L("Parent Thread, Creating the shared RSgImage"));
   1.338 +	TSgImageInfoOpenVgImage imageInfo = TSgImageInfoOpenVgImage(KDefaultSourceFormat, KPixmapSize);
   1.339 +	ASSERT_EQUALS(iSgImageShared.Create(imageInfo,bitmap->DataAddress(),bitmap->DataStride()), KErrNone);
   1.340 +	CleanupStack::PopAndDestroy(bitmap);
   1.341 +	
   1.342 +	// Create an EGLImage from the RSgImage (member variable as it is 'shared' in the thread funtion...) 
   1.343 +	INFO_PRINTF1(_L("Parent Thread, Creating the shared EGLImage"));
   1.344 +	iEGLImageShared = eglSess->eglCreateImageKhrL(iDisplay,EGL_NO_CONTEXT,EGL_NATIVE_PIXMAP_KHR,&iSgImageShared,KEglImageAttribsPreservedTrue);
   1.345 +	ASSERT_EGL_TRUE(iEGLImageShared != EGL_NO_IMAGE_KHR);
   1.346 +	iSgImageShared.Close();
   1.347 +
   1.348 +	// launch 2 threads
   1.349 +	Test_MultiThreadL(2, ETrue);
   1.350 +	
   1.351 +	// cleanup
   1.352 +	ASSERT_EGL_TRUE(eglSess->DestroyEGLImage(iDisplay, iEGLImageShared));
   1.353 +	CleanupStack::PopAndDestroy(eglSess);
   1.354 +	TerminateDisplayL();	
   1.355 +	INFO_PRINTF1(_L("Exit: CEglTest_EGL_Image_Multi_Thread_Sibling_VGImage::doTestStepL"));	
   1.356 +	RecordTestResultL();
   1.357 +	CloseTMSGraphicsStep();
   1.358 +	return TestStepResult();
   1.359 +	}
   1.360 +
   1.361 +void CEglTest_EGL_Image_Multi_Thread_Sibling_VGImage::doThreadFunctionL(TInt aIdx)
   1.362 +	{	
   1.363 +	INFO_PRINTF2(_L("CEglTest_EGL_Image_Multi_Thread_Sibling_VGImage::doThreadFunctionL, Thread %d"),aIdx);
   1.364 +	CTestEglSession* eglSess = CTestEglSession::NewLC(Logger(), iDisplay, aIdx);
   1.365 +	eglSess->InitializeL();
   1.366 +	eglSess->OpenSgDriverL();
   1.367 +
   1.368 +	INFO_PRINTF2(_L("Thread %d, Creating a Surface and a Context bound to OpenVG"),aIdx);
   1.369 +	TUidPixelFormat pixelFormat = EglTestConversion::VgFormatToSgPixelFormat(KDefaultSurfaceFormat);
   1.370 +	TSgImageInfoOpenVgTarget imageInfo = TSgImageInfoOpenVgTarget(pixelFormat, KPixmapSize);
   1.371 +	// Create a pixmap surface matching the native image pixel format
   1.372 +	eglSess->CreatePixmapSurfaceAndMakeCurrentAndMatchL(imageInfo,CTestEglSession::EResourceCloseSgImageEarly);
   1.373 +	
   1.374 +	// Create a VGImage from the EGLImage
   1.375 +	INFO_PRINTF2(_L("Thread %d, Creating one VGImage from the shared EGLImage"),aIdx);
   1.376 +	VGImage vgImageLocal = eglSess->vgCreateImageTargetKHR((VGeglImageKHR)iEGLImageShared);	
   1.377 +	ASSERT_VG_TRUE(vgImageLocal != VG_INVALID_HANDLE);
   1.378 +	
   1.379 +	Rendezvous(aIdx);
   1.380 +		
   1.381 +	if(aIdx == 0)
   1.382 +		{
   1.383 +		INFO_PRINTF2(_L("Thread %d, Updating contents of the VGImage from the shared EGLImage"),aIdx);
   1.384 +		TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(KDefaultSourceFormat);
   1.385 +		CFbsBitmap* bitmap = eglSess->CreateReferenceBitmapL(bitmapMode, KPixmapSize, 8);
   1.386 +    	// Add pixel data to the VGImage reference from the bitmap reference. 
   1.387 +        // Mind the fact that CFbsBitmap and VGImages use different coordinates origin!
   1.388 +		TSize bitmapSize = bitmap->SizeInPixels();
   1.389 +    	TUint8* address = reinterpret_cast<TUint8*>(bitmap->DataAddress());
   1.390 +    	TInt stride = bitmap->DataStride();
   1.391 +    	address += (bitmapSize.iHeight - 1) * stride;
   1.392 +        vgImageSubData(vgImageLocal, address, -stride, KDefaultSurfaceFormat, 0,0, bitmapSize.iWidth, bitmapSize.iHeight);
   1.393 +		delete bitmap;
   1.394 +        bitmap = NULL;
   1.395 +		ASSERT_TRUE(vgGetError()==VG_NO_ERROR);
   1.396 +		eglWaitClient();
   1.397 +		}
   1.398 +
   1.399 +	Rendezvous(aIdx);
   1.400 +	
   1.401 +	if(aIdx == 1)
   1.402 +		{
   1.403 +		INFO_PRINTF2(_L("Thread %d, Drawing the VGImage to the current surface"),aIdx);
   1.404 +		// Copy the source VGImage to the surface
   1.405 +    	vgSetPixels(0, 0, vgImageLocal, 0, 0, KPixmapSize.iWidth, KPixmapSize.iHeight);
   1.406 +		ASSERT_TRUE(vgGetError()==VG_NO_ERROR);
   1.407 +		eglWaitClient();
   1.408 +
   1.409 +		// we can now compare the VgImage to the one we expect after changing it in the other thread
   1.410 +		TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(KDefaultSourceFormat);
   1.411 +		CFbsBitmap* refBitmap = eglSess->CreateReferenceBitmapL(bitmapMode, KPixmapSize, 8);
   1.412 +		CleanupStack::PushL(refBitmap);
   1.413 +		eglSess->CheckVgDrawingL(KDefaultSurfaceFormat, refBitmap);
   1.414 +		CleanupStack::PopAndDestroy(refBitmap);
   1.415 +		INFO_PRINTF2(_L("Thread %d, Drawing successful"),aIdx);
   1.416 +		}		
   1.417 +	
   1.418 +	// cleanup
   1.419 +	vgDestroyImage(vgImageLocal);
   1.420 +	ASSERT_TRUE(vgGetError() == VG_NO_ERROR);
   1.421 +	eglSess->CloseSgDriver();
   1.422 +	CleanupStack::PopAndDestroy(eglSess);
   1.423 +	}
   1.424 +
   1.425 +/**
   1.426 +@SYMTestCaseID GRAPHICS-EGL-0158
   1.427 +
   1.428 +@SYMTestPriority 1
   1.429 +
   1.430 +@SYMPREQ 39
   1.431 +
   1.432 +@SYMREQ See SGL.GT0386.401 document
   1.433 +
   1.434 +@SYMTestCaseDesc
   1.435 +Check if EGL Implementation allows two threads to work in parallel.
   1.436 +Each thread is allowed to create a VGImage from an EGLImage created by another thread.
   1.437 +
   1.438 +@SYMTestActions
   1.439 +Main Thread: creates an RSgImage ; starts thread1 and thread2.
   1.440 +Thread1: Creates an EGLImage from the previous mentioned RSgImage
   1.441 +--------
   1.442 +Thread2: Creates an VGImage from the EGLImage created by the other thread
   1.443 +--------
   1.444 +Thread1: Passes the EGLImage into eglDestroyImageKHR ()
   1.445 +Thread2: Passes the VGImage into vgDestroyImage()
   1.446 +Main Thread: Closes the RSgImage
   1.447 +
   1.448 +@SYMTestExpectedResults
   1.449 +No error is generated within both threads
   1.450 +No memory or handle leaks
   1.451 +*/
   1.452 +TVerdict CEglTest_EGL_Image_Multi_Thread_Sibling_VGImage_PassingEGLImage::doTestStepL()
   1.453 +	{
   1.454 +	SetTestStepID(_L("GRAPHICS-EGL-0158"));
   1.455 +	INFO_PRINTF1(_L("Enter: CEglTest_EGL_Image_Multi_Thread_Sibling_VGImage_PassingEGLImage::doTestStepL"));
   1.456 +
   1.457 +	TBool ret = CheckForExtensionL(KEGL_RSgimage | KEGL_KHR_image_base | KEGL_KHR_image_pixmap | KVG_KHR_EGL_image);
   1.458 +	if(!ret)
   1.459 +		{
   1.460 +		// The extension is not supported
   1.461 +		RecordTestResultL();
   1.462 +		CloseTMSGraphicsStep();
   1.463 +		return TestStepResult();
   1.464 +		}
   1.465 +
   1.466 +	// Create display object
   1.467 +	ASSERT_TRUE(iDisplay == EGL_NO_DISPLAY);
   1.468 +    GetDisplayL();
   1.469 +    CTestEglSession* eglSess = CTestEglSession::NewLC(Logger(), iDisplay, 0);
   1.470 +	eglSess->InitializeL();
   1.471 +
   1.472 +	// Make sure the driver is ready
   1.473 +	eglSess->OpenSgDriverL();
   1.474 +
   1.475 +	// create a reference bitmap (we give index 5, as there's only 1 image in this test case)
   1.476 +	TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(KDefaultSourceFormat);
   1.477 +	CFbsBitmap* bitmap = eglSess->CreateReferenceBitmapL(bitmapMode, KPixmapSize, 5);
   1.478 +	CleanupStack::PushL(bitmap);
   1.479 +	
   1.480 +	// Create an RSgImage (member variable as it is 'shared' in the thread funtion...) 
   1.481 +	INFO_PRINTF1(_L("Parent Thread, Creating the shared RSgImage"));
   1.482 +	TSgImageInfoOpenVgImage imageInfo = TSgImageInfoOpenVgImage(KDefaultSourceFormat, KPixmapSize);
   1.483 +	ASSERT_EQUALS(iSgImageShared.Create(imageInfo,bitmap->DataAddress(),bitmap->DataStride()), KErrNone);
   1.484 +	CleanupStack::PopAndDestroy(bitmap);
   1.485 +	
   1.486 +	// launch 2 threads
   1.487 +	Test_MultiThreadL(2, ETrue);
   1.488 +	
   1.489 +	// cleanup
   1.490 +	iSgImageShared.Close();
   1.491 +	CleanupStack::PopAndDestroy(eglSess);
   1.492 +	TerminateDisplayL();	
   1.493 +	INFO_PRINTF1(_L("Exit: CEglTest_EGL_Image_Multi_Thread_Sibling_VGImage_PassingEGLImage::doTestStepL"));	
   1.494 +	RecordTestResultL();
   1.495 +	CloseTMSGraphicsStep();
   1.496 +	return TestStepResult();
   1.497 +	}
   1.498 +
   1.499 +void CEglTest_EGL_Image_Multi_Thread_Sibling_VGImage_PassingEGLImage::doThreadFunctionL(TInt aIdx)
   1.500 +	{	
   1.501 +	INFO_PRINTF2(_L("CEglTest_EGL_Image_Multi_Thread_Sibling_VGImage_PassingEGLImage::doThreadFunctionL, Thread %d"),aIdx);
   1.502 +	CTestEglSession* eglSess = CTestEglSession::NewLC(Logger(), iDisplay, aIdx);
   1.503 +	eglSess->InitializeL();
   1.504 +	eglSess->OpenSgDriverL();	
   1.505 +
   1.506 +	// check there is no eglImage at the start of either thread
   1.507 +	ASSERT_EGL_TRUE(iEGLImageShared == EGL_NO_IMAGE_KHR);
   1.508 +	
   1.509 +	// Wait for both thread to reach this point
   1.510 +	//	This is important for multicore platforms (i.e., naviengine) as the execution order is not known and it could
   1.511 +	//	happen that the first thread has already created the image before the second checks there is no eglImage 
   1.512 +	Rendezvous(aIdx);
   1.513 +
   1.514 +	if(aIdx == 0)
   1.515 +		{
   1.516 +		// Create an EGLImage from the RSgImage (member variable as it is 'shared' in the thread function...) 
   1.517 +		INFO_PRINTF2(_L("Thread %d, Creating the shared EGLImage"),aIdx);
   1.518 +		iEGLImageShared = eglSess->eglCreateImageKhrL(iDisplay,EGL_NO_CONTEXT,EGL_NATIVE_PIXMAP_KHR,&iSgImageShared,KEglImageAttribsPreservedTrue);
   1.519 +		ASSERT_EGL_TRUE(iEGLImageShared != EGL_NO_IMAGE_KHR);
   1.520 +		iSgImageShared.Close();
   1.521 +		}
   1.522 +	
   1.523 +	Rendezvous(aIdx);
   1.524 +	
   1.525 +	if(aIdx == 1)
   1.526 +		{
   1.527 +		INFO_PRINTF2(_L("Thread %d, Creating a Surface and a Context bound to OpenVG"),aIdx);
   1.528 +		TUidPixelFormat pixelFormat = EglTestConversion::VgFormatToSgPixelFormat(KDefaultSurfaceFormat);
   1.529 +		TSgImageInfoOpenVgTarget imageInfo = TSgImageInfoOpenVgTarget(pixelFormat, KPixmapSize);
   1.530 +		// Create a pixmap surface matching the native image pixel format
   1.531 +		eglSess->CreatePixmapSurfaceAndMakeCurrentAndMatchL(imageInfo,CTestEglSession::EResourceCloseSgImageEarly);
   1.532 +
   1.533 +		// Create a VGImage from the EGLImage
   1.534 +		INFO_PRINTF2(_L("Thread %d, Creating one VGImage from the shared EGLImage"),aIdx);
   1.535 +		VGImage vgImageLocal = eglSess->vgCreateImageTargetKHR((VGeglImageKHR)iEGLImageShared);	
   1.536 +		ASSERT_VG_TRUE(vgImageLocal != VG_INVALID_HANDLE);
   1.537 +
   1.538 +		INFO_PRINTF2(_L("Thread %d, Drawing the VGImage to the current surface"),aIdx);
   1.539 +		// Copy the source VGImage to the surface
   1.540 +    	vgSetPixels(0, 0, vgImageLocal, 0, 0, KPixmapSize.iWidth, KPixmapSize.iHeight);
   1.541 +		ASSERT_TRUE(vgGetError()==VG_NO_ERROR);
   1.542 +		eglWaitClient();
   1.543 +
   1.544 +		// we can now compare the VgImage to the one we expect from the main thread
   1.545 +		TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(KDefaultSourceFormat);
   1.546 +		CFbsBitmap* refBitmap = eglSess->CreateReferenceBitmapL(bitmapMode, KPixmapSize, 5);
   1.547 +		CleanupStack::PushL(refBitmap);
   1.548 +		eglSess->CheckVgDrawingL(KDefaultSurfaceFormat, refBitmap);
   1.549 +		CleanupStack::PopAndDestroy(refBitmap);
   1.550 +		INFO_PRINTF2(_L("Thread %d, Drawing successful"),aIdx);
   1.551 +
   1.552 +		vgDestroyImage(vgImageLocal);
   1.553 +		ASSERT_TRUE(vgGetError() == VG_NO_ERROR);
   1.554 +		}
   1.555 +	
   1.556 +	Rendezvous(aIdx);
   1.557 +	
   1.558 +	if(aIdx == 0)
   1.559 +		{
   1.560 +		ASSERT_EGL_TRUE(eglSess->DestroyEGLImage(iDisplay, iEGLImageShared));
   1.561 +		iEGLImageShared = EGL_NO_IMAGE_KHR;
   1.562 +		}
   1.563 +	
   1.564 +	// cleanup
   1.565 +	eglSess->CloseSgDriver();
   1.566 +	CleanupStack::PopAndDestroy(eglSess);
   1.567 +	}
   1.568 +
   1.569 +/**
   1.570 +@SYMTestCaseID GRAPHICS-EGL-0159
   1.571 +
   1.572 +@SYMTestPriority 1
   1.573 +
   1.574 +@SYMPREQ 39
   1.575 +
   1.576 +@SYMREQ See SGL.GT0386.401 document
   1.577 +
   1.578 +@SYMTestCaseDesc
   1.579 +Check if EGL Implementation allows two threads to work in parallel.
   1.580 +If the thread that has created the EGLImage terminates without destroying it the other thread can still use it.
   1.581 +
   1.582 +@SYMTestActions
   1.583 +Main Thread: Creates an RSgImage ; starts thread1 and thread2.
   1.584 +Thread1: An EGLImage from the previous mentioned RSgImage
   1.585 +--------
   1.586 +Thread1: Calls eglReleaseThread()
   1.587 +Thread1: Finishes gracefully
   1.588 +Thread2: Creates an VGImage the EGLImage created by the other thread
   1.589 +Thread2: Passes the VGImage into vgDestroyImage()
   1.590 +Thread2: Passes the EGLImage into eglDestroyImageKHR ()
   1.591 +Main Thread: Closes the RSgImage.
   1.592 +
   1.593 +@SYMTestExpectedResults
   1.594 +No error is generated within both threads
   1.595 +No memory or handle leaks
   1.596 +*/
   1.597 +TVerdict CEglTest_EGL_Image_Multi_Thread_Exit_Thread::doTestStepL()
   1.598 +	{
   1.599 +	SetTestStepID(_L("GRAPHICS-EGL-0159"));
   1.600 +	INFO_PRINTF1(_L("Enter: CEglTest_EGL_Image_Multi_Thread_Exit_Thread::doTestStepL"));
   1.601 +
   1.602 +	TBool ret = CheckForExtensionL(KEGL_RSgimage | KEGL_KHR_image_base | KEGL_KHR_image_pixmap | KVG_KHR_EGL_image);
   1.603 +	if(!ret)
   1.604 +		{
   1.605 +		// The extension is not supported
   1.606 +		RecordTestResultL();
   1.607 +		CloseTMSGraphicsStep();
   1.608 +		return TestStepResult();
   1.609 +		}
   1.610 +
   1.611 +	// Create display object
   1.612 +	ASSERT_TRUE(iDisplay == EGL_NO_DISPLAY);
   1.613 +    GetDisplayL();
   1.614 +    CTestEglSession* eglSess = CTestEglSession::NewLC(Logger(), iDisplay, 0);
   1.615 +	eglSess->InitializeL();
   1.616 +
   1.617 +	// Make sure the driver is ready
   1.618 +	eglSess->OpenSgDriverL();
   1.619 +
   1.620 +	// create a reference bitmap (we give index 2, as there's only 1 image in this test case)
   1.621 +	TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(KDefaultSourceFormat);
   1.622 +	CFbsBitmap* bitmap = eglSess->CreateReferenceBitmapL(bitmapMode, KPixmapSize, 2);
   1.623 +	CleanupStack::PushL(bitmap);
   1.624 +	
   1.625 +	// Create an RSgImage (member variable as it is 'shared' in the thread funtion...) 
   1.626 +	INFO_PRINTF1(_L("Parent Thread, Creating the shared RSgImage"));
   1.627 +	TSgImageInfoOpenVgImage imageInfo = TSgImageInfoOpenVgImage(KDefaultSourceFormat, KPixmapSize);
   1.628 +	ASSERT_EQUALS(iSgImageShared.Create(imageInfo,bitmap->DataAddress(),bitmap->DataStride()), KErrNone);
   1.629 +	CleanupStack::PopAndDestroy(bitmap);
   1.630 +	
   1.631 +	// launch 2 threads
   1.632 +	Test_MultiThreadL(2, ETrue);
   1.633 +	
   1.634 +	// cleanup
   1.635 +	iSgImageShared.Close();
   1.636 +	CleanupStack::PopAndDestroy(eglSess);	
   1.637 +	TerminateDisplayL();
   1.638 +	INFO_PRINTF1(_L("Exit: CEglTest_EGL_Image_Multi_Thread_Exit_Thread::doTestStepL"));	
   1.639 +	RecordTestResultL();
   1.640 +	CloseTMSGraphicsStep();
   1.641 +	return TestStepResult();
   1.642 +	}
   1.643 +
   1.644 +void CEglTest_EGL_Image_Multi_Thread_Exit_Thread::doThreadFunctionL(TInt aIdx)
   1.645 +	{	
   1.646 +	INFO_PRINTF2(_L("CEglTest_EGL_Image_Multi_Thread_Exit_Thread::doThreadFunctionL, Thread %d"),aIdx);
   1.647 +	CTestEglSession* eglSess = CTestEglSession::NewLC(Logger(), iDisplay, aIdx);
   1.648 +	eglSess->InitializeL();
   1.649 +	eglSess->OpenSgDriverL();
   1.650 +
   1.651 +	// check there is no eglImage at the start of either thread
   1.652 +	ASSERT_EGL_TRUE(iEGLImageShared == EGL_NO_IMAGE_KHR);
   1.653 +
   1.654 +	TRequestStatus statusThread0;
   1.655 +	if(aIdx == 1)
   1.656 +		{
   1.657 +		INFO_PRINTF2(_L("Thread %d, Asking to be notified when thread 0 exits"),aIdx);
   1.658 +		iThreadStatus[0].iThread.Logon(statusThread0);
   1.659 +		}
   1.660 +	
   1.661 +	Rendezvous(aIdx);
   1.662 +	
   1.663 +	//Thread 0 creates the EGLImage and exit
   1.664 +	if(aIdx == 0)	
   1.665 +		{
   1.666 +		// Create an EGLImage from the RSgImage (member variable as it is 'shared' in the thread function...) 
   1.667 +		INFO_PRINTF2(_L("Thread %d, Creating the shared EGLImage"),aIdx);
   1.668 +		iEGLImageShared = eglSess->eglCreateImageKhrL(iDisplay,EGL_NO_CONTEXT,EGL_NATIVE_PIXMAP_KHR,&iSgImageShared,KEglImageAttribsPreservedTrue);
   1.669 +		ASSERT_EGL_TRUE(iEGLImageShared != EGL_NO_IMAGE_KHR);
   1.670 +		iSgImageShared.Close();
   1.671 +		INFO_PRINTF2(_L("Thread %d -----  Exiting ---- EGLImage should be kept alive"),aIdx);
   1.672 +		}
   1.673 +	
   1.674 +	//Thread1 waits for Thread0 to exit and then uses the EGLImage and performs some drawing
   1.675 +	if(aIdx == 1)
   1.676 +		{
   1.677 +		INFO_PRINTF2(_L("Thread %d, Waiting for thread 0 to exit"),aIdx);
   1.678 +		User::WaitForRequest(statusThread0);
   1.679 +
   1.680 +		INFO_PRINTF2(_L("Thread %d, Creating a Surface and a Context bound to OpenVG"),aIdx);
   1.681 +		TUidPixelFormat pixelFormat = EglTestConversion::VgFormatToSgPixelFormat(KDefaultSurfaceFormat);
   1.682 +		TSgImageInfoOpenVgTarget imageInfo = TSgImageInfoOpenVgTarget(pixelFormat, KPixmapSize);
   1.683 +		// Create a pixmap surface matching the native image pixel format
   1.684 +		eglSess->CreatePixmapSurfaceAndMakeCurrentAndMatchL(imageInfo,CTestEglSession::EResourceCloseSgImageEarly);
   1.685 +
   1.686 +		// Create a VGImage from the EGLImage
   1.687 +		INFO_PRINTF2(_L("Thread %d, Creating one VGImage from the shared EGLImage"),aIdx);
   1.688 +		VGImage vgImageLocal = eglSess->vgCreateImageTargetKHR((VGeglImageKHR)iEGLImageShared);	
   1.689 +		ASSERT_VG_TRUE(vgImageLocal != VG_INVALID_HANDLE);
   1.690 +
   1.691 +		INFO_PRINTF2(_L("Thread %d, Drawing the VGImage to the current surface"),aIdx);
   1.692 +		// Copy the source VGImage to the surface
   1.693 +    	vgSetPixels(0, 0, vgImageLocal, 0, 0, KPixmapSize.iWidth, KPixmapSize.iHeight);
   1.694 +		ASSERT_TRUE(vgGetError()==VG_NO_ERROR);
   1.695 +		eglWaitClient();
   1.696 +
   1.697 +		// we can now compare the VgImage to the one we expect after changing it in the other thread
   1.698 +		TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(KDefaultSourceFormat);
   1.699 +		CFbsBitmap* refBitmap = eglSess->CreateReferenceBitmapL(bitmapMode, KPixmapSize, 2);
   1.700 +		CleanupStack::PushL(refBitmap);
   1.701 +		eglSess->CheckVgDrawingL(KDefaultSurfaceFormat, refBitmap);
   1.702 +		CleanupStack::PopAndDestroy(refBitmap);
   1.703 +		INFO_PRINTF2(_L("Thread %d, Drawing successful"),aIdx);
   1.704 +
   1.705 +		vgDestroyImage(vgImageLocal);
   1.706 +		ASSERT_TRUE(vgGetError() == VG_NO_ERROR);
   1.707 +		ASSERT_EGL_TRUE(eglSess->DestroyEGLImage(iDisplay, iEGLImageShared));
   1.708 +		iEGLImageShared = EGL_NO_IMAGE_KHR;
   1.709 +		}
   1.710 +	
   1.711 +	// cleanup
   1.712 +	eglSess->CloseSgDriver();
   1.713 +	CleanupStack::PopAndDestroy(eglSess);
   1.714 +	}
   1.715 +
   1.716 +
   1.717 +/**
   1.718 +@SYMTestCaseID GRAPHICS-EGL-0163
   1.719 +
   1.720 +@SYMTestPriority 1
   1.721 +
   1.722 +@SYMPREQ 39
   1.723 +
   1.724 +@SYMREQ See SGL.GT0386.401 document
   1.725 +
   1.726 +@SYMTestCaseDesc
   1.727 +All the EGL resources may be used implicitly by a thread even after another thread has terminated the display.
   1.728 +
   1.729 +@SYMTestActions
   1.730 +Thread0: Asks to be notified when Thread1 exits
   1.731 +Thread0: Creates a RSgImage having the reference bitmap as content
   1.732 +Thread0: Creates a EGLImage from the RSgImage
   1.733 +Thread0: Creates a surface
   1.734 +Thread0: Creates a VGImage from the EGLImage
   1.735 +--------
   1.736 +Thread1: Calls eglTerminate
   1.737 +--------
   1.738 +Thread1: Exits
   1.739 +Thread0: Resumes when Thread1 exits
   1.740 +Thread0: Uses the VGImage and draw it to the surface
   1.741 +Thread0: Checks the contents
   1.742 +
   1.743 +@SYMTestExpectedResults
   1.744 +Thread0 is able to use successfully the VGmage and the surface's content are the ones expected.
   1.745 +*/
   1.746 +TVerdict CEglTest_EGL_Image_Multi_Thread_DrawAfterTerminate::doTestStepL()
   1.747 +	{
   1.748 +    SetTestStepID(_L("GRAPHICS-EGL-0163"));
   1.749 +	INFO_PRINTF1(_L("Enter: CEglTest_EGL_Image_Multi_Thread_DrawAfterTerminate::doTestStepL"));
   1.750 +
   1.751 +	TBool ret = CheckForExtensionL(KEGL_RSgimage | KEGL_KHR_image_base | KEGL_KHR_image_pixmap | KVG_KHR_EGL_image);
   1.752 +	if(!ret)
   1.753 +		{
   1.754 +		// The extension is not supported
   1.755 +		RecordTestResultL();
   1.756 +		CloseTMSGraphicsStep();
   1.757 +		return TestStepResult();
   1.758 +		}
   1.759 +
   1.760 +	Test_MultiThreadL(2, ETrue);
   1.761 +			
   1.762 +	INFO_PRINTF1(_L("Exit: CEglTest_EGL_Image_Multi_Thread_DrawAfterTerminate::doTestStepL"));	
   1.763 +	RecordTestResultL();
   1.764 +	CloseTMSGraphicsStep();
   1.765 +	return TestStepResult();
   1.766 +	}
   1.767 +
   1.768 +void CEglTest_EGL_Image_Multi_Thread_DrawAfterTerminate::doThreadFunctionL(TInt aIdx)
   1.769 +	{
   1.770 +	INFO_PRINTF2(_L("CEglTest_EGL_Image_Multi_Thread_DrawAfterTerminate::doThreadFunctionL, Thread %d"),aIdx);
   1.771 +	GetDisplayL();
   1.772 +	CTestEglSession* eglSess = CTestEglSession::NewLC(Logger(), iDisplay, aIdx);
   1.773 +	eglSess->InitializeL();
   1.774 +	eglSess->OpenSgDriverL();
   1.775 +
   1.776 +	TRequestStatus statusThread1;
   1.777 +	VGImage vgImageLocal = VG_INVALID_HANDLE;
   1.778 +	EGLint surfaceWidth;
   1.779 +	EGLint surfaceHeigth;
   1.780 +	
   1.781 +	//Thread0 asks to be notified when Thread1 exits
   1.782 +	//Creates a RSgImage having the reference bitmap as content
   1.783 +	//Creates a EGLImage from the RSgImage
   1.784 +	//Creates a surface
   1.785 +	//Creates a VGImage from the EGLImage
   1.786 +	if(aIdx == 0)
   1.787 +		{
   1.788 +		// Thread0 asks to be notified when Thread1 exits
   1.789 +		iThreadStatus[1].iThread.Logon(statusThread1);
   1.790 +
   1.791 +	    RSgImage rSgImageLocal;
   1.792 +		CleanupClosePushL(rSgImageLocal);
   1.793 +
   1.794 +		// create a reference bitmap (we give index 9, as there's only 1 image in this test case)
   1.795 +		TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(KDefaultSourceFormat);
   1.796 +		CFbsBitmap* bitmap = eglSess->CreateReferenceBitmapL(bitmapMode, KPixmapSize, 9);
   1.797 +		CleanupStack::PushL(bitmap);
   1.798 +
   1.799 +		// Create an RSgImage
   1.800 +		INFO_PRINTF2(_L("Thread %d, Creating a RSgImage having the reference bitmap's content"),aIdx);
   1.801 +		TSgImageInfoOpenVgImage imageInfo = TSgImageInfoOpenVgImage(KDefaultSourceFormat, KPixmapSize);
   1.802 +		ASSERT_EQUALS(rSgImageLocal.Create(imageInfo,bitmap->DataAddress(),bitmap->DataStride()), KErrNone);
   1.803 +		CleanupStack::PopAndDestroy(bitmap);
   1.804 +
   1.805 +		INFO_PRINTF2(_L("Thread %d, Creating an EGLImage from the shared RSgImage"),aIdx);
   1.806 +		EGLImageKHR eglImageLocal = eglSess->eglCreateImageKhrL(iDisplay, EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, &rSgImageLocal, KEglImageAttribsPreservedTrue);
   1.807 +		ASSERT_EGL_TRUE(eglImageLocal != EGL_NO_IMAGE_KHR);
   1.808 +		CleanupStack::PopAndDestroy(&rSgImageLocal); 	//transferring ownership of the buffer to the EGLImage
   1.809 +
   1.810 +		INFO_PRINTF2(_L("Thread %d, Creating a Surface and a Context bound to OpenVG"),aIdx);
   1.811 +		TUidPixelFormat pixelFormat = EglTestConversion::VgFormatToSgPixelFormat(KDefaultSurfaceFormat);
   1.812 +		TSgImageInfoOpenVgTarget imageInfo2 = TSgImageInfoOpenVgTarget(pixelFormat, KPixmapSize);
   1.813 +		// Create a pixmap surface matching the native image pixel format
   1.814 +		eglSess->CreatePixmapSurfaceAndMakeCurrentAndMatchL(imageInfo2,CTestEglSession::EResourceCloseSgImageEarly);
   1.815 +
   1.816 +		//We now store the size of the surface because after eglTerminate is called on the display
   1.817 +		//it will not be possible to use explicitly all the resources linked to it
   1.818 +		//i.e. every call to an EGL API who takes a display as an argument will raise a EGL_BAD_DISPLAY error
   1.819 +		eglQuerySurface(iDisplay, eglSess->Surface(), EGL_WIDTH, &surfaceWidth);
   1.820 +		eglQuerySurface(iDisplay, eglSess->Surface(), EGL_HEIGHT, &surfaceHeigth);		
   1.821 +		
   1.822 +		INFO_PRINTF2(_L("Thread %d, Creating one VGImage from the EGLImage"),aIdx);
   1.823 +		vgImageLocal = eglSess->vgCreateImageTargetKHR((VGeglImageKHR)eglImageLocal);	
   1.824 +		ASSERT_VG_TRUE(vgImageLocal != VG_INVALID_HANDLE);
   1.825 +		ASSERT_EGL_TRUE(eglSess->DestroyEGLImage(iDisplay, eglImageLocal));
   1.826 +		}
   1.827 +	
   1.828 +	Rendezvous(aIdx);
   1.829 +	
   1.830 +	//Thread1 calls eglTerminate and exit
   1.831 +	if(aIdx == 1)
   1.832 +		{
   1.833 +		INFO_PRINTF2(_L(", Thread %d, Calling eglTerminate and exiting"),aIdx);
   1.834 +		TerminateDisplayL();
   1.835 +		}
   1.836 +	
   1.837 +	Rendezvous(aIdx);
   1.838 +	
   1.839 +	//Thread0 resumes when Thread1 exits
   1.840 +	//and it uses the resources that are linked to the just destroyed display
   1.841 +	if(aIdx == 0)
   1.842 +		{
   1.843 +		User::WaitForRequest(statusThread1);
   1.844 +
   1.845 +		// It's still possible to use the current context, surface and VGImage even though the display has been terminated
   1.846 +		//Copy the source VGImage to the surface
   1.847 +    	vgSetPixels(0, 0, vgImageLocal, 0, 0, KPixmapSize.iWidth, KPixmapSize.iHeight);
   1.848 +		ASSERT_TRUE(vgGetError()==VG_NO_ERROR);
   1.849 +		eglWaitClient();
   1.850 +
   1.851 +		// we can now compare the VgImage to the one we would expect for this particular thread
   1.852 +		TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(KDefaultSourceFormat);
   1.853 +		CFbsBitmap* refBitmap = eglSess->CreateReferenceBitmapL(bitmapMode, KPixmapSize, 9);
   1.854 +		CleanupStack::PushL(refBitmap);
   1.855 +		eglSess->CheckVgDrawingL(KDefaultSurfaceFormat, refBitmap);
   1.856 +		CleanupStack::PopAndDestroy(refBitmap);
   1.857 +		INFO_PRINTF2(_L("Drawing successful, Thread %d"),aIdx);
   1.858 +
   1.859 +		vgDestroyImage(vgImageLocal);
   1.860 +		ASSERT_TRUE(vgGetError() == VG_NO_ERROR);
   1.861 +		eglReleaseThread();
   1.862 +		}
   1.863 +	
   1.864 +	// cleanup
   1.865 +	eglSess->CloseSgDriver();
   1.866 +	CleanupStack::PopAndDestroy(eglSess);
   1.867 +	}