1 /****************************************************************************
2 **
3 ** Copyright (C) 2015 The Qt Company Ltd.
4 ** Contact: http://www.qt.io/licensing/
5 **
6 ** This file is part of the QtGui module of the Qt Toolkit.
7 **
8 ** $QT_BEGIN_LICENSE:LGPL$
9 ** Commercial License Usage
10 ** Licensees holding valid commercial Qt licenses may use this file in
11 ** accordance with the commercial license agreement provided with the
12 ** Software or, alternatively, in accordance with the terms contained in
13 ** a written agreement between you and The Qt Company. For licensing terms
14 ** and conditions see http://www.qt.io/terms-conditions. For further
15 ** information use the contact form at http://www.qt.io/contact-us.
16 **
17 ** GNU Lesser General Public License Usage
18 ** Alternatively, this file may be used under the terms of the GNU Lesser
19 ** General Public License version 2.1 or version 3 as published by the Free
20 ** Software Foundation and appearing in the file LICENSE.LGPLv21 and
21 ** LICENSE.LGPLv3 included in the packaging of this file. Please review the
22 ** following information to ensure the GNU Lesser General Public License
23 ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and
24 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
25 **
26 ** As a special exception, The Qt Company gives you certain additional
27 ** rights. These rights are described in The Qt Company LGPL Exception
28 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
29 **
30 ** GNU General Public License Usage
31 ** Alternatively, this file may be used under the terms of the GNU
32 ** General Public License version 3.0 as published by the Free Software
33 ** Foundation and appearing in the file LICENSE.GPL included in the
34 ** packaging of this file.  Please review the following information to
35 ** ensure the GNU General Public License version 3.0 requirements will be
36 ** met: http://www.gnu.org/copyleft/gpl.html.
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     f                                                       \
57     readBackInfo();
58 
59 
60 class QDeferredGraphicsSystemChange : public QObject
61 {
62     Q_OBJECT
63 
64 public:
QDeferredGraphicsSystemChange(QRuntimeGraphicsSystem * gs,const QString & graphicsSystemName)65     QDeferredGraphicsSystemChange(QRuntimeGraphicsSystem *gs, const QString& graphicsSystemName)
66     : m_graphicsSystem(gs), m_graphicsSystemName(graphicsSystemName)
67     {
68     }
69 
launch()70     void launch()
71     {
72         QTimer::singleShot(0, this, SLOT(doChange()));
73     }
74 
75 private slots:
76 
doChange()77     void doChange()
78     {
79         m_graphicsSystem->setGraphicsSystem(m_graphicsSystemName);
80         deleteLater();
81     }
82 
83 private:
84 
85     QRuntimeGraphicsSystem *m_graphicsSystem;
86     QString m_graphicsSystemName;
87 };
88 
QRuntimePixmapData(const QRuntimeGraphicsSystem * gs,PixelType type)89 QRuntimePixmapData::QRuntimePixmapData(const QRuntimeGraphicsSystem *gs, PixelType type)
90         : QPixmapData(type, RuntimeClass), m_graphicsSystem(gs)
91 {
92     setSerialNumber(++qt_pixmap_serial);
93 }
94 
~QRuntimePixmapData()95 QRuntimePixmapData::~QRuntimePixmapData()
96 {
97     if (QApplicationPrivate::graphics_system)
98         m_graphicsSystem->removePixmapData(this);
99     delete m_data;
100 }
101 
readBackInfo()102 void QRuntimePixmapData::readBackInfo()
103 {
104     w = m_data->width();
105     h = m_data->height();
106     d = m_data->depth();
107     is_null = m_data->isNull();
108 }
109 
110 
createCompatiblePixmapData() const111 QPixmapData *QRuntimePixmapData::createCompatiblePixmapData() const
112 {
113     QRuntimePixmapData *rtData = new QRuntimePixmapData(m_graphicsSystem, pixelType());
114     rtData->m_data = m_data->createCompatiblePixmapData();
115     return rtData;
116 }
117 
118 
resize(int width,int height)119 void QRuntimePixmapData::resize(int width, int height)
120 {
121     READBACK(
122         m_data->resize(width, height);
123     )
124 }
125 
126 
fromImage(const QImage & image,Qt::ImageConversionFlags flags)127 void QRuntimePixmapData::fromImage(const QImage &image,
128                                    Qt::ImageConversionFlags flags)
129 {
130     READBACK(
131         m_data->fromImage(image, flags);
132     )
133 }
134 
135 
fromFile(const QString & filename,const char * format,Qt::ImageConversionFlags flags)136 bool QRuntimePixmapData::fromFile(const QString &filename, const char *format,
137                                   Qt::ImageConversionFlags flags)
138 {
139     bool success(false);
140     READBACK(
141         success = m_data->fromFile(filename, format, flags);
142     )
143     return success;
144 }
145 
fromData(const uchar * buffer,uint len,const char * format,Qt::ImageConversionFlags flags)146 bool QRuntimePixmapData::fromData(const uchar *buffer, uint len, const char *format,
147                                   Qt::ImageConversionFlags flags)
148 {
149     bool success(false);
150     READBACK(
151         success = m_data->fromData(buffer, len, format, flags);
152     )
153     return success;
154 }
155 
156 
copy(const QPixmapData * data,const QRect & rect)157 void QRuntimePixmapData::copy(const QPixmapData *data, const QRect &rect)
158 {
159     if (data->runtimeData()) {
160         READBACK(
161             m_data->copy(data->runtimeData(), rect);
162         )
163     } else {
164         READBACK(
165             m_data->copy(data, rect);
166         )
167     }
168 }
169 
scroll(int dx,int dy,const QRect & rect)170 bool QRuntimePixmapData::scroll(int dx, int dy, const QRect &rect)
171 {
172     return m_data->scroll(dx, dy, rect);
173 }
174 
175 
metric(QPaintDevice::PaintDeviceMetric metric) const176 int QRuntimePixmapData::metric(QPaintDevice::PaintDeviceMetric metric) const
177 {
178     return m_data->metric(metric);
179 }
180 
fill(const QColor & color)181 void QRuntimePixmapData::fill(const QColor &color)
182 {
183     return m_data->fill(color);
184 }
185 
mask() const186 QBitmap QRuntimePixmapData::mask() const
187 {
188     return m_data->mask();
189 }
190 
setMask(const QBitmap & mask)191 void QRuntimePixmapData::setMask(const QBitmap &mask)
192 {
193     READBACK(
194         m_data->setMask(mask);
195     )
196 }
197 
hasAlphaChannel() const198 bool QRuntimePixmapData::hasAlphaChannel() const
199 {
200     return m_data->hasAlphaChannel();
201 }
202 
transformed(const QTransform & matrix,Qt::TransformationMode mode) const203 QPixmap QRuntimePixmapData::transformed(const QTransform &matrix,
204                                         Qt::TransformationMode mode) const
205 {
206     return m_data->transformed(matrix, mode);
207 }
208 
setAlphaChannel(const QPixmap & alphaChannel)209 void QRuntimePixmapData::setAlphaChannel(const QPixmap &alphaChannel)
210 {
211     READBACK(
212         m_data->setAlphaChannel(alphaChannel);
213     )
214 }
215 
alphaChannel() const216 QPixmap QRuntimePixmapData::alphaChannel() const
217 {
218     return m_data->alphaChannel();
219 }
220 
toImage() const221 QImage QRuntimePixmapData::toImage() const
222 {
223     return m_data->toImage();
224 }
225 
paintEngine() const226 QPaintEngine* QRuntimePixmapData::paintEngine() const
227 {
228     return m_data->paintEngine();
229 }
230 
buffer()231 QImage* QRuntimePixmapData::buffer()
232 {
233     return m_data->buffer();
234 }
235 
236 #if defined(Q_OS_SYMBIAN)
toNativeType(NativeType type)237 void* QRuntimePixmapData::toNativeType(NativeType type)
238 {
239     return m_data->toNativeType(type);
240 }
241 
fromNativeType(void * pixmap,NativeType type)242 void QRuntimePixmapData::fromNativeType(void *pixmap, NativeType type)
243 {
244     m_data->fromNativeType(pixmap, type);
245     readBackInfo();
246 }
247 #endif
248 
runtimeData() const249 QPixmapData* QRuntimePixmapData::runtimeData() const
250 {
251     return m_data;
252 }
253 
QRuntimeWindowSurface(const QRuntimeGraphicsSystem * gs,QWidget * window)254 QRuntimeWindowSurface::QRuntimeWindowSurface(const QRuntimeGraphicsSystem *gs, QWidget *window)
255     : QWindowSurface(window), m_graphicsSystem(gs)
256 {
257 
258 }
259 
~QRuntimeWindowSurface()260 QRuntimeWindowSurface::~QRuntimeWindowSurface()
261 {
262     if (QApplicationPrivate::graphics_system)
263         m_graphicsSystem->removeWindowSurface(this);
264 }
265 
paintDevice()266 QPaintDevice *QRuntimeWindowSurface::paintDevice()
267 {
268     return m_windowSurface->paintDevice();
269 }
270 
flush(QWidget * widget,const QRegion & region,const QPoint & offset)271 void QRuntimeWindowSurface::flush(QWidget *widget, const QRegion &region,
272                                   const QPoint &offset)
273 {
274     m_windowSurface->flush(widget, region, offset);
275 
276     int destroyPolicy = m_graphicsSystem->windowSurfaceDestroyPolicy();
277     if(m_pendingWindowSurface &&
278         destroyPolicy == QRuntimeGraphicsSystem::DestroyAfterFirstFlush) {
279 #ifdef QT_DEBUG
280         qDebug() << "QRuntimeWindowSurface::flush() - destroy pending window surface";
281 #endif
282         m_pendingWindowSurface.reset();
283     }
284 }
285 
setGeometry(const QRect & rect)286 void QRuntimeWindowSurface::setGeometry(const QRect &rect)
287 {
288     QWindowSurface::setGeometry(rect);
289     m_windowSurface->setGeometry(rect);
290 }
291 
scroll(const QRegion & area,int dx,int dy)292 bool QRuntimeWindowSurface::scroll(const QRegion &area, int dx, int dy)
293 {
294     return m_windowSurface->scroll(area, dx, dy);
295 }
296 
beginPaint(const QRegion & rgn)297 void QRuntimeWindowSurface::beginPaint(const QRegion &rgn)
298 {
299     m_windowSurface->beginPaint(rgn);
300 }
301 
endPaint(const QRegion & rgn)302 void QRuntimeWindowSurface::endPaint(const QRegion &rgn)
303 {
304     m_windowSurface->endPaint(rgn);
305 }
306 
buffer(const QWidget * widget)307 QImage* QRuntimeWindowSurface::buffer(const QWidget *widget)
308 {
309     return m_windowSurface->buffer(widget);
310 }
311 
grabWidget(const QWidget * widget,const QRect & rectangle) const312 QPixmap QRuntimeWindowSurface::grabWidget(const QWidget *widget, const QRect& rectangle) const
313 {
314     return m_windowSurface->grabWidget(widget, rectangle);
315 }
316 
offset(const QWidget * widget) const317 QPoint QRuntimeWindowSurface::offset(const QWidget *widget) const
318 {
319     return m_windowSurface->offset(widget);
320 }
321 
features() const322 QWindowSurface::WindowSurfaceFeatures QRuntimeWindowSurface::features() const
323 {
324     return m_windowSurface->features();
325 }
326 
QRuntimeGraphicsSystem()327 QRuntimeGraphicsSystem::QRuntimeGraphicsSystem()
328     : m_windowSurfaceDestroyPolicy(DestroyImmediately),
329       m_graphicsSystem(0)
330 {
331     QApplicationPrivate::runtime_graphics_system = true;
332 
333     if (!qgetenv("QT_DEFAULT_RUNTIME_SYSTEM").isEmpty()) {
334         m_graphicsSystemName = QString::fromLocal8Bit(qgetenv("QT_DEFAULT_RUNTIME_SYSTEM"));
335     } else {
336 #ifdef QT_DEFAULT_RUNTIME_SYSTEM
337         m_graphicsSystemName = QLatin1String(QT_DEFAULT_RUNTIME_SYSTEM);
338         if (m_graphicsSystemName.isNull())
339 #endif
340             m_graphicsSystemName = QLatin1String("raster");
341     }
342 
343 #ifdef Q_OS_SYMBIAN
344     m_windowSurfaceDestroyPolicy = DestroyAfterFirstFlush;
345 #endif
346 
347     m_graphicsSystem = QGraphicsSystemFactory::create(m_graphicsSystemName);
348 
349     QApplicationPrivate::graphics_system_name = QLatin1String("runtime");
350 }
351 
352 
createPixmapData(QPixmapData::PixelType type) const353 QPixmapData *QRuntimeGraphicsSystem::createPixmapData(QPixmapData::PixelType type) const
354 {
355     Q_ASSERT(m_graphicsSystem);
356     QPixmapData *data = m_graphicsSystem->createPixmapData(type);
357 
358     QRuntimePixmapData *rtData = new QRuntimePixmapData(this, type);
359     rtData->m_data = data;
360     m_pixmapDatas << rtData;
361 
362     return rtData;
363 }
364 
createWindowSurface(QWidget * widget) const365 QWindowSurface *QRuntimeGraphicsSystem::createWindowSurface(QWidget *widget) const
366 {
367     Q_ASSERT(m_graphicsSystem);
368     QRuntimeWindowSurface *rtSurface = new QRuntimeWindowSurface(this, widget);
369     rtSurface->m_windowSurface.reset(m_graphicsSystem->createWindowSurface(widget));
370     widget->setWindowSurface(rtSurface);
371     m_windowSurfaces << rtSurface;
372     return rtSurface;
373 }
374 
setGraphicsSystem(const QString & name)375 void QRuntimeGraphicsSystem::setGraphicsSystem(const QString &name)
376 {
377     if (m_graphicsSystemName == name)
378         return;
379 #ifdef QT_DEBUG
380     qDebug() << "QRuntimeGraphicsSystem::setGraphicsSystem( " << name << " )";
381 #endif
382     QGraphicsSystem *oldSystem = m_graphicsSystem;
383     m_graphicsSystem = QGraphicsSystemFactory::create(name);
384     m_graphicsSystemName = name;
385 
386     Q_ASSERT(m_graphicsSystem);
387 
388     m_pendingGraphicsSystemName = QString();
389 
390     for (int i = 0; i < m_pixmapDatas.size(); ++i) {
391         QRuntimePixmapData *proxy = m_pixmapDatas.at(i);
392         QPixmapData *newData = m_graphicsSystem->createPixmapData(proxy->m_data);
393         newData->fromImage(proxy->m_data->toImage(), Qt::NoOpaqueDetection);
394         delete proxy->m_data;
395         proxy->m_data = newData;
396         proxy->readBackInfo();
397     }
398 
399     for (int i = 0; i < m_windowSurfaces.size(); ++i) {
400         QRuntimeWindowSurface *proxy = m_windowSurfaces.at(i);
401         QWidget *widget = proxy->m_windowSurface->window();
402 
403         if(m_windowSurfaceDestroyPolicy == DestroyAfterFirstFlush)
404             proxy->m_pendingWindowSurface.reset(proxy->m_windowSurface.take());
405 
406         QWindowSurface *newWindowSurface = m_graphicsSystem->createWindowSurface(widget);
407         newWindowSurface->setGeometry(proxy->geometry());
408 
409         proxy->m_windowSurface.reset(newWindowSurface);
410         qt_widget_private(widget)->invalidateBuffer(widget->rect());
411     }
412 
413     delete oldSystem;
414 }
415 
removePixmapData(QRuntimePixmapData * pixmapData) const416 void QRuntimeGraphicsSystem::removePixmapData(QRuntimePixmapData *pixmapData) const
417 {
418     int index = m_pixmapDatas.lastIndexOf(pixmapData);
419     m_pixmapDatas.removeAt(index);
420 }
421 
removeWindowSurface(QRuntimeWindowSurface * windowSurface) const422 void QRuntimeGraphicsSystem::removeWindowSurface(QRuntimeWindowSurface *windowSurface) const
423 {
424     int index = m_windowSurfaces.lastIndexOf(windowSurface);
425     m_windowSurfaces.removeAt(index);
426 }
427 
428 #include "qgraphicssystem_runtime.moc"
429 
430 QT_END_NAMESPACE
431