Update contrib.
2 // Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
3 // All rights reserved.
4 // This component and the accompanying materials are made available
5 // under the terms of "Eclipse Public License v1.0"
6 // which accompanies this distribution, and is available
7 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
9 // Initial Contributors:
10 // Nokia Corporation - initial contribution.
22 #include <test/tefunit.h> // for ASSERT macros
23 #include "egltest_image_multithread.h"
25 #include <test/egltestcommonconversion.h>
26 #include <test/egltestcommonsgimageinfo.h>
29 CEglTest_MThread_Image_Base::CEglTest_MThread_Image_Base()
33 CEglTest_MThread_Image_Base::~CEglTest_MThread_Image_Base()
35 iSgImageShared.Close();
39 @SYMTestCaseID GRAPHICS-EGL-0155
45 @SYMREQ See SGL.GT0386.401 document
48 Check if EGL Implementation allows two threads to work in parallel.
51 Run two threads that independently perform the same actions detailed below.
52 This test will check for the VG_KHR_EGL_image extension, if it is not
53 supported on this platform then the test will return immediately without failure.
54 Create and fully construct an RSgImage object
55 Set the iUsage bits to ESgUsageBitOpenVgImage
56 Pass the RSgImage object into eglCreateImageKHR() with
57 The target parameter set to EGL_NATIVE_PIXMAP_KHR
58 Use the current display and EGL_NO_CONTEXT
59 Use a NULL attr_list
60 Check that eglCreateImageKHR() does NOT return EGL_NO_IMAGE_KHR
61 Use vgCreateEGLImageTargetKHR() to construct a VGImage object from the EGLImage.
62 Check for errors (VGInvalidHandle is not returned)
63 Create a second RSgImage, and use it to create a pixmap surface that is
64 compatible as a target for the VGImage to be drawn to.
65 Set the iUsage bit to ESgUsageBitOpenVgSurface
66 Use the same pixel format as the RSgImage above.
67 Now that a eglContext and an OpenVG context have been created, use the
68 OpenVG API vgClearImage to clear to a chosen colour the VGImage previously
69 returned by eglCreateImageKHR.
70 Use OpenVG to draw the just drawn VGImage to the pixmap surface currently
71 linked to the context.
72 Call eglWaitClient() to finish the above drawing instructions synchronously.
73 Destroy the original image data
74 Pass the VGImage into vgDestroyImage()
75 Pass the EGLImage into eglDestroyImageKHR()
76 Close the first RSgImage
77 Check that the pixmap surface contains expected pixel values using
78 OpenVG APIs, vgReadPixels.
79 Close the second RSgImage and destroy the pixmap surface
80 Check for memory and handle leaks
82 @SYMTestExpectedResults
83 Pixmap surface has the expected contents in both threads (within tolerance).
84 No memory or handle leaks.
86 TVerdict CEglTest_EGL_Image_Multi_Thread_Parallel::doTestStepL()
88 SetTestStepID(_L("GRAPHICS-EGL-0155"));
89 INFO_PRINTF1(_L("Enter: CEglTest_EGL_Image_Multi_Thread_Parallel::doTestStepL"));
91 TBool ret = CheckForExtensionL(KEGL_RSgimage | KEGL_KHR_image_base | KEGL_KHR_image_pixmap | KVG_KHR_EGL_image);
94 // The extension is not supported
96 CloseTMSGraphicsStep();
97 return TestStepResult();
100 Test_MultiThreadL(2, ETrue);
103 INFO_PRINTF1(_L("Exit: CEglTest_EGL_Image_Multi_Thread_Parallel::doTestStepL"));
105 CloseTMSGraphicsStep();
106 return TestStepResult();
109 void CEglTest_EGL_Image_Multi_Thread_Parallel::doThreadFunctionL(TInt aIdx)
111 INFO_PRINTF2(_L("CEglTest_EGL_Image_Multi_Thread_Parallel::doThreadFunctionL, Thread %d"),aIdx);
113 CTestEglSession* eglSess = CTestEglSession::NewLC(Logger(), iDisplay, aIdx);
114 eglSess->InitializeL();
115 eglSess->OpenSgDriverL();
117 // create a reference bitmap (we give index 7, as there's only 1 image in this test case)
118 TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(KDefaultSourceFormat);
119 CFbsBitmap* bitmap = eglSess->CreateReferenceBitmapL(bitmapMode, KPixmapSize, 7);
120 CleanupStack::PushL(bitmap);
122 // Create an RSgImage
123 INFO_PRINTF2(_L("Thread %d, Creating a RSgImage having the reference bitmap's content"),aIdx);
124 TSgImageInfoOpenVgImage imageInfo = TSgImageInfoOpenVgImage(KDefaultSourceFormat, KPixmapSize);
125 RSgImage rSgImageLocal;
126 CleanupClosePushL(rSgImageLocal);
127 ASSERT_EQUALS(rSgImageLocal.Create(imageInfo,bitmap->DataAddress(),bitmap->DataStride()), KErrNone);
129 INFO_PRINTF2(_L("Thread %d, Creating an EGLImage from the shared RSgImage"),aIdx);
130 EGLImageKHR eglImageLocal = eglSess->eglCreateImageKhrL(iDisplay, EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, &rSgImageLocal, KEglImageAttribsPreservedTrue);
131 ASSERT_EGL_TRUE(eglImageLocal != EGL_NO_IMAGE_KHR);
132 CleanupStack::PopAndDestroy(&rSgImageLocal); //transferring ownership of the buffer to the EGLImage
133 CleanupStack::PopAndDestroy(bitmap);
135 INFO_PRINTF2(_L("Thread %d, Creating a Surface and a Context bound to OpenVG"),aIdx);
136 TUidPixelFormat pixelFormat = EglTestConversion::VgFormatToSgPixelFormat(KDefaultSurfaceFormat);
137 TSgImageInfoOpenVgTarget imageInfo2 = TSgImageInfoOpenVgTarget(pixelFormat, KPixmapSize);
138 // Create a pixmap surface matching the native image pixel format
139 eglSess->CreatePixmapSurfaceAndMakeCurrentAndMatchL(imageInfo2,CTestEglSession::EResourceCloseSgImageEarly);
141 INFO_PRINTF2(_L("Thread %d, Creating one VGImage from the EGLImage"),aIdx);
142 VGImage vgImageLocal = eglSess->vgCreateImageTargetKHR((VGeglImageKHR)eglImageLocal);
143 ASSERT_VG_TRUE(vgImageLocal != VG_INVALID_HANDLE);
144 ASSERT_EGL_TRUE(eglSess->DestroyEGLImage(iDisplay, eglImageLocal));
146 // Copy the source VGImage to the surface
147 vgSetPixels(0, 0, vgImageLocal, 0, 0, KPixmapSize.iWidth, KPixmapSize.iHeight);
148 ASSERT_TRUE(vgGetError()==VG_NO_ERROR);
152 vgDestroyImage(vgImageLocal);
153 ASSERT_TRUE(vgGetError()==VG_NO_ERROR);
155 // we can now compare the VgImage to the one we would expect for this particular thread
156 CFbsBitmap* refBitmap = eglSess->CreateReferenceBitmapL(bitmapMode, KPixmapSize, 7);
157 CleanupStack::PushL(refBitmap);
158 eglSess->CheckVgDrawingL(KDefaultSurfaceFormat, refBitmap);
159 CleanupStack::PopAndDestroy(refBitmap);
160 INFO_PRINTF2(_L("Drawing successful, Thread %d"),aIdx);
163 eglSess->CloseSgDriver();
164 CleanupStack::PopAndDestroy(eglSess);
168 @SYMTestCaseID GRAPHICS-EGL-0156
174 @SYMREQ See SGL.GT0386.401 document
177 Check if EGL Implementation allows two threads to work in parallel.
178 EGLImage cant be created from an RSgImage that already has been linked to an EGLImage by another thread.
181 Main Thread: creates an RSgImage and starts thread1 and thread2.
182 Thread1: Creates an EGLImage from the RSgImage previous mentioned
184 Thread2: Creates an EGLImage from the RSgImage previous mentioned and check that eglCreateImageKHR() does return EGL_NO_IMAGE_KHR
186 Thread1: Closes the EGLImage
187 Main Thread: Closes the RSgImage.
189 @SYMTestExpectedResults
190 eglCreateImageKHR() does return EGL_NO_IMAGE_KHR in the 2nd thread and EGL_BAD_ACCESS error is generated.
191 No memory or handle leaks
193 TVerdict CEglTest_EGL_Image_Multi_Thread_Sibling_Basic::doTestStepL()
195 SetTestStepID(_L("GRAPHICS-EGL-0156"));
196 INFO_PRINTF1(_L("Enter: CEglTest_EGL_Image_Multi_Thread_Sibling_Basic::doTestStepL"));
198 TBool ret = CheckForExtensionL(KEGL_RSgimage | KEGL_KHR_image_base | KEGL_KHR_image_pixmap | KVG_KHR_EGL_image);
201 // The extension is not supported
203 CloseTMSGraphicsStep();
204 return TestStepResult();
207 // Create display object
208 ASSERT_TRUE(iDisplay == EGL_NO_DISPLAY);
210 CTestEglSession* eglSess = CTestEglSession::NewLC(Logger(), iDisplay, 0);
211 eglSess->InitializeL();
213 // Make sure the driver is ready
214 eglSess->OpenSgDriverL();
216 // create a reference bitmap (we give index 0, as there's only 1 image in this test case)
217 TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(KDefaultSourceFormat);
218 CFbsBitmap* bitmap = eglSess->CreateReferenceBitmapL(bitmapMode, KPixmapSize, 0);
219 CleanupStack::PushL(bitmap);
221 // Create an RSgImage (member variable as it is 'shared' in the thread funtion...)
222 TSgImageInfoOpenVgImage imageInfo = TSgImageInfoOpenVgImage(KDefaultSourceFormat, KPixmapSize);
223 ASSERT_EQUALS(iSgImageShared.Create(imageInfo,bitmap->DataAddress(),bitmap->DataStride()), KErrNone);
224 CleanupStack::PopAndDestroy(bitmap);
227 Test_MultiThreadL(2, ETrue);
230 iSgImageShared.Close();
231 CleanupStack::PopAndDestroy(eglSess);
233 INFO_PRINTF1(_L("Exit: CEglTest_EGL_Image_Multi_Thread_Sibling_Basic::doTestStepL"));
235 CloseTMSGraphicsStep();
236 return TestStepResult();
239 void CEglTest_EGL_Image_Multi_Thread_Sibling_Basic::doThreadFunctionL(TInt aIdx)
241 INFO_PRINTF2(_L("CEglTest_EGL_Image_Multi_Thread_Sibling_Basic::doThreadFunctionL, Thread %d"),aIdx);
242 CTestEglSession* eglSess = CTestEglSession::NewLC(Logger(), iDisplay, aIdx);
243 eglSess->InitializeL();
244 eglSess->OpenSgDriverL();
246 EGLImageKHR eglImageLocal = EGL_NO_IMAGE_KHR;
249 INFO_PRINTF2(_L("Thread %d, Creating an EGLImage from the shared RSgImage"),aIdx);
250 eglImageLocal = eglSess->eglCreateImageKhrL(iDisplay,EGL_NO_CONTEXT,EGL_NATIVE_PIXMAP_KHR,&iSgImageShared,KEglImageAttribsPreservedTrue);
251 ASSERT_EGL_TRUE(eglImageLocal != EGL_NO_IMAGE_KHR);
258 INFO_PRINTF2(_L("Thread %d, Creating an EGLImage from the shared RSgImage"),aIdx);
259 eglImageLocal = eglSess->eglCreateImageKhrL(iDisplay,EGL_NO_CONTEXT,EGL_NATIVE_PIXMAP_KHR,&iSgImageShared,KEglImageAttribsPreservedTrue);
260 ASSERT_EGL_TRUE(eglImageLocal == EGL_NO_IMAGE_KHR);
261 ASSERT_EGL_ERROR(EGL_BAD_ACCESS);
269 ASSERT_EGL_TRUE(eglSess->DestroyEGLImage(iDisplay, eglImageLocal));
271 eglSess->CloseSgDriver();
272 CleanupStack::PopAndDestroy(eglSess);
276 @SYMTestCaseID GRAPHICS-EGL-0157
282 @SYMREQ See SGL.GT0386.401 document
285 Check if EGL Implementation allows two threads to work in parallel.
286 Each thread is allowed to create a VGImage from the same EGLImage
289 Main Thread: creates an RSgImage with the same content as the reference bitmap and creates an EGLImage from it; starts thread1 and thread2.
290 Thread1: Creates an egl context and a pixmap surface linked to it. Creates an VGImage from the EGLImage previous mentioned
291 Thread2: Creates an egl context and a pixmap surface linked to it. Creates an VGImage from the EGLImage previous mentioned
293 Thread 1: Changes the content of the RSgImage by using the VGImage that has a reference to it.
295 Thread1: Passes the VGImage into vgDestroyImage()
296 Thread2: Copies the VGImage to the pixmap surface and checks the contents
297 Thread2: Passes the VGImage into vgDestroyImage()
298 Main Thread: Closes the EGLImage
299 Main Thread: Closes the RSgImage
301 @SYMTestExpectedResults
302 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.
303 No memory or handle leaks
305 TVerdict CEglTest_EGL_Image_Multi_Thread_Sibling_VGImage::doTestStepL()
307 SetTestStepID(_L("GRAPHICS-EGL-0157"));
308 INFO_PRINTF1(_L("Enter: CEglTest_EGL_Image_Multi_Thread_Sibling_VGImage::doTestStepL"));
310 TBool ret = CheckForExtensionL(KEGL_RSgimage | KEGL_KHR_image_base | KEGL_KHR_image_pixmap | KVG_KHR_EGL_image);
313 // The extension is not supported
315 CloseTMSGraphicsStep();
316 return TestStepResult();
319 // Create display object
320 ASSERT_TRUE(iDisplay == EGL_NO_DISPLAY);
322 CTestEglSession* eglSess = CTestEglSession::NewLC(Logger(), iDisplay, 0);
323 eglSess->InitializeL();
325 // Make sure the driver is ready
326 eglSess->OpenSgDriverL();
328 // create a reference bitmap (we give index 3, as there's only 1 image in this test case)
329 TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(KDefaultSourceFormat);
330 CFbsBitmap* bitmap = eglSess->CreateReferenceBitmapL(bitmapMode, KPixmapSize, 3);
331 CleanupStack::PushL(bitmap);
333 // Create an RSgImage (member variable as it is 'shared' in the thread funtion...)
334 INFO_PRINTF1(_L("Parent Thread, Creating the shared RSgImage"));
335 TSgImageInfoOpenVgImage imageInfo = TSgImageInfoOpenVgImage(KDefaultSourceFormat, KPixmapSize);
336 ASSERT_EQUALS(iSgImageShared.Create(imageInfo,bitmap->DataAddress(),bitmap->DataStride()), KErrNone);
337 CleanupStack::PopAndDestroy(bitmap);
339 // Create an EGLImage from the RSgImage (member variable as it is 'shared' in the thread funtion...)
340 INFO_PRINTF1(_L("Parent Thread, Creating the shared EGLImage"));
341 iEGLImageShared = eglSess->eglCreateImageKhrL(iDisplay,EGL_NO_CONTEXT,EGL_NATIVE_PIXMAP_KHR,&iSgImageShared,KEglImageAttribsPreservedTrue);
342 ASSERT_EGL_TRUE(iEGLImageShared != EGL_NO_IMAGE_KHR);
343 iSgImageShared.Close();
346 Test_MultiThreadL(2, ETrue);
349 ASSERT_EGL_TRUE(eglSess->DestroyEGLImage(iDisplay, iEGLImageShared));
350 CleanupStack::PopAndDestroy(eglSess);
352 INFO_PRINTF1(_L("Exit: CEglTest_EGL_Image_Multi_Thread_Sibling_VGImage::doTestStepL"));
354 CloseTMSGraphicsStep();
355 return TestStepResult();
358 void CEglTest_EGL_Image_Multi_Thread_Sibling_VGImage::doThreadFunctionL(TInt aIdx)
360 INFO_PRINTF2(_L("CEglTest_EGL_Image_Multi_Thread_Sibling_VGImage::doThreadFunctionL, Thread %d"),aIdx);
361 CTestEglSession* eglSess = CTestEglSession::NewLC(Logger(), iDisplay, aIdx);
362 eglSess->InitializeL();
363 eglSess->OpenSgDriverL();
365 INFO_PRINTF2(_L("Thread %d, Creating a Surface and a Context bound to OpenVG"),aIdx);
366 TUidPixelFormat pixelFormat = EglTestConversion::VgFormatToSgPixelFormat(KDefaultSurfaceFormat);
367 TSgImageInfoOpenVgTarget imageInfo = TSgImageInfoOpenVgTarget(pixelFormat, KPixmapSize);
368 // Create a pixmap surface matching the native image pixel format
369 eglSess->CreatePixmapSurfaceAndMakeCurrentAndMatchL(imageInfo,CTestEglSession::EResourceCloseSgImageEarly);
371 // Create a VGImage from the EGLImage
372 INFO_PRINTF2(_L("Thread %d, Creating one VGImage from the shared EGLImage"),aIdx);
373 VGImage vgImageLocal = eglSess->vgCreateImageTargetKHR((VGeglImageKHR)iEGLImageShared);
374 ASSERT_VG_TRUE(vgImageLocal != VG_INVALID_HANDLE);
380 INFO_PRINTF2(_L("Thread %d, Updating contents of the VGImage from the shared EGLImage"),aIdx);
381 TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(KDefaultSourceFormat);
382 CFbsBitmap* bitmap = eglSess->CreateReferenceBitmapL(bitmapMode, KPixmapSize, 8);
383 // Add pixel data to the VGImage reference from the bitmap reference.
384 // Mind the fact that CFbsBitmap and VGImages use different coordinates origin!
385 TSize bitmapSize = bitmap->SizeInPixels();
386 TUint8* address = reinterpret_cast<TUint8*>(bitmap->DataAddress());
387 TInt stride = bitmap->DataStride();
388 address += (bitmapSize.iHeight - 1) * stride;
389 vgImageSubData(vgImageLocal, address, -stride, KDefaultSurfaceFormat, 0,0, bitmapSize.iWidth, bitmapSize.iHeight);
392 ASSERT_TRUE(vgGetError()==VG_NO_ERROR);
400 INFO_PRINTF2(_L("Thread %d, Drawing the VGImage to the current surface"),aIdx);
401 // Copy the source VGImage to the surface
402 vgSetPixels(0, 0, vgImageLocal, 0, 0, KPixmapSize.iWidth, KPixmapSize.iHeight);
403 ASSERT_TRUE(vgGetError()==VG_NO_ERROR);
406 // we can now compare the VgImage to the one we expect after changing it in the other thread
407 TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(KDefaultSourceFormat);
408 CFbsBitmap* refBitmap = eglSess->CreateReferenceBitmapL(bitmapMode, KPixmapSize, 8);
409 CleanupStack::PushL(refBitmap);
410 eglSess->CheckVgDrawingL(KDefaultSurfaceFormat, refBitmap);
411 CleanupStack::PopAndDestroy(refBitmap);
412 INFO_PRINTF2(_L("Thread %d, Drawing successful"),aIdx);
416 vgDestroyImage(vgImageLocal);
417 ASSERT_TRUE(vgGetError() == VG_NO_ERROR);
418 eglSess->CloseSgDriver();
419 CleanupStack::PopAndDestroy(eglSess);
423 @SYMTestCaseID GRAPHICS-EGL-0158
429 @SYMREQ See SGL.GT0386.401 document
432 Check if EGL Implementation allows two threads to work in parallel.
433 Each thread is allowed to create a VGImage from an EGLImage created by another thread.
436 Main Thread: creates an RSgImage ; starts thread1 and thread2.
437 Thread1: Creates an EGLImage from the previous mentioned RSgImage
439 Thread2: Creates an VGImage from the EGLImage created by the other thread
441 Thread1: Passes the EGLImage into eglDestroyImageKHR ()
442 Thread2: Passes the VGImage into vgDestroyImage()
443 Main Thread: Closes the RSgImage
445 @SYMTestExpectedResults
446 No error is generated within both threads
447 No memory or handle leaks
449 TVerdict CEglTest_EGL_Image_Multi_Thread_Sibling_VGImage_PassingEGLImage::doTestStepL()
451 SetTestStepID(_L("GRAPHICS-EGL-0158"));
452 INFO_PRINTF1(_L("Enter: CEglTest_EGL_Image_Multi_Thread_Sibling_VGImage_PassingEGLImage::doTestStepL"));
454 TBool ret = CheckForExtensionL(KEGL_RSgimage | KEGL_KHR_image_base | KEGL_KHR_image_pixmap | KVG_KHR_EGL_image);
457 // The extension is not supported
459 CloseTMSGraphicsStep();
460 return TestStepResult();
463 // Create display object
464 ASSERT_TRUE(iDisplay == EGL_NO_DISPLAY);
466 CTestEglSession* eglSess = CTestEglSession::NewLC(Logger(), iDisplay, 0);
467 eglSess->InitializeL();
469 // Make sure the driver is ready
470 eglSess->OpenSgDriverL();
472 // create a reference bitmap (we give index 5, as there's only 1 image in this test case)
473 TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(KDefaultSourceFormat);
474 CFbsBitmap* bitmap = eglSess->CreateReferenceBitmapL(bitmapMode, KPixmapSize, 5);
475 CleanupStack::PushL(bitmap);
477 // Create an RSgImage (member variable as it is 'shared' in the thread funtion...)
478 INFO_PRINTF1(_L("Parent Thread, Creating the shared RSgImage"));
479 TSgImageInfoOpenVgImage imageInfo = TSgImageInfoOpenVgImage(KDefaultSourceFormat, KPixmapSize);
480 ASSERT_EQUALS(iSgImageShared.Create(imageInfo,bitmap->DataAddress(),bitmap->DataStride()), KErrNone);
481 CleanupStack::PopAndDestroy(bitmap);
484 Test_MultiThreadL(2, ETrue);
487 iSgImageShared.Close();
488 CleanupStack::PopAndDestroy(eglSess);
490 INFO_PRINTF1(_L("Exit: CEglTest_EGL_Image_Multi_Thread_Sibling_VGImage_PassingEGLImage::doTestStepL"));
492 CloseTMSGraphicsStep();
493 return TestStepResult();
496 void CEglTest_EGL_Image_Multi_Thread_Sibling_VGImage_PassingEGLImage::doThreadFunctionL(TInt aIdx)
498 INFO_PRINTF2(_L("CEglTest_EGL_Image_Multi_Thread_Sibling_VGImage_PassingEGLImage::doThreadFunctionL, Thread %d"),aIdx);
499 CTestEglSession* eglSess = CTestEglSession::NewLC(Logger(), iDisplay, aIdx);
500 eglSess->InitializeL();
501 eglSess->OpenSgDriverL();
503 // check there is no eglImage at the start of either thread
504 ASSERT_EGL_TRUE(iEGLImageShared == EGL_NO_IMAGE_KHR);
506 // Wait for both thread to reach this point
507 // This is important for multicore platforms (i.e., naviengine) as the execution order is not known and it could
508 // happen that the first thread has already created the image before the second checks there is no eglImage
513 // Create an EGLImage from the RSgImage (member variable as it is 'shared' in the thread function...)
514 INFO_PRINTF2(_L("Thread %d, Creating the shared EGLImage"),aIdx);
515 iEGLImageShared = eglSess->eglCreateImageKhrL(iDisplay,EGL_NO_CONTEXT,EGL_NATIVE_PIXMAP_KHR,&iSgImageShared,KEglImageAttribsPreservedTrue);
516 ASSERT_EGL_TRUE(iEGLImageShared != EGL_NO_IMAGE_KHR);
517 iSgImageShared.Close();
524 INFO_PRINTF2(_L("Thread %d, Creating a Surface and a Context bound to OpenVG"),aIdx);
525 TUidPixelFormat pixelFormat = EglTestConversion::VgFormatToSgPixelFormat(KDefaultSurfaceFormat);
526 TSgImageInfoOpenVgTarget imageInfo = TSgImageInfoOpenVgTarget(pixelFormat, KPixmapSize);
527 // Create a pixmap surface matching the native image pixel format
528 eglSess->CreatePixmapSurfaceAndMakeCurrentAndMatchL(imageInfo,CTestEglSession::EResourceCloseSgImageEarly);
530 // Create a VGImage from the EGLImage
531 INFO_PRINTF2(_L("Thread %d, Creating one VGImage from the shared EGLImage"),aIdx);
532 VGImage vgImageLocal = eglSess->vgCreateImageTargetKHR((VGeglImageKHR)iEGLImageShared);
533 ASSERT_VG_TRUE(vgImageLocal != VG_INVALID_HANDLE);
535 INFO_PRINTF2(_L("Thread %d, Drawing the VGImage to the current surface"),aIdx);
536 // Copy the source VGImage to the surface
537 vgSetPixels(0, 0, vgImageLocal, 0, 0, KPixmapSize.iWidth, KPixmapSize.iHeight);
538 ASSERT_TRUE(vgGetError()==VG_NO_ERROR);
541 // we can now compare the VgImage to the one we expect from the main thread
542 TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(KDefaultSourceFormat);
543 CFbsBitmap* refBitmap = eglSess->CreateReferenceBitmapL(bitmapMode, KPixmapSize, 5);
544 CleanupStack::PushL(refBitmap);
545 eglSess->CheckVgDrawingL(KDefaultSurfaceFormat, refBitmap);
546 CleanupStack::PopAndDestroy(refBitmap);
547 INFO_PRINTF2(_L("Thread %d, Drawing successful"),aIdx);
549 vgDestroyImage(vgImageLocal);
550 ASSERT_TRUE(vgGetError() == VG_NO_ERROR);
557 ASSERT_EGL_TRUE(eglSess->DestroyEGLImage(iDisplay, iEGLImageShared));
558 iEGLImageShared = EGL_NO_IMAGE_KHR;
562 eglSess->CloseSgDriver();
563 CleanupStack::PopAndDestroy(eglSess);
567 @SYMTestCaseID GRAPHICS-EGL-0159
573 @SYMREQ See SGL.GT0386.401 document
576 Check if EGL Implementation allows two threads to work in parallel.
577 If the thread that has created the EGLImage terminates without destroying it the other thread can still use it.
580 Main Thread: Creates an RSgImage ; starts thread1 and thread2.
581 Thread1: An EGLImage from the previous mentioned RSgImage
583 Thread1: Calls eglReleaseThread()
584 Thread1: Finishes gracefully
585 Thread2: Creates an VGImage the EGLImage created by the other thread
586 Thread2: Passes the VGImage into vgDestroyImage()
587 Thread2: Passes the EGLImage into eglDestroyImageKHR ()
588 Main Thread: Closes the RSgImage.
590 @SYMTestExpectedResults
591 No error is generated within both threads
592 No memory or handle leaks
594 TVerdict CEglTest_EGL_Image_Multi_Thread_Exit_Thread::doTestStepL()
596 SetTestStepID(_L("GRAPHICS-EGL-0159"));
597 INFO_PRINTF1(_L("Enter: CEglTest_EGL_Image_Multi_Thread_Exit_Thread::doTestStepL"));
599 TBool ret = CheckForExtensionL(KEGL_RSgimage | KEGL_KHR_image_base | KEGL_KHR_image_pixmap | KVG_KHR_EGL_image);
602 // The extension is not supported
604 CloseTMSGraphicsStep();
605 return TestStepResult();
608 // Create display object
609 ASSERT_TRUE(iDisplay == EGL_NO_DISPLAY);
611 CTestEglSession* eglSess = CTestEglSession::NewLC(Logger(), iDisplay, 0);
612 eglSess->InitializeL();
614 // Make sure the driver is ready
615 eglSess->OpenSgDriverL();
617 // create a reference bitmap (we give index 2, as there's only 1 image in this test case)
618 TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(KDefaultSourceFormat);
619 CFbsBitmap* bitmap = eglSess->CreateReferenceBitmapL(bitmapMode, KPixmapSize, 2);
620 CleanupStack::PushL(bitmap);
622 // Create an RSgImage (member variable as it is 'shared' in the thread funtion...)
623 INFO_PRINTF1(_L("Parent Thread, Creating the shared RSgImage"));
624 TSgImageInfoOpenVgImage imageInfo = TSgImageInfoOpenVgImage(KDefaultSourceFormat, KPixmapSize);
625 ASSERT_EQUALS(iSgImageShared.Create(imageInfo,bitmap->DataAddress(),bitmap->DataStride()), KErrNone);
626 CleanupStack::PopAndDestroy(bitmap);
629 Test_MultiThreadL(2, ETrue);
632 iSgImageShared.Close();
633 CleanupStack::PopAndDestroy(eglSess);
635 INFO_PRINTF1(_L("Exit: CEglTest_EGL_Image_Multi_Thread_Exit_Thread::doTestStepL"));
637 CloseTMSGraphicsStep();
638 return TestStepResult();
641 void CEglTest_EGL_Image_Multi_Thread_Exit_Thread::doThreadFunctionL(TInt aIdx)
643 INFO_PRINTF2(_L("CEglTest_EGL_Image_Multi_Thread_Exit_Thread::doThreadFunctionL, Thread %d"),aIdx);
644 CTestEglSession* eglSess = CTestEglSession::NewLC(Logger(), iDisplay, aIdx);
645 eglSess->InitializeL();
646 eglSess->OpenSgDriverL();
648 // check there is no eglImage at the start of either thread
649 ASSERT_EGL_TRUE(iEGLImageShared == EGL_NO_IMAGE_KHR);
651 TRequestStatus statusThread0;
654 INFO_PRINTF2(_L("Thread %d, Asking to be notified when thread 0 exits"),aIdx);
655 iThreadStatus[0].iThread.Logon(statusThread0);
660 //Thread 0 creates the EGLImage and exit
663 // Create an EGLImage from the RSgImage (member variable as it is 'shared' in the thread function...)
664 INFO_PRINTF2(_L("Thread %d, Creating the shared EGLImage"),aIdx);
665 iEGLImageShared = eglSess->eglCreateImageKhrL(iDisplay,EGL_NO_CONTEXT,EGL_NATIVE_PIXMAP_KHR,&iSgImageShared,KEglImageAttribsPreservedTrue);
666 ASSERT_EGL_TRUE(iEGLImageShared != EGL_NO_IMAGE_KHR);
667 iSgImageShared.Close();
668 INFO_PRINTF2(_L("Thread %d ----- Exiting ---- EGLImage should be kept alive"),aIdx);
671 //Thread1 waits for Thread0 to exit and then uses the EGLImage and performs some drawing
674 INFO_PRINTF2(_L("Thread %d, Waiting for thread 0 to exit"),aIdx);
675 User::WaitForRequest(statusThread0);
677 INFO_PRINTF2(_L("Thread %d, Creating a Surface and a Context bound to OpenVG"),aIdx);
678 TUidPixelFormat pixelFormat = EglTestConversion::VgFormatToSgPixelFormat(KDefaultSurfaceFormat);
679 TSgImageInfoOpenVgTarget imageInfo = TSgImageInfoOpenVgTarget(pixelFormat, KPixmapSize);
680 // Create a pixmap surface matching the native image pixel format
681 eglSess->CreatePixmapSurfaceAndMakeCurrentAndMatchL(imageInfo,CTestEglSession::EResourceCloseSgImageEarly);
683 // Create a VGImage from the EGLImage
684 INFO_PRINTF2(_L("Thread %d, Creating one VGImage from the shared EGLImage"),aIdx);
685 VGImage vgImageLocal = eglSess->vgCreateImageTargetKHR((VGeglImageKHR)iEGLImageShared);
686 ASSERT_VG_TRUE(vgImageLocal != VG_INVALID_HANDLE);
688 INFO_PRINTF2(_L("Thread %d, Drawing the VGImage to the current surface"),aIdx);
689 // Copy the source VGImage to the surface
690 vgSetPixels(0, 0, vgImageLocal, 0, 0, KPixmapSize.iWidth, KPixmapSize.iHeight);
691 ASSERT_TRUE(vgGetError()==VG_NO_ERROR);
694 // we can now compare the VgImage to the one we expect after changing it in the other thread
695 TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(KDefaultSourceFormat);
696 CFbsBitmap* refBitmap = eglSess->CreateReferenceBitmapL(bitmapMode, KPixmapSize, 2);
697 CleanupStack::PushL(refBitmap);
698 eglSess->CheckVgDrawingL(KDefaultSurfaceFormat, refBitmap);
699 CleanupStack::PopAndDestroy(refBitmap);
700 INFO_PRINTF2(_L("Thread %d, Drawing successful"),aIdx);
702 vgDestroyImage(vgImageLocal);
703 ASSERT_TRUE(vgGetError() == VG_NO_ERROR);
704 ASSERT_EGL_TRUE(eglSess->DestroyEGLImage(iDisplay, iEGLImageShared));
705 iEGLImageShared = EGL_NO_IMAGE_KHR;
709 eglSess->CloseSgDriver();
710 CleanupStack::PopAndDestroy(eglSess);
715 @SYMTestCaseID GRAPHICS-EGL-0163
721 @SYMREQ See SGL.GT0386.401 document
724 All the EGL resources may be used implicitly by a thread even after another thread has terminated the display.
727 Thread0: Asks to be notified when Thread1 exits
728 Thread0: Creates a RSgImage having the reference bitmap as content
729 Thread0: Creates a EGLImage from the RSgImage
730 Thread0: Creates a surface
731 Thread0: Creates a VGImage from the EGLImage
733 Thread1: Calls eglTerminate
736 Thread0: Resumes when Thread1 exits
737 Thread0: Uses the VGImage and draw it to the surface
738 Thread0: Checks the contents
740 @SYMTestExpectedResults
741 Thread0 is able to use successfully the VGmage and the surface's content are the ones expected.
743 TVerdict CEglTest_EGL_Image_Multi_Thread_DrawAfterTerminate::doTestStepL()
745 SetTestStepID(_L("GRAPHICS-EGL-0163"));
746 INFO_PRINTF1(_L("Enter: CEglTest_EGL_Image_Multi_Thread_DrawAfterTerminate::doTestStepL"));
748 TBool ret = CheckForExtensionL(KEGL_RSgimage | KEGL_KHR_image_base | KEGL_KHR_image_pixmap | KVG_KHR_EGL_image);
751 // The extension is not supported
753 CloseTMSGraphicsStep();
754 return TestStepResult();
757 Test_MultiThreadL(2, ETrue);
759 INFO_PRINTF1(_L("Exit: CEglTest_EGL_Image_Multi_Thread_DrawAfterTerminate::doTestStepL"));
761 CloseTMSGraphicsStep();
762 return TestStepResult();
765 void CEglTest_EGL_Image_Multi_Thread_DrawAfterTerminate::doThreadFunctionL(TInt aIdx)
767 INFO_PRINTF2(_L("CEglTest_EGL_Image_Multi_Thread_DrawAfterTerminate::doThreadFunctionL, Thread %d"),aIdx);
769 CTestEglSession* eglSess = CTestEglSession::NewLC(Logger(), iDisplay, aIdx);
770 eglSess->InitializeL();
771 eglSess->OpenSgDriverL();
773 TRequestStatus statusThread1;
774 VGImage vgImageLocal = VG_INVALID_HANDLE;
776 EGLint surfaceHeigth;
778 //Thread0 asks to be notified when Thread1 exits
779 //Creates a RSgImage having the reference bitmap as content
780 //Creates a EGLImage from the RSgImage
782 //Creates a VGImage from the EGLImage
785 // Thread0 asks to be notified when Thread1 exits
786 iThreadStatus[1].iThread.Logon(statusThread1);
788 RSgImage rSgImageLocal;
789 CleanupClosePushL(rSgImageLocal);
791 // create a reference bitmap (we give index 9, as there's only 1 image in this test case)
792 TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(KDefaultSourceFormat);
793 CFbsBitmap* bitmap = eglSess->CreateReferenceBitmapL(bitmapMode, KPixmapSize, 9);
794 CleanupStack::PushL(bitmap);
796 // Create an RSgImage
797 INFO_PRINTF2(_L("Thread %d, Creating a RSgImage having the reference bitmap's content"),aIdx);
798 TSgImageInfoOpenVgImage imageInfo = TSgImageInfoOpenVgImage(KDefaultSourceFormat, KPixmapSize);
799 ASSERT_EQUALS(rSgImageLocal.Create(imageInfo,bitmap->DataAddress(),bitmap->DataStride()), KErrNone);
800 CleanupStack::PopAndDestroy(bitmap);
802 INFO_PRINTF2(_L("Thread %d, Creating an EGLImage from the shared RSgImage"),aIdx);
803 EGLImageKHR eglImageLocal = eglSess->eglCreateImageKhrL(iDisplay, EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, &rSgImageLocal, KEglImageAttribsPreservedTrue);
804 ASSERT_EGL_TRUE(eglImageLocal != EGL_NO_IMAGE_KHR);
805 CleanupStack::PopAndDestroy(&rSgImageLocal); //transferring ownership of the buffer to the EGLImage
807 INFO_PRINTF2(_L("Thread %d, Creating a Surface and a Context bound to OpenVG"),aIdx);
808 TUidPixelFormat pixelFormat = EglTestConversion::VgFormatToSgPixelFormat(KDefaultSurfaceFormat);
809 TSgImageInfoOpenVgTarget imageInfo2 = TSgImageInfoOpenVgTarget(pixelFormat, KPixmapSize);
810 // Create a pixmap surface matching the native image pixel format
811 eglSess->CreatePixmapSurfaceAndMakeCurrentAndMatchL(imageInfo2,CTestEglSession::EResourceCloseSgImageEarly);
813 //We now store the size of the surface because after eglTerminate is called on the display
814 //it will not be possible to use explicitly all the resources linked to it
815 //i.e. every call to an EGL API who takes a display as an argument will raise a EGL_BAD_DISPLAY error
816 eglQuerySurface(iDisplay, eglSess->Surface(), EGL_WIDTH, &surfaceWidth);
817 eglQuerySurface(iDisplay, eglSess->Surface(), EGL_HEIGHT, &surfaceHeigth);
819 INFO_PRINTF2(_L("Thread %d, Creating one VGImage from the EGLImage"),aIdx);
820 vgImageLocal = eglSess->vgCreateImageTargetKHR((VGeglImageKHR)eglImageLocal);
821 ASSERT_VG_TRUE(vgImageLocal != VG_INVALID_HANDLE);
822 ASSERT_EGL_TRUE(eglSess->DestroyEGLImage(iDisplay, eglImageLocal));
827 //Thread1 calls eglTerminate and exit
830 INFO_PRINTF2(_L(", Thread %d, Calling eglTerminate and exiting"),aIdx);
836 //Thread0 resumes when Thread1 exits
837 //and it uses the resources that are linked to the just destroyed display
840 User::WaitForRequest(statusThread1);
842 // It's still possible to use the current context, surface and VGImage even though the display has been terminated
843 //Copy the source VGImage to the surface
844 vgSetPixels(0, 0, vgImageLocal, 0, 0, KPixmapSize.iWidth, KPixmapSize.iHeight);
845 ASSERT_TRUE(vgGetError()==VG_NO_ERROR);
848 // we can now compare the VgImage to the one we would expect for this particular thread
849 TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(KDefaultSourceFormat);
850 CFbsBitmap* refBitmap = eglSess->CreateReferenceBitmapL(bitmapMode, KPixmapSize, 9);
851 CleanupStack::PushL(refBitmap);
852 eglSess->CheckVgDrawingL(KDefaultSurfaceFormat, refBitmap);
853 CleanupStack::PopAndDestroy(refBitmap);
854 INFO_PRINTF2(_L("Drawing successful, Thread %d"),aIdx);
856 vgDestroyImage(vgImageLocal);
857 ASSERT_TRUE(vgGetError() == VG_NO_ERROR);
862 eglSess->CloseSgDriver();
863 CleanupStack::PopAndDestroy(eglSess);