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::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; } }
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; }
/* @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; }