summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
authorJani Hautakangas <ext-jani.hautakangas@nokia.com>2010-05-20 09:46:46 (GMT)
committerJani Hautakangas <ext-jani.hautakangas@nokia.com>2010-05-20 09:46:46 (GMT)
commit98972c1b271de1292b4e46484fe689d62a8b8e62 (patch)
tree0949cdc38127261bdd28cee8cb3084052bd8c461 /src/gui
parentb4b4cb3248b987dd6c15908f0b46e131dc2b7cde (diff)
downloadQt-98972c1b271de1292b4e46484fe689d62a8b8e62.zip
Qt-98972c1b271de1292b4e46484fe689d62a8b8e62.tar.gz
Qt-98972c1b271de1292b4e46484fe689d62a8b8e62.tar.bz2
QRuntimeGraphicsSystem
QRuntimeGraphicsSystem is a proxy graphics system which can dynamically switch underlying graphics system on runtime. For example, switch from hardware accelerated graphics system to raster graphics system on low GPU memory situation. This feature is currently supported on Symbian platform. Task-number: QT-3276 Reviewed-by: Jason Barron
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/image/qpixmap.cpp40
-rw-r--r--src/gui/image/qpixmap.h2
-rw-r--r--src/gui/image/qpixmapcache_p.h5
-rw-r--r--src/gui/image/qpixmapdata_p.h5
-rw-r--r--src/gui/kernel/qapplication.cpp13
-rw-r--r--src/gui/kernel/qapplication_s60.cpp66
-rw-r--r--src/gui/kernel/qt_s60_p.h1
-rw-r--r--src/gui/kernel/qwidget.cpp9
-rw-r--r--src/gui/painting/painting.pri2
-rw-r--r--src/gui/painting/qgraphicssystem_runtime.cpp443
-rw-r--r--src/gui/painting/qgraphicssystem_runtime_p.h197
-rw-r--r--src/gui/painting/qgraphicssystemfactory.cpp7
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp20
-rw-r--r--src/gui/painting/qwindowsurface.cpp2
-rw-r--r--src/gui/painting/qwindowsurface_s60.cpp31
15 files changed, 809 insertions, 34 deletions
diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp
index 474cd2e..21216f8 100644
--- a/src/gui/image/qpixmap.cpp
+++ b/src/gui/image/qpixmap.cpp
@@ -635,17 +635,21 @@ void QPixmap::resize_helper(const QSize &s)
if (size() == s)
return;
+ // QPixmap.data member may be QRuntimePixmapData so use pixmapData() function to get
+ // the actual underlaying runtime pixmap data.
+ QPixmapData *pd = pixmapData();
+
// Create new pixmap
- QPixmap pm(QSize(w, h), data ? data->type : QPixmapData::PixmapType);
+ QPixmap pm(QSize(w, h), pd ? pd->type : QPixmapData::PixmapType);
bool uninit = false;
#if defined(Q_WS_X11)
- QX11PixmapData *x11Data = data && data->classId() == QPixmapData::X11Class ? static_cast<QX11PixmapData*>(data.data()) : 0;
+ QX11PixmapData *x11Data = pd && pd->classId() == QPixmapData::X11Class ? static_cast<QX11PixmapData*>(pd) : 0;
if (x11Data) {
pm.x11SetScreen(x11Data->xinfo.screen());
uninit = x11Data->flags & QX11PixmapData::Uninitialized;
}
#elif defined(Q_WS_MAC)
- QMacPixmapData *macData = data && data->classId() == QPixmapData::MacClass ? static_cast<QMacPixmapData*>(data.data()) : 0;
+ QMacPixmapData *macData = pd && pd->classId() == QPixmapData::MacClass ? static_cast<QMacPixmapData*>(pd) : 0;
if (macData)
uninit = macData->uninit;
#endif
@@ -659,7 +663,7 @@ void QPixmap::resize_helper(const QSize &s)
#if defined(Q_WS_X11)
if (x11Data && x11Data->x11_mask) {
- QX11PixmapData *pmData = static_cast<QX11PixmapData*>(pm.data.data());
+ QX11PixmapData *pmData = static_cast<QX11PixmapData*>(pd);
pmData->x11_mask = (Qt::HANDLE)XCreatePixmap(X11->display,
RootWindow(x11Data->xinfo.display(),
x11Data->xinfo.screen()),
@@ -1163,8 +1167,9 @@ QPixmap QPixmap::grabWidget(QWidget * widget, const QRect &rect)
Qt::HANDLE QPixmap::handle() const
{
#if defined(Q_WS_X11)
- if (data && data->classId() == QPixmapData::X11Class)
- return static_cast<const QX11PixmapData*>(data.constData())->handle();
+ const QPixmapData *pd = pixmapData();
+ if (pd && pd->classId() == QPixmapData::X11Class)
+ return static_cast<const QX11PixmapData*>(pd)->handle();
#endif
return 0;
}
@@ -1944,17 +1949,20 @@ void QPixmap::detach()
if (!data)
return;
- QPixmapData::ClassId id = data->classId();
+ // QPixmap.data member may be QRuntimePixmapData so use pixmapData() function to get
+ // the actual underlaying runtime pixmap data.
+ QPixmapData *pd = pixmapData();
+ QPixmapData::ClassId id = pd->classId();
if (id == QPixmapData::RasterClass) {
- QRasterPixmapData *rasterData = static_cast<QRasterPixmapData*>(data.data());
+ QRasterPixmapData *rasterData = static_cast<QRasterPixmapData*>(pd);
rasterData->image.detach();
}
if (data->is_cached && data->ref == 1)
- QImagePixmapCleanupHooks::executePixmapDataModificationHooks(data.data());
+ QImagePixmapCleanupHooks::executePixmapDataModificationHooks(pd);
#if defined(Q_WS_MAC)
- QMacPixmapData *macData = id == QPixmapData::MacClass ? static_cast<QMacPixmapData*>(data.data()) : 0;
+ QMacPixmapData *macData = id == QPixmapData::MacClass ? static_cast<QMacPixmapData*>(pd) : 0;
if (macData) {
if (macData->cg_mask) {
CGImageRelease(macData->cg_mask);
@@ -1969,8 +1977,8 @@ void QPixmap::detach()
++data->detach_no;
#if defined(Q_WS_X11)
- if (data->classId() == QPixmapData::X11Class) {
- QX11PixmapData *d = static_cast<QX11PixmapData*>(data.data());
+ if (pd->classId() == QPixmapData::X11Class) {
+ QX11PixmapData *d = static_cast<QX11PixmapData*>(pd);
d->flags &= ~QX11PixmapData::Uninitialized;
// reset the cache data
@@ -2060,9 +2068,15 @@ QPixmap QPixmap::fromImage(const QImage &image, Qt::ImageConversionFlags flags)
*/
QPixmapData* QPixmap::pixmapData() const
{
- return data.data();
+ if (data) {
+ QPixmapData* pm = data.data();
+ return pm->runtimeData() ? pm->runtimeData() : pm;
+ }
+
+ return 0;
}
+
/*!
\enum QPixmap::HBitmapFormat
diff --git a/src/gui/image/qpixmap.h b/src/gui/image/qpixmap.h
index 180af3b..82546da 100644
--- a/src/gui/image/qpixmap.h
+++ b/src/gui/image/qpixmap.h
@@ -271,9 +271,7 @@ private:
friend class QX11PaintEngine;
friend class QCoreGraphicsPaintEngine;
friend class QWidgetPrivate;
- friend class QRasterPaintEngine;
friend class QRasterBuffer;
- friend class QPixmapCacheEntry;
#if !defined(QT_NO_DATASTREAM)
friend Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QPixmap &);
#endif
diff --git a/src/gui/image/qpixmapcache_p.h b/src/gui/image/qpixmapcache_p.h
index 86a1b78..0ed083c 100644
--- a/src/gui/image/qpixmapcache_p.h
+++ b/src/gui/image/qpixmapcache_p.h
@@ -81,8 +81,9 @@ class QPixmapCacheEntry : public QPixmap
public:
QPixmapCacheEntry(const QPixmapCache::Key &key, const QPixmap &pix) : QPixmap(pix), key(key)
{
- if (data && data->classId() == QPixmapData::RasterClass) {
- QRasterPixmapData *d = static_cast<QRasterPixmapData*>(data.data());
+ QPixmapData *pd = pixmapData();
+ if (pd && pd->classId() == QPixmapData::RasterClass) {
+ QRasterPixmapData *d = static_cast<QRasterPixmapData*>(pd);
if (!d->image.isNull() && d->image.d->paintEngine
&& !d->image.d->paintEngine->isActive())
{
diff --git a/src/gui/image/qpixmapdata_p.h b/src/gui/image/qpixmapdata_p.h
index 827fa18..60ed26a 100644
--- a/src/gui/image/qpixmapdata_p.h
+++ b/src/gui/image/qpixmapdata_p.h
@@ -73,7 +73,7 @@ public:
};
#endif
enum ClassId { RasterClass, X11Class, MacClass, DirectFBClass,
- OpenGLClass, OpenVGClass, CustomClass = 1024 };
+ OpenGLClass, OpenVGClass, RuntimeClass, CustomClass = 1024 };
QPixmapData(PixelType pixelType, int classId);
virtual ~QPixmapData();
@@ -133,7 +133,10 @@ public:
static QPixmapData *create(int w, int h, PixelType type);
+ virtual QPixmapData *runtimeData() const { return 0; }
+
protected:
+
void setSerialNumber(int serNo);
int w;
int h;
diff --git a/src/gui/kernel/qapplication.cpp b/src/gui/kernel/qapplication.cpp
index ec635d4..590b000 100644
--- a/src/gui/kernel/qapplication.cpp
+++ b/src/gui/kernel/qapplication.cpp
@@ -70,6 +70,10 @@
#include "qmessagebox.h"
#include <QtGui/qgraphicsproxywidget.h>
+#ifdef QT_GRAPHICSSYSTEM_RUNTIME
+#include "private/qgraphicssystem_runtime_p.h"
+#endif
+
#include "qinputcontext.h"
#include "qkeymapper_p.h"
@@ -1561,7 +1565,14 @@ QStyle* QApplication::setStyle(const QString& style)
void QApplication::setGraphicsSystem(const QString &system)
{
- QApplicationPrivate::graphics_system_name = system;
+#ifdef QT_GRAPHICSSYSTEM_RUNTIME
+ if (QApplicationPrivate::graphics_system_name == QLatin1String("runtime")) {
+ QRuntimeGraphicsSystem *r =
+ static_cast<QRuntimeGraphicsSystem *>(QApplicationPrivate::graphics_system);
+ r->setGraphicsSystem(system);
+ } else
+#endif
+ QApplicationPrivate::graphics_system_name = system;
}
/*!
diff --git a/src/gui/kernel/qapplication_s60.cpp b/src/gui/kernel/qapplication_s60.cpp
index f4c7304..1134a9b 100644
--- a/src/gui/kernel/qapplication_s60.cpp
+++ b/src/gui/kernel/qapplication_s60.cpp
@@ -62,6 +62,10 @@
#include "qpaintengine.h"
#include "private/qmenubar_p.h"
#include "private/qsoftkeymanager_p.h"
+#ifdef QT_GRAPHICSSYSTEM_RUNTIME
+#include "private/qgraphicssystem_runtime_p.h"
+#endif
+
#include "apgwgnam.h" // For CApaWindowGroupName
#include <mdaaudiotoneplayer.h> // For CMdaAudioToneUtility
@@ -83,6 +87,10 @@
QT_BEGIN_NAMESPACE
+// Goom Events through Window Server
+static const int KGoomMemoryLowEvent = 0x10282DBF;
+static const int KGoomMemoryGoodEvent = 0x20026790;
+
#if defined(QT_DEBUG)
static bool appNoGrab = false; // Grabbing enabled
#endif
@@ -855,7 +863,16 @@ void QSymbianControl::Draw(const TRect& controlRect) const
const TRect backingStoreRect(TPoint(backingStoreBase.x(), backingStoreBase.y()), controlRect.Size());
if (engine->type() == QPaintEngine::Raster) {
- QS60WindowSurface *s60Surface = static_cast<QS60WindowSurface *>(qwidget->windowSurface());
+ QS60WindowSurface *s60Surface;
+#ifdef QT_GRAPHICSSYSTEM_RUNTIME
+ if (QApplicationPrivate::graphics_system_name == QLatin1String("runtime")) {
+ QRuntimeWindowSurface *rtSurface =
+ static_cast<QRuntimeWindowSurface*>(qwidget->windowSurface());
+ s60Surface = static_cast<QS60WindowSurface *>(rtSurface->m_windowSurface);
+ } else
+#endif
+ s60Surface = static_cast<QS60WindowSurface *>(qwidget->windowSurface());
+
CFbsBitmap *bitmap = s60Surface->symbianBitmap();
CWindowGc &gc = SystemGc();
@@ -1738,6 +1755,53 @@ int QApplicationPrivate::symbianProcessWsEvent(const QSymbianEvent *symbianEvent
}
#endif
break;
+ case KGoomMemoryLowEvent:
+#ifdef QT_DEBUG
+ qDebug() << "QApplicationPrivate::symbianProcessWsEvent - KGoomMemoryLowEvent";
+#endif
+ if (callSymbianEventFilters(symbianEvent))
+ return 1;
+#ifdef QT_GRAPHICSSYSTEM_RUNTIME
+ if(QApplicationPrivate::graphics_system_name == QLatin1String("runtime")) {
+ bool switchToSwRendering(false);
+
+ foreach (QWidget *w, QApplication::topLevelWidgets()) {
+ if(w->d_func()->topData()->backingStore) {
+ switchToSwRendering = true;
+ break;
+ }
+ }
+
+ if (switchToSwRendering) {
+ QRuntimeGraphicsSystem *gs =
+ static_cast<QRuntimeGraphicsSystem*>(QApplicationPrivate::graphics_system);
+
+ uint memoryUsage = gs->memoryUsage();
+ uint memoryForFullscreen = ( S60->screenDepth / 8 )
+ * S60->screenWidthInPixels
+ * S60->screenHeightInPixels;
+
+ S60->memoryLimitForHwRendering = memoryUsage - memoryForFullscreen;
+ gs->setGraphicsSystem(QLatin1String("raster"));
+ }
+ }
+#endif
+ break;
+ case KGoomMemoryGoodEvent:
+#ifdef QT_DEBUG
+ qDebug() << "QApplicationPrivate::symbianProcessWsEvent - KGoomMemoryGoodEvent";
+#endif
+ if (callSymbianEventFilters(symbianEvent))
+ return 1;
+#ifdef QT_GRAPHICSSYSTEM_RUNTIME
+ if(QApplicationPrivate::graphics_system_name == QLatin1String("runtime")) {
+ QRuntimeGraphicsSystem *gs =
+ static_cast<QRuntimeGraphicsSystem*>(QApplicationPrivate::graphics_system);
+ gs->setGraphicsSystem(QLatin1String("openvg"), S60->memoryLimitForHwRendering);
+ S60->memoryLimitForHwRendering = 0;
+ }
+#endif
+ break;
default:
break;
}
diff --git a/src/gui/kernel/qt_s60_p.h b/src/gui/kernel/qt_s60_p.h
index 58da302..645e969 100644
--- a/src/gui/kernel/qt_s60_p.h
+++ b/src/gui/kernel/qt_s60_p.h
@@ -123,6 +123,7 @@ public:
int supportsPremultipliedAlpha : 1;
int avkonComponentsSupportTransparency : 1;
int menuBeingConstructed : 1;
+ int memoryLimitForHwRendering;
QApplication::QS60MainApplicationFactory s60ApplicationFactory; // typedef'ed pointer type
static inline void updateScreenSize();
static inline RWsSession& wsSession();
diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp
index 60f38f2..064bf03 100644
--- a/src/gui/kernel/qwidget.cpp
+++ b/src/gui/kernel/qwidget.cpp
@@ -248,9 +248,14 @@ QWidgetPrivate::~QWidgetPrivate()
QWindowSurface *QWidgetPrivate::createDefaultWindowSurface()
{
Q_Q(QWidget);
+
+ QWindowSurface *surface;
if (QApplicationPrivate::graphicsSystem())
- return QApplicationPrivate::graphicsSystem()->createWindowSurface(q);
- return createDefaultWindowSurface_sys();
+ surface = QApplicationPrivate::graphicsSystem()->createWindowSurface(q);
+ else
+ surface = createDefaultWindowSurface_sys();
+
+ return surface;
}
/*!
diff --git a/src/gui/painting/painting.pri b/src/gui/painting/painting.pri
index ed8ee76..123af1c 100644
--- a/src/gui/painting/painting.pri
+++ b/src/gui/painting/painting.pri
@@ -118,12 +118,14 @@ embedded {
} else {
HEADERS += \
painting/qgraphicssystem_raster_p.h \
+ painting/qgraphicssystem_runtime_p.h \
painting/qgraphicssystemfactory_p.h \
painting/qgraphicssystemplugin_p.h \
painting/qwindowsurface_raster_p.h \
SOURCES += \
painting/qgraphicssystem_raster.cpp \
+ painting/qgraphicssystem_runtime.cpp \
painting/qgraphicssystemfactory.cpp \
painting/qgraphicssystemplugin.cpp \
painting/qwindowsurface_raster.cpp \
diff --git a/src/gui/painting/qgraphicssystem_runtime.cpp b/src/gui/painting/qgraphicssystem_runtime.cpp
new file mode 100644
index 0000000..dfa9bd3
--- /dev/null
+++ b/src/gui/painting/qgraphicssystem_runtime.cpp
@@ -0,0 +1,443 @@
+#include <private/qgraphicssystem_runtime_p.h>
+#include <private/qgraphicssystem_raster_p.h>
+#include <private/qgraphicssystemfactory_p.h>
+#include <private/qapplication_p.h>
+#include <private/qwidget_p.h>
+#include <QtCore/QDebug>
+#include <QtCore/QTimer>
+#include <QtGui/QBitmap>
+
+QT_BEGIN_NAMESPACE
+
+#define READBACK(f) \
+ m_graphicsSystem->decreaseMemoryUsage(memoryUsage()); \
+ f \
+ readBackInfo(); \
+ m_graphicsSystem->increaseMemoryUsage(memoryUsage()); \
+
+
+class QDeferredGraphicsSystemChange : public QObject
+{
+ Q_OBJECT
+
+public:
+ QDeferredGraphicsSystemChange(QRuntimeGraphicsSystem *gs, const QString& graphicsSystemName)
+ : m_graphicsSystem(gs), m_graphicsSystemName(graphicsSystemName)
+ {
+ }
+
+ void launch()
+ {
+ QTimer::singleShot(0, this, SLOT(doChange()));
+ }
+
+private slots:
+
+ void doChange()
+ {
+ m_graphicsSystem->setGraphicsSystem(m_graphicsSystemName);
+ deleteLater();
+ }
+
+private:
+
+ QRuntimeGraphicsSystem *m_graphicsSystem;
+ QString m_graphicsSystemName;
+};
+
+QRuntimePixmapData::QRuntimePixmapData(const QRuntimeGraphicsSystem *gs, PixelType type)
+ : QPixmapData(type, RuntimeClass), m_graphicsSystem(gs)
+{
+ setSerialNumber((int)this);
+}
+
+QRuntimePixmapData::~QRuntimePixmapData()
+{
+ m_graphicsSystem->removePixmapData(this);
+ delete m_data;
+}
+
+void QRuntimePixmapData::readBackInfo()
+{
+ w = m_data->width();
+ h = m_data->height();
+ d = m_data->depth();
+ is_null = m_data->isNull();
+}
+
+
+QPixmapData *QRuntimePixmapData::createCompatiblePixmapData() const
+{
+ QRuntimePixmapData *rtData = new QRuntimePixmapData(m_graphicsSystem, pixelType());
+ rtData->m_data = m_data->createCompatiblePixmapData();
+ return rtData;
+}
+
+
+void QRuntimePixmapData::resize(int width, int height)
+{
+ READBACK(
+ m_data->resize(width, height);
+ )
+}
+
+
+void QRuntimePixmapData::fromImage(const QImage &image,
+ Qt::ImageConversionFlags flags)
+{
+ READBACK(
+ m_data->fromImage(image, flags);
+ )
+}
+
+
+bool QRuntimePixmapData::fromFile(const QString &filename, const char *format,
+ Qt::ImageConversionFlags flags)
+{
+ bool success(false);
+ READBACK(
+ success = m_data->fromFile(filename, format, flags);
+ )
+ return success;
+}
+
+bool QRuntimePixmapData::fromData(const uchar *buffer, uint len, const char *format,
+ Qt::ImageConversionFlags flags)
+{
+ bool success(false);
+ READBACK(
+ success = m_data->fromData(buffer, len, format, flags);
+ )
+ return success;
+}
+
+
+void QRuntimePixmapData::copy(const QPixmapData *data, const QRect &rect)
+{
+ if (data->runtimeData()) {
+ READBACK(
+ m_data->copy(data->runtimeData(), rect);
+ )
+ } else {
+ READBACK(
+ m_data->copy(data, rect);
+ )
+ }
+}
+
+bool QRuntimePixmapData::scroll(int dx, int dy, const QRect &rect)
+{
+ return m_data->scroll(dx, dy, rect);
+}
+
+
+int QRuntimePixmapData::metric(QPaintDevice::PaintDeviceMetric metric) const
+{
+ return m_data->metric(metric);
+}
+
+void QRuntimePixmapData::fill(const QColor &color)
+{
+ return m_data->fill(color);
+}
+
+QBitmap QRuntimePixmapData::mask() const
+{
+ return m_data->mask();
+}
+
+void QRuntimePixmapData::setMask(const QBitmap &mask)
+{
+ READBACK(
+ m_data->setMask(mask);
+ )
+}
+
+bool QRuntimePixmapData::hasAlphaChannel() const
+{
+ return m_data->hasAlphaChannel();
+}
+
+QPixmap QRuntimePixmapData::transformed(const QTransform &matrix,
+ Qt::TransformationMode mode) const
+{
+ return m_data->transformed(matrix, mode);
+}
+
+void QRuntimePixmapData::setAlphaChannel(const QPixmap &alphaChannel)
+{
+ READBACK(
+ m_data->setAlphaChannel(alphaChannel);
+ )
+}
+
+QPixmap QRuntimePixmapData::alphaChannel() const
+{
+ return m_data->alphaChannel();
+}
+
+QImage QRuntimePixmapData::toImage() const
+{
+ return m_data->toImage();
+}
+
+QPaintEngine* QRuntimePixmapData::paintEngine() const
+{
+ return m_data->paintEngine();
+}
+
+QImage* QRuntimePixmapData::buffer()
+{
+ return m_data->buffer();
+}
+
+#if defined(Q_OS_SYMBIAN)
+void* QRuntimePixmapData::toNativeType(NativeType type)
+{
+ return m_data->toNativeType(type);
+}
+
+void QRuntimePixmapData::fromNativeType(void *pixmap, NativeType type)
+{
+ m_data->fromNativeType(pixmap, type);
+ readBackInfo();
+}
+#endif
+
+QPixmapData* QRuntimePixmapData::runtimeData() const
+{
+ return m_data;
+}
+
+uint QRuntimePixmapData::memoryUsage() const
+{
+ if(is_null || d == 0)
+ return 0;
+ return w * h * (d / 8);
+}
+
+
+QRuntimeWindowSurface::QRuntimeWindowSurface(const QRuntimeGraphicsSystem *gs, QWidget *window)
+ : QWindowSurface(window), m_windowSurface(0), m_pendingWindowSurface(0), m_graphicsSystem(gs)
+{
+
+}
+
+QRuntimeWindowSurface::~QRuntimeWindowSurface()
+{
+ m_graphicsSystem->removeWindowSurface(this);
+ delete m_windowSurface;
+}
+
+QPaintDevice *QRuntimeWindowSurface::paintDevice()
+{
+ return m_windowSurface->paintDevice();
+}
+
+void QRuntimeWindowSurface::flush(QWidget *widget, const QRegion &region,
+ const QPoint &offset)
+{
+ m_windowSurface->flush(widget, region, offset);
+
+ int destroyPolicy = m_graphicsSystem->windowSurfaceDestroyPolicy();
+ if(m_pendingWindowSurface &&
+ destroyPolicy == QRuntimeGraphicsSystem::DestroyAfterFirstFlush) {
+#ifdef QT_DEBUG
+ qDebug() << "QRuntimeWindowSurface::flush() - destroy pending window surface";
+#endif
+ delete m_pendingWindowSurface;
+ m_pendingWindowSurface = 0;
+ }
+}
+
+void QRuntimeWindowSurface::setGeometry(const QRect &rect)
+{
+ m_graphicsSystem->decreaseMemoryUsage(memoryUsage());
+ m_windowSurface->setGeometry(rect);
+ m_graphicsSystem->increaseMemoryUsage(memoryUsage());
+}
+
+bool QRuntimeWindowSurface::scroll(const QRegion &area, int dx, int dy)
+{
+ return m_windowSurface->scroll(area, dx, dy);
+}
+
+void QRuntimeWindowSurface::beginPaint(const QRegion &rgn)
+{
+ m_windowSurface->beginPaint(rgn);
+}
+
+void QRuntimeWindowSurface::endPaint(const QRegion &rgn)
+{
+ m_windowSurface->endPaint(rgn);
+}
+
+QImage* QRuntimeWindowSurface::buffer(const QWidget *widget)
+{
+ return m_windowSurface->buffer(widget);
+}
+
+QPixmap QRuntimeWindowSurface::grabWidget(const QWidget *widget, const QRect& rectangle) const
+{
+ return m_windowSurface->grabWidget(widget, rectangle);
+}
+
+QPoint QRuntimeWindowSurface::offset(const QWidget *widget) const
+{
+ return m_windowSurface->offset(widget);
+}
+
+uint QRuntimeWindowSurface::memoryUsage() const
+{
+ QPaintDevice *pdev = m_windowSurface->paintDevice();
+ if (pdev && pdev->depth() != 0)
+ return pdev->width() * pdev->height() * (pdev->depth()/8);
+
+ return 0;
+}
+
+QRuntimeGraphicsSystem::QRuntimeGraphicsSystem()
+ : m_memoryUsage(0), m_windowSurfaceDestroyPolicy(DestroyImmediately),
+ m_graphicsSystem(0), m_graphicsSystemChangeMemoryLimit(0)
+{
+ QApplicationPrivate::graphics_system_name = QLatin1String("runtime");
+
+#ifdef Q_OS_SYMBIAN
+ m_graphicsSystemName = QLatin1String("openvg");
+ m_windowSurfaceDestroyPolicy = DestroyAfterFirstFlush;
+#else
+ m_graphicsSystemName = QLatin1String("raster");
+#endif
+
+ m_graphicsSystem = QGraphicsSystemFactory::create(m_graphicsSystemName);
+}
+
+
+QPixmapData *QRuntimeGraphicsSystem::createPixmapData(QPixmapData::PixelType type) const
+{
+ Q_ASSERT(m_graphicsSystem);
+ QPixmapData *data = m_graphicsSystem->createPixmapData(type);
+
+ QRuntimePixmapData *rtData = new QRuntimePixmapData(this, type);
+ rtData->m_data = data;
+ m_pixmapDatas << rtData;
+
+ return rtData;
+}
+
+QWindowSurface *QRuntimeGraphicsSystem::createWindowSurface(QWidget *widget) const
+{
+ Q_ASSERT(m_graphicsSystem);
+ QRuntimeWindowSurface *rtSurface = new QRuntimeWindowSurface(this, widget);
+ rtSurface->m_windowSurface = m_graphicsSystem->createWindowSurface(widget);
+ widget->setWindowSurface(rtSurface);
+ m_windowSurfaces << rtSurface;
+ increaseMemoryUsage(rtSurface->memoryUsage());
+ return rtSurface;
+}
+
+/*!
+ Sets graphics system when resource memory consumption is under /a memoryUsageLimit.
+*/
+void QRuntimeGraphicsSystem::setGraphicsSystem(const QString &name, uint memoryUsageLimit)
+{
+#ifdef QT_DEBUG
+ qDebug() << "QRuntimeGraphicsSystem::setGraphicsSystem( "<< name <<", " << memoryUsageLimit << ")";
+ qDebug() << " current approximated graphics system memory usage " << memoryUsage() << " bytes";
+#endif
+ if (memoryUsage() >= memoryUsageLimit) {
+ m_graphicsSystemChangeMemoryLimit = memoryUsageLimit;
+ m_pendingGraphicsSystemName = name;
+ } else {
+ setGraphicsSystem(name);
+ }
+}
+
+void QRuntimeGraphicsSystem::setGraphicsSystem(const QString &name)
+{
+ if (m_graphicsSystemName == name)
+ return;
+#ifdef QT_DEBUG
+ qDebug() << "QRuntimeGraphicsSystem::setGraphicsSystem( " << name << " )";
+ qDebug() << " current approximated graphics system memory usage "<< memoryUsage() << " bytes";
+#endif
+ delete m_graphicsSystem;
+ m_graphicsSystem = QGraphicsSystemFactory::create(name);
+ m_graphicsSystemName = name;
+
+ Q_ASSERT(m_graphicsSystem);
+
+ m_graphicsSystemChangeMemoryLimit = 0;
+ m_pendingGraphicsSystemName = QString();
+
+ for (int i = 0; i < m_pixmapDatas.size(); ++i) {
+ QRuntimePixmapData *proxy = m_pixmapDatas.at(i);
+ QPixmapData *newData = m_graphicsSystem->createPixmapData(proxy->m_data->pixelType());
+ // ### TODO Optimize. Openvg and s60raster graphics systems could switch internal ARGB32_PRE QImage buffers.
+ newData->fromImage(proxy->m_data->toImage(), Qt::AutoColor | Qt::OrderedAlphaDither);
+ delete proxy->m_data;
+ proxy->m_data = newData;
+ proxy->readBackInfo();
+ }
+
+ for (int i = 0; i < m_windowSurfaces.size(); ++i) {
+ QRuntimeWindowSurface *proxy = m_windowSurfaces.at(i);
+ QWidget *widget = proxy->m_windowSurface->window();
+
+ if(m_windowSurfaceDestroyPolicy == DestroyImmediately) {
+ delete proxy->m_windowSurface;
+ proxy->m_pendingWindowSurface = 0;
+ } else {
+ proxy->m_pendingWindowSurface = proxy->m_windowSurface;
+ }
+
+ proxy->m_windowSurface = m_graphicsSystem->createWindowSurface(widget);
+ qt_widget_private(widget)->invalidateBuffer(widget->rect());
+ }
+}
+
+void QRuntimeGraphicsSystem::removePixmapData(QRuntimePixmapData *pixmapData) const
+{
+ int index = m_pixmapDatas.lastIndexOf(pixmapData);
+ m_pixmapDatas.removeAt(index);
+ decreaseMemoryUsage(pixmapData->memoryUsage(), true);
+}
+
+void QRuntimeGraphicsSystem::removeWindowSurface(QRuntimeWindowSurface *windowSurface) const
+{
+ int index = m_windowSurfaces.lastIndexOf(windowSurface);
+ m_windowSurfaces.removeAt(index);
+ decreaseMemoryUsage(windowSurface->memoryUsage(), true);
+}
+
+void QRuntimeGraphicsSystem::increaseMemoryUsage(uint amount) const
+{
+ m_memoryUsage += amount;
+
+ if (m_graphicsSystemChangeMemoryLimit &&
+ m_memoryUsage < m_graphicsSystemChangeMemoryLimit) {
+
+ QRuntimeGraphicsSystem *gs = const_cast<QRuntimeGraphicsSystem*>(this);
+ QDeferredGraphicsSystemChange *deferredChange =
+ new QDeferredGraphicsSystemChange(gs, m_pendingGraphicsSystemName);
+ deferredChange->launch();
+ }
+}
+
+void QRuntimeGraphicsSystem::decreaseMemoryUsage(uint amount, bool persistent) const
+{
+ m_memoryUsage -= amount;
+
+ if (persistent && m_graphicsSystemChangeMemoryLimit &&
+ m_memoryUsage < m_graphicsSystemChangeMemoryLimit) {
+
+ QRuntimeGraphicsSystem *gs = const_cast<QRuntimeGraphicsSystem*>(this);
+ QDeferredGraphicsSystemChange *deferredChange =
+ new QDeferredGraphicsSystemChange(gs, m_pendingGraphicsSystemName);
+ deferredChange->launch();
+ }
+}
+
+#include "qgraphicssystem_runtime.moc"
+
+QT_END_NAMESPACE
diff --git a/src/gui/painting/qgraphicssystem_runtime_p.h b/src/gui/painting/qgraphicssystem_runtime_p.h
new file mode 100644
index 0000000..445f83d
--- /dev/null
+++ b/src/gui/painting/qgraphicssystem_runtime_p.h
@@ -0,0 +1,197 @@
+/****************************************************************************
+**
+** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the plugins of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** No Commercial Usage
+** This file contains pre-release code and may not be distributed.
+** You may use this file in accordance with the terms and conditions
+** contained in the Technology Preview License Agreement accompanying
+** this package.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGRAPHICSSYSTEM_RUNTIME_P_H
+#define QGRAPHICSSYSTEM_RUNTIME_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists for the convenience
+// of other Qt classes. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include "qgraphicssystem_p.h"
+
+#include <private/qpixmapdata_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QRuntimeGraphicsSystem;
+
+class QRuntimePixmapData : public QPixmapData {
+public:
+ QRuntimePixmapData(const QRuntimeGraphicsSystem *gs, PixelType type);
+ ~QRuntimePixmapData();
+
+ virtual QPixmapData *createCompatiblePixmapData() const;
+ virtual void resize(int width, int height);
+ virtual void fromImage(const QImage &image,
+ Qt::ImageConversionFlags flags);
+
+ virtual bool fromFile(const QString &filename, const char *format,
+ Qt::ImageConversionFlags flags);
+ virtual bool fromData(const uchar *buffer, uint len, const char *format,
+ Qt::ImageConversionFlags flags);
+
+ virtual void copy(const QPixmapData *data, const QRect &rect);
+ virtual bool scroll(int dx, int dy, const QRect &rect);
+
+ virtual int metric(QPaintDevice::PaintDeviceMetric metric) const;
+ virtual void fill(const QColor &color);
+ virtual QBitmap mask() const;
+ virtual void setMask(const QBitmap &mask);
+ virtual bool hasAlphaChannel() const;
+ virtual QPixmap transformed(const QTransform &matrix,
+ Qt::TransformationMode mode) const;
+ virtual void setAlphaChannel(const QPixmap &alphaChannel);
+ virtual QPixmap alphaChannel() const;
+ virtual QImage toImage() const;
+ virtual QPaintEngine *paintEngine() const;
+
+ virtual QImage *buffer();
+
+ void readBackInfo();
+
+ QPixmapData *m_data;
+
+#if defined(Q_OS_SYMBIAN)
+ void* toNativeType(NativeType type);
+ void fromNativeType(void* pixmap, NativeType type);
+#endif
+
+ virtual QPixmapData *runtimeData() const;
+
+ virtual uint memoryUsage() const;
+
+private:
+ const QRuntimeGraphicsSystem *m_graphicsSystem;
+
+};
+
+class QRuntimeWindowSurface : public QWindowSurface {
+public:
+ QRuntimeWindowSurface(const QRuntimeGraphicsSystem *gs, QWidget *window);
+ ~QRuntimeWindowSurface();
+
+ virtual QPaintDevice *paintDevice();
+ virtual void flush(QWidget *widget, const QRegion &region,
+ const QPoint &offset);
+ virtual void setGeometry(const QRect &rect);
+
+ virtual bool scroll(const QRegion &area, int dx, int dy);
+
+ virtual void beginPaint(const QRegion &);
+ virtual void endPaint(const QRegion &);
+
+ virtual QImage* buffer(const QWidget *widget);
+ virtual QPixmap grabWidget(const QWidget *widget, const QRect& rectangle = QRect()) const;
+
+ virtual QPoint offset(const QWidget *widget) const;
+
+ virtual uint memoryUsage() const;
+
+ QWindowSurface *m_windowSurface;
+ QWindowSurface *m_pendingWindowSurface;
+
+private:
+ const QRuntimeGraphicsSystem *m_graphicsSystem;
+};
+
+class QRuntimeGraphicsSystem : public QGraphicsSystem
+{
+public:
+
+ enum WindowSurfaceDestroyPolicy
+ {
+ DestroyImmediately,
+ DestroyAfterFirstFlush
+ };
+
+public:
+ QRuntimeGraphicsSystem();
+
+ QPixmapData *createPixmapData(QPixmapData::PixelType type) const;
+ QWindowSurface *createWindowSurface(QWidget *widget) const;
+
+ void removePixmapData(QRuntimePixmapData *pixmapData) const;
+ void removeWindowSurface(QRuntimeWindowSurface *windowSurface) const;
+
+ void setGraphicsSystem(const QString &name, uint memoryUsageLimit);
+ void setGraphicsSystem(const QString &name);
+ QString graphicsSystemName() const { return m_graphicsSystemName; }
+
+ void setWindowSurfaceDestroyPolicy(WindowSurfaceDestroyPolicy policy)
+ {
+ m_windowSurfaceDestroyPolicy = policy;
+ }
+
+ int windowSurfaceDestroyPolicy() const { return m_windowSurfaceDestroyPolicy; }
+
+ int memoryUsage() const { return m_memoryUsage; }
+
+private:
+
+ void increaseMemoryUsage(uint amount) const;
+ void decreaseMemoryUsage(uint amount, bool persistent = false) const;
+
+private:
+ mutable uint m_memoryUsage;
+ int m_windowSurfaceDestroyPolicy;
+ QGraphicsSystem *m_graphicsSystem;
+ mutable QList<QRuntimePixmapData *> m_pixmapDatas;
+ mutable QList<QRuntimeWindowSurface *> m_windowSurfaces;
+ QString m_graphicsSystemName;
+
+ uint m_graphicsSystemChangeMemoryLimit;
+ QString m_pendingGraphicsSystemName;
+
+ friend class QRuntimePixmapData;
+ friend class QRuntimeWindowSurface;
+};
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/gui/painting/qgraphicssystemfactory.cpp b/src/gui/painting/qgraphicssystemfactory.cpp
index 3c09894..ee6fbd8 100644
--- a/src/gui/painting/qgraphicssystemfactory.cpp
+++ b/src/gui/painting/qgraphicssystemfactory.cpp
@@ -46,6 +46,7 @@
#include "qapplication.h"
#include "qgraphicssystem_raster_p.h"
+#include "qgraphicssystem_runtime_p.h"
#include "qdebug.h"
QT_BEGIN_NAMESPACE
@@ -68,6 +69,10 @@ QGraphicsSystem *QGraphicsSystemFactory::create(const QString& key)
if (system.isEmpty()) {
system = QLatin1String("openvg");
}
+#elif defined (QT_GRAPHICSSYSTEM_RUNTIME)
+ if (system.isEmpty()) {
+ system = QLatin1String("runtime");
+ }
#elif defined (QT_GRAPHICSSYSTEM_RASTER) && !defined(Q_WS_WIN) && !defined(Q_OS_SYMBIAN)
if (system.isEmpty()) {
system = QLatin1String("raster");
@@ -76,6 +81,8 @@ QGraphicsSystem *QGraphicsSystemFactory::create(const QString& key)
if (system == QLatin1String("raster"))
return new QRasterGraphicsSystem;
+ else if (system == QLatin1String("runtime"))
+ return new QRuntimeGraphicsSystem;
else if (system.isEmpty() || system == QLatin1String("native"))
return 0;
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp
index 6f395f6..48974e8 100644
--- a/src/gui/painting/qpaintengine_raster.cpp
+++ b/src/gui/painting/qpaintengine_raster.cpp
@@ -441,8 +441,9 @@ bool QRasterPaintEngine::begin(QPaintDevice *device)
if (device->devType() == QInternal::Pixmap) {
QPixmap *pixmap = static_cast<QPixmap *>(device);
- if (pixmap->data->classId() == QPixmapData::RasterClass)
- d->device = pixmap->data->buffer();
+ QPixmapData *pd = pixmap->pixmapData();
+ if (pd->classId() == QPixmapData::RasterClass)
+ d->device = pd->buffer();
} else {
d->device = device;
}
@@ -2358,8 +2359,9 @@ void QRasterPaintEngine::drawPixmap(const QPointF &pos, const QPixmap &pixmap)
qDebug() << " - QRasterPaintEngine::drawPixmap(), pos=" << pos << " pixmap=" << pixmap.size() << "depth=" << pixmap.depth();
#endif
- if (pixmap.data->classId() == QPixmapData::RasterClass) {
- const QImage &image = static_cast<QRasterPixmapData *>(pixmap.data.data())->image;
+ QPixmapData *pd = pixmap.pixmapData();
+ if (pd->classId() == QPixmapData::RasterClass) {
+ const QImage &image = static_cast<QRasterPixmapData *>(pd)->image;
if (image.depth() == 1) {
Q_D(QRasterPaintEngine);
QRasterPaintEngineState *s = state();
@@ -2398,8 +2400,9 @@ void QRasterPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pixmap, cons
qDebug() << " - QRasterPaintEngine::drawPixmap(), r=" << r << " sr=" << sr << " pixmap=" << pixmap.size() << "depth=" << pixmap.depth();
#endif
- if (pixmap.data->classId() == QPixmapData::RasterClass) {
- const QImage &image = static_cast<QRasterPixmapData *>(pixmap.data.data())->image;
+ QPixmapData* pd = pixmap.pixmapData();
+ if (pd->classId() == QPixmapData::RasterClass) {
+ const QImage &image = static_cast<QRasterPixmapData *>(pd)->image;
if (image.depth() == 1) {
Q_D(QRasterPaintEngine);
QRasterPaintEngineState *s = state();
@@ -2703,8 +2706,9 @@ void QRasterPaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap,
QImage image;
- if (pixmap.data->classId() == QPixmapData::RasterClass) {
- image = static_cast<QRasterPixmapData *>(pixmap.data.data())->image;
+ QPixmapData *pd = pixmap.pixmapData();
+ if (pd->classId() == QPixmapData::RasterClass) {
+ image = static_cast<QRasterPixmapData *>(pd)->image;
} else {
image = pixmap.toImage();
}
diff --git a/src/gui/painting/qwindowsurface.cpp b/src/gui/painting/qwindowsurface.cpp
index e18ea3f..2fe9036 100644
--- a/src/gui/painting/qwindowsurface.cpp
+++ b/src/gui/painting/qwindowsurface.cpp
@@ -116,8 +116,6 @@ public:
QWindowSurface::QWindowSurface(QWidget *window)
: d_ptr(new QWindowSurfacePrivate(window))
{
- if (window)
- window->setWindowSurface(this);
}
/*!
diff --git a/src/gui/painting/qwindowsurface_s60.cpp b/src/gui/painting/qwindowsurface_s60.cpp
index b25dce5..93d4d18 100644
--- a/src/gui/painting/qwindowsurface_s60.cpp
+++ b/src/gui/painting/qwindowsurface_s60.cpp
@@ -43,10 +43,15 @@
#include <QtGui/qpaintdevice.h>
#include <private/qwidget_p.h>
-#include "qwindowsurface_s60_p.h"
+#include <private/qwindowsurface_s60_p.h>
#include <private/qpixmap_s60_p.h>
#include <private/qt_s60_p.h>
-#include "private/qdrawhelper_p.h"
+#include <private/qapplication_p.h>
+#include <private/qdrawhelper_p.h>
+
+#ifdef QT_GRAPHICSSYSTEM_RUNTIME
+#include <private/qgraphicssystem_runtime_p.h>
+#endif
QT_BEGIN_NAMESPACE
@@ -79,13 +84,35 @@ QS60WindowSurface::QS60WindowSurface(QWidget* widget)
setStaticContentsSupport(true);
}
+
QS60WindowSurface::~QS60WindowSurface()
{
+#if defined(QT_GRAPHICSSYSTEM_RUNTIME) && defined(Q_SYMBIAN_SUPPORTS_SURFACES)
+ if(QApplicationPrivate::graphics_system_name == QLatin1String("runtime")) {
+ QRuntimeGraphicsSystem *runtimeGraphicsSystem =
+ static_cast<QRuntimeGraphicsSystem*>(QApplicationPrivate::graphics_system);
+ if(runtimeGraphicsSystem->graphicsSystemName() == QLatin1String("openvg")) {
+
+ // Graphics system has been switched from raster to openvg.
+ // Issue empty redraw to clear the UI surface
+
+ QWidget *w = window();
+ RWindow *const window = static_cast<RWindow *>(w->winId()->DrawableWindow());
+ window->BeginRedraw();
+ window->EndRedraw();
+ }
+ }
+#endif
+
delete d_ptr;
}
void QS60WindowSurface::beginPaint(const QRegion &rgn)
{
+#ifdef Q_SYMBIAN_SUPPORTS_SURFACES
+ S60->wsSession().Finish();
+#endif
+
if (!qt_widget_private(window())->isOpaque) {
QS60PixmapData *pixmapData = static_cast<QS60PixmapData *>(d_ptr->device.data_ptr().data());
pixmapData->beginDataAccess();