--- 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