diff -r 41300fa6a67c -r f7bc934e204c src/openvg/qpixmapdata_vg.cpp --- a/src/openvg/qpixmapdata_vg.cpp Tue Feb 02 00:43:10 2010 +0200 +++ b/src/openvg/qpixmapdata_vg.cpp Wed Mar 31 11:06:36 2010 +0300 @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** @@ -45,12 +45,16 @@ #include "qvg_p.h" #include "qvgimagepool_p.h" +#if defined(Q_OS_SYMBIAN) +#include +#include +#endif #ifdef QT_SYMBIAN_SUPPORTS_SGIMAGE -#include +#include typedef EGLImageKHR (*pfnEglCreateImageKHR)(EGLDisplay, EGLContext, EGLenum, EGLClientBuffer, EGLint*); typedef EGLBoolean (*pfnEglDestroyImageKHR)(EGLDisplay, EGLImageKHR); typedef VGImage (*pfnVgCreateEGLImageTargetKHR)(VGeglImageKHR); -#endif +#endif // QT_SYMBIAN_SUPPORTS_SGIMAGE QT_BEGIN_NAMESPACE @@ -232,7 +236,7 @@ // This function works around QImage::bits() making a deep copy if the // QImage is not const. We force it to be const and then get the bits. // XXX: Should add a QImage::constBits() in the future to replace this. -static inline const uchar *qt_vg_imageBits(const QImage& image) +const uchar *qt_vg_imageBits(const QImage& image) { return image.bits(); } @@ -425,6 +429,34 @@ } #if defined(Q_OS_SYMBIAN) + +static CFbsBitmap* createBlitCopy(CFbsBitmap* bitmap) +{ + CFbsBitmap *copy = q_check_ptr(new CFbsBitmap); + if(!copy) + return 0; + + if (copy->Create(bitmap->SizeInPixels(), bitmap->DisplayMode()) != KErrNone) { + delete copy; + copy = 0; + + return 0; + } + + CFbsBitmapDevice* bitmapDevice = 0; + CFbsBitGc *bitmapGc = 0; + QT_TRAP_THROWING(bitmapDevice = CFbsBitmapDevice::NewL(copy)); + QT_TRAP_THROWING(bitmapGc = CFbsBitGc::NewL()); + bitmapGc->Activate(bitmapDevice); + + bitmapGc->BitBlt(TPoint(), bitmap); + + delete bitmapGc; + delete bitmapDevice; + + return copy; +} + void QVGPixmapData::cleanup() { is_null = w = h = 0; @@ -434,36 +466,33 @@ void QVGPixmapData::fromNativeType(void* pixmap, NativeType type) { + if (type == QPixmapData::SgImage && pixmap) { #if defined(QT_SYMBIAN_SUPPORTS_SGIMAGE) && !defined(QT_NO_EGL) - if (type == QPixmapData::SgImage && pixmap) { RSgImage *sgImage = reinterpret_cast(pixmap); - // when "0" used as argument then - // default display, context are used - if (!context) - context = qt_vg_create_context(0, QInternal::Pixmap); destroyImages(); prevSize = QSize(); TInt err = 0; - err = SgDriver::Open(); - if(err != KErrNone) { + RSgDriver driver; + err = driver.Open(); + if (err != KErrNone) { cleanup(); return; } - if(sgImage->IsNull()) { + if (sgImage->IsNull()) { cleanup(); - SgDriver::Close(); + driver.Close(); return; } TSgImageInfo sgImageInfo; err = sgImage->GetInfo(sgImageInfo); - if(err != KErrNone) { + if (err != KErrNone) { cleanup(); - SgDriver::Close(); + driver.Close(); return; } @@ -471,30 +500,30 @@ pfnEglDestroyImageKHR eglDestroyImageKHR = (pfnEglDestroyImageKHR) eglGetProcAddress("eglDestroyImageKHR"); pfnVgCreateEGLImageTargetKHR vgCreateEGLImageTargetKHR = (pfnVgCreateEGLImageTargetKHR) eglGetProcAddress("vgCreateEGLImageTargetKHR"); - if(eglGetError() != EGL_SUCCESS || !eglCreateImageKHR || !eglDestroyImageKHR || !vgCreateEGLImageTargetKHR) { + if (eglGetError() != EGL_SUCCESS || !eglCreateImageKHR || !eglDestroyImageKHR || !vgCreateEGLImageTargetKHR) { cleanup(); - SgDriver::Close(); + driver.Close(); return; } const EGLint KEglImageAttribs[] = {EGL_IMAGE_PRESERVED_SYMBIAN, EGL_TRUE, EGL_NONE}; - EGLImageKHR eglImage = eglCreateImageKHR(context->display(), + EGLImageKHR eglImage = eglCreateImageKHR(QEglContext::display(), EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, (EGLClientBuffer)sgImage, (EGLint*)KEglImageAttribs); - if(eglGetError() != EGL_SUCCESS) { + if (eglGetError() != EGL_SUCCESS) { cleanup(); - SgDriver::Close(); + driver.Close(); return; } vgImage = vgCreateEGLImageTargetKHR(eglImage); - if(vgGetError() != VG_NO_ERROR) { + if (vgGetError() != VG_NO_ERROR) { cleanup(); - eglDestroyImageKHR(context->display(), eglImage); - SgDriver::Close(); + eglDestroyImageKHR(QEglContext::display(), eglImage); + driver.Close(); return; } @@ -507,46 +536,81 @@ prevSize = QSize(w, h); setSerialNumber(++qt_vg_pixmap_serial); // release stuff - eglDestroyImageKHR(context->display(), eglImage); - SgDriver::Close(); + eglDestroyImageKHR(QEglContext::display(), eglImage); + driver.Close(); +#endif } else if (type == QPixmapData::FbsBitmap) { + CFbsBitmap *bitmap = reinterpret_cast(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; } -#else - Q_UNUSED(pixmap); - Q_UNUSED(type); -#endif } void* QVGPixmapData::toNativeType(NativeType type) { + if (type == QPixmapData::SgImage) { #if defined(QT_SYMBIAN_SUPPORTS_SGIMAGE) && !defined(QT_NO_EGL) - if (type == QPixmapData::SgImage) { toVGImage(); - if(!isValid() || vgImage == VG_INVALID_HANDLE) + if (!isValid() || vgImage == VG_INVALID_HANDLE) return 0; TInt err = 0; - err = SgDriver::Open(); - if(err != KErrNone) + RSgDriver driver; + err = driver.Open(); + if (err != KErrNone) return 0; TSgImageInfo sgInfo; sgInfo.iPixelFormat = EUidPixelFormatARGB_8888_PRE; sgInfo.iSizeInPixels.SetSize(w, h); - sgInfo.iUsage = ESgUsageOpenVgImage | ESgUsageOpenVgTarget; - sgInfo.iShareable = ETrue; - sgInfo.iCpuAccess = ESgCpuAccessNone; - sgInfo.iScreenId = KSgScreenIdMain; //KSgScreenIdAny; - sgInfo.iUserAttributes = NULL; - sgInfo.iUserAttributeCount = 0; + sgInfo.iUsage = ESgUsageBitOpenVgImage | ESgUsageBitOpenVgSurface; RSgImage *sgImage = q_check_ptr(new RSgImage()); err = sgImage->Create(sgInfo, NULL, NULL); - if(err != KErrNone) { - SgDriver::Close(); + if (err != KErrNone) { + driver.Close(); return 0; } @@ -554,28 +618,28 @@ pfnEglDestroyImageKHR eglDestroyImageKHR = (pfnEglDestroyImageKHR) eglGetProcAddress("eglDestroyImageKHR"); pfnVgCreateEGLImageTargetKHR vgCreateEGLImageTargetKHR = (pfnVgCreateEGLImageTargetKHR) eglGetProcAddress("vgCreateEGLImageTargetKHR"); - if(eglGetError() != EGL_SUCCESS || !eglCreateImageKHR || !eglDestroyImageKHR || !vgCreateEGLImageTargetKHR) { - SgDriver::Close(); + if (eglGetError() != EGL_SUCCESS || !eglCreateImageKHR || !eglDestroyImageKHR || !vgCreateEGLImageTargetKHR) { + driver.Close(); return 0; } const EGLint KEglImageAttribs[] = {EGL_IMAGE_PRESERVED_SYMBIAN, EGL_TRUE, EGL_NONE}; - EGLImageKHR eglImage = eglCreateImageKHR(context->display(), + EGLImageKHR eglImage = eglCreateImageKHR(QEglContext::display(), EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, (EGLClientBuffer)sgImage, (EGLint*)KEglImageAttribs); - if(eglGetError() != EGL_SUCCESS) { + if (eglGetError() != EGL_SUCCESS) { sgImage->Close(); - SgDriver::Close(); + driver.Close(); return 0; } VGImage dstVgImage = vgCreateEGLImageTargetKHR(eglImage); - if(vgGetError() != VG_NO_ERROR) { - eglDestroyImageKHR(context->display(), eglImage); + if (vgGetError() != VG_NO_ERROR) { + eglDestroyImageKHR(QEglContext::display(), eglImage); sgImage->Close(); - SgDriver::Close(); + driver.Close(); return 0; } @@ -583,22 +647,38 @@ vgImage, 0, 0, w, h, VG_FALSE); - if(vgGetError() != VG_NO_ERROR) { + if (vgGetError() != VG_NO_ERROR) { sgImage->Close(); sgImage = 0; } // release stuff vgDestroyImage(dstVgImage); - eglDestroyImageKHR(context->display(), eglImage); - SgDriver::Close(); + eglDestroyImageKHR(QEglContext::display(), eglImage); + driver.Close(); return reinterpret_cast(sgImage); +#endif } else if (type == QPixmapData::FbsBitmap) { - return 0; + CFbsBitmap *bitmap = q_check_ptr(new CFbsBitmap); + + if (bitmap) { + if (bitmap->Create(TSize(source.width(), source.height()), + EColor16MAP) == KErrNone) { + const uchar *sptr = qt_vg_imageBits(source); + bitmap->BeginDataAccess(); + + uchar *dptr = (uchar*)bitmap->DataAddress(); + Mem::Copy(dptr, sptr, source.byteCount()); + + bitmap->EndDataAccess(); + } else { + delete bitmap; + bitmap = 0; + } + } + + return reinterpret_cast(bitmap); } -#else - Q_UNUSED(type); return 0; -#endif } #endif //Q_OS_SYMBIAN