src/gui/painting/qgraphicssystem_runtime.cpp
changeset 33 3e2da88830cd
child 37 758a864f9613
equal deleted inserted replaced
30:5dc02b23752f 33:3e2da88830cd
       
     1 /****************************************************************************
       
     2 **
       
     3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     4 ** All rights reserved.
       
     5 ** Contact: Nokia Corporation (qt-info@nokia.com)
       
     6 **
       
     7 ** This file is part of the QtGui module of the Qt Toolkit.
       
     8 **
       
     9 ** $QT_BEGIN_LICENSE:LGPL$
       
    10 ** No Commercial Usage
       
    11 ** This file contains pre-release code and may not be distributed.
       
    12 ** You may use this file in accordance with the terms and conditions
       
    13 ** contained in the Technology Preview License Agreement accompanying
       
    14 ** this package.
       
    15 **
       
    16 ** GNU Lesser General Public License Usage
       
    17 ** Alternatively, this file may be used under the terms of the GNU Lesser
       
    18 ** General Public License version 2.1 as published by the Free Software
       
    19 ** Foundation and appearing in the file LICENSE.LGPL included in the
       
    20 ** packaging of this file.  Please review the following information to
       
    21 ** ensure the GNU Lesser General Public License version 2.1 requirements
       
    22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    23 **
       
    24 ** In addition, as a special exception, Nokia gives you certain additional
       
    25 ** rights.  These rights are described in the Nokia Qt LGPL Exception
       
    26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    27 **
       
    28 ** If you have questions regarding the use of this file, please contact
       
    29 ** Nokia at qt-info@nokia.com.
       
    30 **
       
    31 **
       
    32 **
       
    33 **
       
    34 **
       
    35 **
       
    36 **
       
    37 **
       
    38 ** $QT_END_LICENSE$
       
    39 **
       
    40 ****************************************************************************/
       
    41 
       
    42 #include <private/qgraphicssystem_runtime_p.h>
       
    43 #include <private/qgraphicssystem_raster_p.h>
       
    44 #include <private/qgraphicssystemfactory_p.h>
       
    45 #include <private/qapplication_p.h>
       
    46 #include <private/qwidget_p.h>
       
    47 #include <QtCore/QDebug>
       
    48 #include <QtCore/QTimer>
       
    49 #include <QtGui/QBitmap>
       
    50 
       
    51 QT_BEGIN_NAMESPACE
       
    52 
       
    53 static int qt_pixmap_serial = 0;
       
    54 
       
    55 #define READBACK(f)                                         \
       
    56     m_graphicsSystem->decreaseMemoryUsage(memoryUsage());   \
       
    57     f                                                       \
       
    58     readBackInfo();                                         \
       
    59     m_graphicsSystem->increaseMemoryUsage(memoryUsage());   \
       
    60 
       
    61 
       
    62 class QDeferredGraphicsSystemChange : public QObject
       
    63 {
       
    64     Q_OBJECT
       
    65 
       
    66 public:
       
    67     QDeferredGraphicsSystemChange(QRuntimeGraphicsSystem *gs, const QString& graphicsSystemName)
       
    68     : m_graphicsSystem(gs), m_graphicsSystemName(graphicsSystemName)
       
    69     {
       
    70     }
       
    71 
       
    72     void launch()
       
    73     {
       
    74         QTimer::singleShot(0, this, SLOT(doChange()));
       
    75     }
       
    76 
       
    77 private slots:
       
    78 
       
    79     void doChange()
       
    80     {
       
    81         m_graphicsSystem->setGraphicsSystem(m_graphicsSystemName);
       
    82         deleteLater();
       
    83     }
       
    84 
       
    85 private:
       
    86 
       
    87     QRuntimeGraphicsSystem *m_graphicsSystem;
       
    88     QString m_graphicsSystemName;
       
    89 };
       
    90 
       
    91 QRuntimePixmapData::QRuntimePixmapData(const QRuntimeGraphicsSystem *gs, PixelType type)
       
    92         : QPixmapData(type, RuntimeClass), m_graphicsSystem(gs)
       
    93 {
       
    94     setSerialNumber(++qt_pixmap_serial);
       
    95 }
       
    96 
       
    97 QRuntimePixmapData::~QRuntimePixmapData()
       
    98 {
       
    99     m_graphicsSystem->removePixmapData(this);
       
   100     delete m_data;
       
   101 }
       
   102 
       
   103 void QRuntimePixmapData::readBackInfo()
       
   104 {
       
   105     w = m_data->width();
       
   106     h = m_data->height();
       
   107     d = m_data->depth();
       
   108     is_null = m_data->isNull();
       
   109 }
       
   110 
       
   111 
       
   112 QPixmapData *QRuntimePixmapData::createCompatiblePixmapData() const
       
   113 {
       
   114     QRuntimePixmapData *rtData = new QRuntimePixmapData(m_graphicsSystem, pixelType());
       
   115     rtData->m_data = m_data->createCompatiblePixmapData();
       
   116     return rtData;
       
   117 }
       
   118 
       
   119 
       
   120 void QRuntimePixmapData::resize(int width, int height)
       
   121 {
       
   122     READBACK(
       
   123         m_data->resize(width, height);
       
   124     )
       
   125 }
       
   126 
       
   127 
       
   128 void QRuntimePixmapData::fromImage(const QImage &image,
       
   129                                    Qt::ImageConversionFlags flags)
       
   130 {
       
   131     READBACK(
       
   132         m_data->fromImage(image, flags);
       
   133     )
       
   134 }
       
   135 
       
   136 
       
   137 bool QRuntimePixmapData::fromFile(const QString &filename, const char *format,
       
   138                                   Qt::ImageConversionFlags flags)
       
   139 {
       
   140     bool success(false);
       
   141     READBACK(
       
   142         success = m_data->fromFile(filename, format, flags);
       
   143     )
       
   144     return success;
       
   145 }
       
   146 
       
   147 bool QRuntimePixmapData::fromData(const uchar *buffer, uint len, const char *format,
       
   148                                   Qt::ImageConversionFlags flags)
       
   149 {
       
   150     bool success(false);
       
   151     READBACK(
       
   152         success = m_data->fromData(buffer, len, format, flags);
       
   153     )
       
   154     return success;
       
   155 }
       
   156 
       
   157 
       
   158 void QRuntimePixmapData::copy(const QPixmapData *data, const QRect &rect)
       
   159 {
       
   160     if (data->runtimeData()) {
       
   161         READBACK(
       
   162             m_data->copy(data->runtimeData(), rect);
       
   163         )
       
   164     } else {
       
   165         READBACK(
       
   166             m_data->copy(data, rect);
       
   167         )
       
   168     }
       
   169 }
       
   170 
       
   171 bool QRuntimePixmapData::scroll(int dx, int dy, const QRect &rect)
       
   172 {
       
   173     return m_data->scroll(dx, dy, rect);
       
   174 }
       
   175 
       
   176 
       
   177 int QRuntimePixmapData::metric(QPaintDevice::PaintDeviceMetric metric) const
       
   178 {
       
   179     return m_data->metric(metric);
       
   180 }
       
   181 
       
   182 void QRuntimePixmapData::fill(const QColor &color)
       
   183 {
       
   184     return m_data->fill(color);
       
   185 }
       
   186 
       
   187 QBitmap QRuntimePixmapData::mask() const
       
   188 {
       
   189     return m_data->mask();
       
   190 }
       
   191 
       
   192 void QRuntimePixmapData::setMask(const QBitmap &mask)
       
   193 {
       
   194     READBACK(
       
   195         m_data->setMask(mask);
       
   196     )
       
   197 }
       
   198 
       
   199 bool QRuntimePixmapData::hasAlphaChannel() const
       
   200 {
       
   201     return m_data->hasAlphaChannel();
       
   202 }
       
   203 
       
   204 QPixmap QRuntimePixmapData::transformed(const QTransform &matrix,
       
   205                                         Qt::TransformationMode mode) const
       
   206 {
       
   207     return m_data->transformed(matrix, mode);
       
   208 }
       
   209 
       
   210 void QRuntimePixmapData::setAlphaChannel(const QPixmap &alphaChannel)
       
   211 {
       
   212     READBACK(
       
   213         m_data->setAlphaChannel(alphaChannel);
       
   214     )
       
   215 }
       
   216 
       
   217 QPixmap QRuntimePixmapData::alphaChannel() const
       
   218 {
       
   219     return m_data->alphaChannel();
       
   220 }
       
   221 
       
   222 QImage QRuntimePixmapData::toImage() const
       
   223 {
       
   224     return m_data->toImage();
       
   225 }
       
   226 
       
   227 QPaintEngine* QRuntimePixmapData::paintEngine() const
       
   228 {
       
   229     return m_data->paintEngine();
       
   230 }
       
   231 
       
   232 QImage* QRuntimePixmapData::buffer()
       
   233 {
       
   234     return m_data->buffer();
       
   235 }
       
   236 
       
   237 #if defined(Q_OS_SYMBIAN)
       
   238 void* QRuntimePixmapData::toNativeType(NativeType type)
       
   239 {
       
   240     return m_data->toNativeType(type);
       
   241 }
       
   242 
       
   243 void QRuntimePixmapData::fromNativeType(void *pixmap, NativeType type)
       
   244 {
       
   245     m_data->fromNativeType(pixmap, type);
       
   246     readBackInfo();
       
   247 }
       
   248 #endif
       
   249 
       
   250 QPixmapData* QRuntimePixmapData::runtimeData() const
       
   251 {
       
   252     return m_data;
       
   253 }
       
   254 
       
   255 uint QRuntimePixmapData::memoryUsage() const
       
   256 {
       
   257     if(is_null || d == 0)
       
   258         return 0;
       
   259     return w * h * (d / 8);
       
   260 }
       
   261 
       
   262 
       
   263 QRuntimeWindowSurface::QRuntimeWindowSurface(const QRuntimeGraphicsSystem *gs, QWidget *window)
       
   264     : QWindowSurface(window), m_windowSurface(0), m_pendingWindowSurface(0), m_graphicsSystem(gs)
       
   265 {
       
   266 
       
   267 }
       
   268 
       
   269 QRuntimeWindowSurface::~QRuntimeWindowSurface()
       
   270 {
       
   271     m_graphicsSystem->removeWindowSurface(this);
       
   272     delete m_windowSurface;
       
   273 }
       
   274 
       
   275 QPaintDevice *QRuntimeWindowSurface::paintDevice()
       
   276 {
       
   277     return m_windowSurface->paintDevice();
       
   278 }
       
   279 
       
   280 void QRuntimeWindowSurface::flush(QWidget *widget, const QRegion &region,
       
   281                                   const QPoint &offset)
       
   282 {
       
   283     m_windowSurface->flush(widget, region, offset);
       
   284 
       
   285     int destroyPolicy = m_graphicsSystem->windowSurfaceDestroyPolicy();
       
   286     if(m_pendingWindowSurface &&
       
   287         destroyPolicy == QRuntimeGraphicsSystem::DestroyAfterFirstFlush) {
       
   288 #ifdef QT_DEBUG
       
   289         qDebug() << "QRuntimeWindowSurface::flush() - destroy pending window surface";
       
   290 #endif
       
   291         delete m_pendingWindowSurface;
       
   292         m_pendingWindowSurface = 0;
       
   293     }
       
   294 }
       
   295 
       
   296 void QRuntimeWindowSurface::setGeometry(const QRect &rect)
       
   297 {
       
   298     m_graphicsSystem->decreaseMemoryUsage(memoryUsage());
       
   299     m_windowSurface->setGeometry(rect);
       
   300     m_graphicsSystem->increaseMemoryUsage(memoryUsage());
       
   301 }
       
   302 
       
   303 bool QRuntimeWindowSurface::scroll(const QRegion &area, int dx, int dy)
       
   304 {
       
   305     return m_windowSurface->scroll(area, dx, dy);
       
   306 }
       
   307 
       
   308 void QRuntimeWindowSurface::beginPaint(const QRegion &rgn)
       
   309 {
       
   310     m_windowSurface->beginPaint(rgn);
       
   311 }
       
   312 
       
   313 void QRuntimeWindowSurface::endPaint(const QRegion &rgn)
       
   314 {
       
   315     m_windowSurface->endPaint(rgn);
       
   316 }
       
   317 
       
   318 QImage* QRuntimeWindowSurface::buffer(const QWidget *widget)
       
   319 {
       
   320     return m_windowSurface->buffer(widget);
       
   321 }
       
   322 
       
   323 QPixmap QRuntimeWindowSurface::grabWidget(const QWidget *widget, const QRect& rectangle) const
       
   324 {
       
   325     return m_windowSurface->grabWidget(widget, rectangle);
       
   326 }
       
   327 
       
   328 QPoint QRuntimeWindowSurface::offset(const QWidget *widget) const
       
   329 {
       
   330     return m_windowSurface->offset(widget);
       
   331 }
       
   332 
       
   333 uint QRuntimeWindowSurface::memoryUsage() const
       
   334 {
       
   335     QPaintDevice *pdev = m_windowSurface->paintDevice();
       
   336     if (pdev && pdev->depth() != 0)
       
   337         return pdev->width() * pdev->height() * (pdev->depth()/8);
       
   338 
       
   339     return 0;
       
   340 }
       
   341 
       
   342 QRuntimeGraphicsSystem::QRuntimeGraphicsSystem()
       
   343     : m_memoryUsage(0), m_windowSurfaceDestroyPolicy(DestroyImmediately),
       
   344 	m_graphicsSystem(0), m_graphicsSystemChangeMemoryLimit(0)
       
   345 {
       
   346     QApplicationPrivate::graphics_system_name = QLatin1String("runtime");
       
   347     QApplicationPrivate::runtime_graphics_system = true;
       
   348 
       
   349 #ifdef Q_OS_SYMBIAN
       
   350     m_graphicsSystemName = QLatin1String("openvg");
       
   351     m_windowSurfaceDestroyPolicy = DestroyAfterFirstFlush;
       
   352 #else
       
   353     m_graphicsSystemName = QLatin1String("raster");
       
   354 #endif
       
   355 
       
   356     m_graphicsSystem = QGraphicsSystemFactory::create(m_graphicsSystemName);
       
   357 }
       
   358 
       
   359 
       
   360 QPixmapData *QRuntimeGraphicsSystem::createPixmapData(QPixmapData::PixelType type) const
       
   361 {
       
   362     Q_ASSERT(m_graphicsSystem);
       
   363     QPixmapData *data = m_graphicsSystem->createPixmapData(type);
       
   364 
       
   365     QRuntimePixmapData *rtData = new QRuntimePixmapData(this, type);
       
   366     rtData->m_data = data;
       
   367     m_pixmapDatas << rtData;
       
   368 
       
   369     return rtData;
       
   370 }
       
   371 
       
   372 QWindowSurface *QRuntimeGraphicsSystem::createWindowSurface(QWidget *widget) const
       
   373 {
       
   374     Q_ASSERT(m_graphicsSystem);
       
   375     QRuntimeWindowSurface *rtSurface = new QRuntimeWindowSurface(this, widget);
       
   376     rtSurface->m_windowSurface = m_graphicsSystem->createWindowSurface(widget);
       
   377     widget->setWindowSurface(rtSurface);
       
   378     m_windowSurfaces << rtSurface;
       
   379     increaseMemoryUsage(rtSurface->memoryUsage());
       
   380     return rtSurface;
       
   381 }
       
   382 
       
   383 /*!
       
   384     Sets graphics system when resource memory consumption is under /a memoryUsageLimit.
       
   385 */
       
   386 void QRuntimeGraphicsSystem::setGraphicsSystem(const QString &name, uint memoryUsageLimit)
       
   387 {
       
   388 #ifdef QT_DEBUG
       
   389     qDebug() << "QRuntimeGraphicsSystem::setGraphicsSystem( "<< name <<", " << memoryUsageLimit << ")";
       
   390     qDebug() << "        current approximated graphics system memory usage " << memoryUsage() << " bytes";
       
   391 #endif
       
   392     if (memoryUsage() >= memoryUsageLimit) {
       
   393         m_graphicsSystemChangeMemoryLimit = memoryUsageLimit;
       
   394         m_pendingGraphicsSystemName = name;
       
   395     } else {
       
   396         setGraphicsSystem(name);
       
   397     }
       
   398 }
       
   399 
       
   400 void QRuntimeGraphicsSystem::setGraphicsSystem(const QString &name)
       
   401 {
       
   402     if (m_graphicsSystemName == name)
       
   403         return;
       
   404 #ifdef QT_DEBUG
       
   405     qDebug() << "QRuntimeGraphicsSystem::setGraphicsSystem( " << name << " )";
       
   406     qDebug() << "        current approximated graphics system memory usage "<< memoryUsage() << " bytes";
       
   407 #endif
       
   408     delete m_graphicsSystem;
       
   409     m_graphicsSystem = QGraphicsSystemFactory::create(name);
       
   410     m_graphicsSystemName = name;
       
   411 
       
   412     Q_ASSERT(m_graphicsSystem);
       
   413 
       
   414     m_graphicsSystemChangeMemoryLimit = 0;
       
   415     m_pendingGraphicsSystemName = QString();
       
   416 
       
   417     for (int i = 0; i < m_pixmapDatas.size(); ++i) {
       
   418         QRuntimePixmapData *proxy = m_pixmapDatas.at(i);
       
   419         QPixmapData *newData = m_graphicsSystem->createPixmapData(proxy->m_data);
       
   420         // ### TODO Optimize. Openvg and s60raster graphics systems could switch internal ARGB32_PRE QImage buffers.
       
   421         newData->fromImage(proxy->m_data->toImage(), Qt::NoOpaqueDetection);
       
   422         delete proxy->m_data;
       
   423         proxy->m_data = newData;
       
   424         proxy->readBackInfo();
       
   425     }
       
   426 
       
   427     for (int i = 0; i < m_windowSurfaces.size(); ++i) {
       
   428         QRuntimeWindowSurface *proxy = m_windowSurfaces.at(i);
       
   429         QWidget *widget = proxy->m_windowSurface->window();
       
   430 
       
   431         if(m_windowSurfaceDestroyPolicy == DestroyImmediately) {
       
   432             delete proxy->m_windowSurface;
       
   433             proxy->m_pendingWindowSurface = 0;
       
   434         } else {
       
   435             proxy->m_pendingWindowSurface = proxy->m_windowSurface;
       
   436         }
       
   437 
       
   438         proxy->m_windowSurface = m_graphicsSystem->createWindowSurface(widget);
       
   439         qt_widget_private(widget)->invalidateBuffer(widget->rect());
       
   440     }
       
   441 }
       
   442 
       
   443 void QRuntimeGraphicsSystem::removePixmapData(QRuntimePixmapData *pixmapData) const
       
   444 {
       
   445     int index = m_pixmapDatas.lastIndexOf(pixmapData);
       
   446     m_pixmapDatas.removeAt(index);
       
   447     decreaseMemoryUsage(pixmapData->memoryUsage(), true);
       
   448 }
       
   449 
       
   450 void QRuntimeGraphicsSystem::removeWindowSurface(QRuntimeWindowSurface *windowSurface) const
       
   451 {
       
   452     int index = m_windowSurfaces.lastIndexOf(windowSurface);
       
   453     m_windowSurfaces.removeAt(index);
       
   454     decreaseMemoryUsage(windowSurface->memoryUsage(), true);
       
   455 }
       
   456 
       
   457 void QRuntimeGraphicsSystem::increaseMemoryUsage(uint amount) const
       
   458 {
       
   459     m_memoryUsage += amount;
       
   460 
       
   461     if (m_graphicsSystemChangeMemoryLimit &&
       
   462         m_memoryUsage < m_graphicsSystemChangeMemoryLimit) {
       
   463 
       
   464         QRuntimeGraphicsSystem *gs = const_cast<QRuntimeGraphicsSystem*>(this);
       
   465         QDeferredGraphicsSystemChange *deferredChange =
       
   466                     new QDeferredGraphicsSystemChange(gs, m_pendingGraphicsSystemName);
       
   467         deferredChange->launch();
       
   468     }
       
   469 }
       
   470 
       
   471 void QRuntimeGraphicsSystem::decreaseMemoryUsage(uint amount, bool persistent) const
       
   472 {
       
   473     m_memoryUsage -= amount;
       
   474 
       
   475     if (persistent && m_graphicsSystemChangeMemoryLimit &&
       
   476         m_memoryUsage < m_graphicsSystemChangeMemoryLimit) {
       
   477 
       
   478         QRuntimeGraphicsSystem *gs = const_cast<QRuntimeGraphicsSystem*>(this);
       
   479         QDeferredGraphicsSystemChange *deferredChange =
       
   480                     new QDeferredGraphicsSystemChange(gs, m_pendingGraphicsSystemName);
       
   481         deferredChange->launch();
       
   482     }
       
   483 }
       
   484 
       
   485 #include "qgraphicssystem_runtime.moc"
       
   486 
       
   487 QT_END_NAMESPACE