From ad32d9a2d2c3b1202867f8563a69afb93effecd0 Mon Sep 17 00:00:00 2001 From: Aleksandar Sasha Babic Date: Fri, 18 Sep 2009 14:11:05 +0200 Subject: Adding support for symbian graphics resources. This enables us to convert from and to new Symbian type of graphics resource, namely SgImage. This only supported with the OpenVG graphics system. On other graphics systems this will return null QPixmap. Conflicts: src/corelib/global/qglobal.h src/gui/image/qpixmap.h src/gui/image/qpixmap_s60.cpp Reviewed-by: Jason Barron --- mkspecs/common/symbian/symbian.conf | 2 +- src/corelib/global/qglobal.h | 4 +- src/gui/egl/qegl_symbian.cpp | 3 + src/gui/gui.pro | 2 +- src/gui/image/image.pri | 2 +- src/gui/image/qpixmap.h | 5 +- src/gui/image/qpixmap_s60.cpp | 58 ++++++++++++ src/gui/image/qpixmapdata.cpp | 11 +++ src/gui/image/qpixmapdata_p.h | 9 ++ src/openvg/qpixmapdata_vg.cpp | 178 ++++++++++++++++++++++++++++++++++++ src/openvg/qpixmapdata_vg_p.h | 14 ++- tests/auto/qpixmap/qpixmap.pro | 3 + 12 files changed, 285 insertions(+), 6 deletions(-) diff --git a/mkspecs/common/symbian/symbian.conf b/mkspecs/common/symbian/symbian.conf index b69e308..728703f 100644 --- a/mkspecs/common/symbian/symbian.conf +++ b/mkspecs/common/symbian/symbian.conf @@ -68,7 +68,7 @@ QMAKE_LIBS_GUI = $$QMAKE_LIBS_CORE -lfbscli -lbitgdi -lhal -lgdi -lws32 QMAKE_LIBS_NETWORK = QMAKE_LIBS_EGL = -llibEGL QMAKE_LIBS_OPENGL = -QMAKE_LIBS_OPENVG = -llibOpenVG +QMAKE_LIBS_OPENVG = -llibOpenVG -lgraphicsresource QMAKE_LIBS_COMPAT = QMAKE_LIBS_QT_ENTRY = -llibcrt0.lib QMAKE_LIBS_S60 = -lavkon diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 79a253a..e722268 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -820,7 +820,6 @@ namespace QT_NAMESPACE {} # define Q_WS_WIN #endif - QT_BEGIN_HEADER QT_BEGIN_NAMESPACE @@ -2390,8 +2389,11 @@ QT3_SUPPORT Q_CORE_EXPORT const char *qInstallPathSysconf(); //RWsPointerCursor is fixed, so don't use low performance sprites #define Q_SYMBIAN_FIXED_POINTER_CURSORS #define Q_SYMBIAN_HAS_EXTENDED_BITMAP_TYPE +//enabling new graphics resources +#define QT_SYMBIAN_SUPPORTS_SGIMAGE #endif + //Symbian does not support data imports from a DLL #define Q_NO_DATA_RELOCATION diff --git a/src/gui/egl/qegl_symbian.cpp b/src/gui/egl/qegl_symbian.cpp index 3355f0e..fa0b5cb 100644 --- a/src/gui/egl/qegl_symbian.cpp +++ b/src/gui/egl/qegl_symbian.cpp @@ -98,6 +98,9 @@ EGLDisplay QEglContext::getDisplay(QPaintDevice *device) // Set pixel format and other properties based on a paint device. void QEglProperties::setPaintDeviceFormat(QPaintDevice *dev) { + if(!dev) + return; + int devType = dev->devType(); if (devType == QInternal::Image) setPixelFormat(static_cast(dev)->format()); diff --git a/src/gui/gui.pro b/src/gui/gui.pro index 7c24002..83ac5fe 100644 --- a/src/gui/gui.pro +++ b/src/gui/gui.pro @@ -54,4 +54,4 @@ DEFINES += Q_INTERNAL_QAPP_SRC symbian:TARGET.UID3=0x2001B2DD # ro-section in gui can exceed default allocated space, so more rw-section little further -symbian-sbsv2: MMP_RULES += "LINKEROPTION armcc --rw-base 0x800000" +symbian-sbsv2: MMP_RULES += "LINKEROPTION armcc --rw-base 0x800000" \ No newline at end of file diff --git a/src/gui/image/image.pri b/src/gui/image/image.pri index f365f66..b67be55 100644 --- a/src/gui/image/image.pri +++ b/src/gui/image/image.pri @@ -24,7 +24,7 @@ HEADERS += \ image/qpixmap.h \ image/qpixmap_raster_p.h \ image/qpixmapcache.h \ - image/qpixmapcache_p.h \ + image/qpixmapcache_p.h \ image/qpixmapdata_p.h \ image/qpixmapdatafactory_p.h \ image/qpixmapfilter_p.h \ diff --git a/src/gui/image/qpixmap.h b/src/gui/image/qpixmap.h index 4a8a876..54e89ff 100644 --- a/src/gui/image/qpixmap.h +++ b/src/gui/image/qpixmap.h @@ -54,6 +54,7 @@ QT_BEGIN_HEADER #if defined(Q_OS_SYMBIAN) class CFbsBitmap; +class RSgImage; #endif QT_BEGIN_NAMESPACE @@ -158,9 +159,11 @@ public: #if defined(Q_OS_SYMBIAN) enum ConversionMode { CopyData, DuplicateHandle }; - + CFbsBitmap *toSymbianCFbsBitmap(ConversionMode mode = DuplicateHandle) const; static QPixmap fromSymbianCFbsBitmap(CFbsBitmap *bitmap, ConversionMode mode = DuplicateHandle); + RSgImage* toSymbianRSgImage() const; + static QPixmap fromSymbianRSgImage(RSgImage *sgImage); #endif inline QPixmap copy(int x, int y, int width, int height) const; diff --git a/src/gui/image/qpixmap_s60.cpp b/src/gui/image/qpixmap_s60.cpp index 8a6ecb0..0a81ebd 100644 --- a/src/gui/image/qpixmap_s60.cpp +++ b/src/gui/image/qpixmap_s60.cpp @@ -42,6 +42,8 @@ #include #include +#include +#include #include #include @@ -895,5 +897,61 @@ void QS60PixmapData::endDataAccess(bool readOnly) const symbianBitmapDataAccess->endDataAccess(cfbsBitmap); } +/*! + \since 4.6 + + Returns a QPixmap that wraps given \c RSgImage \a graphics resource. + The data should be valid even when original RSgImage handle has been + closed. + + \warning This function is only available on Symbian OS. + + \sa toSymbianRSgImage(), {QPixmap#Pixmap Conversion}{Pixmap Conversion} +*/ + +QPixmap QPixmap::fromSymbianRSgImage(RSgImage *sgImage) +{ + // It is expected that RSgImage will + // CURRENTLY be used in conjuction with + // OpenVG graphics system + // + // Surely things might change in future + + if (!sgImage) + return QPixmap(); + + QPixmap pixmap; + pixmap.pixmapData()->fromRSgImage(sgImage); + + return pixmap; +} + +/*! +\since 4.6 + +Returns a \c RSgImage that is equivalent to the QPixmap by copying the data. + +It is the caller's responsibility to close/delete the \c RSgImage after use. + +\warning This function is only available on Symbian OS. + +\sa fromSymbianRSgImage() +*/ + +RSgImage *QPixmap::toSymbianRSgImage() const +{ + // It is expected that RSgImage will + // CURRENTLY be used in conjuction with + // OpenVG graphics system + // + // Surely things might change in future + + if (isNull()) + return 0; + + RSgImage *sgImage = pixmapData()->toRSgImage(); + + return sgImage; +} QT_END_NAMESPACE diff --git a/src/gui/image/qpixmapdata.cpp b/src/gui/image/qpixmapdata.cpp index 8ce5447..65899a4 100644 --- a/src/gui/image/qpixmapdata.cpp +++ b/src/gui/image/qpixmapdata.cpp @@ -223,4 +223,15 @@ QImage* QPixmapData::buffer() return 0; } +#if defined(Q_OS_SYMBIAN) +RSgImage* QPixmapData::toRSgImage() +{ + return 0; +} + +void QPixmapData::fromRSgImage(RSgImage* rsgImage) +{ + return; +} +#endif QT_END_NAMESPACE diff --git a/src/gui/image/qpixmapdata_p.h b/src/gui/image/qpixmapdata_p.h index 0af2af8..bac5065 100644 --- a/src/gui/image/qpixmapdata_p.h +++ b/src/gui/image/qpixmapdata_p.h @@ -56,6 +56,10 @@ #include #include +#if defined(Q_OS_SYMBIAN) +class RSgImage; +#endif + QT_BEGIN_NAMESPACE class Q_GUI_EXPORT QPixmapData @@ -109,6 +113,11 @@ public: inline int depth() const { return d; } inline bool isNull() const { return is_null; } +#if defined(Q_OS_SYMBIAN) + virtual RSgImage* toRSgImage(); + virtual void fromRSgImage(RSgImage* rsgImage); +#endif + protected: void setSerialNumber(int serNo); int w; diff --git a/src/openvg/qpixmapdata_vg.cpp b/src/openvg/qpixmapdata_vg.cpp index 03e4a35..53975d7 100644 --- a/src/openvg/qpixmapdata_vg.cpp +++ b/src/openvg/qpixmapdata_vg.cpp @@ -44,6 +44,13 @@ #include #include "qvg_p.h" +#ifdef QT_SYMBIAN_SUPPORTS_SGIMAGE +#include +typedef EGLImageKHR (*pfnEglCreateImageKHR)(EGLDisplay, EGLContext, EGLenum, EGLClientBuffer, EGLint*); +typedef EGLBoolean (*pfnEglDestroyImageKHR)(EGLDisplay, EGLImageKHR); +typedef VGImage (*pfnVgCreateEGLImageTargetKHR)(VGeglImageKHR); +#endif + QT_BEGIN_NAMESPACE static int qt_vg_pixmap_serial = 0; @@ -366,4 +373,175 @@ Q_OPENVG_EXPORT VGImage qPixmapToVGImage(const QPixmap& pixmap) return VG_INVALID_HANDLE; } +#if defined(Q_OS_SYMBIAN) +void QVGPixmapData::cleanup() +{ + is_null = w = h = 0; + recreate = false; + source = QImage(); +} + +void QVGPixmapData::fromRSgImage(RSgImage* sgImage) +{ + Q_UNUSED(sgImage); +#if defined(QT_SYMBIAN_SUPPORTS_SGIMAGE) && !defined(QT_NO_EGL) + // when "0" used as argument then + // default display, context are used + if (!context) + context = qt_vg_create_context(0); + + if (vgImage != VG_INVALID_HANDLE) { + vgDestroyImage(vgImage); + vgImage = VG_INVALID_HANDLE; + } + if (vgImageOpacity != VG_INVALID_HANDLE) { + vgDestroyImage(vgImageOpacity); + vgImageOpacity = VG_INVALID_HANDLE; + } + + TInt err = 0; + + err = SgDriver::Open(); + if(err != KErrNone) { + cleanup(); + return; + } + + if(sgImage->IsNull()) { + cleanup(); + SgDriver::Close(); + return; + } + + TSgImageInfo sgImageInfo; + err = sgImage->GetInfo(sgImageInfo); + if(err != KErrNone) { + cleanup(); + SgDriver::Close(); + return; + } + + pfnEglCreateImageKHR eglCreateImageKHR = (pfnEglCreateImageKHR) eglGetProcAddress("eglCreateImageKHR"); + pfnEglDestroyImageKHR eglDestroyImageKHR = (pfnEglDestroyImageKHR) eglGetProcAddress("eglDestroyImageKHR"); + pfnVgCreateEGLImageTargetKHR vgCreateEGLImageTargetKHR = (pfnVgCreateEGLImageTargetKHR) eglGetProcAddress("vgCreateEGLImageTargetKHR"); + + if(eglGetError() != EGL_SUCCESS || !eglCreateImageKHR || !eglDestroyImageKHR || !vgCreateEGLImageTargetKHR) { + cleanup(); + SgDriver::Close(); + return; + } + + const EGLint KEglImageAttribs[] = {EGL_IMAGE_PRESERVED_SYMBIAN, EGL_TRUE, EGL_NONE}; + EGLImageKHR eglImage = eglCreateImageKHR(context->display(), + EGL_NO_CONTEXT, + EGL_NATIVE_PIXMAP_KHR, + (EGLClientBuffer)sgImage, + (EGLint*)KEglImageAttribs); + + if(eglGetError() != EGL_SUCCESS) { + cleanup(); + SgDriver::Close(); + return; + } + + vgImage = vgCreateEGLImageTargetKHR(eglImage); + if(vgGetError() != VG_NO_ERROR) { + cleanup(); + eglDestroyImageKHR(context->display(), eglImage); + SgDriver::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; + setSerialNumber(++qt_vg_pixmap_serial); + // release stuff + eglDestroyImageKHR(context->display(), eglImage); + SgDriver::Close(); +#else +#endif +} + +RSgImage* QVGPixmapData::toRSgImage() +{ +#if defined(QT_SYMBIAN_SUPPORTS_SGIMAGE) && !defined(QT_NO_EGL) + toVGImage(); + + if(!isValid() || vgImage == VG_INVALID_HANDLE) + return 0; + + TInt err = 0; + + err = SgDriver::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; + + RSgImage *sgImage = q_check_ptr(new RSgImage()); + err = sgImage->Create(sgInfo, NULL, NULL); + if(err != KErrNone) { + SgDriver::Close(); + return 0; + } + + pfnEglCreateImageKHR eglCreateImageKHR = (pfnEglCreateImageKHR) eglGetProcAddress("eglCreateImageKHR"); + pfnEglDestroyImageKHR eglDestroyImageKHR = (pfnEglDestroyImageKHR) eglGetProcAddress("eglDestroyImageKHR"); + pfnVgCreateEGLImageTargetKHR vgCreateEGLImageTargetKHR = (pfnVgCreateEGLImageTargetKHR) eglGetProcAddress("vgCreateEGLImageTargetKHR"); + + if(eglGetError() != EGL_SUCCESS || !eglCreateImageKHR || !eglDestroyImageKHR || !vgCreateEGLImageTargetKHR) { + SgDriver::Close(); + return 0; + } + + const EGLint KEglImageAttribs[] = {EGL_IMAGE_PRESERVED_SYMBIAN, EGL_TRUE, EGL_NONE}; + EGLImageKHR eglImage = eglCreateImageKHR(context->display(), + EGL_NO_CONTEXT, + EGL_NATIVE_PIXMAP_KHR, + (EGLClientBuffer)sgImage, + (EGLint*)KEglImageAttribs); + if(eglGetError() != EGL_SUCCESS) { + sgImage->Close(); + SgDriver::Close(); + return 0; + } + + VGImage dstVgImage = vgCreateEGLImageTargetKHR(eglImage); + if(vgGetError() != VG_NO_ERROR) { + eglDestroyImageKHR(context->display(), eglImage); + sgImage->Close(); + SgDriver::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); + eglDestroyImageKHR(context->display(), eglImage); + SgDriver::Close(); + return sgImage; +#else + return 0; +#endif +} +#endif //Q_OS_SYMBIAN QT_END_NAMESPACE diff --git a/src/openvg/qpixmapdata_vg_p.h b/src/openvg/qpixmapdata_vg_p.h index 9bb701b..122f596 100644 --- a/src/openvg/qpixmapdata_vg_p.h +++ b/src/openvg/qpixmapdata_vg_p.h @@ -56,7 +56,10 @@ #include #include #if !defined(QT_NO_EGL) -#include +#endif + +#if defined(Q_OS_SYMBIAN) +class RSGImage; #endif QT_BEGIN_NAMESPACE @@ -91,9 +94,18 @@ public: QSize size() const { return QSize(w, h); } +#if defined(Q_OS_SYMBIAN) + RSgImage* toRSgImage(); + void fromRSgImage(RSgImage* sgImage); +#endif + protected: int metric(QPaintDevice::PaintDeviceMetric metric) const; +#if defined(Q_OS_SYMBIAN) + void cleanup(); +#endif + private: VGImage vgImage; VGImage vgImageOpacity; diff --git a/tests/auto/qpixmap/qpixmap.pro b/tests/auto/qpixmap/qpixmap.pro index 02ed3f2..31d6eaa 100644 --- a/tests/auto/qpixmap/qpixmap.pro +++ b/tests/auto/qpixmap/qpixmap.pro @@ -14,6 +14,9 @@ wince*: { } symbian*: { DEPLOYMENT_PLUGIN += qmng LIBS += -lfbscli.dll -lbitgdi.dll -lgdi.dll + contains(QT_CONFIG, openvg) { + LIBS += $$QMAKE_LIBS_OPENVG + } } else { DEFINES += SRCDIR=\\\"$$PWD\\\" win32:LIBS += -lgdi32 -luser32 -- cgit v0.12