void QVGPixmapData::destroyImageAndContext() { if (vgImage != VG_INVALID_HANDLE) { // We need to have a context current to destroy the image. #if !defined(QT_NO_EGL) if (context->isCurrent()) { destroyImages(); } else { // We don't currently have a widget surface active, but we // need a surface to make the context current. So use the // shared pbuffer surface instead. context->makeCurrent(qt_vg_shared_surface()); destroyImages(); context->lazyDoneCurrent(); } #else destroyImages(); #endif } #if !defined(QT_NO_EGL) if (context) { qt_vg_destroy_context(context, QInternal::Pixmap); context = 0; } #endif recreate = true; }
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(); vgImage = sgImageToVGImage(context, *sgImage); if (vgImage != VG_INVALID_HANDLE) { w = vgGetParameteri(vgImage, VG_IMAGE_WIDTH); h = vgGetParameteri(vgImage, VG_IMAGE_HEIGHT); d = 32; // We always use ARGB_Premultiplied for VG pixmaps. } is_null = (w <= 0 || h <= 0); source = QVolatileImage(); // readback will be done later, only when needed recreate = false; prevSize = QSize(w, h); updateSerial(); #endif } else if (type == QPixmapData::FbsBitmap && pixmap) { CFbsBitmap *bitmap = reinterpret_cast<CFbsBitmap *>(pixmap); QSize size(bitmap->SizeInPixels().iWidth, bitmap->SizeInPixels().iHeight); resize(size.width(), size.height()); source = QVolatileImage(bitmap); // duplicates only, if possible if (source.isNull()) return; if (!conversionLessFormat(source.format())) { // Here we may need to copy if the formats do not match. // (e.g. for display modes other than EColor16MAP and EColor16MU) source.beginDataAccess(); QImage::Format format = idealFormat(&source.imageRef(), Qt::AutoColor); source.endDataAccess(true); source.ensureFormat(format); } recreate = true; } else if (type == QPixmapData::VolatileImage && pixmap) { QVolatileImage *img = static_cast<QVolatileImage *>(pixmap); resize(img->width(), img->height()); source = *img; recreate = true; } else if (type == QPixmapData::NativeImageHandleProvider && pixmap) { destroyImages(); nativeImageHandleProvider = static_cast<QNativeImageHandleProvider *>(pixmap); // Cannot defer the retrieval, we need at least the size right away. createFromNativeImageHandleProvider(); } }
void QVGPixmapData::reclaimImages() { if (!inImagePool) return; forceToImage(); destroyImages(); }
VGImage QVGPixmapData::toVGImage() { if (!isValid() || failedToAlloc) return VG_INVALID_HANDLE; #if !defined(QT_NO_EGL) // Increase the reference count on the shared context. if (!context) context = qt_vg_create_context(0, QInternal::Pixmap); #endif if (recreate && prevSize != QSize(w, h)) destroyImages(); else if (recreate) cachedOpacity = -1.0f; // Force opacity image to be refreshed later. #if defined(Q_OS_SYMBIAN) if (recreate && nativeImageHandleProvider && !nativeImageHandle) { createFromNativeImageHandleProvider(); } #endif if (vgImage == VG_INVALID_HANDLE) { vgImage = QVGImagePool::instance()->createImageForPixmap (qt_vg_image_to_vg_format(source.format()), w, h, VG_IMAGE_QUALITY_FASTER, this); // Bail out if we run out of GPU memory - try again next time. if (vgImage == VG_INVALID_HANDLE) { failedToAlloc = true; return VG_INVALID_HANDLE; } inImagePool = true; } else if (inImagePool) { QVGImagePool::instance()->useImage(this); } if (!source.isNull() && recreate) { source.beginDataAccess(); vgImageSubData (vgImage, source.constBits(), source.bytesPerLine(), qt_vg_image_to_vg_format(source.format()), 0, 0, w, h); source.endDataAccess(true); } recreate = false; prevSize = QSize(w, h); return vgImage; }
VGImage QVGPixmapData::toVGImage() { if (!isValid()) return VG_INVALID_HANDLE; #if !defined(QT_NO_EGL) // Increase the reference count on the shared context. if (!context) context = qt_vg_create_context(0, QInternal::Pixmap); #endif if (recreate && prevSize != QSize(w, h)) destroyImages(); else if (recreate) cachedOpacity = -1.0f; // Force opacity image to be refreshed later. if (vgImage == VG_INVALID_HANDLE) { vgImage = QVGImagePool::instance()->createImageForPixmap (VG_sARGB_8888_PRE, w, h, VG_IMAGE_QUALITY_FASTER, this); // Bail out if we run out of GPU memory - try again next time. if (vgImage == VG_INVALID_HANDLE) return VG_INVALID_HANDLE; inImagePool = true; } else if (inImagePool) { QVGImagePool::instance()->useImage(this); } if (!source.isNull() && recreate) { vgImageSubData (vgImage, source.constBits(), source.bytesPerLine(), VG_sARGB_8888_PRE, 0, 0, w, h); } recreate = false; prevSize = QSize(w, h); return vgImage; }
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; } }