First public contribution.
1 // Copyright (c) 2009-2010 Nokia Corporation and/or its subsidiary(-ies).
2 // All rights reserved.
3 // This component and the accompanying materials are made available
4 // under the terms of "Eclipse Public License v1.0"
5 // which accompanies this distribution, and is available
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
8 // Initial Contributors:
9 // Nokia Corporation - initial contribution.
21 #include <test/tefunit.h> // for ASSERT macros
22 #include <iniparser.h>
23 #include <e32msgqueue.h>
25 #include "egltest_image_multiprocess.h"
27 #include <test/egltestcommonconversion.h>
28 #include <test/egltestcommoninisettings.h>
29 #include <test/egltestcommonsgimageinfo.h>
30 #include <test/egltestcommonprocess.h>
33 // Constant definitions
35 const TInt KNumProcesses = 8;
36 const TInt KNumImages = 4;
37 #define KImageSize TSize(100,100) // use #define to avoid global temporary constructors
41 @SYMTestCaseID GRAPHICS-EGL-0160
47 @SYMREQ See SGL.GT0386.401 document
50 Check if EGL Implementation allows two processes to work in parallel.
51 A process can create an EGLImage from the same RSgImage that already has been linked to an EGLImage by another process.
54 Main Process: creates an RsgImage and starts Process and Process.
55 Process1: Creates an EGLImage from the RsgImage previous mentioned
57 Process2: Creates an EGLImage from the RsgImage previous mentioned and check that eglCreateImageKHR() does NOT return EGL_NO_IMAGE_KHR
59 Process1: Closes the EGLImage
60 Process2: Closes the EGLImage
61 Main Process: Closes the RsgImage
63 @SYMTestExpectedResults
64 No errors within both processes.
65 No memory or handle leaks
67 TVerdict CEglTest_EGL_Image_Multi_Process_Sibling_Basic::doTestStepL()
69 SetTestStepID(_L("GRAPHICS-EGL-0160"));
70 SetTestStepName(KEGL_Image_Multi_Process_Sibling_Basic);
71 INFO_PRINTF1(_L("Enter: CEglTest_EGL_Image_Multi_Process_Sibling_Basic::doTestStepL"));
73 TBool ret = CheckForExtensionL(KEGL_RSgimage | KEGL_KHR_image_base | KEGL_KHR_image_pixmap | KVG_KHR_EGL_image);
76 // The extension is not supported
78 CloseTMSGraphicsStep();
79 return TestStepResult();
82 // Create display object
83 ASSERT_TRUE(iDisplay == EGL_NO_DISPLAY);
86 iEglSess->InitializeL();
87 iEglSess->OpenSgDriverL();
89 // create a reference bitmap (we give index 0, as there's only 1 image in this test case)
90 TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(KDefaultSourceFormat);
91 CFbsBitmap* bitmap = iEglSess->CreateReferenceBitmapL(bitmapMode, KImageSize, 0);
92 CleanupStack::PushL(bitmap);
95 TSgImageInfoOpenVgImage imageInfo = TSgImageInfoOpenVgImage(KDefaultSourceFormat, KImageSize);
96 #ifndef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
97 imageInfo.iShareable = ETrue;
98 #endif //SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
100 CleanupClosePushL(sgImage);
101 ASSERT_EQUALS(sgImage.Create(imageInfo,bitmap->DataAddress(),bitmap->DataStride()), KErrNone);
103 // launch 2 processes
104 Test_MultiProcessL(KEglTestStepDllName, 2, TestStepName(), sgImage.Id());
107 CleanupStack::PopAndDestroy(2, bitmap);
111 INFO_PRINTF1(_L("Exit: CEglTest_EGL_Image_Multi_Process_Sibling_Basic::doTestStepL"));
113 CloseTMSGraphicsStep();
114 return TestStepResult();
117 void CEglTest_EGL_Image_Multi_Process_Sibling_Basic::doProcessFunctionL(TInt aIdx,const TSgDrawableId& aSgId)
119 INFO_PRINTF2(_L("CEglTest_EGL_Image_Multi_Process_Sibling_Basic::doProcessFunctionL, Process %d"),aIdx);
121 CreateEglSessionL(aIdx);
122 iEglSess->InitializeL();
123 iEglSess->OpenSgDriverL();
125 RSgImage sgImageFromId;
126 CleanupClosePushL(sgImageFromId);
127 ASSERT_EQUALS(sgImageFromId.Open(aSgId),KErrNone);
129 INFO_PRINTF2(_L("Process %d, Creating an EGLImage from the shared RSgImage"),aIdx);
130 EGLImageKHR eglImage = iEglSess->eglCreateImageKhrL(iDisplay, EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, &sgImageFromId, KEglImageAttribsPreservedTrue);
131 ASSERT_EGL_TRUE(eglImage != EGL_NO_IMAGE_KHR);
132 CleanupStack::PopAndDestroy(&sgImageFromId);
134 INFO_PRINTF2(_L("Process %d, EGLImage successfully created, now destroying it"),aIdx);
135 ASSERT_EGL_TRUE(iEglSess->DestroyEGLImage(iDisplay, eglImage));
143 @SYMTestCaseID GRAPHICS-EGL-0161
149 @SYMREQ See SGL.GT0386.401 document
152 Check if EGL Implementation allows two processes to work in parallel.
155 Run two processes that independently perform the same actions detailed below.
156 This test will check for the “VG_KHR_EGL_image” extension, if it is not
157 supported on this platform then the test will return immediately without failure.
158 Create and fully construct an RSgImage object
159 • Set the iUsage bits to ESgUsageBitOpenVgImage
160 Pass the RSgImage object into eglCreateImageKHR() with
161 • The target parameter set to EGL_NATIVE_PIXMAP_KHR
162 • Use the current display and EGL_NO_CONTEXT
163 • Use a NULL attr_list
164 Check that eglCreateImageKHR() does NOT return EGL_NO_IMAGE_KHR
165 Use vgCreateEGLImageTargetKHR() to construct a VGImage object from the EGLImage.
166 • Check for errors (VGInvalidHandle is not returned)
167 Create a second RSgImage, and use it to create a pixmap surface that is
168 compatible as a target for the VGImage to be drawn to.
169 • Set the iUsage bit to ESgUsageBitOpenVgSurface
170 • Use the same pixel format as the RSgImage above.
171 Now that a eglContext and an OpenVG context have been created, use the
172 OpenVG API vgClearImage to clear to a chosen colour the VGImage previously
173 returned by eglCreateImageKHR.
174 Use OpenVG to draw the just drawn VGImage to the pixmap surface currently
175 linked to the context.
176 Call eglWaitClient() to finish the above drawing instructions synchronously.
177 Destroy the original image data
178 • Pass the VGImage into vgDestroyImage()
179 • Pass the EGLImage into eglDestroyImageKHR()
180 • Close the first RSgImage
181 • Check that the pixmap surface contains expected pixel values using
182 OpenVG APIs, vgReadPixels.
183 Close the second RSgImage and destroy the pixmap surface
184 Check for memory and handle leaks
186 @SYMTestExpectedResults
187 Pixmap surface has the expected contents in both processes (within tolerance)
188 No memory or handle leaks
190 TVerdict CEglTest_EGL_Image_Multi_Process_Parallel::doTestStepL()
192 SetTestStepID(_L("GRAPHICS-EGL-0161"));
193 SetTestStepName(KEGL_Image_Multi_Process_Parallel);
194 INFO_PRINTF1(_L("Enter: CEglTest_EGL_Image_Multi_Process_Parallel::doTestStepL"));
196 TBool ret = CheckForExtensionL(KEGL_RSgimage | KEGL_KHR_image_base | KEGL_KHR_image_pixmap | KVG_KHR_EGL_image);
199 // The extension is not supported
201 CloseTMSGraphicsStep();
202 return TestStepResult();
205 // launch 2 processes
206 Test_MultiProcessL(KEglTestStepDllName, 2, TestStepName());
208 INFO_PRINTF1(_L("Exit: CEglTest_EGL_Image_Multi_Process_Parallel::doTestStepL"));
210 CloseTMSGraphicsStep();
211 return TestStepResult();
214 void CEglTest_EGL_Image_Multi_Process_Parallel::doProcessFunctionL(TInt aIdx)
216 INFO_PRINTF2(_L("CEglTest_EGL_Image_Multi_Process_Parallel::doProcessFunctionL, Process %d"),aIdx);
218 CreateEglSessionL(aIdx);
219 iEglSess->InitializeL();
220 iEglSess->OpenSgDriverL();
222 // create a reference bitmap (we give index 3 for example, as there's only 1 image in this test case)
223 TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(KDefaultSourceFormat);
224 CFbsBitmap* bitmap = iEglSess->CreateReferenceBitmapL(bitmapMode, KImageSize, 3);
225 CleanupStack::PushL(bitmap);
227 // Create an RSgImage
228 INFO_PRINTF2(_L("Process %d, Creating a RSgImage having the reference bitmap's content"),aIdx);
229 TSgImageInfoOpenVgImage imageInfo = TSgImageInfoOpenVgImage(KDefaultSourceFormat, KImageSize);
230 RSgImage rSgImageLocal;
231 CleanupClosePushL(rSgImageLocal);
232 ASSERT_EQUALS(rSgImageLocal.Create(imageInfo,bitmap->DataAddress(),bitmap->DataStride()), KErrNone);
234 INFO_PRINTF2(_L("Process %d, Creating an EGLImage from the shared RSgImage"),aIdx);
235 EGLImageKHR eglImageLocal = iEglSess->eglCreateImageKhrL(iDisplay, EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, &rSgImageLocal, KEglImageAttribsPreservedTrue);
236 ASSERT_EGL_TRUE(eglImageLocal != EGL_NO_IMAGE_KHR);
237 CleanupStack::PopAndDestroy(&rSgImageLocal); //transferring ownership of the buffer to the EGLImage
238 CleanupStack::PopAndDestroy(bitmap);
240 INFO_PRINTF2(_L("Process %d, Creating a Surface and a Context bound to OpenVG"),aIdx);
241 TUidPixelFormat pixelFormat = EglTestConversion::VgFormatToSgPixelFormat(KDefaultSurfaceFormat);
242 TSgImageInfoOpenVgTarget imageInfo2 = TSgImageInfoOpenVgTarget(pixelFormat, KImageSize);
243 // Create a pixmap surface matching the native image pixel format
244 iEglSess->CreatePixmapSurfaceAndMakeCurrentAndMatchL(imageInfo2,CTestEglSession::EResourceCloseSgImageEarly);
246 INFO_PRINTF2(_L("Process %d, Creating one VGImage from the EGLImage"),aIdx);
247 VGImage vgImageLocal = iEglSess->vgCreateImageTargetKHR((VGeglImageKHR)eglImageLocal);
248 ASSERT_VG_TRUE(vgImageLocal != VG_INVALID_HANDLE);
249 ASSERT_EGL_TRUE(iEglSess->DestroyEGLImage(iDisplay, eglImageLocal));
251 // Copy the source VGImage to the surface
252 vgSetPixels(0, 0, vgImageLocal, 0, 0, KImageSize.iWidth, KImageSize.iHeight);
253 ASSERT_TRUE(vgGetError()==VG_NO_ERROR);
257 vgDestroyImage(vgImageLocal);
258 ASSERT_TRUE(vgGetError()==VG_NO_ERROR);
260 // we can now compare the VgImage to the one we would expect for this particular process
261 CFbsBitmap* refBitmap = iEglSess->CreateReferenceBitmapL(bitmapMode, KImageSize, 3);
262 CleanupStack::PushL(refBitmap);
263 iEglSess->CheckVgDrawingL(KDefaultSurfaceFormat, refBitmap);
264 CleanupStack::PopAndDestroy(refBitmap);
265 INFO_PRINTF2(_L("Drawing successful, Process %d"),aIdx);
272 @SYMTestCaseID GRAPHICS-EGL-0162
278 @SYMREQ See SGL.GT0386.401 document
281 Check if EGL Implementation allows two processes to work in parallel.
282 A process can create an EGLImage from the same RSgImage that already has been linked to an EGLImage by another process.
283 Both process can create a VGImage from it.
284 Another process uses the VGImage as a target
285 One process uses the VGImage as a source being able to see the drawing done by the other process
288 Main Process: creates an RsgImage and starts Process and Process.
289 Process1: Creates an egl context and a pizmap surface linked to it. Creates an EGLImage from the RsgImage previous mentioned. Creates a VGImage from the EGLImage.
290 Process2: Creates an egl context and a pizmap surface linked to it. Creates an EGLImage from the RsgImage previous mentioned. Creates a VGImage from the EGLImage.
291 Process1: Changes the contents of the VGImage
293 Process1: Closes the VGImage and the EGLImage
294 Process2: Draws the VGImage to the surface and checks if the contets match the reference bitmap plus the chages made by the first process.
295 Process2: Closes the VGImage and the EGLImage
296 Main Process: Closes the RsgImage
298 @SYMTestExpectedResults
299 No errors within both processes.
300 The content of the pixmap surface will match the one of the reference bitmap changed by the first process.
301 No memory or handle leaks.
303 TVerdict CEglTest_EGL_Image_Multi_Process_Sibling_CheckContents::doTestStepL()
305 SetTestStepID(_L("GRAPHICS-EGL-0162"));
306 SetTestStepName(KEGL_Image_Multi_Process_Sibling_CheckContents);
307 INFO_PRINTF1(_L("Enter: CEglTest_EGL_Image_Multi_Process_Sibling_CheckContents::doTestStepL"));
309 TBool ret = CheckForExtensionL(KEGL_RSgimage | KEGL_KHR_image_base | KEGL_KHR_image_pixmap | KVG_KHR_EGL_image);
312 // The extension is not supported
314 CloseTMSGraphicsStep();
315 return TestStepResult();
318 // Create display object
319 ASSERT_TRUE(iDisplay == EGL_NO_DISPLAY);
322 iEglSess->InitializeL();
323 iEglSess->OpenSgDriverL();
325 // create a reference bitmap (we give index 0, as there's only 1 image in this test case)
326 TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(KDefaultSourceFormat);
327 CFbsBitmap* bitmap = iEglSess->CreateReferenceBitmapL(bitmapMode, KImageSize, 0);
328 CleanupStack::PushL(bitmap);
330 // Create an RSgImage
331 TSgImageInfoOpenVgImage imageInfo = TSgImageInfoOpenVgImage(KDefaultSourceFormat, KImageSize);
332 #ifndef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
333 imageInfo.iShareable = ETrue;
334 #endif //SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
336 CleanupClosePushL(sgImage);
337 ASSERT_EQUALS(sgImage.Create(imageInfo,bitmap->DataAddress(),bitmap->DataStride()), KErrNone);
339 // launch 2 processes
340 Test_MultiProcessL(KEglTestStepDllName, 2, TestStepName(), sgImage.Id());
343 CleanupStack::PopAndDestroy(&sgImage);
344 CleanupStack::PopAndDestroy(bitmap);
348 INFO_PRINTF1(_L("Exit: CEglTest_EGL_Image_Multi_Process_Sibling_CheckContents::doTestStepL"));
350 CloseTMSGraphicsStep();
351 return TestStepResult();
354 void CEglTest_EGL_Image_Multi_Process_Sibling_CheckContents::doProcessFunctionL(TInt aIdx,const TSgDrawableId& aSgId)
356 INFO_PRINTF2(_L("CEglTest_EGL_Image_Multi_Process_Sibling_CheckContents::doProcessFunctionL, Process %d"),aIdx);
358 CreateEglSessionL(aIdx);
359 iEglSess->InitializeL();
360 iEglSess->OpenSgDriverL();
362 RSgImage sgImageFromId;
363 CleanupClosePushL(sgImageFromId);
364 ASSERT_EQUALS(sgImageFromId.Open(aSgId),KErrNone);
366 INFO_PRINTF2(_L("Process %d, Creating an EGLImage from the shared RSgImage"),aIdx);
367 EGLImageKHR eglImageLocal = iEglSess->eglCreateImageKhrL(iDisplay, EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, &sgImageFromId, KEglImageAttribsPreservedTrue);
368 ASSERT_EGL_TRUE(eglImageLocal != EGL_NO_IMAGE_KHR);
369 CleanupStack::PopAndDestroy(&sgImageFromId);
371 INFO_PRINTF2(_L("Process %d, Creating a Surface and a Context bound to OpenVG"),aIdx);
372 TUidPixelFormat pixelFormat = EglTestConversion::VgFormatToSgPixelFormat(KDefaultSurfaceFormat);
373 TSgImageInfoOpenVgTarget imageInfo = TSgImageInfoOpenVgTarget(pixelFormat, KImageSize);
374 // Create a pixmap surface matching the native image pixel format
375 iEglSess->CreatePixmapSurfaceAndMakeCurrentAndMatchL(imageInfo,CTestEglSession::EResourceCloseSgImageEarly);
377 INFO_PRINTF2(_L("Process %d, Creating one VGImage from the EGLImage"),aIdx);
378 VGImage vgImageLocal = iEglSess->vgCreateImageTargetKHR((VGeglImageKHR)eglImageLocal);
379 ASSERT_VG_TRUE(vgImageLocal != VG_INVALID_HANDLE);
380 ASSERT_EGL_TRUE(iEglSess->DestroyEGLImage(iDisplay, eglImageLocal));
384 TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(KDefaultSourceFormat);
385 CFbsBitmap* bitmap = iEglSess->CreateReferenceBitmapL(bitmapMode, KImageSize, 4);
386 // Add pixel data to the VGImage reference from the bitmap reference.
387 // Mind the fact that CFbsBitmap and VGImages use different coordinates origin!
388 TSize bitmapSize = bitmap->SizeInPixels();
389 TUint8* address = reinterpret_cast<TUint8*>(bitmap->DataAddress());
390 TInt stride = bitmap->DataStride();
391 address += (bitmapSize.iHeight - 1) * stride;
392 vgImageSubData(vgImageLocal, address, -stride, KDefaultSurfaceFormat, 0,0, bitmapSize.iWidth, bitmapSize.iHeight);
395 ASSERT_TRUE(vgGetError()==VG_NO_ERROR);
399 // Wait for both processes to reach this point (process 0 will have updated the VGImage)
404 INFO_PRINTF2(_L("Process %d, Drawing the VGImage to the current surface"),aIdx);
405 // Copy the source VGImage to the surface
406 vgSetPixels(0, 0, vgImageLocal, 0, 0, KImageSize.iWidth, KImageSize.iHeight);
407 ASSERT_TRUE(vgGetError()==VG_NO_ERROR);
410 // we can now compare the VgImage to the one we expect after changing it in the other process
411 TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(KDefaultSourceFormat);
412 CFbsBitmap* refBitmap = iEglSess->CreateReferenceBitmapL(bitmapMode, KImageSize, 4);
413 CleanupStack::PushL(refBitmap);
414 iEglSess->CheckVgDrawingL(KDefaultSurfaceFormat, refBitmap);
415 CleanupStack::PopAndDestroy(refBitmap);
416 INFO_PRINTF2(_L("Process %d, Drawing successful"),aIdx);
420 vgDestroyImage(vgImageLocal);
421 ASSERT_TRUE(vgGetError()==VG_NO_ERROR);
428 @SYMTestCaseID GRAPHICS-EGL-0350
435 Check sharing SgImage between 2 processes where a writer process populates SgImage through VgImage and a reader process draws SgImage to window surface.
438 Main Process: starts Process1 and Process2.
439 Process1: Creates an RsgImage and passes RsgImage ID to process2. Creates an egl context and a pixmap surface linked to it. Creates an EGLImage from the RsgImage previous mentioned. Creates a VGImage from the EGLImage.
440 Process2: Creates an RsgImage using RsgImage ID passed into it. Creates an egl context and a pixmap surface linked to it. Creates an EGLImage from the RsgImage previous mentioned. Creates a VGImage from the EGLImage.
442 Process2: Draws the VGImage to the surface before Process1 changes the contents of the VGImage.
444 Process1: Changes the contents of the VGImage
446 Process2: Draws the VGImage to the surface after Process1 changes the contents of the VGImage and checks if the contets match the reference bitmap plus the chages made by the process1.
447 Process1: Closes the VGImage, the EGLImage, the RsgImage.
448 Process2: Closes the VGImage, the EGLImage, the RsgImage.
450 @SYMTestExpectedResults
451 No errors within both processes.
452 The content of the pixmap surface will match the one of the reference bitmap changed by the first process.
453 No memory or handle leaks.
455 TVerdict CEglTest_EGL_Image_Multi_Process_VgImage_Source::doTestStepL()
457 SetTestStepID(_L("GRAPHICS-EGL-0350"));
458 SetTestStepName(KEGL_Image_Multi_Process_VgImage_Source);
459 INFO_PRINTF1(_L("Enter: CEglTest_EGL_Image_Multi_Process_VgImage_Source::doTestStepL"));
461 TBool ret = CheckForExtensionL(KEGL_RSgimage | KEGL_KHR_image_base | KEGL_KHR_image_pixmap | KVG_KHR_EGL_image);
464 // The extension is not supported
466 CloseTMSGraphicsStep();
467 return TestStepResult();
470 // launch 2 processes
471 Test_MultiProcessL(KEglTestStepDllName, 2, TestStepName());
473 INFO_PRINTF1(_L("Exit: CEglTest_EGL_Image_Multi_Process_VgImage_Source::doTestStepL"));
475 CloseTMSGraphicsStep();
476 return TestStepResult();
479 void CEglTest_EGL_Image_Multi_Process_VgImage_Source::doProcessFunctionL(TInt aIdx)
481 INFO_PRINTF2(_L("CEglTest_EGL_Image_Multi_Process_VgImage_Source::doProcessFunctionL, Process %d"),aIdx);
483 CreateEglSessionL(aIdx);
484 iEglSess->InitializeL();
485 iEglSess->OpenSgDriverL();
487 RMsgQueue<TSgDrawableId> messageQueue;
488 User::LeaveIfError(messageQueue.Open(EProcSlotMsgQueueSgId, EOwnerProcess));
489 CleanupClosePushL(messageQueue);
491 RSgImage rSgImageLocal;
494 // create a reference bitmap (we give index 0, as there's only 1 image in this test case)
495 TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(KDefaultSourceFormat);
496 CFbsBitmap* bitmap = iEglSess->CreateReferenceBitmapL(bitmapMode, KImageSize, 0);
497 CleanupStack::PushL(bitmap);
499 // Create an RSgImage
500 INFO_PRINTF2(_L("Process %d, Creating a RSgImage having the reference bitmap's content"),aIdx);
501 TSgImageInfoOpenVgImage imageInfo = TSgImageInfoOpenVgImage(KDefaultSourceFormat, KImageSize);
502 #ifndef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
503 imageInfo.iShareable = ETrue;
505 ASSERT_EQUALS(rSgImageLocal.Create(imageInfo,bitmap->DataAddress(),bitmap->DataStride()), KErrNone);
506 CleanupStack::PopAndDestroy(bitmap);
508 INFO_PRINTF2(_L("Process %d, Sending SgImage ID to other process..."), aIdx);
509 messageQueue.SendBlocking(rSgImageLocal.Id());
513 INFO_PRINTF2(_L("Process %d, Receiving SgImage ID from other process..."), aIdx);
514 TSgDrawableId sgImageId;
515 messageQueue.ReceiveBlocking(sgImageId);
516 ASSERT_EQUALS(rSgImageLocal.Open(sgImageId), KErrNone);
519 // Wait for both processes to reach this point
522 INFO_PRINTF2(_L("Process %d, Creating an EGLImage from the shared RSgImage"),aIdx);
523 CleanupClosePushL(rSgImageLocal);
524 EGLImageKHR eglImageLocal = iEglSess->eglCreateImageKhrL(iDisplay, EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, &rSgImageLocal, KEglImageAttribsPreservedTrue);
525 ASSERT_EGL_TRUE(eglImageLocal != EGL_NO_IMAGE_KHR);
526 CleanupStack::PopAndDestroy(&rSgImageLocal); //transferring ownership of the buffer to the EGLImage
528 INFO_PRINTF2(_L("Creating a Surface and a Context bound to OpenVG, Process %d"),aIdx);
529 TUidPixelFormat pixelFormat = EglTestConversion::VgFormatToSgPixelFormat(KDefaultSurfaceFormat);
530 TSgImageInfoOpenVgTarget imageInfo = TSgImageInfoOpenVgTarget(pixelFormat, KImageSize);
531 // Create a pixmap surface matching the native image pixel format
532 iEglSess->CreatePixmapSurfaceAndMakeCurrentAndMatchL(imageInfo,CTestEglSession::EResourceCloseSgImageEarly);
534 INFO_PRINTF2(_L("Process %d, Creating one VGImage from the EGLImage"),aIdx);
535 VGImage vgImageLocal = iEglSess->vgCreateImageTargetKHR((VGeglImageKHR)eglImageLocal);
536 ASSERT_VG_TRUE(vgImageLocal != VG_INVALID_HANDLE);
537 ASSERT_EGL_TRUE(iEglSess->DestroyEGLImage(iDisplay, eglImageLocal));
541 INFO_PRINTF2(_L("Process %d, Drawing the VGImage to the current surface before changing contents of the VGImage"),aIdx);
542 // Copy the source VGImage to the surface
543 vgSetPixels(0, 0, vgImageLocal, 0, 0, KImageSize.iWidth, KImageSize.iHeight);
544 ASSERT_TRUE(vgGetError()==VG_NO_ERROR);
547 // we can now compare the VgImage to the one we expect before we apply any change to it
548 TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(KDefaultSourceFormat);
549 CFbsBitmap* refBitmap = iEglSess->CreateReferenceBitmapL(bitmapMode, KImageSize, 0);
550 CleanupStack::PushL(refBitmap);
551 iEglSess->CheckVgDrawingL(KDefaultSurfaceFormat, refBitmap);
552 CleanupStack::PopAndDestroy(refBitmap);
553 INFO_PRINTF2(_L("Process %d, Drawing successful"),aIdx);
556 // Wait for both processes to reach this point
561 INFO_PRINTF2(_L("Process %d, Changing contents of the VGImage"),aIdx);
562 TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(KDefaultSourceFormat);
563 CFbsBitmap* bitmap = iEglSess->CreateReferenceBitmapL(bitmapMode, KImageSize, 4);
564 // Add pixel data to the VGImage reference from the bitmap reference.
565 // Mind the fact that CFbsBitmap and VGImages use different coordinates origin!
566 TSize bitmapSize = bitmap->SizeInPixels();
567 TUint8* address = reinterpret_cast<TUint8*>(bitmap->DataAddress());
568 TInt stride = bitmap->DataStride();
569 address += (bitmapSize.iHeight - 1) * stride;
570 vgImageSubData(vgImageLocal, address, -stride, KDefaultSurfaceFormat, 0,0, bitmapSize.iWidth, bitmapSize.iHeight);
573 ASSERT_TRUE(vgGetError()==VG_NO_ERROR);
577 // Wait for both processes to reach this point (process 0 will have updated the VGImage)
582 INFO_PRINTF2(_L("Drawing the VGImage to the current surface after changing contents of the VGImage, Process %d"),aIdx);
583 // Copy the source VGImage to the surface
584 vgSetPixels(0, 0, vgImageLocal, 0, 0, KImageSize.iWidth, KImageSize.iHeight);
585 ASSERT_TRUE(vgGetError()==VG_NO_ERROR);
588 // we can now compare the VgImage to the one we expect after changing it in the other process
589 TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(KDefaultSourceFormat);
590 CFbsBitmap* refBitmap = iEglSess->CreateReferenceBitmapL(bitmapMode, KImageSize, 4);
591 CleanupStack::PushL(refBitmap);
592 iEglSess->CheckVgDrawingL(KDefaultSurfaceFormat, refBitmap);
593 CleanupStack::PopAndDestroy(refBitmap);
594 INFO_PRINTF2(_L("Process %d, Drawing successful"),aIdx);
597 vgDestroyImage(vgImageLocal);
598 ASSERT_TRUE(vgGetError() == VG_NO_ERROR);
600 CleanupStack::PopAndDestroy(&messageQueue);
605 @SYMTestCaseID GRAPHICS-EGL-0351
612 Check when sharing SgImage between 2 processes where a writer process populates SgImage through VgImage and a reader process draws SgImage to window surface,
613 process2 has reference to SgImage even after process1 loses all references to SgImage
616 Main Process: starts Process1 and Process2.
617 Process1: Creates an RsgImage and passes RsgImage ID to process2. Creates an egl context and a pixmap surface linked to it. Creates an EGLImage from the RsgImage previous mentioned. Creates a VGImage from the EGLImage.
618 Process2: Creates an RsgImage using RsgImage ID passed into it. Creates an egl context and a pixmap surface linked to it. Creates an EGLImage from the RsgImage previous mentioned. Creates a VGImage from the EGLImage.
619 Process2: Drawss the VGImage to the surface before Process1 changes the contents of the VGImage.
621 Process1: Changes the contents of the VGImage
622 Process1: Closes the VGImage, the EGLImage, the RsgImage.
624 Process2: Draws the VGImage to the surface after Process1 changes the contents of the VGImage and checks if the contents match the reference bitmap plus the changes made by the process1.
625 Process2: Closes the VGImage, the EGLImage, the RsgImage.
627 @SYMTestExpectedResults
628 No errors within both processes.
629 The content of the pixmap surface will match the one of the reference bitmap changed by the process1.
630 No memory or handle leaks.
632 TVerdict CEglTest_EGL_Image_Multi_Process_VgImage_DrawAfterTerminate::doTestStepL()
634 SetTestStepID(_L("GRAPHICS-EGL-0351"));
635 SetTestStepName(KEGL_Image_Multi_Process_VgImage_DrawAfterTerminate);
636 INFO_PRINTF1(_L("Enter: CEglTest_EGL_Image_Multi_Process_VgImage_DrawAfterTerminate::doTestStepL"));
638 TBool ret = CheckForExtensionL(KEGL_RSgimage | KEGL_KHR_image_base | KEGL_KHR_image_pixmap | KVG_KHR_EGL_image);
641 // The extension is not supported
643 CloseTMSGraphicsStep();
644 return TestStepResult();
647 // This test is performed for default pixel format
648 PrintUsedPixelConfiguration();
650 // launch 2 processes
651 Test_MultiProcessL(KEglTestStepDllName, 2, TestStepName());
653 INFO_PRINTF1(_L("Exit: CEglTest_EGL_Image_Multi_Process_VgImage_DrawAfterTerminate::doTestStepL"));
655 CloseTMSGraphicsStep();
656 return TestStepResult();
659 void CEglTest_EGL_Image_Multi_Process_VgImage_DrawAfterTerminate::doProcessFunctionL(TInt aIdx)
661 INFO_PRINTF2(_L("CEglTest_EGL_Image_Multi_Process_VgImage_DrawAfterTerminate::doProcessFunctionL, Process %d"),aIdx);
663 CreateEglSessionL(aIdx);
664 iEglSess->InitializeL();
665 iEglSess->OpenSgDriverL();
667 RMsgQueue<TSgDrawableId> messageQueue;
668 User::LeaveIfError(messageQueue.Open(EProcSlotMsgQueueSgId, EOwnerProcess));
669 CleanupClosePushL(messageQueue);
671 RSgImage rSgImageLocal;
674 // create a reference bitmap (we give index 0, as there's only 1 image in this test case)
675 TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(KDefaultSourceFormat);
676 CFbsBitmap* bitmap = iEglSess->CreateReferenceBitmapL(bitmapMode, KImageSize, 0);
677 CleanupStack::PushL(bitmap);
679 // Create an RSgImage
680 INFO_PRINTF2(_L("Process %d, Creating a RSgImage having the reference bitmap's content"),aIdx);
681 TSgImageInfoOpenVgImage imageInfo = TSgImageInfoOpenVgImage(KDefaultSourceFormat, KImageSize);
682 #ifndef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
683 imageInfo.iShareable = ETrue;
685 ASSERT_EQUALS(rSgImageLocal.Create(imageInfo,bitmap->DataAddress(),bitmap->DataStride()), KErrNone);
686 CleanupStack::PopAndDestroy(bitmap);
688 INFO_PRINTF2(_L("Process %d, Sending SgImage ID to other process..."), aIdx);
689 messageQueue.SendBlocking(rSgImageLocal.Id());
693 INFO_PRINTF2(_L("Process %d: Receiving SgImage ID from other process..."), aIdx);
694 TSgDrawableId sgImageId;
695 messageQueue.ReceiveBlocking(sgImageId);
696 ASSERT_EQUALS(rSgImageLocal.Open(sgImageId),KErrNone);
699 // Wait for both processes to reach this point
702 INFO_PRINTF2(_L("Process %d, Creating an EGLImage from the shared RSgImage"),aIdx);
703 CleanupClosePushL(rSgImageLocal);
704 EGLImageKHR eglImageLocal = iEglSess->eglCreateImageKhrL(iDisplay, EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, &rSgImageLocal, KEglImageAttribsPreservedTrue);
705 ASSERT_EGL_TRUE(eglImageLocal != EGL_NO_IMAGE_KHR);
706 CleanupStack::PopAndDestroy(&rSgImageLocal); //transferring ownership of the buffer to the EGLImage
708 INFO_PRINTF2(_L("Creating a Surface and a Context bound to OpenVG, Process %d"),aIdx);
709 TUidPixelFormat pixelFormat = EglTestConversion::VgFormatToSgPixelFormat(KDefaultSurfaceFormat);
710 TSgImageInfoOpenVgTarget imageInfo = TSgImageInfoOpenVgTarget(pixelFormat, KImageSize);
711 // Create a pixmap surface matching the native image pixel format
712 iEglSess->CreatePixmapSurfaceAndMakeCurrentAndMatchL(imageInfo,CTestEglSession::EResourceCloseSgImageEarly);
714 INFO_PRINTF2(_L("Process %d, Creating one VGImage from the EGLImage"),aIdx);
715 VGImage vgImageLocal = iEglSess->vgCreateImageTargetKHR((VGeglImageKHR)eglImageLocal);
716 ASSERT_VG_TRUE(vgImageLocal != VG_INVALID_HANDLE);
717 ASSERT_EGL_TRUE(iEglSess->DestroyEGLImage(iDisplay, eglImageLocal));
721 INFO_PRINTF2(_L("Process %d, Drawing the VGImage to the current surface before changing contents of the VGImage"),aIdx);
722 // Copy the source VGImage to the surface
723 vgSetPixels(0, 0, vgImageLocal, 0, 0, KImageSize.iWidth, KImageSize.iHeight);
724 ASSERT_TRUE(vgGetError()==VG_NO_ERROR);
728 // we can now compare the VgImage to the one we expect before we apply any change to it
729 TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(KDefaultSourceFormat);
730 CFbsBitmap* refBitmap = iEglSess->CreateReferenceBitmapL(bitmapMode, KImageSize, 0);
731 CleanupStack::PushL(refBitmap);
732 iEglSess->CheckVgDrawingL(KDefaultSurfaceFormat, refBitmap);
733 CleanupStack::PopAndDestroy(refBitmap);
734 INFO_PRINTF2(_L("Process %d, Drawing successful"),aIdx);
737 // Wait for both processes to reach this point
742 INFO_PRINTF2(_L("Process %d, Changing contents of the VGImage"),aIdx);
743 TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(KDefaultSourceFormat);
744 CFbsBitmap* bitmap = iEglSess->CreateReferenceBitmapL(bitmapMode, KImageSize, 2);
745 // Add pixel data to the VGImage reference from the bitmap reference.
746 // Mind the fact that CFbsBitmap and VGImages use different coordinates origin!
747 TSize bitmapSize = bitmap->SizeInPixels();
748 TUint8* address = reinterpret_cast<TUint8*>(bitmap->DataAddress());
749 TInt stride = bitmap->DataStride();
750 address += (bitmapSize.iHeight - 1) * stride;
751 vgImageSubData(vgImageLocal, address, -stride, KDefaultSurfaceFormat, 0,0, bitmapSize.iWidth, bitmapSize.iHeight);
754 ASSERT_TRUE(vgGetError()==VG_NO_ERROR);
757 vgDestroyImage(vgImageLocal);
758 ASSERT_TRUE(vgGetError() == VG_NO_ERROR);
759 CleanupStack::PopAndDestroy(&messageQueue);
763 // Wait for both processes to reach this point
768 INFO_PRINTF2(_L("Drawing the VGImage to the current surface after changing contents of the VGImage, Process %d"),aIdx);
769 // Copy the source VGImage to the surface
770 vgSetPixels(0, 0, vgImageLocal, 0, 0, KImageSize.iWidth, KImageSize.iHeight);
771 ASSERT_TRUE(vgGetError()==VG_NO_ERROR);
774 // we can now compare the VgImage to the one we expect after changing it in the other process
775 TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(KDefaultSourceFormat);
776 CFbsBitmap* refBitmap = iEglSess->CreateReferenceBitmapL(bitmapMode, KImageSize, 2);
777 CleanupStack::PushL(refBitmap);
778 iEglSess->CheckVgDrawingL(KDefaultSurfaceFormat, refBitmap);
779 CleanupStack::PopAndDestroy(refBitmap);
780 INFO_PRINTF2(_L("Process %d, Drawing successful"),aIdx);
782 vgDestroyImage(vgImageLocal);
783 ASSERT_TRUE(vgGetError() == VG_NO_ERROR);
785 CleanupStack::PopAndDestroy(&messageQueue);
791 @SYMTestCaseID GRAPHICS-EGL-0406
798 To ensure that RSgImage with uploaded data can be shared across processes.
799 To ensure that reference counting of RSgImage works correctly.
802 From the main process:
803 - Create M SgImage(s) with the flag ESgUsageBitOpenVgImage. The size are all the same.
804 We are running through all the possible configurations, with the values assumed being:
805 • EUidPixelFormatRGB_565
806 • EUidPixelFormatXRGB_8888
807 • EUidPixelFormatARGB_8888 (source only)
808 • EUidPixelFormatARGB_8888_PRE
809 • EUidPixelFormatA_8 (source only)
810 - Note that when using EUidPixelFormatA_8 as a source, the reference bitmap display mode used is EGray256,
811 This is to enable using the reference bitmap as an alpha mask.
812 - Spawn N client processes. During the process launching, pass to each process single drawable ID from the SgImages.
813 In order to define which SgImage needs to be passed to the particular process, there will be following
814 formula applied: J = P Mod (M), where J is the sequence number of the image, P is the particular process number.
815 From processes 1 to N:
816 - Open SgImage by using TSgDrawableId, obtained from the SgImage which was passed from the process A.
817 - Using EGL extension, create EGLImage specifying as EGLClientBuffer SgImage which was created on
818 previous step, EGL_NATIVE_PIXMAP_KHR as a target and EGL_IMAGE_PRESERVED_KHR as an attribute
819 - Using VG extension, create VG image based on EGLImage from the previous step.
820 - Close Sg and EGL images
821 - Create second SgImage with the same size and pixel format as first SgImage and usage flag is set to ESgUsageBitOpenVgSurface.
822 - Create off-screen pixmap surface with underlining second SgImage and make it current for the drawing context.
823 - Draw VGImage to the off-screen surface (note that when using EUidPixelFormatA_8 as a source, the
824 reference bitmap is used as an alpha mask).
825 - Draw VGImage to the off-screen surface.
826 - Retrieve surface data (see vgReadPixels() API)
828 @SYMTestExpectedResults
829 Creation of all drawable resources have been completed without errors.
830 Image data obtained in client processes 1-N matches to the data which have been uploaded to the SgImages buffer from
831 process A. Reference counting works correctly and keeps VG image alive although bound Sg and EGL images have been destroyed.
832 When all resources are closed, resource count maintained by RSgDriver extension is zero in all processes.
834 TVerdict CEglTest_EGL_Image_Multi_Process_FontServer_Upfront::doTestStepL()
836 SetTestStepID(_L("GRAPHICS-EGL-0406"));
837 SetTestStepName(KEGL_Image_Multi_Process_FontServer_Upfront);
838 INFO_PRINTF1(_L("CEglTest_EGL_Image_Multi_Process_FontServer_Upfront::doTestStepL"));
840 TBool ret = CheckForExtensionL(KEGL_RSgimage | KEGL_KHR_image_base | KEGL_KHR_image_pixmap | KVG_KHR_EGL_image);
843 // The extension is not supported
845 CloseTMSGraphicsStep();
846 return TestStepResult();
849 CEglTestCommonIniSettings* iniParser = CEglTestCommonIniSettings::NewL();
850 CleanupStack::PushL(iniParser);
852 TInt numPixmapSgSurfaceFormats = iniParser->GetNumberOfFormats(KSectionPixmapSgSurfaceFormats);
853 TInt numImageSourceFormats = iniParser->GetNumberOfFormats(KSectionImageSourceFormats);
854 if(!numImageSourceFormats && !numPixmapSgSurfaceFormats)
856 ERR_PRINTF1(_L("No formats to iterate through"));
857 User::Leave(KErrArgument);
859 for(TUint j=0; j < numPixmapSgSurfaceFormats; j++)
861 iSurfaceFormat = iniParser->GetVgFormat(KSectionPixmapSgSurfaceFormats,j);
862 for(TUint i=0; i < numImageSourceFormats; i++)
864 iSourceFormat = iniParser->GetPixelFormat(KSectionImageSourceFormats,i);
865 if (iSourceFormat == EUidPixelFormatARGB_8888 && (iSurfaceFormat == VG_sARGB_8888_PRE || iSurfaceFormat == VG_sARGB_8888))
867 // Don't perform the test for this particular format combination
868 // Causes issues converting pixel values from non-pre to pre
871 #ifndef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
872 // A_8 related tests are only performed for SgImage-Lite
873 if (iSourceFormat == EUidPixelFormatA_8)
876 doTestPartialStepL();
880 CleanupStack::PopAndDestroy(iniParser);
882 CloseTMSGraphicsStep();
883 return TestStepResult();
886 TVerdict CEglTest_EGL_Image_Multi_Process_FontServer_Upfront::doTestPartialStepL()
888 INFO_PRINTF1(_L("CEglTest_EGL_Image_Multi_Process_FontServer_Upfront::doTestPartialStepL"));
889 PrintUsedPixelConfiguration();
891 // Create display object
892 ASSERT_TRUE(iDisplay == EGL_NO_DISPLAY);
895 iEglSess->InitializeL();
896 iEglSess->OpenSgDriverL();
898 // list to maintain TSgDrawableId
899 RArray<TSgDrawableId> sgIdList;
900 CleanupClosePushL(sgIdList);
901 RSgImage sgImages[KNumImages];
903 INFO_PRINTF2(_L("MAIN PROCESS: Creating %d RSgImage(s)..."), KNumImages);
904 for (TInt i=0; i<KNumImages; i++)
906 TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(iSourceFormat);
907 CFbsBitmap* bitmap = iEglSess->CreateReferenceBitmapL(bitmapMode, KImageSize, i);
908 CleanupStack::PushL(bitmap);
910 TSgImageInfoOpenVgImage imageInfo = TSgImageInfoOpenVgImage(iSourceFormat, KImageSize);
911 #ifndef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
912 imageInfo.iShareable = ETrue;
914 ASSERT_EQUALS(sgImages[i].Create(imageInfo, bitmap->DataAddress(), bitmap->DataStride()), KErrNone);
915 CleanupClosePushL(sgImages[i]);
916 ASSERT_EQUALS(sgIdList.Insert(sgImages[i].Id(),i), KErrNone);
919 INFO_PRINTF2(_L("MAIN PROCESS: About to launch %d processes..."), KNumProcesses);
920 Test_MultiProcessL(KEglTestStepDllName, KNumProcesses, TestStepName(), sgIdList); //the function will guarantee that all images will be opened before it returns
921 CleanupStack::PopAndDestroy(2 * KNumImages + 1, &sgIdList); // KNumImages SgImages, KNumImages bitmaps, sgIdList
922 INFO_PRINTF2(_L("MAIN PROCESS: All %d launched processes have completed!"), KNumProcesses);
925 INFO_PRINTF1(_L("End of CEglTest_EGL_Image_Multi_Process_FontServer_Upfront::doTestPartialStepL"));
926 return TestStepResult();
929 void CEglTest_EGL_Image_Multi_Process_FontServer_Upfront::doProcessFunctionL(TInt aIdx,const TSgDrawableId& aSgId)
931 INFO_PRINTF2(_L("CEglTest_EGL_Image_Multi_Process_FontServer_Upfront::doProcessFunctionL, Process %d"),aIdx);
933 CreateEglSessionL(aIdx);
934 iEglSess->InitializeL();
935 iEglSess->OpenSgDriverL();
937 //Retrieve source formats for the launched process from the process parameters.
938 User::LeaveIfError(User::GetTIntParameter(EProcSlotSourceFormat, reinterpret_cast<TInt&>(iSourceFormat)));
939 User::LeaveIfError(User::GetTIntParameter(EProcSlotSurfaceFormat, reinterpret_cast<TInt&>(iSurfaceFormat)));
941 RSgImage sgImageFromId;
942 CleanupClosePushL(sgImageFromId);
943 ASSERT_EQUALS(sgImageFromId.Open(aSgId), KErrNone);
945 INFO_PRINTF2(_L("Process %d, Creating an EGLImage from the shared RSgImage"),aIdx);
946 EGLImageKHR eglImage = iEglSess->eglCreateImageKhrL(iDisplay, EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, &sgImageFromId, KEglImageAttribsPreservedTrue);
947 ASSERT_EGL_TRUE(eglImage != EGL_NO_IMAGE_KHR);
948 CleanupStack::PopAndDestroy(&sgImageFromId);
950 INFO_PRINTF2(_L("Process %d, Creating a Surface and a Context bound to OpenVG"),aIdx);
951 TUidPixelFormat pixelFormat = EglTestConversion::VgFormatToSgPixelFormat(iSurfaceFormat);
952 TSgImageInfoOpenVgTarget imageInfo = TSgImageInfoOpenVgTarget(pixelFormat, KImageSize);
953 // Create a pixmap surface matching the native image pixel format
954 iEglSess->CreatePixmapSurfaceAndMakeCurrentAndMatchL(imageInfo,CTestEglSession::EResourceCloseSgImageEarly);
956 INFO_PRINTF2(_L("Process %d, Creating one VGImage from the EGLImage"),aIdx);
957 VGImage vgImage = iEglSess->vgCreateImageTargetKHR((VGeglImageKHR)eglImage);
958 ASSERT_VG_TRUE(vgImage != VG_INVALID_HANDLE);
959 ASSERT_EGL_TRUE(iEglSess->DestroyEGLImage(iDisplay, eglImage));
961 // At this point we draw the VGImage created from the SgImage to the current surface.
962 // # if the source is a A_8, the VGImage acts as a mask and the target surface must contain
963 // as a result the pen colour set above blended with the mask
964 // # otherwise, drawing the VGImage is just a simple copy via vgSetPixels (no blending required)
965 INFO_PRINTF1(_L("Copying the VGImage to the surface"));
966 if (iSourceFormat == EUidPixelFormatA_8)
968 // clear surface background
969 VGfloat bgColor[] = {0.0, 0.0, 0.0, 1.0}; // opaque black
970 vgSetfv(VG_CLEAR_COLOR, 4, bgColor);
971 vgClear(0, 0, KImageSize.iWidth, KImageSize.iHeight);
972 ASSERT_EGL_TRUE(vgGetError() == VG_NO_ERROR);
975 VGPaint fillPaint = vgCreatePaint();
976 vgSetPaint(fillPaint, VG_FILL_PATH);
977 ASSERT_EGL_TRUE(vgGetError() == VG_NO_ERROR);
978 vgSetParameteri(fillPaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
979 VGuint fillColor = 0x008000ff; // opaque dark green
980 vgSetColor(fillPaint, fillColor);
981 ASSERT_EGL_TRUE(vgGetError() == VG_NO_ERROR);
983 vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_STENCIL);
984 vgSeti(VG_BLEND_MODE, VG_BLEND_SRC_OVER);
985 vgDrawImage(vgImage);
986 ASSERT_EGL_TRUE(vgGetError() == VG_NO_ERROR);
988 vgDestroyPaint(fillPaint);
989 ASSERT_EGL_TRUE(vgGetError() == VG_NO_ERROR);
993 vgSetPixels(0, 0, vgImage, 0, 0, KImageSize.iWidth, KImageSize.iHeight);
994 ASSERT_TRUE(vgGetError()==VG_NO_ERROR);
998 // Check that the surface contains the expected pixels
999 // # if the source is a A_8, to compare the surface with a reference bitmap, the following is needed:
1000 // a) a reference bitmap needs to be cleared to black (same colour as the surface was cleared to)
1001 // b) a Pen bitmap, that we clear to dark green (same colour as the fillPaint used to draw to the surface)
1002 // c) a mask bitmap, which is the reference bitmap used to create the SgImage
1003 // # otherwise, the surface must contain the same pixels as the bitmap used to create the SgImage
1004 if (iSourceFormat == EUidPixelFormatA_8)
1006 TDisplayMode maskMode = EglTestConversion::PixelFormatToDisplayMode(iSourceFormat);
1007 CFbsBitmap* mask = iEglSess->CreateReferenceBitmapL(maskMode, KImageSize, ImageIndexFromProcessId(aIdx, KNumImages));
1008 CleanupStack::PushL(mask);
1010 // we need a reference bitmap with the same pixel format as the target surface
1011 TUidPixelFormat format = EglTestConversion::VgFormatToSgPixelFormat(iSurfaceFormat);
1012 TDisplayMode refbitmapMode = EglTestConversion::PixelFormatToDisplayMode(format);
1014 CFbsBitmap* refBitmap = iEglSess->CreateReferenceMaskedBitmapL(refbitmapMode, KRgbDarkGreen, mask);
1015 CleanupStack::PushL(refBitmap);
1017 // compare the obtained reference bitmap with the surface drawn
1018 iEglSess->CheckVgDrawingL(iSurfaceFormat, refBitmap);
1019 CleanupStack::PopAndDestroy(2, mask); //mask, refBitmap
1023 TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(iSourceFormat);
1024 CFbsBitmap* refBitmap = iEglSess->CreateReferenceBitmapL(bitmapMode, KImageSize, ImageIndexFromProcessId(aIdx, KNumImages));
1025 CleanupStack::PushL(refBitmap);
1026 iEglSess->CheckVgDrawingL(iSurfaceFormat, refBitmap);
1027 CleanupStack::PopAndDestroy(refBitmap);
1029 INFO_PRINTF2(_L("Process %d, VG drawing successfully completed and checked"),aIdx);
1032 vgDestroyImage(vgImage);
1033 ASSERT_TRUE(vgGetError()==VG_NO_ERROR);
1041 @SYMTestCaseID GRAPHICS-EGL-0410
1048 To ensure that RSgImage with uploaded data can be shared across processes.
1049 To ensure that reference counting of RSgImage works correctly
1052 From the main process:
1053 - Create M SgImage(s) with the flag ESgUsageBitOpenVgImage. The size are all the same.
1054 We are running through all the possible target configurations, with the values assumed being:
1055 • EUidPixelFormatRGB_565
1056 • EUidPixelFormatXRGB_8888
1057 • EUidPixelFormatARGB_8888_PRE
1058 - Using EGL extension, create M EGLImage(s), specifying as EGLClientBuffer SgImage(s) which were created on
1059 first step and EGL_NATIVE_PIXMAP_KHR as a target
1060 - Using VG extension, create VG images based on EGLImage(s) from the previous step
1061 - Close Sg and EGL Images
1062 - Populate data in VGImages (see vgImageSubData(..) API), there will be different data uploaded for each VGImage
1063 - Spawn N client processes. During the process launching, pass to each process single drawable ID from the SgImages.
1064 In order to define which SgImage(s) needs to be passed to the particular processes, there will be following
1065 formula applied: J = P Mod (M), where J is the sequence number of the image, P is the particular process number.
1066 From processes 1 to N:
1067 - Open SgImage by using TSgDrawableId, obtained from the SgImage which was passed from the process A.
1068 - Using EGL extension, create EGLImage specifying as EGLClientBuffer SgImage which was created on previous step,
1069 EGL_NATIVE_PIXMAP_KHR as a target and EGL_IMAGE_PRESERVED_KHR as an attribute
1070 - Using VG extension, create VG image based on EGLImage from the previous step.
1071 - Close Sg and EGL images
1072 - Create second SgImage with the same size and pixel format as first SgImage and usage flag is set to ESgUsageBitOpenVgSurface.
1073 - Create off-screen pixmap surface with underlining second SgImage and make it current for the drawing context.
1074 - Draw VGImage to the off-screen surface.
1075 - Retrieve surface data (see vgReadPixels() API)
1077 @SYMTestExpectedResults
1078 Creation of all drawable resources have been completed without errors.
1079 Image data obtained in client processes 1-N matches to the data which have been uploaded to the SgImages buffer from
1080 process A. Reference counting works correctly and keep VG image alive although bound Sg and EGL images have been closed.
1081 When all resources are closed, resource count maintained by RSgDriver extension is zero in all processes.
1083 TVerdict CEglTest_EGL_Image_Multi_Process_FontServer_Deferred::doTestStepL()
1085 SetTestStepID(_L("GRAPHICS-EGL-0410"));
1086 SetTestStepName(KEGL_Image_Multi_Process_FontServer_Deferred);
1087 INFO_PRINTF1(_L("CEglTest_EGL_Image_Multi_Process_FontServer_Deferred::doTestStepL"));
1089 TBool ret = CheckForExtensionL(KEGL_RSgimage | KEGL_KHR_image_base | KEGL_KHR_image_pixmap | KVG_KHR_EGL_image);
1092 // The extension is not supported
1093 RecordTestResultL();
1094 CloseTMSGraphicsStep();
1095 return TestStepResult();
1098 CEglTestCommonIniSettings* iniParser = CEglTestCommonIniSettings::NewL();
1099 CleanupStack::PushL(iniParser);
1101 TInt numPixmapSgSurfaceFormats = iniParser->GetNumberOfFormats(KSectionPixmapSgSurfaceFormats);
1102 if(!numPixmapSgSurfaceFormats)
1104 ERR_PRINTF1(_L("No formats to iterate through"));
1105 User::Leave(KErrArgument);
1107 for(TUint j=0; j < numPixmapSgSurfaceFormats; j++)
1109 iSurfaceFormat = iniParser->GetVgFormat(KSectionPixmapSgSurfaceFormats,j);
1110 iSourceFormat = EglTestConversion::VgFormatToSgPixelFormat(iSurfaceFormat);
1111 #ifndef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
1112 // A_8 related tests are only performed for SgImage-Lite
1113 if (iSourceFormat == EUidPixelFormatA_8)
1116 doTestPartialStepL();
1119 CleanupStack::PopAndDestroy(iniParser);
1120 RecordTestResultL();
1121 CloseTMSGraphicsStep();
1122 return TestStepResult();
1125 TVerdict CEglTest_EGL_Image_Multi_Process_FontServer_Deferred::doTestPartialStepL()
1127 INFO_PRINTF1(_L("CEglTest_EGL_Image_Multi_Process_FontServer_Deferred::doTestPartialStepL"));
1128 PrintUsedPixelConfiguration();
1130 // Create display object
1131 ASSERT_TRUE(iDisplay == EGL_NO_DISPLAY);
1133 CreateEglSessionL();
1134 iEglSess->InitializeL();
1135 iEglSess->OpenSgDriverL();
1137 // Create RSgImage's attributes
1138 TSgImageInfoTest imageInfo = TSgImageInfoTest(iSourceFormat, KImageSize);
1139 #ifdef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
1140 imageInfo.iUsage = ESgUsageBitOpenVgImage | ESgUsageBitOpenVgSurface;
1142 imageInfo.iUsage = ESgUsageOpenVgImage | ESgUsageOpenVgTarget;
1143 imageInfo.iShareable = ETrue;
1144 #endif //SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
1145 // Create a pixmap surface matching the given pixel format
1146 iEglSess->CreatePixmapSurfaceAndMakeCurrentAndMatchL(imageInfo,CTestEglSession::EResourceCloseSgImageEarly);
1148 // list to maintain TSgDrawableId
1149 RArray<TSgDrawableId> sgIdList;
1150 CleanupClosePushL(sgIdList);
1151 RSgImage sgImages[KNumImages];
1153 INFO_PRINTF2(_L("MAIN PROCESS: Creating %d RSgImage(s)..."), KNumImages);
1154 for (TInt i=0; i<KNumImages; i++)
1156 ASSERT_EQUALS(sgImages[i].Create(imageInfo, NULL, NULL), KErrNone);
1157 CleanupClosePushL(sgImages[i]);
1158 ASSERT_EQUALS(sgIdList.Insert(sgImages[i].Id(),i), KErrNone);
1160 EGLImageKHR eglImage = iEglSess->eglCreateImageKhrL(iDisplay, EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, &sgImages[i], KEglImageAttribsPreservedTrue);
1161 ASSERT_EGL_TRUE(eglImage != EGL_NO_IMAGE_KHR);
1163 VGImage vgImage = iEglSess->vgCreateImageTargetKHR((VGeglImageKHR)eglImage);
1164 ASSERT_VG_TRUE(vgImage != VG_INVALID_HANDLE);
1165 ASSERT_EGL_TRUE(iEglSess->DestroyEGLImage(iDisplay, eglImage));
1167 TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(iSourceFormat);
1168 CFbsBitmap* bitmap = iEglSess->CreateReferenceBitmapL(bitmapMode, KImageSize, i);
1169 // Add pixel data to the VGImage reference from the bitmap reference.
1170 // Mind the fact that CFbsBitmap and VGImages use different coordinates origin!
1171 TSize bitmapSize = bitmap->SizeInPixels();
1172 TUint8* address = reinterpret_cast<TUint8*>(bitmap->DataAddress());
1173 TInt stride = bitmap->DataStride();
1174 address += (bitmapSize.iHeight - 1) * stride;
1175 vgImageSubData(vgImage, address, -stride, iSurfaceFormat, 0,0, bitmapSize.iWidth, bitmapSize.iHeight);
1178 ASSERT_TRUE(vgGetError()==VG_NO_ERROR);
1182 INFO_PRINTF2(_L("MAIN PROCESS: About to launch %d processes..."), KNumProcesses);
1183 Test_MultiProcessL(KEglTestStepDllName, KNumProcesses, TestStepName(), sgIdList);
1184 CleanupStack::PopAndDestroy(KNumImages + 1, &sgIdList); //KNumImages SgImages, sgIdList
1185 INFO_PRINTF2(_L("MAIN PROCESS: All %d launched processes have completed!"), KNumProcesses);
1188 INFO_PRINTF1(_L("End of CEglTest_EGL_Image_Multi_Process_FontServer_Deferred::doTestPartialStepL"));
1189 return TestStepResult();
1192 void CEglTest_EGL_Image_Multi_Process_FontServer_Deferred::doProcessFunctionL(TInt aIdx,const TSgDrawableId& aSgId)
1194 INFO_PRINTF2(_L("CEglTest_EGL_Image_Multi_Process_FontServer_Deferred::doProcessFunctionL, Process %d"),aIdx);
1196 CreateEglSessionL(aIdx);
1197 iEglSess->InitializeL();
1198 iEglSess->OpenSgDriverL();
1200 //Retrieve source formats for the launched process from the process parameters.
1201 User::LeaveIfError(User::GetTIntParameter(EProcSlotSourceFormat, reinterpret_cast<TInt&>(iSourceFormat)));
1202 User::LeaveIfError(User::GetTIntParameter(EProcSlotSurfaceFormat, reinterpret_cast<TInt&>(iSurfaceFormat)));
1204 RSgImage sgImageFromId;
1205 CleanupClosePushL(sgImageFromId);
1206 ASSERT_EQUALS(sgImageFromId.Open(aSgId), KErrNone);
1208 INFO_PRINTF2(_L("Process %d, Creating an EGLImage from the shared RSgImage"),aIdx);
1209 EGLImageKHR eglImage = iEglSess->eglCreateImageKhrL(iDisplay, EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, &sgImageFromId, KEglImageAttribsPreservedTrue);
1210 ASSERT_EGL_TRUE(eglImage != EGL_NO_IMAGE_KHR);
1211 CleanupStack::PopAndDestroy(&sgImageFromId);
1213 INFO_PRINTF2(_L("Process %d, Creating a Surface and a Context bound to OpenVG"),aIdx);
1214 TUidPixelFormat pixelFormat = EglTestConversion::VgFormatToSgPixelFormat(iSurfaceFormat);
1215 TSgImageInfoOpenVgTarget imageInfo = TSgImageInfoOpenVgTarget(pixelFormat, KImageSize);
1216 // Create a pixmap surface matching the native image pixel format
1217 iEglSess->CreatePixmapSurfaceAndMakeCurrentAndMatchL(imageInfo,CTestEglSession::EResourceCloseSgImageEarly);
1219 INFO_PRINTF2(_L("Process %d, Creating one VGImage from the EGLImage"),aIdx);
1220 VGImage vgImage = iEglSess->vgCreateImageTargetKHR((VGeglImageKHR)eglImage);
1221 ASSERT_VG_TRUE(vgImage != VG_INVALID_HANDLE);
1222 ASSERT_EGL_TRUE(iEglSess->DestroyEGLImage(iDisplay, eglImage));
1224 // At this point we draw the VGImage created from the SgImage to the current surface.
1225 // # if the source is a A_8, the VGImage acts as a mask and the target surface must contain
1226 // as a result the pen colour set above blended with the mask
1227 // # otherwise, drawing the VGImage is just a simple copy via vgSetPixels (no blending required)
1228 INFO_PRINTF1(_L("Copying the VGImage to the surface"));
1229 if (iSourceFormat == EUidPixelFormatA_8)
1231 // clear surface background
1232 VGfloat bgColor[] = {0.0, 0.0, 0.0, 1.0}; // opaque black
1233 vgSetfv(VG_CLEAR_COLOR, 4, bgColor);
1234 vgClear(0, 0, KImageSize.iWidth, KImageSize.iHeight);
1235 ASSERT_EGL_TRUE(vgGetError() == VG_NO_ERROR);
1238 VGPaint fillPaint = vgCreatePaint();
1239 vgSetPaint(fillPaint, VG_FILL_PATH);
1240 ASSERT_EGL_TRUE(vgGetError() == VG_NO_ERROR);
1241 vgSetParameteri(fillPaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
1242 VGuint fillColor = 0x008000ff; // opaque dark green
1243 vgSetColor(fillPaint, fillColor);
1244 ASSERT_EGL_TRUE(vgGetError() == VG_NO_ERROR);
1246 vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_STENCIL);
1247 vgSeti(VG_BLEND_MODE, VG_BLEND_SRC_OVER);
1248 vgDrawImage(vgImage);
1249 ASSERT_EGL_TRUE(vgGetError() == VG_NO_ERROR);
1251 vgDestroyPaint(fillPaint);
1252 ASSERT_EGL_TRUE(vgGetError() == VG_NO_ERROR);
1256 vgSetPixels(0, 0, vgImage, 0, 0, KImageSize.iWidth, KImageSize.iHeight);
1257 ASSERT_TRUE(vgGetError()==VG_NO_ERROR);
1261 // Check that the surface contains the expected pixels
1262 // # if the source is a A_8, to compare the surface with a reference bitmap, the following is needed:
1263 // a) a reference bitmap needs to be cleared to black (same colour as the surface was cleared to)
1264 // b) a Pen bitmap, that we clear to dark green (same colour as the fillPaint used to draw to the surface)
1265 // c) a mask bitmap, which is the reference bitmap used to create the SgImage
1266 // # otherwise, the surface must contain the same pixels as the bitmap used to create the SgImage
1267 if (iSourceFormat == EUidPixelFormatA_8)
1269 TDisplayMode maskMode = EglTestConversion::PixelFormatToDisplayMode(iSourceFormat);
1270 CFbsBitmap* mask = iEglSess->CreateReferenceBitmapL(maskMode, KImageSize, ImageIndexFromProcessId(aIdx, KNumImages));
1271 CleanupStack::PushL(mask);
1273 // we need a reference bitmap with the same pixel format as the target surface
1274 TUidPixelFormat format = EglTestConversion::VgFormatToSgPixelFormat(iSurfaceFormat);
1275 TDisplayMode refbitmapMode = EglTestConversion::PixelFormatToDisplayMode(format);
1277 CFbsBitmap* refBitmap = iEglSess->CreateReferenceMaskedBitmapL(refbitmapMode, KRgbDarkGreen, mask);
1278 CleanupStack::PushL(refBitmap);
1280 // compare the obtained reference bitmap with the surface drawn
1281 iEglSess->CheckVgDrawingL(iSurfaceFormat, refBitmap);
1282 CleanupStack::PopAndDestroy(2, mask); //mask, refBitmap
1286 TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(iSourceFormat);
1287 CFbsBitmap* refBitmap = iEglSess->CreateReferenceBitmapL(bitmapMode, KImageSize, ImageIndexFromProcessId(aIdx, KNumImages));
1288 CleanupStack::PushL(refBitmap);
1289 iEglSess->CheckVgDrawingL(iSurfaceFormat, refBitmap);
1290 CleanupStack::PopAndDestroy(refBitmap);
1292 INFO_PRINTF2(_L("Process %d, VG drawing successfully completed and checked"),aIdx);
1295 vgDestroyImage(vgImage);
1296 ASSERT_TRUE(vgGetError()==VG_NO_ERROR);
1304 @SYMTestCaseID GRAPHICS-EGL-0415
1311 To ensure that SgImage with the data rendered as Pixmap surface can be shared across processes.
1312 To ensure that reference counting of SgImage works correctly
1315 From the main process:
1316 - Create M SgImages with the flags ESgUsageBitOpenVgImage & ESgUsageBitOpenVgSurface. The size are all the same.
1317 We are running through all the possible target configurations, with the values assumed being:
1318 • EUidPixelFormatRGB_565
1319 • EUidPixelFormatXRGB_8888
1320 • EUidPixelFormatARGB_8888_PRE
1321 - Choose egl config, supplying as a native pixmap type in attribute (flag EGL_MATCH_NATIVE_PIXMAP) the SgImages which
1322 were created on the previous step. The EGL_RENDERABLE_TYPE of the config attributes must include EGL_OPENVG_BIT.
1323 - Create M pixmap surfaces based on SgImages from the first step. The surface is created with EGL_ALPHA_FORMAT_PRE
1324 flag supplied in attribute list if the underlining SgImage was of type ESgPixelFormatARGB_8888_PRE.
1325 - In iteration from 1 to M perform three following steps:
1326 1. Make the pixmap surface current (see eglMakeCurrent(.) API)
1327 2. Draw something to the current surface, for instance, clear the whole area with color and then draw a
1328 few graphics primitives. The drawing needs to be unique for each surface and complicated enough to
1329 ensure that bit comparison will reveal any mismatch
1330 3. Make no surface current
1331 - Close all pixmap surfaces
1332 - Spawn N client processes. During the process launching, pass to each process single drawable ID from the SgImages.
1333 In order to define which SgImage(s) needs to be passed to the particular processes, there will be following
1334 formula applied: J = P Mod (M), where J is the sequence number of the image, P is the particular process number.
1335 From processes 1 to N:
1336 - Open SgImage by TSgDrawableId obtained from the SgImage which was passed from the process A.
1337 - Using EGL extension, create EGLImage specifying as EGLClientBuffer SgImage which was opened on the previous
1338 step, EGL_NATIVE_PIXMAP_KHR as a target and EGL_IMAGE_PRESERVED_KHR as an attribute
1339 - Using VG extension, create VG image based on EGLImage from the previous step.
1340 - Close both Sg and EGL images
1341 - Create second SgImage with the same size and pixel format as first SgImage and usage flag is set to ESgUsageBitOpenVgSurface.
1342 - Create off-screen pixmap surface with underlining second SgImage and make it current for the drawing context.
1343 - Draw VGImage to the off-screen surface.
1344 - Retrieve surface data (see vgReadPixels() API)
1346 @SYMTestExpectedResults
1347 Creation of all drawable resources has been completed without errors.
1348 On return eglChooseConfig() must return EGL_OPENVG_BIT in config attribute list (actual attributes should
1349 be retrieved via call to eglGetConfigAttrib()).
1350 Image data obtained in client processes 1 - N matches to the pixmap surface which was drawn in the process A.
1351 Reference counting works correctly and keep VG image alive although bound Sg and EGL images have been closed.
1352 When all resources are closed, resource count maintained by RSgDriver extension is zero in all processes.
1354 TVerdict CEglTest_EGL_Image_Multi_Process_ThemeServer::doTestStepL()
1356 SetTestStepID(_L("GRAPHICS-EGL-0415"));
1357 SetTestStepName(KEGL_Image_Multi_Process_ThemeServer);
1358 INFO_PRINTF1(_L("CEglTest_EGL_Image_Multi_Process_ThemeServer::doTestStepL"));
1360 TBool ret = CheckForExtensionL(KEGL_RSgimage | KEGL_KHR_image_base | KEGL_KHR_image_pixmap | KVG_KHR_EGL_image);
1363 // The extension is not supported
1364 RecordTestResultL();
1365 CloseTMSGraphicsStep();
1366 return TestStepResult();
1369 CEglTestCommonIniSettings* iniParser = CEglTestCommonIniSettings::NewL();
1370 CleanupStack::PushL(iniParser);
1372 TInt numPixmapSgSurfaceFormats = iniParser->GetNumberOfFormats(KSectionPixmapSgSurfaceFormats);
1373 if(!numPixmapSgSurfaceFormats)
1375 ERR_PRINTF1(_L("No formats to iterate through"));
1376 User::Leave(KErrArgument);
1378 for(TUint j=0; j < numPixmapSgSurfaceFormats; j++)
1380 iSurfaceFormat = iniParser->GetVgFormat(KSectionPixmapSgSurfaceFormats,j);
1381 iSourceFormat = EglTestConversion::VgFormatToSgPixelFormat(iSurfaceFormat);
1382 #ifndef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
1383 // A_8 related tests are only performed for SgImage-Lite
1384 if (iSourceFormat == EUidPixelFormatA_8)
1387 doTestPartialStepL();
1390 CleanupStack::PopAndDestroy(iniParser);
1391 RecordTestResultL();
1392 CloseTMSGraphicsStep();
1393 return TestStepResult();
1396 TVerdict CEglTest_EGL_Image_Multi_Process_ThemeServer::doTestPartialStepL()
1398 INFO_PRINTF1(_L("CEglTest_EGL_Image_Multi_Process_ThemeServer::doTestPartialStepL"));
1399 PrintUsedPixelConfiguration();
1401 // Create display object
1402 ASSERT_TRUE(iDisplay == EGL_NO_DISPLAY);
1404 CreateEglSessionL();
1405 iEglSess->InitializeL();
1406 iEglSess->OpenSgDriverL();
1408 // list to maintain TSgDrawableId
1409 RArray<TSgDrawableId> sgIdList;
1410 CleanupClosePushL(sgIdList);
1411 RSgImage sgImages[KNumImages];
1413 INFO_PRINTF2(_L("MAIN PROCESS: Creating %d RSgImage(s)..."), KNumImages);
1414 for (TInt i=0; i<KNumImages; i++)
1416 // Create RSgImage's attributes
1417 TSgImageInfoTest imageInfo = TSgImageInfoTest(iSourceFormat, KImageSize);
1418 #ifdef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
1419 imageInfo.iUsage = ESgUsageBitOpenVgImage | ESgUsageBitOpenVgSurface;
1421 imageInfo.iUsage = ESgUsageOpenVgImage | ESgUsageOpenVgTarget;
1422 imageInfo.iShareable = ETrue;
1423 #endif //SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
1425 ASSERT_EQUALS(sgImages[i].Create(imageInfo, NULL, NULL), KErrNone);
1426 CleanupClosePushL(sgImages[i]);
1427 ASSERT_EQUALS(sgIdList.Insert(sgImages[i].Id(),i), KErrNone);
1429 INFO_PRINTF1(_L("Calling sequence - eglBindAPI(EGL_OPENVG_API) - eglCreatePixmapSurface - eglCreateContext - eglMakeCurrent"));
1430 ASSERT_EGL_TRUE(eglBindAPI(EGL_OPENVG_API));
1432 const EGLint KAttrib_list_image_pre[] = { EGL_MATCH_NATIVE_PIXMAP, reinterpret_cast<EGLint>(&sgImages[i]),
1433 EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT,
1434 EGL_SURFACE_TYPE, EGL_PIXMAP_BIT | EGL_VG_ALPHA_FORMAT_PRE_BIT,
1436 const EGLint KAttrib_list_image_nonpre[] = {EGL_MATCH_NATIVE_PIXMAP, reinterpret_cast<EGLint>(&sgImages[i]),
1437 EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT,
1438 EGL_SURFACE_TYPE, EGL_PIXMAP_BIT,
1440 EGLConfig currentConfig;
1441 EGLint numconfigs =0;
1442 EGLSurface surface = EGL_NO_SURFACE;
1443 if (iSourceFormat == EUidPixelFormatARGB_8888_PRE)
1445 ASSERT_EGL_TRUE(eglChooseConfig(iDisplay,KAttrib_list_image_pre,¤tConfig,1,&numconfigs))
1446 ASSERT_EGL_TRUE(numconfigs==1);
1447 surface = eglCreatePixmapSurface(iDisplay, currentConfig,&sgImages[i], KPixmapAttribsVgAlphaFormatPre);
1451 ASSERT_EGL_TRUE(eglChooseConfig(iDisplay,KAttrib_list_image_nonpre,¤tConfig,1,&numconfigs))
1452 ASSERT_EGL_TRUE(numconfigs==1);
1453 surface = eglCreatePixmapSurface(iDisplay, currentConfig,&sgImages[i], KPixmapAttribsVgAlphaFormatNonPre);
1455 ASSERT_EGL_TRUE(surface != EGL_NO_SURFACE);
1456 EGLContext context = eglCreateContext(iDisplay, currentConfig, EGL_NO_CONTEXT, NULL);
1457 ASSERT_EGL_TRUE(context != EGL_NO_CONTEXT);
1458 ASSERT_EGL_TRUE(eglMakeCurrent(iDisplay, surface, surface, context));
1460 //Drawing to the current surface (and hence to the RSgImage) to test that the contents are preserved
1461 TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(iSourceFormat);
1462 CFbsBitmap* bitmap = iEglSess->CreateReferenceBitmapL(bitmapMode, KImageSize, i);
1463 // Mind the fact that CFbsBitmap and VGImages use different coordinates origin!
1464 TSize bitmapSize = bitmap->SizeInPixels();
1465 TUint8* address = reinterpret_cast<TUint8*>(bitmap->DataAddress());
1466 TInt stride = bitmap->DataStride();
1467 address += (bitmapSize.iHeight - 1) * stride;
1468 vgWritePixels(address, -stride, iSurfaceFormat, 0,0, bitmapSize.iWidth, bitmapSize.iHeight);
1469 eglWaitClient(); // wait for writing to finish
1472 ASSERT_TRUE(vgGetError()==VG_NO_ERROR);
1474 // Make no surface current and destroy surface
1475 ASSERT_EGL_TRUE(eglDestroySurface(iDisplay, surface));
1476 ASSERT_EGL_TRUE(eglMakeCurrent(iDisplay, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT));
1479 INFO_PRINTF2(_L("MAIN PROCESS: About to launch %d processes..."), KNumProcesses);
1480 Test_MultiProcessL(KEglTestStepDllName, KNumProcesses, TestStepName(), sgIdList);
1481 CleanupStack::PopAndDestroy(KNumImages + 1, &sgIdList); //KNumImages SgImages, sgIdList
1482 INFO_PRINTF2(_L("MAIN PROCESS: All %d launched processes have completed!"), KNumProcesses);
1485 INFO_PRINTF1(_L("End of CEglTest_EGL_Image_Multi_Process_ThemeServer::doTestPartialStepL"));
1486 return TestStepResult();
1489 void CEglTest_EGL_Image_Multi_Process_ThemeServer::doProcessFunctionL(TInt aIdx,const TSgDrawableId& aSgId)
1491 INFO_PRINTF2(_L("CEglTest_EGL_Image_Multi_Process_ThemeServer::doProcessFunctionL, Process %d"),aIdx);
1493 CreateEglSessionL(aIdx);
1494 iEglSess->InitializeL();
1495 iEglSess->OpenSgDriverL();
1497 //Retrieve source formats for the launched process from the process parameters.
1498 User::LeaveIfError(User::GetTIntParameter(EProcSlotSourceFormat, reinterpret_cast<TInt&>(iSourceFormat)));
1499 User::LeaveIfError(User::GetTIntParameter(EProcSlotSurfaceFormat, reinterpret_cast<TInt&>(iSurfaceFormat)));
1501 RSgImage sgImageFromId;
1502 CleanupClosePushL(sgImageFromId);
1503 ASSERT_EQUALS(sgImageFromId.Open(aSgId), KErrNone);
1505 INFO_PRINTF2(_L("Process %d, Creating an EGLImage from the shared RSgImage"),aIdx);
1506 EGLImageKHR eglImage = iEglSess->eglCreateImageKhrL(iDisplay, EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, &sgImageFromId, KEglImageAttribsPreservedTrue);
1507 ASSERT_EGL_TRUE(eglImage != EGL_NO_IMAGE_KHR);
1508 CleanupStack::PopAndDestroy(&sgImageFromId);
1510 INFO_PRINTF2(_L("Process %d, Creating a Surface and a Context bound to OpenVG"),aIdx);
1511 TUidPixelFormat pixelFormat = EglTestConversion::VgFormatToSgPixelFormat(KDefaultSurfaceFormat);
1512 TSgImageInfoOpenVgTarget imageInfo = TSgImageInfoOpenVgTarget(pixelFormat, KImageSize);
1513 // Create a pixmap surface matching the native image pixel format
1514 iEglSess->CreatePixmapSurfaceAndMakeCurrentAndMatchL(imageInfo,CTestEglSession::EResourceCloseSgImageEarly);
1516 INFO_PRINTF2(_L("Process %d, Creating one VGImage from the EGLImage"),aIdx);
1517 VGImage vgImage = iEglSess->vgCreateImageTargetKHR((VGeglImageKHR)eglImage);
1518 ASSERT_VG_TRUE(vgImage != VG_INVALID_HANDLE);
1519 ASSERT_EGL_TRUE(iEglSess->DestroyEGLImage(iDisplay, eglImage));
1521 // At this point we draw the VGImage created from the SgImage to the current surface.
1522 // # if the source is a A_8, the VGImage acts as a mask and the target surface must contain
1523 // as a result the pen colour set above blended with the mask
1524 // # otherwise, drawing the VGImage is just a simple copy via vgSetPixels (no blending required)
1525 INFO_PRINTF1(_L("Copying the VGImage to the surface"));
1526 if (iSourceFormat == EUidPixelFormatA_8)
1528 // clear surface background
1529 VGfloat bgColor[] = {0.0, 0.0, 0.0, 1.0}; // opaque black
1530 vgSetfv(VG_CLEAR_COLOR, 4, bgColor);
1531 vgClear(0, 0, KImageSize.iWidth, KImageSize.iHeight);
1532 ASSERT_EGL_TRUE(vgGetError() == VG_NO_ERROR);
1535 VGPaint fillPaint = vgCreatePaint();
1536 vgSetPaint(fillPaint, VG_FILL_PATH);
1537 ASSERT_EGL_TRUE(vgGetError() == VG_NO_ERROR);
1538 vgSetParameteri(fillPaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
1539 VGuint fillColor = 0x008000ff; // opaque dark green
1540 vgSetColor(fillPaint, fillColor);
1541 ASSERT_EGL_TRUE(vgGetError() == VG_NO_ERROR);
1543 vgSeti(VG_IMAGE_MODE, VG_DRAW_IMAGE_STENCIL);
1544 vgSeti(VG_BLEND_MODE, VG_BLEND_SRC_OVER);
1545 vgDrawImage(vgImage);
1546 ASSERT_EGL_TRUE(vgGetError() == VG_NO_ERROR);
1548 vgDestroyPaint(fillPaint);
1549 ASSERT_EGL_TRUE(vgGetError() == VG_NO_ERROR);
1553 vgSetPixels(0, 0, vgImage, 0, 0, KImageSize.iWidth, KImageSize.iHeight);
1554 ASSERT_TRUE(vgGetError()==VG_NO_ERROR);
1558 // Check that the surface contains the expected pixels
1559 // # if the source is a A_8, to compare the surface with a reference bitmap, the following is needed:
1560 // a) a reference bitmap needs to be cleared to black (same colour as the surface was cleared to)
1561 // b) a Pen bitmap, that we clear to dark green (same colour as the fillPaint used to draw to the surface)
1562 // c) a mask bitmap, which is the reference bitmap used to create the SgImage
1563 // # otherwise, the surface must contain the same pixels as the bitmap used to create the SgImage
1564 if (iSourceFormat == EUidPixelFormatA_8)
1566 TDisplayMode maskMode = EglTestConversion::PixelFormatToDisplayMode(iSourceFormat);
1567 CFbsBitmap* mask = iEglSess->CreateReferenceBitmapL(maskMode, KImageSize, ImageIndexFromProcessId(aIdx, KNumImages));
1568 CleanupStack::PushL(mask);
1570 // we need a reference bitmap with the same pixel format as the target surface
1571 TUidPixelFormat format = EglTestConversion::VgFormatToSgPixelFormat(iSurfaceFormat);
1572 TDisplayMode refbitmapMode = EglTestConversion::PixelFormatToDisplayMode(format);
1574 CFbsBitmap* refBitmap = iEglSess->CreateReferenceMaskedBitmapL(refbitmapMode, KRgbDarkGreen, mask);
1575 CleanupStack::PushL(refBitmap);
1577 // compare the obtained reference bitmap with the surface drawn
1578 iEglSess->CheckVgDrawingL(iSurfaceFormat, refBitmap);
1579 CleanupStack::PopAndDestroy(2, mask); //mask, refBitmap
1583 TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(iSourceFormat);
1584 CFbsBitmap* refBitmap = iEglSess->CreateReferenceBitmapL(bitmapMode, KImageSize, ImageIndexFromProcessId(aIdx, KNumImages));
1585 CleanupStack::PushL(refBitmap);
1586 iEglSess->CheckVgDrawingL(iSurfaceFormat, refBitmap);
1587 CleanupStack::PopAndDestroy(refBitmap);
1589 INFO_PRINTF2(_L("Process %d, VG drawing successfully completed and checked"),aIdx);
1592 vgDestroyImage(vgImage);
1593 ASSERT_TRUE(vgGetError()==VG_NO_ERROR);
1601 @SYMTestCaseID GRAPHICS-EGL-0430
1608 Functional test - Killing the RSgImage creating process
1611 To verify correct operation of RSgImage sharing across processes when the creating process is killed
1614 Run two processes that independently perform the actions detailed below.
1617 Create an RSgImage passing an initialised bitmap
1618 Signal (by semaphore or otherwise) to process B, passing the drawable ID to it
1622 Using the drawable ID, open the RSgImage
1624 Re-open the RSgImage
1627 Unexpectedly terminate process A without performing any explicit clean-up
1630 Wait for Process A to be killed:
1631 Create an EGLImage from the RSgImage
1632 Create a VGImage from the EGLImage
1635 Create an off-screen surface
1636 Draw VGImage to the off-screen surface
1637 Read the pixel data and verify that it matches the data populated by process A
1638 Destroy the off-screen surface
1643 @SYMTestExpectedResults
1644 Process B should be able to populate the VGImage with data and copy it to the off-screen surface
1645 All allocated image memory should be freed
1647 TVerdict CEglTest_EGL_Image_Multi_Process_VgImage_ProcessTerminate::doTestStepL()
1649 SetTestStepID(_L("GRAPHICS-EGL-0430"));
1650 SetTestStepName(KEGL_Image_Multi_Process_VgImage_ProcessTerminate);
1651 INFO_PRINTF1(_L("Enter: CEglTest_EGL_Image_Multi_Process_VgImage_ProcessTerminate::doTestStepL"));
1653 TBool ret = CheckForExtensionL(KEGL_RSgimage | KEGL_KHR_image_base | KEGL_KHR_image_pixmap | KVG_KHR_EGL_image);
1656 // The extension is not supported
1657 RecordTestResultL();
1658 CloseTMSGraphicsStep();
1659 return TestStepResult();
1662 // This test is performed for default pixel format
1663 PrintUsedPixelConfiguration();
1665 // launch 2 processes
1666 Test_MultiProcessL(KEglTestStepDllName, 2, TestStepName());
1668 INFO_PRINTF1(_L("Exit: CEglTest_EGL_Image_Multi_Process_VgImage_ProcessTerminate::doTestStepL"));
1669 RecordTestResultL();
1670 CloseTMSGraphicsStep();
1671 return TestStepResult();
1674 void CEglTest_EGL_Image_Multi_Process_VgImage_ProcessTerminate::doProcessFunctionL(TInt aIdx)
1676 INFO_PRINTF2(_L("CEglTest_EGL_Image_Multi_Process_VgImage_ProcessTerminate::doProcessFunctionL, Process %d"),aIdx);
1678 CreateEglSessionL(aIdx);
1679 iEglSess->InitializeL();
1680 iEglSess->OpenSgDriverL();
1682 //Retrieve source formats for the launched process from the process parameters.
1683 User::LeaveIfError(User::GetTIntParameter(EProcSlotSourceFormat, reinterpret_cast<TInt&>(iSourceFormat)));
1684 User::LeaveIfError(User::GetTIntParameter(EProcSlotSurfaceFormat, reinterpret_cast<TInt&>(iSurfaceFormat)));
1686 //create the queue to send/receive SgImage ID between processes
1687 RMsgQueue<TSgDrawableId> messageQueueSgId;
1688 User::LeaveIfError(messageQueueSgId.Open(EProcSlotMsgQueueSgId, EOwnerProcess));
1689 CleanupClosePushL(messageQueueSgId);
1691 //create the queue to send/receive Process ID between processes
1692 RMsgQueue<TProcessId> messageQueueProcId;
1693 User::LeaveIfError(messageQueueProcId.Open(EProcSlotMsgQueueProcId, EOwnerProcess));
1694 CleanupClosePushL(messageQueueProcId);
1697 CleanupClosePushL(process);
1698 TRequestStatus status;
1700 TDisplayMode bitmapMode = EglTestConversion::PixelFormatToDisplayMode(iSourceFormat);
1701 CFbsBitmap* bitmap = iEglSess->CreateReferenceBitmapL(bitmapMode, KImageSize, 6);
1702 CleanupStack::PushL(bitmap);
1704 RSgImage rSgImageLocal;
1707 // Create an RSgImage
1708 INFO_PRINTF2(_L("Process %d, Creating a RSgImage"),aIdx);
1709 TSgImageInfoOpenVgImage imageInfo = TSgImageInfoOpenVgImage(iSourceFormat, KImageSize);
1710 #ifndef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
1711 imageInfo.iShareable = ETrue;
1712 imageInfo.iCpuAccess = ESgCpuAccessReadWrite;
1714 ASSERT_EQUALS(rSgImageLocal.Create(imageInfo, bitmap->DataAddress(), bitmap->DataStride()), KErrNone);
1716 INFO_PRINTF2(_L("Process %d, Sending SgImage ID to other process..."), aIdx);
1717 messageQueueSgId.SendBlocking(rSgImageLocal.Id());
1719 // Sending Process ID to other process... so that the other process can identify when this one dies.
1720 messageQueueProcId.SendBlocking(RProcess().Id());
1724 INFO_PRINTF2(_L("Process %d: Receiving SgImage ID from other process..."), aIdx);
1725 TSgDrawableId sgImageId;
1726 messageQueueSgId.ReceiveBlocking(sgImageId);
1727 ASSERT_EQUALS(rSgImageLocal.Open(sgImageId),KErrNone);
1729 // Also receiving RProcess ID from other process to be able to identify when it dies
1731 messageQueueProcId.ReceiveBlocking(procId);
1732 process.Open(procId);
1733 process.Logon(status);
1735 INFO_PRINTF2(_L("Process %d: Closing and Opening SgImage again..."), aIdx);
1736 rSgImageLocal.Close();
1737 ASSERT_EQUALS(rSgImageLocal.Open(sgImageId),KErrNone);
1740 // Wait for both processes to reach this point
1745 // simulate this process being killed
1746 // note that we terminate with reason=0 (otherwise the egl test framework would think it's an error)
1747 INFO_PRINTF2(_L("Process %d, Simulate the process is being killed!"),aIdx);
1748 RProcess().Terminate(KErrNone);
1750 // this line is unreachable
1755 // first wait for the other process to finish
1756 User::WaitForRequest(status);
1757 ASSERT_EQUALS(status.Int(), KErrNone);
1759 INFO_PRINTF2(_L("Process %d, Creating an EGLImage from the shared RSgImage"),aIdx);
1760 CleanupClosePushL(rSgImageLocal);
1761 EGLImageKHR eglImageLocal = iEglSess->eglCreateImageKhrL(iDisplay, EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, &rSgImageLocal, KEglImageAttribsPreservedTrue);
1762 ASSERT_EGL_TRUE(eglImageLocal != EGL_NO_IMAGE_KHR);
1763 CleanupStack::PopAndDestroy(&rSgImageLocal); //transferring ownership of the buffer to the EGLImage
1765 INFO_PRINTF2(_L("Creating a Surface and a Context bound to OpenVG, Process %d"),aIdx);
1766 TUidPixelFormat pixelFormat = EglTestConversion::VgFormatToSgPixelFormat(iSurfaceFormat);
1767 TSgImageInfoOpenVgTarget imageInfo = TSgImageInfoOpenVgTarget(pixelFormat, KImageSize);
1768 // Create a pixmap surface matching the native image pixel format
1769 iEglSess->CreatePixmapSurfaceAndMakeCurrentAndMatchL(imageInfo,CTestEglSession::EResourceCloseSgImageEarly);
1771 INFO_PRINTF2(_L("Process %d, Creating one VGImage from the EGLImage"),aIdx);
1772 VGImage vgImageLocal = iEglSess->vgCreateImageTargetKHR((VGeglImageKHR)eglImageLocal);
1773 ASSERT_VG_TRUE(vgImageLocal != VG_INVALID_HANDLE);
1774 ASSERT_EGL_TRUE(iEglSess->DestroyEGLImage(iDisplay, eglImageLocal));
1776 INFO_PRINTF2(_L("Process %d, Drawing the VGImage to the current surface before changing contents of the VGImage"),aIdx);
1777 // Copy the source VGImage to the surface
1778 vgSetPixels(0, 0, vgImageLocal, 0, 0, KImageSize.iWidth, KImageSize.iHeight);
1779 ASSERT_TRUE(vgGetError()==VG_NO_ERROR);
1782 // we can now compare the VgImage to the one we expect
1783 iEglSess->CheckVgDrawingL(iSurfaceFormat, bitmap);
1784 INFO_PRINTF2(_L("Process %d, Drawing successful"),aIdx);
1787 vgDestroyImage(vgImageLocal);
1788 ASSERT_TRUE(vgGetError() == VG_NO_ERROR);
1791 //cleanup and finish
1792 CleanupStack::PopAndDestroy(4, &messageQueueSgId); //messageQueueSgId, messageQueueProcId, process, bitmap
1798 @SYMTestCaseID GRAPHICS-EGL-0429
1805 Functional test - Killing the RSgImage creating process
1808 To verify correct operation of RSgImage sharing across processes when the creating process is killed
1811 Run two processes that independently perform the actions detailed below.
1815 Signal (by semaphore or otherwise) to process B, passing the drawable ID to it
1821 Unexpectedly terminate process A without performing any explicit clean-up
1824 Wait for Process A to be killed:
1825 Using the drawable ID, attempt to open the RSgImage
1829 @SYMTestExpectedResults
1830 Process B should be unable to open the RSgImage and the call to Open() should return error code KErrNotFound.
1831 All allocated image memory should be freed
1833 TVerdict CEglTest_EGL_Image_Multi_Process_VgImage_ProcessTerminateNegative::doTestStepL()
1835 SetTestStepID(_L("GRAPHICS-EGL-0429"));
1836 SetTestStepName(KEGL_Image_Multi_Process_VgImage_ProcessTerminateNegative);
1837 INFO_PRINTF1(_L("Enter: CEglTest_EGL_Image_Multi_Process_VgImage_ProcessTerminateNegative::doTestStepL"));
1839 TBool ret = CheckForExtensionL(KEGL_RSgimage);
1842 // The extension is not supported
1843 RecordTestResultL();
1844 CloseTMSGraphicsStep();
1845 return TestStepResult();
1848 // This test is performed for default pixel format
1849 PrintUsedPixelConfiguration();
1851 // launch 2 processes
1852 Test_MultiProcessL(KEglTestStepDllName, 2, TestStepName());
1854 INFO_PRINTF1(_L("Exit: CEglTest_EGL_Image_Multi_Process_VgImage_ProcessTerminateNegative::doTestStepL"));
1855 RecordTestResultL();
1856 CloseTMSGraphicsStep();
1857 return TestStepResult();
1860 void CEglTest_EGL_Image_Multi_Process_VgImage_ProcessTerminateNegative::doProcessFunctionL(TInt aIdx)
1862 INFO_PRINTF2(_L("CEglTest_EGL_Image_Multi_Process_VgImage_ProcessTerminateNegative::doProcessFunctionL, Process %d"),aIdx);
1864 CreateEglSessionL(aIdx);
1865 iEglSess->InitializeL();
1866 iEglSess->OpenSgDriverL();
1868 //Retrieve source formats for the launched process from the process parameters.
1869 User::LeaveIfError(User::GetTIntParameter(EProcSlotSourceFormat, reinterpret_cast<TInt&>(iSourceFormat)));
1870 User::LeaveIfError(User::GetTIntParameter(EProcSlotSurfaceFormat, reinterpret_cast<TInt&>(iSurfaceFormat)));
1872 //create the queue to send/receive SgImage ID between processes
1873 RMsgQueue<TSgDrawableId> messageQueueSgId;
1874 User::LeaveIfError(messageQueueSgId.Open(EProcSlotMsgQueueSgId, EOwnerProcess));
1875 CleanupClosePushL(messageQueueSgId);
1877 //create the queue to send/receive Process ID between processes
1878 RMsgQueue<TProcessId> messageQueueProcId;
1879 User::LeaveIfError(messageQueueProcId.Open(EProcSlotMsgQueueProcId, EOwnerProcess));
1880 CleanupClosePushL(messageQueueProcId);
1883 CleanupClosePushL(process);
1884 TRequestStatus status;
1886 RSgImage rSgImageLocal;
1887 TSgDrawableId sgImageId;
1890 // Create an RSgImage
1891 INFO_PRINTF2(_L("Process %d, Creating a RSgImage"),aIdx);
1892 TSgImageInfoOpenVgImage imageInfo = TSgImageInfoOpenVgImage(iSourceFormat, KImageSize);
1893 #ifndef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
1894 imageInfo.iShareable = ETrue;
1895 imageInfo.iCpuAccess = ESgCpuAccessReadWrite;
1897 ASSERT_EQUALS(rSgImageLocal.Create(imageInfo,NULL, NULL), KErrNone);
1899 INFO_PRINTF2(_L("Process %d, Sending SgImage ID to other process..."), aIdx);
1900 messageQueueSgId.SendBlocking(rSgImageLocal.Id());
1902 // Sending Process ID to other process... so that the other process can identify when this one dies.
1903 messageQueueProcId.SendBlocking(RProcess().Id());
1907 INFO_PRINTF2(_L("Process %d: Receiving SgImage ID from other process..."), aIdx);
1908 //unlike the other cases, do not open it (yet)
1909 messageQueueSgId.ReceiveBlocking(sgImageId);
1911 // Also receiving RProcess ID from other process to be able to identify when it dies
1913 messageQueueProcId.ReceiveBlocking(procId);
1914 process.Open(procId);
1915 process.Logon(status);
1918 // Wait for both processes to reach this point
1923 // simulate this process being killed
1924 // note that we terminate with reason=0 (otherwise the egl test framework would think it's an error)
1925 INFO_PRINTF2(_L("Process %d, Simulate the process is being killed!"),aIdx);
1926 RProcess().Terminate(KErrNone);
1928 // this line is unreachable
1933 // first wait for the other process to finish
1934 User::WaitForRequest(status);
1935 ASSERT_EQUALS(status.Int(), KErrNone);
1937 // NOTE: We can't guarante when the kernel will have completed the cleanup. This process
1938 // could have been notified that the other process has terminated but this does not guarantee
1939 // that all handles to the process have been released.
1940 // This is not generally a problem in single processor hardware, but can be a problem in dual
1941 // processor hardware (ie, NaviEngine) where one processor could be cleaning up the terminated
1942 // process, the other processor could already be issuing the notification to the waiting process
1943 // Not much we can do other than adding a small delay to ensure this...
1944 User::After(1*1000*1000); // 1 second
1946 // we're expecting it to fail with the appropriate error
1947 TInt ret = rSgImageLocal.Open(sgImageId);
1948 #ifdef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
1949 INFO_PRINTF4(_L("Process %d: Opening SgImage resulted in %d (expected was %d)."), aIdx, ret, KErrNotFound);
1950 ASSERT_EQUALS(ret, KErrNotFound);
1952 INFO_PRINTF4(_L("Process %d: Opening SgImage resulted in %d (expected was %d)."), aIdx, ret, KErrArgument);
1953 ASSERT_EQUALS(ret, KErrArgument);
1957 //cleanup and finish
1958 CleanupStack::PopAndDestroy(3, &messageQueueSgId); //messageQueueSgId, messageQueueProcId, process
1964 @SYMTestCaseID GRAPHICS-EGL-0431
1971 Functional test - Simultaneous reading and writing of simulated glyphs.
1972 The rectangular area of RSgImage will be divided into the following section:
1980 The image size is taken to be 90x90 so that it is easily split between 9 sub-sections
1981 It is obvoious that each sub-section will therefore be of 30x30:
1984 To determine that the system can cope with simultaneous
1985 reading and writing from/to area within RSgImage without corrupting each other.
1988 Run two processes that independently perform the actions detailed below.
1991 Create an RSgImages with no content
1992 For each RSgImage, create an EGLImage and from that create a VGImage
1993 Close the RSgImage and the EGLImage
1996 Open the RSgImage using the drawable ID passed from process A
1997 Create an EGLImage and then a VGImage
1998 Close the RSgImage and the EGLImage
1999 Wait for signal from process A
2001 * Concurrently from Process A and the client process:
2004 Shade section[i] to colour[i]
2005 Signal client process that section[i] can be read
2006 Repeat until client process signal read complete
2007 Shade sections surrounding section[i] to other colors e.g. when i=1,
2008 surrounding sections are section 0, 2 and 4
2014 Wait for signal that section[i] is ready
2015 Create child VGImage for section[i]
2016 Read the value of child VGImage and compare it with colour[i]
2017 Signal process A to indicate read is complete
2018 Destroy child VGImage
2021 * Processes A and B:
2022 Close the VGImage and RSgImage driver
2024 @SYMTestExpectedResults
2025 The content of each section read by client process should match the content written by Process A.
2026 All image memory should be freed
2028 TVerdict CEglTest_EGL_Image_Multi_Process_VgImage_ReadWrite::doTestStepL()
2030 SetTestStepID(_L("GRAPHICS-EGL-0431"));
2031 SetTestStepName(KEGL_Image_Multi_Process_VgImage_ReadWrite);
2032 INFO_PRINTF1(_L("Enter: CEglTest_EGL_Image_Multi_Process_VgImage_ReadWrite::doTestStepL"));
2034 TBool ret = CheckForExtensionL(KEGL_RSgimage | KEGL_KHR_image_base | KEGL_KHR_image_pixmap | KVG_KHR_EGL_image);
2037 // The extension is not supported
2038 RecordTestResultL();
2039 CloseTMSGraphicsStep();
2040 return TestStepResult();
2043 // This test is performed for ARGB_8888 non pre-multiplied
2044 // as we compare pixels manually, we avoid having to do the pre-multiply in the test itself
2045 iSourceFormat = EUidPixelFormatARGB_8888;
2046 iSurfaceFormat = VG_sARGB_8888;
2047 PrintUsedPixelConfiguration();
2049 // launch 2 processes
2050 Test_MultiProcessL(KEglTestStepDllName, 2, TestStepName());
2052 INFO_PRINTF1(_L("Exit: CEglTest_EGL_Image_Multi_Process_VgImage_ReadWrite::doTestStepL"));
2053 RecordTestResultL();
2054 CloseTMSGraphicsStep();
2055 return TestStepResult();
2058 void CEglTest_EGL_Image_Multi_Process_VgImage_ReadWrite::doProcessFunctionL(TInt aIdx)
2060 INFO_PRINTF2(_L("CEglTest_EGL_Image_Multi_Process_VgImage_ReadWrite::doProcessFunctionL, Process %d"),aIdx);
2062 CreateEglSessionL(aIdx);
2063 iEglSess->InitializeL();
2064 iEglSess->OpenSgDriverL();
2066 const TSize KTestReadWriteImageSize(90,90);
2067 const TInt KTestReadWriteSubImageLength = KTestReadWriteImageSize.iHeight / 3;
2068 const TInt KTestNumColors = 9;
2069 const VGfloat KTestClearColors[KTestNumColors][4] =
2071 {0.11f, 0.13f, 0.15f, 0.17f}, // arbitrary colour 1
2072 {0.21f, 0.23f, 0.25f, 0.27f}, // arbitrary colour 2
2073 {0.31f, 0.33f, 0.35f, 0.37f}, // arbitrary colour 3
2074 {0.41f, 0.43f, 0.45f, 0.47f}, // arbitrary colour 4
2075 {0.51f, 0.53f, 0.55f, 0.57f}, // arbitrary colour 5
2076 {0.61f, 0.63f, 0.65f, 0.67f}, // arbitrary colour 6
2077 {0.71f, 0.73f, 0.75f, 0.77f}, // arbitrary colour 7
2078 {0.81f, 0.83f, 0.85f, 0.87f}, // arbitrary colour 8
2079 {0.91f, 0.93f, 0.95f, 0.97f} // arbitrary colour 9
2082 //Retrieve source formats for the launched process from the process parameters.
2083 User::LeaveIfError(User::GetTIntParameter(EProcSlotSourceFormat, reinterpret_cast<TInt&>(iSourceFormat)));
2084 User::LeaveIfError(User::GetTIntParameter(EProcSlotSurfaceFormat, reinterpret_cast<TInt&>(iSurfaceFormat)));
2086 //create the queue to send/receive SgImage ID between processes
2087 RMsgQueue<TSgDrawableId> messageQueueSgId;
2088 User::LeaveIfError(messageQueueSgId.Open(EProcSlotMsgQueueSgId, EOwnerProcess));
2089 CleanupClosePushL(messageQueueSgId);
2091 RSgImage rSgImageLocal;
2094 // Create an RSgImage
2095 INFO_PRINTF2(_L("Process %d, Creating a RSgImage"),aIdx);
2096 TSgImageInfoOpenVgImage imageInfo = TSgImageInfoOpenVgImage(iSourceFormat, KImageSize);
2097 #ifndef SYMBIAN_GRAPHICS_EGL_SGIMAGELITE
2098 imageInfo.iShareable = ETrue;
2099 imageInfo.iCpuAccess = ESgCpuAccessReadWrite;
2101 ASSERT_EQUALS(rSgImageLocal.Create(imageInfo,NULL, NULL), KErrNone);
2103 INFO_PRINTF2(_L("Process %d, Sending SgImage ID to other process..."), aIdx);
2104 messageQueueSgId.SendBlocking(rSgImageLocal.Id());
2108 INFO_PRINTF2(_L("Process %d: Receiving SgImage ID from other process..."), aIdx);
2109 TSgDrawableId sgImageId;
2110 messageQueueSgId.ReceiveBlocking(sgImageId);
2111 ASSERT_EQUALS(rSgImageLocal.Open(sgImageId),KErrNone);
2114 // Wait for both processes to reach this point
2117 INFO_PRINTF2(_L("Process %d, Creating an EGLImage from the shared RSgImage"),aIdx);
2118 CleanupClosePushL(rSgImageLocal);
2119 EGLImageKHR eglImageLocal = iEglSess->eglCreateImageKhrL(iDisplay, EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, &rSgImageLocal, KEglImageAttribsPreservedTrue);
2120 ASSERT_EGL_TRUE(eglImageLocal != EGL_NO_IMAGE_KHR);
2121 CleanupStack::PopAndDestroy(&rSgImageLocal); //transferring ownership of the buffer to the EGLImage
2123 // OpenVG needs a current VG context before it will allow the call vgCreateEGLImageTargetKHR
2124 // The created surface will remain un-used, hence we create it with the default pixel format, as we don't care
2125 TUidPixelFormat pixelFormat = EglTestConversion::VgFormatToSgPixelFormat(KDefaultSurfaceFormat);
2126 TSgImageInfoOpenVgTarget imageInfo = TSgImageInfoOpenVgTarget(pixelFormat, KTestReadWriteImageSize);
2127 iEglSess->CreatePixmapSurfaceAndMakeCurrentAndMatchL(imageInfo,CTestEglSession::EResourceCloseSgImageEarly);
2129 INFO_PRINTF2(_L("Process %d, Creating one VGImage from the EGLImage"),aIdx);
2130 VGImage vgImageLocal = iEglSess->vgCreateImageTargetKHR((VGeglImageKHR)eglImageLocal);
2131 ASSERT_VG_TRUE(vgImageLocal != VG_INVALID_HANDLE);
2132 ASSERT_EGL_TRUE(iEglSess->DestroyEGLImage(iDisplay, eglImageLocal));
2134 // Wait for both processes to reach this point
2137 for (TInt section=0; section<9; section++)
2139 INFO_PRINTF3(_L("Process %d, Starting loop for section[%d]"),aIdx, section);
2142 INFO_PRINTF3(_L("Process %d, Shading section[%d]"),aIdx, section);
2143 //Shade section[i] to color[i]
2144 vgSetfv(VG_CLEAR_COLOR, 4, KTestClearColors[section]);
2145 vgClearImage(vgImageLocal, (section%3)*KTestReadWriteSubImageLength, (section/3)*KTestReadWriteSubImageLength, KTestReadWriteSubImageLength, KTestReadWriteSubImageLength);
2149 // Wait for both processes to reach this point
2152 VGImage childImage = VG_INVALID_HANDLE;
2155 INFO_PRINTF3(_L("Process %d, Creating child vgimage for section[%d]"),aIdx, section);
2156 //Create child VGImage for section[i]
2157 childImage = vgChildImage(vgImageLocal, (section%3)*KTestReadWriteSubImageLength, (section/3)*KTestReadWriteSubImageLength, KTestReadWriteSubImageLength, KTestReadWriteSubImageLength);
2158 //Read the value of child VGImage and compare it with colour[i]
2159 TUint32* vgPixel = new(ELeave) TUint32[KTestReadWriteSubImageLength];
2160 CleanupArrayDeletePushL(vgPixel);
2161 for (TInt i=0; i<KTestReadWriteSubImageLength; i++)
2163 // Read childImage, a line at a time
2164 vgGetImageSubData(childImage, vgPixel, 1, iSurfaceFormat, 0, i, KTestReadWriteSubImageLength, 1);
2165 for (TInt j=0; j<KTestReadWriteSubImageLength; j++)
2167 // Should be exact, but give a tolerance of 1 because VG rounds to nearer integer, whereas TInt rounds down
2168 ASSERT_TRUE(Abs(((vgPixel[j] & 0xff000000) >> 24) - (255 * KTestClearColors[section][3])) <= 1); //alpha
2169 ASSERT_TRUE(Abs(((vgPixel[j] & 0x00ff0000) >> 16) - (255 * KTestClearColors[section][0])) <= 1); //red
2170 ASSERT_TRUE(Abs(((vgPixel[j] & 0x0000ff00) >> 8) - (255 * KTestClearColors[section][1])) <= 1); //green
2171 ASSERT_TRUE(Abs(((vgPixel[j] & 0x000000ff) >> 0) - (255 * KTestClearColors[section][2])) <= 1); //blue
2174 CleanupStack::PopAndDestroy(vgPixel);
2178 INFO_PRINTF3(_L("Process %d, Shading surrounding sections to section[%d]"),aIdx, section);
2179 for (TInt k=-3; k<=3; k=k+2)
2181 TInt surroundingSection = (KTestNumColors + section + k) % KTestNumColors;
2182 vgSetfv(VG_CLEAR_COLOR, 4, KTestClearColors[surroundingSection]);
2183 vgClearImage(vgImageLocal, (surroundingSection%3)*KTestReadWriteSubImageLength, (surroundingSection/3)*KTestReadWriteSubImageLength, KTestReadWriteSubImageLength, KTestReadWriteSubImageLength);
2188 // Wait for both processes to reach this point
2193 INFO_PRINTF3(_L("Process %d, destroying child vgimage for section[%d]"),aIdx, section);
2194 //Destroy child VGImage
2195 vgDestroyImage(childImage);
2196 ASSERT_TRUE(vgGetError() == VG_NO_ERROR);
2201 vgDestroyImage(vgImageLocal);
2202 ASSERT_TRUE(vgGetError() == VG_NO_ERROR);
2203 CleanupStack::PopAndDestroy(&messageQueueSgId);