src/openvg/qpixmapdata_vg.cpp
changeset 7 f7bc934e204c
parent 3 41300fa6a67c
--- 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 <private/qt_s60_p.h>
+#include <fbs.h>
+#endif
 #ifdef QT_SYMBIAN_SUPPORTS_SGIMAGE
-#include <graphics/sgimage.h>
+#include <sgresource/sgimage.h>
 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<RSgImage*>(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<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;
     }
-#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<void*>(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<void*>(bitmap);
     }
-#else
-    Q_UNUSED(type);
     return 0;
-#endif
 }
 #endif //Q_OS_SYMBIAN