/** @SYMTestCaseID GRAPHICS-RESOURCE-0201 @SYMTestCaseDesc Test Graphics Resource with low memory conditions. @SYMPREQ PREQ2637 @SYMFssID RSgImage RSgDrawable RSgDriver @SYMTestPriority High @SYMTestType UT @SYMTestPurpose To ensure the correct errors or KErrNoMemory are returned by graphics resource apis under low memory conditions. @SYMTestActions Force allocations to fail on the RSgDrivers heap, try running each of the conformance tests and stress tests to ensure no RSgDriver allocated memory or heap memory is leaked. It also creates an image in this process which is used in another process for OOM testing. @SYMTestExpectedResults Return codes of the functions tested should be either the expected value or KErrNoMemory This is handled by CTSgTestStepBase::CheckErrorL. No ALLOC or SGALLOC panics should occur. */ void CTGraphicsResourceInternal::TestOOML() { // drawable OOM test TSgResIntTestInfo testInfo = { ESgResIntDrawableOOM }; TInt result = CreateSecondProcessAndDoTestL(KInternalTestsSecondProcess, testInfo); TEST(result & EFirstTestPassed); // image OOM test testInfo.iTestCase = ESgResIntImageOOM; RSgDriver sgDriver; TInt err = sgDriver.Open(); TESTEL(err == KErrNone, err); CleanupClosePushL(sgDriver); RSgImage image1; TSgImageInfo info1(TSize(8, 8), EUidPixelFormatRGB_565, ESgUsageBitOpenVgImage); err = image1.Create(info1); TESTEL(err == KErrNone, err); CleanupClosePushL(image1); testInfo.iDrawableId = image1.Id(); result = CreateSecondProcessAndDoTestL(KInternalTestsSecondProcess, testInfo); TEST(result & EFirstTestPassed); CleanupStack::PopAndDestroy(2, &sgDriver); }
/** @SYMTestCaseID GRAPHICS-RESOURCE-0022 @SYMTestCaseDesc Shuts down an uninitialised driver. @SYMPREQ PREQ2637 @SYMFssID RSgDriver::Close() @SYMTestPriority Low @SYMTestType UT @SYMTestPurpose To ensure invalid Close() calls on the driver will cause no errors. @SYMTestActions Call RSgDriver::Close() several times without calling RSgDriver::Open(). @SYMTestExpectedResults No errors should be returned. */ void CTSgDriver::TestShutdownUninitialized() { __UHEAP_MARK; RSgDriver sgDriver; sgDriver.Close(); sgDriver.Close(); sgDriver.Close(); __UHEAP_MARKEND; }
/** @SYMTestCaseID GRAPHICS-RESOURCE-0096 @SYMTestCaseDesc Test the version number returned by RSgDriver is correct. @SYMPREQ PREQ2637 @SYMFssID RSgDriver::Version() @SYMTestPriority Medium @SYMTestType UT @SYMTestPurpose To check the correct version of the driver is being used in the conformance tests. @SYMTestActions Call RSgDriver::Version(). @SYMTestExpectedResults The correct version should be returned. */ void CTSgDriver::TestVersion() { __UHEAP_MARK; RSgDriver sgDriver; TVersion vers = sgDriver.Version(); TEST(vers.iMajor == 1); TEST(vers.iMinor == 1); __UHEAP_MARKEND; }
/* @SYMTestCaseID GRAPHICS-RESOURCE-0204 @SYMTestCaseDesc Test usage bit @SYMPREQ PREQ2637 @SYMFssID RSgImage RSgDrawable RSgDriver @SYMTestPriority High @SYMTestType UT @SYMTestPurpose To ensure that an image can be created using various usage bit, and the usage bit of created image is correct. @SYMTestActions Create an image with selection of usage bit. Check if the return code of SgImage::Create is correct. If creation succeeds, open the image and check if the usage bit is the same to the one expected. NOTE: The usage bit may not be the same as the one that is used to create an image - it depends on the implementation. @SYMTestExpectedResults The usage bit should match the expected usage bit. */ void CTGraphicsResourceInternal::TestUsageBitsL() { RSgDriver driver; User::LeaveIfError(driver.Open()); CleanupClosePushL(driver); for(TInt i=0; i < KUsageBitTestCount; ++i) { TSgImageInfo info(TSize(8, 8), KUsageBitTestCases[i].iPixelFormat, KUsageBitTestCases[i].iUsageBit); RSgImage image; TInt err = image.Create(info); CleanupClosePushL(image); if(err != KUsageBitTestCases[i].iExpectedReturnCode) { ERR_PRINTF3(_L("Test case index: %d, Test failed with error: %d"), i, err); SetTestStepResult(EFail); } if(err == KErrNone) { TSgImageInfo info1; User::LeaveIfError(image.GetInfo(info1)); if(info1.iUsage != KUsageBitTestCases[i].iExpectedUsageBit) { ERR_PRINTF3(_L("Test case index: %d, info1 usage bit 0x%04X"), i, info1.iUsage); SetTestStepResult(EFail); } } CleanupStack::PopAndDestroy(&image); } CleanupStack::PopAndDestroy(&driver); }
/** @SYMTestCaseID GRAPHICS-RESOURCE-0099 @SYMTestCaseDesc Test SgDriver Handles Multiple Calls to Open Correctly @SYMPREQ PREQ2637 @SYMFssID RSgDriver::Open() @SYMTestPriority High @SYMTestType UT @SYMTestPurpose To ensure the correct error code is returned when an open driver is opened @SYMTestActions Call RSgDriver::Open(). @SYMTestExpectedResults KErrInUse should be returned when the driver is opened for the second time and all subsequent times. */ void CTSgDriver::TestMultipleOpens() { __UHEAP_MARK; TInt err = KErrNone; RSgDriver sgDriver; err = sgDriver.Open(); TESTE(KErrNone == err, err); err = sgDriver.Open(); TESTE(KErrInUse == err, err); err = sgDriver.Open(); TESTE(KErrInUse == err, err); err = sgDriver.Open(); TESTE(KErrInUse == err, err); sgDriver.Close(); __UHEAP_MARKEND; }
void CTSgDriver::TestGetInterface() { __UHEAP_MARK; RSgDriver sgDriver; TInt err = sgDriver.Open(); TESTE(err == KErrNone, err); MFakeInterface* fakeInterface = NULL; err = sgDriver.GetInterface(fakeInterface); TESTE(err == KErrExtensionNotSupported, err); MNullInterface* nullInterface = NULL; err = sgDriver.GetInterface(nullInterface); TESTE(err == KErrArgument, err); sgDriver.Close(); err = sgDriver.GetInterface(fakeInterface); TESTE(err == KErrBadHandle, err); err = sgDriver.GetInterface(nullInterface); TESTE(err == KErrBadHandle, err); __UHEAP_MARKEND; }
void* QVGPixmapData::toNativeType(NativeType type) { if (type == QPixmapData::SgImage) { #if defined(QT_SYMBIAN_SUPPORTS_SGIMAGE) && !defined(QT_NO_EGL) toVGImage(); if (!isValid() || vgImage == VG_INVALID_HANDLE) return 0; TInt err = 0; RSgDriver driver; err = driver.Open(); if (err != KErrNone) return 0; TSgImageInfo sgInfo; sgInfo.iPixelFormat = EUidPixelFormatARGB_8888_PRE; sgInfo.iSizeInPixels.SetSize(w, h); sgInfo.iUsage = ESgUsageBitOpenVgImage | ESgUsageBitOpenVgSurface; QScopedPointer<RSgImage> sgImage(new RSgImage()); err = sgImage->Create(sgInfo, NULL, NULL); if (err != KErrNone) { driver.Close(); return 0; } const EGLint KEglImageAttribs[] = {EGL_IMAGE_PRESERVED_SYMBIAN, EGL_TRUE, EGL_NONE}; EGLImageKHR eglImage = QEgl::eglCreateImageKHR(QEgl::display(), EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, (EGLClientBuffer)sgImage.data(), (EGLint*)KEglImageAttribs); if (!eglImage || eglGetError() != EGL_SUCCESS) { sgImage->Close(); driver.Close(); return 0; } VGImage dstVgImage = QVG::vgCreateEGLImageTargetKHR(eglImage); if (!dstVgImage || vgGetError() != VG_NO_ERROR) { QEgl::eglDestroyImageKHR(QEgl::display(), eglImage); sgImage->Close(); driver.Close(); return 0; } vgCopyImage(dstVgImage, 0, 0, vgImage, 0, 0, w, h, VG_FALSE); if (vgGetError() != VG_NO_ERROR) { sgImage->Close(); sgImage.reset(); } // release stuff vgDestroyImage(dstVgImage); QEgl::eglDestroyImageKHR(QEgl::display(), eglImage); driver.Close(); return reinterpret_cast<void*>(sgImage.take()); #endif } else if (type == QPixmapData::FbsBitmap && isValid()) { ensureReadback(true); if (source.isNull()) { source = QVolatileImage(w, h, sourceFormat()); } // Just duplicate the bitmap handle, no data copying happens. return source.duplicateNativeImage(); } return 0; }
void* QVGPixmapData::toNativeType(NativeType type) { if (type == QPixmapData::SgImage) { #if defined(QT_SYMBIAN_SUPPORTS_SGIMAGE) && !defined(QT_NO_EGL) toVGImage(); if (!isValid() || vgImage == VG_INVALID_HANDLE) return 0; TInt err = 0; RSgDriver driver; err = driver.Open(); if (err != KErrNone) return 0; TSgImageInfo sgInfo; sgInfo.iPixelFormat = EUidPixelFormatARGB_8888_PRE; sgInfo.iSizeInPixels.SetSize(w, h); sgInfo.iUsage = ESgUsageBitOpenVgImage | ESgUsageBitOpenVgSurface; RSgImage *sgImage = q_check_ptr(new RSgImage()); err = sgImage->Create(sgInfo, NULL, NULL); if (err != KErrNone) { driver.Close(); return 0; } pfnVgCreateEGLImageTargetKHR vgCreateEGLImageTargetKHR = (pfnVgCreateEGLImageTargetKHR) eglGetProcAddress("vgCreateEGLImageTargetKHR"); if (eglGetError() != EGL_SUCCESS || !(QEgl::hasExtension("EGL_KHR_image") || QEgl::hasExtension("EGL_KHR_image_pixmap")) || !vgCreateEGLImageTargetKHR) { driver.Close(); return 0; } const EGLint KEglImageAttribs[] = {EGL_IMAGE_PRESERVED_SYMBIAN, EGL_TRUE, EGL_NONE}; EGLImageKHR eglImage = QEgl::eglCreateImageKHR(QEgl::display(), EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, (EGLClientBuffer)sgImage, (EGLint*)KEglImageAttribs); if (eglGetError() != EGL_SUCCESS) { sgImage->Close(); driver.Close(); return 0; } VGImage dstVgImage = vgCreateEGLImageTargetKHR(eglImage); if (vgGetError() != VG_NO_ERROR) { QEgl::eglDestroyImageKHR(QEgl::display(), eglImage); sgImage->Close(); driver.Close(); return 0; } vgCopyImage(dstVgImage, 0, 0, vgImage, 0, 0, w, h, VG_FALSE); if (vgGetError() != VG_NO_ERROR) { sgImage->Close(); sgImage = 0; } // release stuff vgDestroyImage(dstVgImage); QEgl::eglDestroyImageKHR(QEgl::display(), eglImage); driver.Close(); return reinterpret_cast<void*>(sgImage); #endif } else if (type == QPixmapData::FbsBitmap) { CFbsBitmap *bitmap = q_check_ptr(new CFbsBitmap); if (bitmap) { if (bitmap->Create(TSize(source.width(), source.height()), EColor16MAP) == KErrNone) { const uchar *sptr = source.constBits(); bitmap->BeginDataAccess(); uchar *dptr = (uchar*)bitmap->DataAddress(); Mem::Copy(dptr, sptr, source.byteCount()); bitmap->EndDataAccess(); } else { delete bitmap; bitmap = 0; } } return reinterpret_cast<void*>(bitmap); } return 0; }
void QVGPixmapData::fromNativeType(void* pixmap, NativeType type) { if (type == QPixmapData::SgImage && pixmap) { #if defined(QT_SYMBIAN_SUPPORTS_SGIMAGE) && !defined(QT_NO_EGL) RSgImage *sgImage = reinterpret_cast<RSgImage*>(pixmap); destroyImages(); prevSize = QSize(); TInt err = 0; RSgDriver driver; err = driver.Open(); if (err != KErrNone) { cleanup(); return; } if (sgImage->IsNull()) { cleanup(); driver.Close(); return; } TSgImageInfo sgImageInfo; err = sgImage->GetInfo(sgImageInfo); if (err != KErrNone) { cleanup(); driver.Close(); return; } pfnVgCreateEGLImageTargetKHR vgCreateEGLImageTargetKHR = (pfnVgCreateEGLImageTargetKHR) eglGetProcAddress("vgCreateEGLImageTargetKHR"); if (eglGetError() != EGL_SUCCESS || !(QEgl::hasExtension("EGL_KHR_image") || QEgl::hasExtension("EGL_KHR_image_pixmap")) || !vgCreateEGLImageTargetKHR) { cleanup(); driver.Close(); return; } const EGLint KEglImageAttribs[] = {EGL_IMAGE_PRESERVED_SYMBIAN, EGL_TRUE, EGL_NONE}; EGLImageKHR eglImage = QEgl::eglCreateImageKHR(QEgl::display(), EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, (EGLClientBuffer)sgImage, (EGLint*)KEglImageAttribs); if (eglGetError() != EGL_SUCCESS) { cleanup(); driver.Close(); return; } vgImage = vgCreateEGLImageTargetKHR(eglImage); if (vgGetError() != VG_NO_ERROR) { cleanup(); QEgl::eglDestroyImageKHR(QEgl::display(), eglImage); driver.Close(); return; } w = sgImageInfo.iSizeInPixels.iWidth; h = sgImageInfo.iSizeInPixels.iHeight; d = 32; // We always use ARGB_Premultiplied for VG pixmaps. is_null = (w <= 0 || h <= 0); source = QImage(); recreate = false; prevSize = QSize(w, h); setSerialNumber(++qt_vg_pixmap_serial); // release stuff QEgl::eglDestroyImageKHR(QEgl::display(), eglImage); driver.Close(); #endif } else if (type == QPixmapData::FbsBitmap) { CFbsBitmap *bitmap = reinterpret_cast<CFbsBitmap*>(pixmap); bool deleteSourceBitmap = false; #ifdef Q_SYMBIAN_HAS_EXTENDED_BITMAP_TYPE // Rasterize extended bitmaps TUid extendedBitmapType = bitmap->ExtendedBitmapType(); if (extendedBitmapType != KNullUid) { bitmap = createBlitCopy(bitmap); deleteSourceBitmap = true; } #endif if (bitmap->IsCompressedInRAM()) { bitmap = createBlitCopy(bitmap); deleteSourceBitmap = true; } TDisplayMode displayMode = bitmap->DisplayMode(); QImage::Format format = qt_TDisplayMode2Format(displayMode); TSize size = bitmap->SizeInPixels(); bitmap->BeginDataAccess(); uchar *bytes = (uchar*)bitmap->DataAddress(); QImage img = QImage(bytes, size.iWidth, size.iHeight, format); img = img.copy(); bitmap->EndDataAccess(); if(displayMode == EGray2) { //Symbian thinks set pixels are white/transparent, Qt thinks they are foreground/solid //So invert mono bitmaps so that masks work correctly. img.invertPixels(); } else if(displayMode == EColor16M) { img = img.rgbSwapped(); // EColor16M is BGR } fromImage(img, Qt::AutoColor); if(deleteSourceBitmap) delete bitmap; } }
LOCAL_C void LaunchClientProcessL() { __UHEAP_MARK; RProcess::Rendezvous(KErrNone); RSemaphore sem; User::LeaveIfError(sem.OpenGlobal(KEglStressTest)); CleanupClosePushL(sem); //Access data passed from the main process TStressProcessInfo info; TPckg<TStressProcessInfo> pckgInfo(info); User::LeaveIfError(User::GetDesParameter(KMultiProcessSlot, pckgInfo)); //Create RSgDriver and open the image RSgDriver driver; User::LeaveIfError(driver.Open()); CleanupClosePushL(driver); RSgImage image; User::LeaveIfError(image.Open(info.iSgId)); CleanupClosePushL(image); EGLDisplay display; EGL_LEAVE_NULL(display, eglGetDisplay(EGL_DEFAULT_DISPLAY)); EGL_LEAVE_ERROR(eglInitialize(display, NULL, NULL)); EGL_LEAVE_ERROR(eglBindAPI(EGL_OPENVG_API)); //Initialise to remove arm compiler warnings EGLConfig config = 0; EGLContext context = EGL_NO_CONTEXT; EGLSurface surface = EGL_NO_SURFACE; if(info.iTestType == EStressRead) { TSgImageInfo sginfo; User::LeaveIfError(image.GetInfo(sginfo)); //Create an independant pixmap surface on which to copy the vgimage RSgImage image2; User::LeaveIfError(image2.Create(sginfo, NULL, NULL)); CleanupClosePushL(image2); ChooseConfigAndCreateContextL(display, context, config, image2, KStressTestChildAppPanic, info.iAlphaPre); EGL_LEAVE_NULL(surface, CreatePixmapSurfaceL(display, config, image2, info.iAlphaPre)); CleanupStack::PopAndDestroy(&image2); } else { ChooseConfigAndCreateContextL(display, context, config, image, KStressTestChildAppPanic, info.iAlphaPre); EGL_LEAVE_NULL(surface, CreatePixmapSurfaceL(display, config, image, info.iAlphaPre)); } EGL_LEAVE_ERROR(eglMakeCurrent(display, surface, surface, context)); VGImage vgImage; GenerateVgImageL(display, &image, vgImage); /* Create and install the active scheduler */ CActiveScheduler* sched = new(ELeave) CActiveScheduler; CActiveScheduler::Install(sched); CleanupStack::PushL(sched); TInt width = vgGetParameteri(vgImage, VG_IMAGE_WIDTH); VgLeaveIfErrorL(); TInt height = vgGetParameteri(vgImage, VG_IMAGE_HEIGHT); VgLeaveIfErrorL(); VGImageFormat format = static_cast<VGImageFormat>(vgGetParameteri(vgImage, VG_IMAGE_FORMAT)); VgLeaveIfErrorL(); TBool testPass = ETrue; CTReadWriteChild* painter = CTReadWriteChild::NewL(vgImage, width, height, info.iByteSize, format, info.iTestType, testPass); CleanupStack::PushL(painter); painter->After(TTimeIntervalMicroSeconds32(0)); //Data access is synchronised from the main process sem.Wait(); sched->Start(); if(testPass == EFalse) { // Leave with a 'known' test error so that we can catch this particular failure User::Leave(KTestStressUnexpectedPixelError); } CleanupStack::PopAndDestroy(5, &sem); //painter, sched, image, driver, sem __UHEAP_MARKEND; }
/* @SYMTestCaseID GRAPHICS-RESOURCE-0111 @SYMTestCaseDesc Test MSgDriver_Profiling extension. @SYMPREQ PREQ2637 @SYMFssID RSgImage RSgDriver MSgDriver_Profiling @SYMTestPriority Medium @SYMTestType UT @SYMTestPurpose To test that the extension MSgDriver_Profiling correctly reports the correct global and local resource count and memory usage when resources are created in separate processes. @SYMTestActions Get the MSgDriver_Profiling extension, query memory/resource usage. Create an image and check the memory usage and count. Launch a separate process that checks the same memory usage/count. Create an image in this separate process and check the global resource count and memory. Close the image nad check the memory usage and resource count. Terminate the second process. Check the local and global count in the first process. Close the image in this process and check the global and local resource count. @SYMTestExpectedResults When creating the first image, the local resource count should equal one, the global count should increment. The local memory usage should increase by at least the size of the image in pixels * byte-depth. The global memory usage should increase by the same amount. Second process should report the same global resouce count and memory as the first process. Second process image creation to cause same usage/count increase as did first image. Closing the image in the second process should set count and memory usage back to initial values, and local count/usage to zero. Closing the image in the first process should set the count and memory usage back to their pre-test values, and local count/usage to zero. */ void CTGraphicsResourceInternal::TestResourceProfilingL() { __UHEAP_MARK; RSgDriver sgDriver; TInt err = sgDriver.Open(); TESTE(err == KErrNone, err); if (KErrNone == err) { MSgDriver_Profiling* profiling = NULL; err = sgDriver.GetInterface(profiling); if (!profiling || err != KErrNone) { ERR_PRINTF2(_L("Failed to get MSgDriver_Profiling extension [%d]"), err); SetTestStepResult(EFail); return; } const TInt originalGlobalResourceCount = profiling->GlobalResourceCount(); const TInt originalGlobalGraphicsMemory = profiling->GlobalGraphicsMemoryUsed(); TEST(profiling->LocalGraphicsMemoryUsed() == 0); RSgImage image; const TSize KImageSize(8, 8); err = image.Create(TSgImageInfo(KImageSize, EUidPixelFormatARGB_8888, ESgUsageBitOpenVgImage)); TESTE(err == KErrNone, err); // Check that having created an image, the global resource count and memory usage has // increased. TInt localGraphicsMemory = profiling->LocalGraphicsMemoryUsed(); TEST(localGraphicsMemory >= (KImageSize.iWidth * KImageSize.iHeight * 4)); TEST(profiling->GlobalResourceCount() == (originalGlobalResourceCount + 1)); TEST(profiling->GlobalGraphicsMemoryUsed() == (localGraphicsMemory + originalGlobalResourceCount)); TSgResIntTestInfo testInfo = { ESgResIntResourceProfiling }; testInfo.iGlobalGraphicsMemory = profiling->GlobalGraphicsMemoryUsed(); testInfo.iGlobalResourceCount = profiling->GlobalResourceCount(); TInt result = CreateSecondProcessAndDoTestL(KInternalTestsSecondProcess, testInfo); TEST(result & EFirstTestPassed); TEST(result & ESecondTestPassed); TEST(result & EThirdTestPassed); TEST(result & EFourthTestPassed); TEST(result & EFifthTestPassed); TEST(result & ESixthTestPassed); TEST(result & ESeventhTestPassed); TEST(result & EEighthTestPassed); TEST(result & ENinthTestPassed); TEST(result & ETenthTestPassed); TEST(result & EEleventhTestPassed); // Check that the global and local counts are unchanged. TEST(profiling->LocalGraphicsMemoryUsed() == localGraphicsMemory); TEST(profiling->GlobalResourceCount() == (originalGlobalResourceCount + 1)); TEST(profiling->GlobalGraphicsMemoryUsed() == (localGraphicsMemory + originalGlobalResourceCount)); // Check that closing the image shows the image memory is back to zero. image.Close(); TEST(profiling->LocalGraphicsMemoryUsed() == 0); TEST(profiling->GlobalGraphicsMemoryUsed() == originalGlobalGraphicsMemory); TEST(profiling->GlobalResourceCount() == originalGlobalResourceCount); // Cleanup sgDriver.Close(); profiling = NULL; } __UHEAP_MARKEND; }