1 | /****************************************************************************
|
---|
2 | **
|
---|
3 | ** Copyright (C) 2011 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 plugins of the Qt Toolkit.
|
---|
8 | **
|
---|
9 | ** $QT_BEGIN_LICENSE:LGPL$
|
---|
10 | ** Commercial Usage
|
---|
11 | ** Licensees holding valid Qt Commercial licenses may use this file in
|
---|
12 | ** accordance with the Qt Commercial License Agreement provided with the
|
---|
13 | ** Software or, alternatively, in accordance with the terms contained in
|
---|
14 | ** a written agreement between you and Nokia.
|
---|
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 | ** GNU General Public License Usage
|
---|
29 | ** Alternatively, this file may be used under the terms of the GNU
|
---|
30 | ** General Public License version 3.0 as published by the Free Software
|
---|
31 | ** Foundation and appearing in the file LICENSE.GPL included in the
|
---|
32 | ** packaging of this file. Please review the following information to
|
---|
33 | ** ensure the GNU General Public License version 3.0 requirements will be
|
---|
34 | ** met: http://www.gnu.org/copyleft/gpl.html.
|
---|
35 | **
|
---|
36 | ** If you have questions regarding the use of this file, please contact
|
---|
37 | ** Nokia at qt-info@nokia.com.
|
---|
38 | ** $QT_END_LICENSE$
|
---|
39 | **
|
---|
40 | ****************************************************************************/
|
---|
41 |
|
---|
42 | #include "qdirectfbpaintengine.h"
|
---|
43 |
|
---|
44 | #ifndef QT_NO_QWS_DIRECTFB
|
---|
45 |
|
---|
46 | #include "qdirectfbwindowsurface.h"
|
---|
47 | #include "qdirectfbscreen.h"
|
---|
48 | #include "qdirectfbpixmap.h"
|
---|
49 | #include <directfb.h>
|
---|
50 | #include <qtransform.h>
|
---|
51 | #include <qvarlengtharray.h>
|
---|
52 | #include <qcache.h>
|
---|
53 | #include <qmath.h>
|
---|
54 | #include <private/qpixmapdata_p.h>
|
---|
55 | #include <private/qpixmap_raster_p.h>
|
---|
56 | #include <private/qimagepixmapcleanuphooks_p.h>
|
---|
57 |
|
---|
58 |
|
---|
59 | QT_BEGIN_NAMESPACE
|
---|
60 |
|
---|
61 | class SurfaceCache;
|
---|
62 | class QDirectFBPaintEnginePrivate : public QRasterPaintEnginePrivate
|
---|
63 | {
|
---|
64 | public:
|
---|
65 | enum TransformationTypeFlags {
|
---|
66 | Matrix_NegativeScale = 0x100,
|
---|
67 | Matrix_RectsUnsupported = (QTransform::TxRotate|QTransform::TxShear|QTransform::TxProject),
|
---|
68 | Matrix_BlitsUnsupported = (Matrix_NegativeScale|Matrix_RectsUnsupported)
|
---|
69 | };
|
---|
70 |
|
---|
71 | inline static uint getTransformationType(const QTransform &transform)
|
---|
72 | {
|
---|
73 | int ret = transform.type();
|
---|
74 | if (qMin(transform.m11(), transform.m22()) < 0) {
|
---|
75 | ret |= QDirectFBPaintEnginePrivate::Matrix_NegativeScale;
|
---|
76 | }
|
---|
77 | return ret;
|
---|
78 | }
|
---|
79 |
|
---|
80 | enum CompositionModeStatus {
|
---|
81 | PorterDuff_None = 0x0,
|
---|
82 | PorterDuff_Supported = 0x1,
|
---|
83 | PorterDuff_PremultiplyColors = 0x2,
|
---|
84 | PorterDuff_AlwaysBlend = 0x4
|
---|
85 | };
|
---|
86 |
|
---|
87 | enum ClipType {
|
---|
88 | ClipUnset,
|
---|
89 | NoClip,
|
---|
90 | RectClip,
|
---|
91 | RegionClip,
|
---|
92 | ComplexClip
|
---|
93 | };
|
---|
94 |
|
---|
95 | QDirectFBPaintEnginePrivate(QDirectFBPaintEngine *p);
|
---|
96 | ~QDirectFBPaintEnginePrivate();
|
---|
97 |
|
---|
98 | inline void setTransform(const QTransform &transforma);
|
---|
99 | inline void setPen(const QPen &pen);
|
---|
100 | inline void setCompositionMode(QPainter::CompositionMode mode);
|
---|
101 | inline void setRenderHints(QPainter::RenderHints hints);
|
---|
102 |
|
---|
103 | inline void setDFBColor(const QColor &color);
|
---|
104 |
|
---|
105 | inline void lock();
|
---|
106 | inline void unlock();
|
---|
107 | static inline void unlock(QDirectFBPaintDevice *device);
|
---|
108 |
|
---|
109 | inline bool isSimpleBrush(const QBrush &brush) const;
|
---|
110 |
|
---|
111 | void drawTiledPixmap(const QRectF &dest, const QPixmap &pixmap, const QPointF &pos, const QTransform &pixmapTransform);
|
---|
112 | void blit(const QRectF &dest, IDirectFBSurface *surface, const QRectF &src);
|
---|
113 |
|
---|
114 | inline bool supportsStretchBlit() const;
|
---|
115 |
|
---|
116 | inline void updateClip();
|
---|
117 | virtual void systemStateChanged();
|
---|
118 |
|
---|
119 | static IDirectFBSurface *getSurface(const QImage &img, bool *release);
|
---|
120 |
|
---|
121 | #ifdef QT_DIRECTFB_IMAGECACHE
|
---|
122 | static inline int cacheCost(const QImage &img) { return img.width() * img.height() * img.depth() / 8; }
|
---|
123 | #endif
|
---|
124 |
|
---|
125 | enum BlitFlag {
|
---|
126 | HasAlpha = 0x1,
|
---|
127 | Premultiplied = 0x2
|
---|
128 | };
|
---|
129 | void prepareForBlit(uint blitFlags);
|
---|
130 |
|
---|
131 | IDirectFBSurface *surface;
|
---|
132 |
|
---|
133 | bool antialiased;
|
---|
134 | bool simplePen;
|
---|
135 |
|
---|
136 | uint transformationType; // this is QTransform::type() + Matrix_NegativeScale if qMin(transform.m11(), transform.m22()) < 0
|
---|
137 |
|
---|
138 | SurfaceCache *surfaceCache;
|
---|
139 | IDirectFB *fb;
|
---|
140 | quint8 opacity;
|
---|
141 |
|
---|
142 | ClipType clipType;
|
---|
143 | QDirectFBPaintDevice *dfbDevice;
|
---|
144 | uint compositionModeStatus;
|
---|
145 | bool isPremultiplied;
|
---|
146 |
|
---|
147 | bool inClip;
|
---|
148 | QRect currentClip;
|
---|
149 |
|
---|
150 | QDirectFBPaintEngine *q;
|
---|
151 | };
|
---|
152 |
|
---|
153 | class SurfaceCache
|
---|
154 | {
|
---|
155 | public:
|
---|
156 | SurfaceCache() : surface(0), buffer(0), bufsize(0) {}
|
---|
157 | ~SurfaceCache() { clear(); }
|
---|
158 | IDirectFBSurface *getSurface(const uint *buf, int size);
|
---|
159 | void clear();
|
---|
160 | private:
|
---|
161 | IDirectFBSurface *surface;
|
---|
162 | uint *buffer;
|
---|
163 | int bufsize;
|
---|
164 | };
|
---|
165 |
|
---|
166 |
|
---|
167 | #ifdef QT_DIRECTFB_IMAGECACHE
|
---|
168 | QT_BEGIN_INCLUDE_NAMESPACE
|
---|
169 | #include <private/qimage_p.h>
|
---|
170 | QT_END_INCLUDE_NAMESPACE
|
---|
171 | struct CachedImage
|
---|
172 | {
|
---|
173 | IDirectFBSurface *surface;
|
---|
174 | ~CachedImage()
|
---|
175 | {
|
---|
176 | if (surface && QDirectFBScreen::instance()) {
|
---|
177 | QDirectFBScreen::instance()->releaseDFBSurface(surface);
|
---|
178 | }
|
---|
179 | }
|
---|
180 | };
|
---|
181 | static QCache<qint64, CachedImage> imageCache(4*1024*1024); // 4 MB
|
---|
182 | #endif
|
---|
183 |
|
---|
184 | #define VOID_ARG() static_cast<bool>(false)
|
---|
185 | enum PaintOperation {
|
---|
186 | DRAW_RECTS = 0x0001, DRAW_LINES = 0x0002, DRAW_IMAGE = 0x0004,
|
---|
187 | DRAW_PIXMAP = 0x0008, DRAW_TILED_PIXMAP = 0x0010, STROKE_PATH = 0x0020,
|
---|
188 | DRAW_PATH = 0x0040, DRAW_POINTS = 0x0080, DRAW_ELLIPSE = 0x0100,
|
---|
189 | DRAW_POLYGON = 0x0200, DRAW_TEXT = 0x0400, FILL_PATH = 0x0800,
|
---|
190 | FILL_RECT = 0x1000, DRAW_COLORSPANS = 0x2000, DRAW_ROUNDED_RECT = 0x4000,
|
---|
191 | DRAW_STATICTEXT = 0x8000, ALL = 0xffff
|
---|
192 | };
|
---|
193 |
|
---|
194 | enum { RasterWarn = 1, RasterDisable = 2 };
|
---|
195 | static inline uint rasterFallbacksMask(PaintOperation op)
|
---|
196 | {
|
---|
197 | uint ret = 0;
|
---|
198 | #ifdef QT_DIRECTFB_WARN_ON_RASTERFALLBACKS
|
---|
199 | if (op & QT_DIRECTFB_WARN_ON_RASTERFALLBACKS)
|
---|
200 | ret |= RasterWarn;
|
---|
201 | #endif
|
---|
202 | #ifdef QT_DIRECTFB_DISABLE_RASTERFALLBACKS
|
---|
203 | if (op & QT_DIRECTFB_DISABLE_RASTERFALLBACKS)
|
---|
204 | ret |= RasterDisable;
|
---|
205 | #endif
|
---|
206 | static int warningMask = -1;
|
---|
207 | static int disableMask = -1;
|
---|
208 | if (warningMask < 0) {
|
---|
209 | struct {
|
---|
210 | const char *name;
|
---|
211 | PaintOperation operation;
|
---|
212 | } const operations[] = {
|
---|
213 | { "DRAW_RECTS", DRAW_RECTS },
|
---|
214 | { "DRAW_LINES", DRAW_LINES },
|
---|
215 | { "DRAW_IMAGE", DRAW_IMAGE },
|
---|
216 | { "DRAW_PIXMAP", DRAW_PIXMAP },
|
---|
217 | { "DRAW_TILED_PIXMAP", DRAW_TILED_PIXMAP },
|
---|
218 | { "STROKE_PATH", STROKE_PATH },
|
---|
219 | { "DRAW_PATH", DRAW_PATH },
|
---|
220 | { "DRAW_POINTS", DRAW_POINTS },
|
---|
221 | { "DRAW_ELLIPSE", DRAW_ELLIPSE },
|
---|
222 | { "DRAW_POLYGON", DRAW_POLYGON },
|
---|
223 | { "DRAW_TEXT", DRAW_TEXT },
|
---|
224 | { "FILL_PATH", FILL_PATH },
|
---|
225 | { "FILL_RECT", FILL_RECT },
|
---|
226 | { "DRAW_COLORSPANS", DRAW_COLORSPANS },
|
---|
227 | { "DRAW_ROUNDED_RECT", DRAW_ROUNDED_RECT },
|
---|
228 | { "ALL", ALL },
|
---|
229 | { 0, ALL }
|
---|
230 | };
|
---|
231 |
|
---|
232 | QStringList warning = QString::fromLatin1(qgetenv("QT_DIRECTFB_WARN_ON_RASTERFALLBACKS")).toUpper().split(QLatin1Char('|'),
|
---|
233 | QString::SkipEmptyParts);
|
---|
234 | QStringList disable = QString::fromLatin1(qgetenv("QT_DIRECTFB_DISABLE_RASTERFALLBACKS")).toUpper().split(QLatin1Char('|'),
|
---|
235 | QString::SkipEmptyParts);
|
---|
236 | warningMask = 0;
|
---|
237 | disableMask = 0;
|
---|
238 | if (!warning.isEmpty() || !disable.isEmpty()) {
|
---|
239 | for (int i=0; operations[i].name; ++i) {
|
---|
240 | const QString name = QString::fromLatin1(operations[i].name);
|
---|
241 | int idx = warning.indexOf(name);
|
---|
242 | if (idx != -1) {
|
---|
243 | warningMask |= operations[i].operation;
|
---|
244 | warning.erase(warning.begin() + idx);
|
---|
245 | }
|
---|
246 | idx = disable.indexOf(name);
|
---|
247 | if (idx != -1) {
|
---|
248 | disableMask |= operations[i].operation;
|
---|
249 | disable.erase(disable.begin() + idx);
|
---|
250 | }
|
---|
251 | }
|
---|
252 | }
|
---|
253 | if (!warning.isEmpty()) {
|
---|
254 | qWarning("QDirectFBPaintEngine QT_DIRECTFB_WARN_ON_RASTERFALLBACKS Unknown operation(s): %s",
|
---|
255 | qPrintable(warning.join(QLatin1String("|"))));
|
---|
256 | }
|
---|
257 | if (!disable.isEmpty()) {
|
---|
258 | qWarning("QDirectFBPaintEngine QT_DIRECTFB_DISABLE_RASTERFALLBACKS Unknown operation(s): %s",
|
---|
259 | qPrintable(disable.join(QLatin1String("|"))));
|
---|
260 | }
|
---|
261 | }
|
---|
262 | if (op & warningMask)
|
---|
263 | ret |= RasterWarn;
|
---|
264 | if (op & disableMask)
|
---|
265 | ret |= RasterDisable;
|
---|
266 | return ret;
|
---|
267 | }
|
---|
268 |
|
---|
269 | template <typename device, typename T1, typename T2, typename T3>
|
---|
270 | static void rasterFallbackWarn(const char *msg, const char *func, const device *dev,
|
---|
271 | uint transformationType, bool simplePen,
|
---|
272 | uint clipType, uint compositionModeStatus,
|
---|
273 | const char *nameOne, const T1 &one,
|
---|
274 | const char *nameTwo, const T2 &two,
|
---|
275 | const char *nameThree, const T3 &three);
|
---|
276 |
|
---|
277 | #define RASTERFALLBACK(op, one, two, three) \
|
---|
278 | { \
|
---|
279 | static const uint rasterFallbacks = rasterFallbacksMask(op); \
|
---|
280 | switch (rasterFallbacks) { \
|
---|
281 | case 0: break; \
|
---|
282 | case RasterWarn: \
|
---|
283 | rasterFallbackWarn("Falling back to raster engine for", \
|
---|
284 | __FUNCTION__, \
|
---|
285 | state()->painter->device(), \
|
---|
286 | d_func()->transformationType, \
|
---|
287 | d_func()->simplePen, \
|
---|
288 | d_func()->clipType, \
|
---|
289 | d_func()->compositionModeStatus, \
|
---|
290 | #one, one, #two, two, #three, three); \
|
---|
291 | break; \
|
---|
292 | case RasterDisable|RasterWarn: \
|
---|
293 | rasterFallbackWarn("Disabled raster engine operation", \
|
---|
294 | __FUNCTION__, \
|
---|
295 | state()->painter->device(), \
|
---|
296 | d_func()->transformationType, \
|
---|
297 | d_func()->simplePen, \
|
---|
298 | d_func()->clipType, \
|
---|
299 | d_func()->compositionModeStatus, \
|
---|
300 | #one, one, #two, two, #three, three); \
|
---|
301 | case RasterDisable: \
|
---|
302 | return; \
|
---|
303 | } \
|
---|
304 | }
|
---|
305 |
|
---|
306 | template <class T>
|
---|
307 | static inline void drawLines(const T *lines, int n, const QTransform &transform, IDirectFBSurface *surface);
|
---|
308 | template <class T>
|
---|
309 | static inline void fillRects(const T *rects, int n, const QTransform &transform, IDirectFBSurface *surface);
|
---|
310 | template <class T>
|
---|
311 | static inline void drawRects(const T *rects, int n, const QTransform &transform, IDirectFBSurface *surface);
|
---|
312 |
|
---|
313 | #define CLIPPED_PAINT(operation) { \
|
---|
314 | d->unlock(); \
|
---|
315 | DFBRegion clipRegion; \
|
---|
316 | switch (d->clipType) { \
|
---|
317 | case QDirectFBPaintEnginePrivate::NoClip: \
|
---|
318 | case QDirectFBPaintEnginePrivate::RectClip: \
|
---|
319 | operation; \
|
---|
320 | break; \
|
---|
321 | case QDirectFBPaintEnginePrivate::RegionClip: { \
|
---|
322 | Q_ASSERT(d->clip()); \
|
---|
323 | const QVector<QRect> cr = d->clip()->clipRegion.rects(); \
|
---|
324 | const int size = cr.size(); \
|
---|
325 | for (int i=0; i<size; ++i) { \
|
---|
326 | d->currentClip = cr.at(i); \
|
---|
327 | clipRegion.x1 = d->currentClip.x(); \
|
---|
328 | clipRegion.y1 = d->currentClip.y(); \
|
---|
329 | clipRegion.x2 = d->currentClip.right(); \
|
---|
330 | clipRegion.y2 = d->currentClip.bottom(); \
|
---|
331 | d->surface->SetClip(d->surface, &clipRegion); \
|
---|
332 | operation; \
|
---|
333 | } \
|
---|
334 | d->updateClip(); \
|
---|
335 | break; } \
|
---|
336 | case QDirectFBPaintEnginePrivate::ComplexClip: \
|
---|
337 | case QDirectFBPaintEnginePrivate::ClipUnset: \
|
---|
338 | qFatal("CLIPPED_PAINT internal error %d", d->clipType); \
|
---|
339 | break; \
|
---|
340 | } \
|
---|
341 | }
|
---|
342 |
|
---|
343 |
|
---|
344 | QDirectFBPaintEngine::QDirectFBPaintEngine(QPaintDevice *device)
|
---|
345 | : QRasterPaintEngine(*(new QDirectFBPaintEnginePrivate(this)), device)
|
---|
346 | {
|
---|
347 | }
|
---|
348 |
|
---|
349 | QDirectFBPaintEngine::~QDirectFBPaintEngine()
|
---|
350 | {
|
---|
351 | }
|
---|
352 |
|
---|
353 | bool QDirectFBPaintEngine::begin(QPaintDevice *device)
|
---|
354 | {
|
---|
355 | Q_D(QDirectFBPaintEngine);
|
---|
356 | if (device->devType() == QInternal::CustomRaster) {
|
---|
357 | d->dfbDevice = static_cast<QDirectFBPaintDevice*>(device);
|
---|
358 | } else if (device->devType() == QInternal::Pixmap) {
|
---|
359 | QPixmapData *data = static_cast<QPixmap*>(device)->pixmapData();
|
---|
360 | Q_ASSERT(data->classId() == QPixmapData::DirectFBClass);
|
---|
361 | QDirectFBPixmapData *dfbPixmapData = static_cast<QDirectFBPixmapData*>(data);
|
---|
362 | QDirectFBPaintEnginePrivate::unlock(dfbPixmapData);
|
---|
363 | d->dfbDevice = static_cast<QDirectFBPaintDevice*>(dfbPixmapData);
|
---|
364 | }
|
---|
365 |
|
---|
366 | if (d->dfbDevice)
|
---|
367 | d->surface = d->dfbDevice->directFBSurface();
|
---|
368 |
|
---|
369 | if (!d->surface) {
|
---|
370 | qFatal("QDirectFBPaintEngine used on an invalid device: 0x%x",
|
---|
371 | device->devType());
|
---|
372 | }
|
---|
373 | d->isPremultiplied = QDirectFBScreen::isPremultiplied(d->dfbDevice->format());
|
---|
374 |
|
---|
375 | d->prepare(d->dfbDevice);
|
---|
376 | gccaps = AllFeatures;
|
---|
377 | d->setCompositionMode(state()->composition_mode);
|
---|
378 |
|
---|
379 | return QRasterPaintEngine::begin(device);
|
---|
380 | }
|
---|
381 |
|
---|
382 | bool QDirectFBPaintEngine::end()
|
---|
383 | {
|
---|
384 | Q_D(QDirectFBPaintEngine);
|
---|
385 | d->unlock();
|
---|
386 | d->dfbDevice = 0;
|
---|
387 | #if (Q_DIRECTFB_VERSION >= 0x010000)
|
---|
388 | d->surface->ReleaseSource(d->surface);
|
---|
389 | #endif
|
---|
390 | d->currentClip = QRect();
|
---|
391 | d->surface->SetClip(d->surface, NULL);
|
---|
392 | d->surface = 0;
|
---|
393 | return QRasterPaintEngine::end();
|
---|
394 | }
|
---|
395 |
|
---|
396 | void QDirectFBPaintEngine::clipEnabledChanged()
|
---|
397 | {
|
---|
398 | Q_D(QDirectFBPaintEngine);
|
---|
399 | QRasterPaintEngine::clipEnabledChanged();
|
---|
400 | d->updateClip();
|
---|
401 | }
|
---|
402 |
|
---|
403 | void QDirectFBPaintEngine::penChanged()
|
---|
404 | {
|
---|
405 | Q_D(QDirectFBPaintEngine);
|
---|
406 | d->setPen(state()->pen);
|
---|
407 |
|
---|
408 | QRasterPaintEngine::penChanged();
|
---|
409 | }
|
---|
410 |
|
---|
411 | void QDirectFBPaintEngine::opacityChanged()
|
---|
412 | {
|
---|
413 | Q_D(QDirectFBPaintEngine);
|
---|
414 | d->opacity = quint8(state()->opacity * 255);
|
---|
415 | QRasterPaintEngine::opacityChanged();
|
---|
416 | }
|
---|
417 |
|
---|
418 | void QDirectFBPaintEngine::compositionModeChanged()
|
---|
419 | {
|
---|
420 | Q_D(QDirectFBPaintEngine);
|
---|
421 | d->setCompositionMode(state()->compositionMode());
|
---|
422 | QRasterPaintEngine::compositionModeChanged();
|
---|
423 | }
|
---|
424 |
|
---|
425 | void QDirectFBPaintEngine::renderHintsChanged()
|
---|
426 | {
|
---|
427 | Q_D(QDirectFBPaintEngine);
|
---|
428 | d->setRenderHints(state()->renderHints);
|
---|
429 | QRasterPaintEngine::renderHintsChanged();
|
---|
430 | }
|
---|
431 |
|
---|
432 | void QDirectFBPaintEngine::transformChanged()
|
---|
433 | {
|
---|
434 | Q_D(QDirectFBPaintEngine);
|
---|
435 | d->setTransform(state()->matrix);
|
---|
436 | QRasterPaintEngine::transformChanged();
|
---|
437 | }
|
---|
438 |
|
---|
439 | void QDirectFBPaintEngine::setState(QPainterState *state)
|
---|
440 | {
|
---|
441 | Q_D(QDirectFBPaintEngine);
|
---|
442 | QRasterPaintEngine::setState(state);
|
---|
443 | d->setPen(state->pen);
|
---|
444 | d->opacity = quint8(state->opacity * 255);
|
---|
445 | d->setCompositionMode(state->compositionMode());
|
---|
446 | d->setTransform(state->transform());
|
---|
447 | d->setRenderHints(state->renderHints);
|
---|
448 | if (d->surface)
|
---|
449 | d->updateClip();
|
---|
450 | }
|
---|
451 |
|
---|
452 | void QDirectFBPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op)
|
---|
453 | {
|
---|
454 | Q_D(QDirectFBPaintEngine);
|
---|
455 | const bool wasInClip = d->inClip;
|
---|
456 | d->inClip = true;
|
---|
457 | QRasterPaintEngine::clip(path, op);
|
---|
458 | if (!wasInClip) {
|
---|
459 | d->inClip = false;
|
---|
460 | d->updateClip();
|
---|
461 | }
|
---|
462 | }
|
---|
463 |
|
---|
464 | void QDirectFBPaintEngine::clip(const QRegion ®ion, Qt::ClipOperation op)
|
---|
465 | {
|
---|
466 | Q_D(QDirectFBPaintEngine);
|
---|
467 | const bool wasInClip = d->inClip;
|
---|
468 | d->inClip = true;
|
---|
469 | QRasterPaintEngine::clip(region, op);
|
---|
470 | if (!wasInClip) {
|
---|
471 | d->inClip = false;
|
---|
472 | d->updateClip();
|
---|
473 | }
|
---|
474 | }
|
---|
475 |
|
---|
476 | void QDirectFBPaintEngine::clip(const QRect &rect, Qt::ClipOperation op)
|
---|
477 | {
|
---|
478 | Q_D(QDirectFBPaintEngine);
|
---|
479 | const bool wasInClip = d->inClip;
|
---|
480 | d->inClip = true;
|
---|
481 | QRasterPaintEngine::clip(rect, op);
|
---|
482 | if (!wasInClip) {
|
---|
483 | d->inClip = false;
|
---|
484 | d->updateClip();
|
---|
485 | }
|
---|
486 | }
|
---|
487 |
|
---|
488 | void QDirectFBPaintEngine::drawRects(const QRect *rects, int rectCount)
|
---|
489 | {
|
---|
490 | Q_D(QDirectFBPaintEngine);
|
---|
491 | const QPen &pen = state()->pen;
|
---|
492 | const QBrush &brush = state()->brush;
|
---|
493 | if (brush.style() == Qt::NoBrush && pen.style() == Qt::NoPen)
|
---|
494 | return;
|
---|
495 |
|
---|
496 | if ((d->transformationType & QDirectFBPaintEnginePrivate::Matrix_RectsUnsupported)
|
---|
497 | || !d->simplePen
|
---|
498 | || d->clipType == QDirectFBPaintEnginePrivate::ComplexClip
|
---|
499 | || !d->isSimpleBrush(brush)
|
---|
500 | || !(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported)) {
|
---|
501 | RASTERFALLBACK(DRAW_RECTS, rectCount, VOID_ARG(), VOID_ARG());
|
---|
502 | d->lock();
|
---|
503 | QRasterPaintEngine::drawRects(rects, rectCount);
|
---|
504 | return;
|
---|
505 | }
|
---|
506 |
|
---|
507 | if (brush.style() != Qt::NoBrush) {
|
---|
508 | d->setDFBColor(brush.color());
|
---|
509 | CLIPPED_PAINT(QT_PREPEND_NAMESPACE(fillRects<QRect>)(rects, rectCount, state()->matrix, d->surface));
|
---|
510 | }
|
---|
511 |
|
---|
512 | if (pen.style() != Qt::NoPen) {
|
---|
513 | d->setDFBColor(pen.color());
|
---|
514 | CLIPPED_PAINT(QT_PREPEND_NAMESPACE(drawRects<QRect>)(rects, rectCount, state()->matrix, d->surface));
|
---|
515 | }
|
---|
516 | }
|
---|
517 |
|
---|
518 | void QDirectFBPaintEngine::drawRects(const QRectF *rects, int rectCount)
|
---|
519 | {
|
---|
520 | Q_D(QDirectFBPaintEngine);
|
---|
521 | const QPen &pen = state()->pen;
|
---|
522 | const QBrush &brush = state()->brush;
|
---|
523 | if (brush.style() == Qt::NoBrush && pen.style() == Qt::NoPen)
|
---|
524 | return;
|
---|
525 |
|
---|
526 | if ((d->transformationType & QDirectFBPaintEnginePrivate::Matrix_RectsUnsupported)
|
---|
527 | || !d->simplePen
|
---|
528 | || d->clipType == QDirectFBPaintEnginePrivate::ComplexClip
|
---|
529 | || !d->isSimpleBrush(brush)
|
---|
530 | || !(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported)) {
|
---|
531 | RASTERFALLBACK(DRAW_RECTS, rectCount, VOID_ARG(), VOID_ARG());
|
---|
532 | d->lock();
|
---|
533 | QRasterPaintEngine::drawRects(rects, rectCount);
|
---|
534 | return;
|
---|
535 | }
|
---|
536 |
|
---|
537 | if (brush.style() != Qt::NoBrush) {
|
---|
538 | d->setDFBColor(brush.color());
|
---|
539 | CLIPPED_PAINT(fillRects<QRectF>(rects, rectCount, state()->matrix, d->surface));
|
---|
540 | }
|
---|
541 |
|
---|
542 | if (pen.style() != Qt::NoPen) {
|
---|
543 | d->setDFBColor(pen.color());
|
---|
544 | CLIPPED_PAINT(QT_PREPEND_NAMESPACE(drawRects<QRectF>)(rects, rectCount, state()->matrix, d->surface));
|
---|
545 | }
|
---|
546 | }
|
---|
547 |
|
---|
548 | void QDirectFBPaintEngine::drawLines(const QLine *lines, int lineCount)
|
---|
549 | {
|
---|
550 | Q_D(QDirectFBPaintEngine);
|
---|
551 |
|
---|
552 | const QPen &pen = state()->pen;
|
---|
553 | if (!d->simplePen
|
---|
554 | || d->clipType == QDirectFBPaintEnginePrivate::ComplexClip
|
---|
555 | || !(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported)) {
|
---|
556 | RASTERFALLBACK(DRAW_LINES, lineCount, VOID_ARG(), VOID_ARG());
|
---|
557 | d->lock();
|
---|
558 | QRasterPaintEngine::drawLines(lines, lineCount);
|
---|
559 | return;
|
---|
560 | }
|
---|
561 |
|
---|
562 | if (pen.style() != Qt::NoPen) {
|
---|
563 | d->setDFBColor(pen.color());
|
---|
564 | CLIPPED_PAINT(QT_PREPEND_NAMESPACE(drawLines<QLine>)(lines, lineCount, state()->matrix, d->surface));
|
---|
565 | }
|
---|
566 | }
|
---|
567 |
|
---|
568 | void QDirectFBPaintEngine::drawLines(const QLineF *lines, int lineCount)
|
---|
569 | {
|
---|
570 | Q_D(QDirectFBPaintEngine);
|
---|
571 |
|
---|
572 | const QPen &pen = state()->pen;
|
---|
573 | if (!d->simplePen
|
---|
574 | || d->clipType == QDirectFBPaintEnginePrivate::ComplexClip
|
---|
575 | || !(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported)) {
|
---|
576 | RASTERFALLBACK(DRAW_LINES, lineCount, VOID_ARG(), VOID_ARG());
|
---|
577 | d->lock();
|
---|
578 | QRasterPaintEngine::drawLines(lines, lineCount);
|
---|
579 | return;
|
---|
580 | }
|
---|
581 |
|
---|
582 | if (pen.style() != Qt::NoPen) {
|
---|
583 | d->setDFBColor(pen.color());
|
---|
584 | CLIPPED_PAINT(QT_PREPEND_NAMESPACE(drawLines<QLineF>)(lines, lineCount, state()->matrix, d->surface));
|
---|
585 | }
|
---|
586 | }
|
---|
587 |
|
---|
588 | void QDirectFBPaintEngine::drawImage(const QRectF &r, const QImage &image,
|
---|
589 | const QRectF &sr,
|
---|
590 | Qt::ImageConversionFlags flags)
|
---|
591 | {
|
---|
592 | Q_D(QDirectFBPaintEngine);
|
---|
593 | Q_UNUSED(flags);
|
---|
594 |
|
---|
595 | /* This is hard to read. The way it works is like this:
|
---|
596 |
|
---|
597 | - If you do not have support for preallocated surfaces and do not use an
|
---|
598 | image cache we always fall back to raster engine.
|
---|
599 |
|
---|
600 | - If it's rotated/sheared/mirrored (negative scale) or we can't
|
---|
601 | clip it we fall back to raster engine.
|
---|
602 |
|
---|
603 | - If we don't cache the image, but we do have support for
|
---|
604 | preallocated surfaces we fall back to the raster engine if the
|
---|
605 | image is in a format DirectFB can't handle.
|
---|
606 |
|
---|
607 | - If we do cache the image but don't have support for preallocated
|
---|
608 | images and the cost of caching the image (bytes used) is higher
|
---|
609 | than the max image cache size we fall back to raster engine.
|
---|
610 | */
|
---|
611 |
|
---|
612 | #if !defined QT_NO_DIRECTFB_PREALLOCATED || defined QT_DIRECTFB_IMAGECACHE
|
---|
613 | if (!(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported)
|
---|
614 | || (d->transformationType & QDirectFBPaintEnginePrivate::Matrix_BlitsUnsupported)
|
---|
615 | || (d->clipType == QDirectFBPaintEnginePrivate::ComplexClip)
|
---|
616 | || (!d->supportsStretchBlit() && state()->matrix.mapRect(r).size() != sr.size())
|
---|
617 | #ifndef QT_DIRECTFB_IMAGECACHE
|
---|
618 | || (QDirectFBScreen::getSurfacePixelFormat(image.format()) == DSPF_UNKNOWN)
|
---|
619 | #elif defined QT_NO_DIRECTFB_PREALLOCATED
|
---|
620 | || (QDirectFBPaintEnginePrivate::cacheCost(image) > imageCache.maxCost())
|
---|
621 | #endif
|
---|
622 | )
|
---|
623 | #endif
|
---|
624 | {
|
---|
625 | RASTERFALLBACK(DRAW_IMAGE, r, image.size(), sr);
|
---|
626 | d->lock();
|
---|
627 | QRasterPaintEngine::drawImage(r, image, sr, flags);
|
---|
628 | return;
|
---|
629 | }
|
---|
630 | #if !defined QT_NO_DIRECTFB_PREALLOCATED || defined QT_DIRECTFB_IMAGECACHE
|
---|
631 | bool release;
|
---|
632 | IDirectFBSurface *imgSurface = d->getSurface(image, &release);
|
---|
633 | uint blitFlags = 0;
|
---|
634 | if (image.hasAlphaChannel())
|
---|
635 | blitFlags |= QDirectFBPaintEnginePrivate::HasAlpha;
|
---|
636 | if (QDirectFBScreen::isPremultiplied(image.format()))
|
---|
637 | blitFlags |= QDirectFBPaintEnginePrivate::Premultiplied;
|
---|
638 | d->prepareForBlit(blitFlags);
|
---|
639 | CLIPPED_PAINT(d->blit(r, imgSurface, sr));
|
---|
640 | if (release) {
|
---|
641 | #if (Q_DIRECTFB_VERSION >= 0x010000)
|
---|
642 | d->surface->ReleaseSource(d->surface);
|
---|
643 | #endif
|
---|
644 | imgSurface->Release(imgSurface);
|
---|
645 | }
|
---|
646 | #endif
|
---|
647 | }
|
---|
648 |
|
---|
649 | void QDirectFBPaintEngine::drawImage(const QPointF &p, const QImage &img)
|
---|
650 | {
|
---|
651 | drawImage(QRectF(p, img.size()), img, img.rect());
|
---|
652 | }
|
---|
653 |
|
---|
654 | void QDirectFBPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pixmap,
|
---|
655 | const QRectF &sr)
|
---|
656 | {
|
---|
657 | Q_D(QDirectFBPaintEngine);
|
---|
658 |
|
---|
659 | if (pixmap.pixmapData()->classId() != QPixmapData::DirectFBClass) {
|
---|
660 | RASTERFALLBACK(DRAW_PIXMAP, r, pixmap.size(), sr);
|
---|
661 | d->lock();
|
---|
662 | QRasterPaintEngine::drawPixmap(r, pixmap, sr);
|
---|
663 | } else {
|
---|
664 | QPixmapData *data = pixmap.pixmapData();
|
---|
665 | Q_ASSERT(data->classId() == QPixmapData::DirectFBClass);
|
---|
666 | QDirectFBPixmapData *dfbData = static_cast<QDirectFBPixmapData*>(data);
|
---|
667 | if (!(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported)
|
---|
668 | || (d->transformationType & QDirectFBPaintEnginePrivate::Matrix_BlitsUnsupported)
|
---|
669 | || (d->clipType == QDirectFBPaintEnginePrivate::ComplexClip)
|
---|
670 | || (!d->supportsStretchBlit() && state()->matrix.mapRect(r).size() != sr.size())) {
|
---|
671 | RASTERFALLBACK(DRAW_PIXMAP, r, pixmap.size(), sr);
|
---|
672 | const QImage *img = dfbData->buffer();
|
---|
673 | d->lock();
|
---|
674 | QRasterPaintEngine::drawImage(r, *img, sr);
|
---|
675 | } else {
|
---|
676 | QDirectFBPaintEnginePrivate::unlock(dfbData);
|
---|
677 | IDirectFBSurface *s = dfbData->directFBSurface();
|
---|
678 | uint blitFlags = 0;
|
---|
679 | if (pixmap.hasAlphaChannel())
|
---|
680 | blitFlags |= QDirectFBPaintEnginePrivate::HasAlpha;
|
---|
681 | if (QDirectFBScreen::isPremultiplied(dfbData->pixelFormat()))
|
---|
682 | blitFlags |= QDirectFBPaintEnginePrivate::Premultiplied;
|
---|
683 |
|
---|
684 | d->prepareForBlit(blitFlags);
|
---|
685 | CLIPPED_PAINT(d->blit(r, s, sr));
|
---|
686 | }
|
---|
687 | }
|
---|
688 | }
|
---|
689 |
|
---|
690 | void QDirectFBPaintEngine::drawPixmap(const QPointF &p, const QPixmap &pm)
|
---|
691 | {
|
---|
692 | drawPixmap(QRectF(p, pm.size()), pm, pm.rect());
|
---|
693 | }
|
---|
694 |
|
---|
695 | void QDirectFBPaintEngine::drawTiledPixmap(const QRectF &r,
|
---|
696 | const QPixmap &pixmap,
|
---|
697 | const QPointF &offset)
|
---|
698 | {
|
---|
699 | Q_D(QDirectFBPaintEngine);
|
---|
700 | if (pixmap.pixmapData()->classId() != QPixmapData::DirectFBClass) {
|
---|
701 | RASTERFALLBACK(DRAW_TILED_PIXMAP, r, pixmap.size(), offset);
|
---|
702 | d->lock();
|
---|
703 | QRasterPaintEngine::drawTiledPixmap(r, pixmap, offset);
|
---|
704 | } else if (!(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported)
|
---|
705 | || (d->transformationType & QDirectFBPaintEnginePrivate::Matrix_BlitsUnsupported)
|
---|
706 | || (d->clipType == QDirectFBPaintEnginePrivate::ComplexClip)
|
---|
707 | || (!d->supportsStretchBlit() && state()->matrix.isScaling())) {
|
---|
708 | RASTERFALLBACK(DRAW_TILED_PIXMAP, r, pixmap.size(), offset);
|
---|
709 | QPixmapData *pixmapData = pixmap.pixmapData();
|
---|
710 | Q_ASSERT(pixmapData->classId() == QPixmapData::DirectFBClass);
|
---|
711 | QDirectFBPixmapData *dfbData = static_cast<QDirectFBPixmapData*>(pixmapData);
|
---|
712 | const QImage *img = dfbData->buffer();
|
---|
713 | d->lock();
|
---|
714 | QRasterPixmapData *data = new QRasterPixmapData(QPixmapData::PixmapType);
|
---|
715 | data->fromImage(*img, Qt::AutoColor);
|
---|
716 | const QPixmap pix(data);
|
---|
717 | QRasterPaintEngine::drawTiledPixmap(r, pix, offset);
|
---|
718 | } else {
|
---|
719 | QTransform transform(state()->matrix);
|
---|
720 | CLIPPED_PAINT(d->drawTiledPixmap(r, pixmap, offset, transform));
|
---|
721 | }
|
---|
722 | }
|
---|
723 |
|
---|
724 |
|
---|
725 | void QDirectFBPaintEngine::stroke(const QVectorPath &path, const QPen &pen)
|
---|
726 | {
|
---|
727 | RASTERFALLBACK(STROKE_PATH, path, VOID_ARG(), VOID_ARG());
|
---|
728 | Q_D(QDirectFBPaintEngine);
|
---|
729 | d->lock();
|
---|
730 | QRasterPaintEngine::stroke(path, pen);
|
---|
731 | }
|
---|
732 |
|
---|
733 | void QDirectFBPaintEngine::drawPath(const QPainterPath &path)
|
---|
734 | {
|
---|
735 | RASTERFALLBACK(DRAW_PATH, path, VOID_ARG(), VOID_ARG());
|
---|
736 | Q_D(QDirectFBPaintEngine);
|
---|
737 | d->lock();
|
---|
738 | QRasterPaintEngine::drawPath(path);
|
---|
739 | }
|
---|
740 |
|
---|
741 | void QDirectFBPaintEngine::drawPoints(const QPointF *points, int pointCount)
|
---|
742 | {
|
---|
743 | RASTERFALLBACK(DRAW_POINTS, pointCount, VOID_ARG(), VOID_ARG());
|
---|
744 | Q_D(QDirectFBPaintEngine);
|
---|
745 | d->lock();
|
---|
746 | QRasterPaintEngine::drawPoints(points, pointCount);
|
---|
747 | }
|
---|
748 |
|
---|
749 | void QDirectFBPaintEngine::drawPoints(const QPoint *points, int pointCount)
|
---|
750 | {
|
---|
751 | RASTERFALLBACK(DRAW_POINTS, pointCount, VOID_ARG(), VOID_ARG());
|
---|
752 | Q_D(QDirectFBPaintEngine);
|
---|
753 | d->lock();
|
---|
754 | QRasterPaintEngine::drawPoints(points, pointCount);
|
---|
755 | }
|
---|
756 |
|
---|
757 | void QDirectFBPaintEngine::drawEllipse(const QRectF &rect)
|
---|
758 | {
|
---|
759 | RASTERFALLBACK(DRAW_ELLIPSE, rect, VOID_ARG(), VOID_ARG());
|
---|
760 | Q_D(QDirectFBPaintEngine);
|
---|
761 | d->lock();
|
---|
762 | QRasterPaintEngine::drawEllipse(rect);
|
---|
763 | }
|
---|
764 |
|
---|
765 | void QDirectFBPaintEngine::drawPolygon(const QPointF *points, int pointCount,
|
---|
766 | PolygonDrawMode mode)
|
---|
767 | {
|
---|
768 | RASTERFALLBACK(DRAW_POLYGON, pointCount, mode, VOID_ARG());
|
---|
769 | Q_D(QDirectFBPaintEngine);
|
---|
770 | d->lock();
|
---|
771 | QRasterPaintEngine::drawPolygon(points, pointCount, mode);
|
---|
772 | }
|
---|
773 |
|
---|
774 | void QDirectFBPaintEngine::drawPolygon(const QPoint *points, int pointCount,
|
---|
775 | PolygonDrawMode mode)
|
---|
776 | {
|
---|
777 | RASTERFALLBACK(DRAW_POLYGON, pointCount, mode, VOID_ARG());
|
---|
778 | Q_D(QDirectFBPaintEngine);
|
---|
779 | d->lock();
|
---|
780 | QRasterPaintEngine::drawPolygon(points, pointCount, mode);
|
---|
781 | }
|
---|
782 |
|
---|
783 | void QDirectFBPaintEngine::drawTextItem(const QPointF &p,
|
---|
784 | const QTextItem &textItem)
|
---|
785 | {
|
---|
786 | RASTERFALLBACK(DRAW_TEXT, p, textItem.text(), VOID_ARG());
|
---|
787 | Q_D(QDirectFBPaintEngine);
|
---|
788 | d->lock();
|
---|
789 | QRasterPaintEngine::drawTextItem(p, textItem);
|
---|
790 | }
|
---|
791 |
|
---|
792 | void QDirectFBPaintEngine::fill(const QVectorPath &path, const QBrush &brush)
|
---|
793 | {
|
---|
794 | if (brush.style() == Qt::NoBrush)
|
---|
795 | return;
|
---|
796 | RASTERFALLBACK(FILL_PATH, path, brush, VOID_ARG());
|
---|
797 | Q_D(QDirectFBPaintEngine);
|
---|
798 | d->lock();
|
---|
799 | QRasterPaintEngine::fill(path, brush);
|
---|
800 | }
|
---|
801 |
|
---|
802 | void QDirectFBPaintEngine::drawRoundedRect(const QRectF &rect, qreal xrad, qreal yrad, Qt::SizeMode mode)
|
---|
803 | {
|
---|
804 | RASTERFALLBACK(DRAW_ROUNDED_RECT, rect, xrad, yrad);
|
---|
805 | Q_D(QDirectFBPaintEngine);
|
---|
806 | d->lock();
|
---|
807 | QRasterPaintEngine::drawRoundedRect(rect, xrad, yrad, mode);
|
---|
808 | }
|
---|
809 |
|
---|
810 | void QDirectFBPaintEngine::drawStaticTextItem(QStaticTextItem *item)
|
---|
811 | {
|
---|
812 | RASTERFALLBACK(DRAW_STATICTEXT, item, VOID_ARG(), VOID_ARG());
|
---|
813 | Q_D(QDirectFBPaintEngine);
|
---|
814 | d->lock();
|
---|
815 | QRasterPaintEngine::drawStaticTextItem(item);
|
---|
816 | }
|
---|
817 |
|
---|
818 | void QDirectFBPaintEngine::fillRect(const QRectF &rect, const QBrush &brush)
|
---|
819 | {
|
---|
820 | Q_D(QDirectFBPaintEngine);
|
---|
821 | if (brush.style() == Qt::NoBrush)
|
---|
822 | return;
|
---|
823 | if (d->clipType != QDirectFBPaintEnginePrivate::ComplexClip) {
|
---|
824 | switch (brush.style()) {
|
---|
825 | case Qt::SolidPattern: {
|
---|
826 | const QColor color = brush.color();
|
---|
827 | if (!color.isValid())
|
---|
828 | return;
|
---|
829 |
|
---|
830 | if (d->transformationType & QDirectFBPaintEnginePrivate::Matrix_RectsUnsupported
|
---|
831 | || !(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported)) {
|
---|
832 | break;
|
---|
833 | }
|
---|
834 | d->setDFBColor(color);
|
---|
835 | const QRect r = state()->matrix.mapRect(rect).toRect();
|
---|
836 | CLIPPED_PAINT(d->surface->FillRectangle(d->surface, r.x(), r.y(), r.width(), r.height()));
|
---|
837 | return; }
|
---|
838 |
|
---|
839 | case Qt::TexturePattern: {
|
---|
840 | const QPointF &brushOrigin = state()->brushOrigin;
|
---|
841 | const QTransform stateTransform = state()->matrix;
|
---|
842 | QTransform transform(stateTransform);
|
---|
843 | transform.translate(brushOrigin.x(), brushOrigin.y());
|
---|
844 | transform = brush.transform() * transform;
|
---|
845 | if (!(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported)
|
---|
846 | || (QDirectFBPaintEnginePrivate::getTransformationType(transform) & QDirectFBPaintEnginePrivate::Matrix_BlitsUnsupported)
|
---|
847 | || (!d->supportsStretchBlit() && transform.isScaling())) {
|
---|
848 | break;
|
---|
849 | }
|
---|
850 |
|
---|
851 | const QPixmap texture = brush.texture();
|
---|
852 | if (texture.pixmapData()->classId() != QPixmapData::DirectFBClass)
|
---|
853 | break;
|
---|
854 |
|
---|
855 | CLIPPED_PAINT(d->drawTiledPixmap(stateTransform.mapRect(rect), texture, rect.topLeft() - brushOrigin, transform));
|
---|
856 | return; }
|
---|
857 | default:
|
---|
858 | break;
|
---|
859 | }
|
---|
860 | }
|
---|
861 | RASTERFALLBACK(FILL_RECT, rect, brush, VOID_ARG());
|
---|
862 | d->lock();
|
---|
863 | QRasterPaintEngine::fillRect(rect, brush);
|
---|
864 | }
|
---|
865 |
|
---|
866 | void QDirectFBPaintEngine::fillRect(const QRectF &rect, const QColor &color)
|
---|
867 | {
|
---|
868 | if (!color.isValid())
|
---|
869 | return;
|
---|
870 | Q_D(QDirectFBPaintEngine);
|
---|
871 | if ((d->transformationType & QDirectFBPaintEnginePrivate::Matrix_RectsUnsupported)
|
---|
872 | || (d->clipType == QDirectFBPaintEnginePrivate::ComplexClip)
|
---|
873 | || !(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported)) {
|
---|
874 | RASTERFALLBACK(FILL_RECT, rect, color, VOID_ARG());
|
---|
875 | d->lock();
|
---|
876 | QRasterPaintEngine::fillRect(rect, color);
|
---|
877 | } else {
|
---|
878 | d->setDFBColor(color);
|
---|
879 | const QRect r = state()->matrix.mapRect(rect).toRect();
|
---|
880 | CLIPPED_PAINT(d->surface->FillRectangle(d->surface, r.x(), r.y(), r.width(), r.height()));
|
---|
881 | }
|
---|
882 | }
|
---|
883 |
|
---|
884 | void QDirectFBPaintEngine::drawBufferSpan(const uint *buffer, int bufsize,
|
---|
885 | int x, int y, int length,
|
---|
886 | uint const_alpha)
|
---|
887 | {
|
---|
888 | Q_D(QDirectFBPaintEngine);
|
---|
889 | IDirectFBSurface *src = d->surfaceCache->getSurface(buffer, bufsize);
|
---|
890 | // ### how does this play with setDFBColor
|
---|
891 | src->SetColor(src, 0, 0, 0, const_alpha);
|
---|
892 | const DFBRectangle rect = { 0, 0, length, 1 };
|
---|
893 | d->surface->Blit(d->surface, src, &rect, x, y);
|
---|
894 | }
|
---|
895 |
|
---|
896 | #ifdef QT_DIRECTFB_IMAGECACHE
|
---|
897 | static void cachedImageCleanupHook(qint64 key)
|
---|
898 | {
|
---|
899 | delete imageCache.take(key);
|
---|
900 | }
|
---|
901 | void QDirectFBPaintEngine::initImageCache(int size)
|
---|
902 | {
|
---|
903 | Q_ASSERT(size >= 0);
|
---|
904 | imageCache.setMaxCost(size);
|
---|
905 | QImagePixmapCleanupHooks::instance()->addImageHook(cachedImageCleanupHook);
|
---|
906 | }
|
---|
907 |
|
---|
908 | #endif // QT_DIRECTFB_IMAGECACHE
|
---|
909 |
|
---|
910 | // ---- QDirectFBPaintEnginePrivate ----
|
---|
911 |
|
---|
912 |
|
---|
913 | QDirectFBPaintEnginePrivate::QDirectFBPaintEnginePrivate(QDirectFBPaintEngine *p)
|
---|
914 | : surface(0), antialiased(false), simplePen(false),
|
---|
915 | transformationType(0), opacity(255),
|
---|
916 | clipType(ClipUnset), dfbDevice(0),
|
---|
917 | compositionModeStatus(0), isPremultiplied(false), inClip(false), q(p)
|
---|
918 | {
|
---|
919 | fb = QDirectFBScreen::instance()->dfb();
|
---|
920 | surfaceCache = new SurfaceCache;
|
---|
921 | }
|
---|
922 |
|
---|
923 | QDirectFBPaintEnginePrivate::~QDirectFBPaintEnginePrivate()
|
---|
924 | {
|
---|
925 | delete surfaceCache;
|
---|
926 | }
|
---|
927 |
|
---|
928 | bool QDirectFBPaintEnginePrivate::isSimpleBrush(const QBrush &brush) const
|
---|
929 | {
|
---|
930 | return (brush.style() == Qt::NoBrush) || (brush.style() == Qt::SolidPattern && !antialiased);
|
---|
931 | }
|
---|
932 |
|
---|
933 | void QDirectFBPaintEnginePrivate::lock()
|
---|
934 | {
|
---|
935 | // We will potentially get a new pointer to the buffer after a
|
---|
936 | // lock so we need to call the base implementation of prepare so
|
---|
937 | // it updates its rasterBuffer to point to the new buffer address.
|
---|
938 | Q_ASSERT(dfbDevice);
|
---|
939 | if (dfbDevice->lockSurface(DSLF_READ|DSLF_WRITE)) {
|
---|
940 | prepare(dfbDevice);
|
---|
941 | }
|
---|
942 | }
|
---|
943 |
|
---|
944 | void QDirectFBPaintEnginePrivate::unlock()
|
---|
945 | {
|
---|
946 | Q_ASSERT(dfbDevice);
|
---|
947 | #ifdef QT_DIRECTFB_SUBSURFACE
|
---|
948 | dfbDevice->syncPending = true;
|
---|
949 | #else
|
---|
950 | QDirectFBPaintEnginePrivate::unlock(dfbDevice);
|
---|
951 | #endif
|
---|
952 | }
|
---|
953 |
|
---|
954 | void QDirectFBPaintEnginePrivate::unlock(QDirectFBPaintDevice *device)
|
---|
955 | {
|
---|
956 | #ifdef QT_NO_DIRECTFB_SUBSURFACE
|
---|
957 | Q_ASSERT(device);
|
---|
958 | device->unlockSurface();
|
---|
959 | #else
|
---|
960 | Q_UNUSED(device);
|
---|
961 | #endif
|
---|
962 | }
|
---|
963 |
|
---|
964 | void QDirectFBPaintEnginePrivate::setTransform(const QTransform &transform)
|
---|
965 | {
|
---|
966 | transformationType = getTransformationType(transform);
|
---|
967 | setPen(q->state()->pen);
|
---|
968 | }
|
---|
969 |
|
---|
970 | void QDirectFBPaintEnginePrivate::setPen(const QPen &pen)
|
---|
971 | {
|
---|
972 | if (pen.style() == Qt::NoPen) {
|
---|
973 | simplePen = true;
|
---|
974 | } else if (pen.style() == Qt::SolidLine
|
---|
975 | && !antialiased
|
---|
976 | && pen.brush().style() == Qt::SolidPattern
|
---|
977 | && pen.widthF() <= 1.0
|
---|
978 | && (transformationType < QTransform::TxScale || pen.isCosmetic())) {
|
---|
979 | simplePen = true;
|
---|
980 | } else {
|
---|
981 | simplePen = false;
|
---|
982 | }
|
---|
983 | }
|
---|
984 |
|
---|
985 | void QDirectFBPaintEnginePrivate::setCompositionMode(QPainter::CompositionMode mode)
|
---|
986 | {
|
---|
987 | if (!surface)
|
---|
988 | return;
|
---|
989 |
|
---|
990 | static const bool forceRasterFallBack = qgetenv("QT_DIRECTFB_FORCE_RASTER").toInt() > 0;
|
---|
991 | if (forceRasterFallBack) {
|
---|
992 | compositionModeStatus = PorterDuff_None;
|
---|
993 | return;
|
---|
994 | }
|
---|
995 |
|
---|
996 | compositionModeStatus = PorterDuff_Supported|PorterDuff_PremultiplyColors|PorterDuff_AlwaysBlend;
|
---|
997 | switch (mode) {
|
---|
998 | case QPainter::CompositionMode_Clear:
|
---|
999 | surface->SetPorterDuff(surface, DSPD_CLEAR);
|
---|
1000 | break;
|
---|
1001 | case QPainter::CompositionMode_Source:
|
---|
1002 | surface->SetPorterDuff(surface, DSPD_SRC);
|
---|
1003 | compositionModeStatus &= ~PorterDuff_AlwaysBlend;
|
---|
1004 | if (!isPremultiplied)
|
---|
1005 | compositionModeStatus &= ~PorterDuff_PremultiplyColors;
|
---|
1006 | break;
|
---|
1007 | case QPainter::CompositionMode_SourceOver:
|
---|
1008 | compositionModeStatus &= ~PorterDuff_AlwaysBlend;
|
---|
1009 | surface->SetPorterDuff(surface, DSPD_SRC_OVER);
|
---|
1010 | break;
|
---|
1011 | case QPainter::CompositionMode_DestinationOver:
|
---|
1012 | surface->SetPorterDuff(surface, DSPD_DST_OVER);
|
---|
1013 | break;
|
---|
1014 | case QPainter::CompositionMode_SourceIn:
|
---|
1015 | surface->SetPorterDuff(surface, DSPD_SRC_IN);
|
---|
1016 | if (!isPremultiplied)
|
---|
1017 | compositionModeStatus &= ~PorterDuff_PremultiplyColors;
|
---|
1018 | break;
|
---|
1019 | case QPainter::CompositionMode_DestinationIn:
|
---|
1020 | surface->SetPorterDuff(surface, DSPD_DST_IN);
|
---|
1021 | break;
|
---|
1022 | case QPainter::CompositionMode_SourceOut:
|
---|
1023 | surface->SetPorterDuff(surface, DSPD_SRC_OUT);
|
---|
1024 | break;
|
---|
1025 | case QPainter::CompositionMode_DestinationOut:
|
---|
1026 | surface->SetPorterDuff(surface, DSPD_DST_OUT);
|
---|
1027 | break;
|
---|
1028 | #if (Q_DIRECTFB_VERSION >= 0x010209)
|
---|
1029 | case QPainter::CompositionMode_Destination:
|
---|
1030 | surface->SetPorterDuff(surface, DSPD_DST);
|
---|
1031 | break;
|
---|
1032 | #endif
|
---|
1033 | #if (Q_DIRECTFB_VERSION >= 0x010000)
|
---|
1034 | case QPainter::CompositionMode_SourceAtop:
|
---|
1035 | surface->SetPorterDuff(surface, DSPD_SRC_ATOP);
|
---|
1036 | break;
|
---|
1037 | case QPainter::CompositionMode_DestinationAtop:
|
---|
1038 | surface->SetPorterDuff(surface, DSPD_DST_ATOP);
|
---|
1039 | break;
|
---|
1040 | case QPainter::CompositionMode_Plus:
|
---|
1041 | surface->SetPorterDuff(surface, DSPD_ADD);
|
---|
1042 | break;
|
---|
1043 | case QPainter::CompositionMode_Xor:
|
---|
1044 | surface->SetPorterDuff(surface, DSPD_XOR);
|
---|
1045 | break;
|
---|
1046 | #endif
|
---|
1047 | default:
|
---|
1048 | compositionModeStatus = PorterDuff_None;
|
---|
1049 | break;
|
---|
1050 | }
|
---|
1051 | }
|
---|
1052 |
|
---|
1053 | void QDirectFBPaintEnginePrivate::setRenderHints(QPainter::RenderHints hints)
|
---|
1054 | {
|
---|
1055 | const bool old = antialiased;
|
---|
1056 | antialiased = bool(hints & QPainter::Antialiasing);
|
---|
1057 | if (old != antialiased) {
|
---|
1058 | setPen(q->state()->pen);
|
---|
1059 | }
|
---|
1060 | }
|
---|
1061 |
|
---|
1062 | void QDirectFBPaintEnginePrivate::prepareForBlit(uint flags)
|
---|
1063 | {
|
---|
1064 | DFBSurfaceBlittingFlags blittingFlags = DSBLIT_NOFX;
|
---|
1065 | if (flags & Premultiplied)
|
---|
1066 | blittingFlags |= DSBLIT_SRC_PREMULTIPLY;
|
---|
1067 | if (flags & HasAlpha)
|
---|
1068 | blittingFlags |= DSBLIT_BLEND_ALPHACHANNEL;
|
---|
1069 | if (opacity != 255) {
|
---|
1070 | blittingFlags |= DSBLIT_BLEND_COLORALPHA;
|
---|
1071 | surface->SetColor(surface, 0xff, 0xff, 0xff, opacity);
|
---|
1072 | }
|
---|
1073 |
|
---|
1074 | surface->SetBlittingFlags(surface, blittingFlags);
|
---|
1075 | }
|
---|
1076 |
|
---|
1077 | static inline uint ALPHA_MUL(uint x, uint a)
|
---|
1078 | {
|
---|
1079 | uint t = x * a;
|
---|
1080 | t = ((t + (t >> 8) + 0x80) >> 8) & 0xff;
|
---|
1081 | return t;
|
---|
1082 | }
|
---|
1083 |
|
---|
1084 | void QDirectFBPaintEnginePrivate::setDFBColor(const QColor &color)
|
---|
1085 | {
|
---|
1086 | Q_ASSERT(surface);
|
---|
1087 | Q_ASSERT(compositionModeStatus & PorterDuff_Supported);
|
---|
1088 | const quint8 alpha = (opacity == 255 ?
|
---|
1089 | color.alpha() : ALPHA_MUL(color.alpha(), opacity));
|
---|
1090 | QColor col;
|
---|
1091 | if (compositionModeStatus & PorterDuff_PremultiplyColors) {
|
---|
1092 | col = QColor(ALPHA_MUL(color.red(), alpha),
|
---|
1093 | ALPHA_MUL(color.green(), alpha),
|
---|
1094 | ALPHA_MUL(color.blue(), alpha),
|
---|
1095 | alpha);
|
---|
1096 | } else {
|
---|
1097 | col = QColor(color.red(), color.green(), color.blue(), alpha);
|
---|
1098 | }
|
---|
1099 | surface->SetColor(surface, col.red(), col.green(), col.blue(), col.alpha());
|
---|
1100 | surface->SetDrawingFlags(surface, alpha == 255 && !(compositionModeStatus & PorterDuff_AlwaysBlend) ? DSDRAW_NOFX : DSDRAW_BLEND);
|
---|
1101 | }
|
---|
1102 |
|
---|
1103 | IDirectFBSurface *QDirectFBPaintEnginePrivate::getSurface(const QImage &img, bool *release)
|
---|
1104 | {
|
---|
1105 | #ifdef QT_NO_DIRECTFB_IMAGECACHE
|
---|
1106 | *release = true;
|
---|
1107 | return QDirectFBScreen::instance()->createDFBSurface(img, img.format(), QDirectFBScreen::DontTrackSurface);
|
---|
1108 | #else
|
---|
1109 | const qint64 key = img.cacheKey();
|
---|
1110 | *release = false;
|
---|
1111 | if (imageCache.contains(key)) {
|
---|
1112 | return imageCache[key]->surface;
|
---|
1113 | }
|
---|
1114 |
|
---|
1115 | const int cost = cacheCost(img);
|
---|
1116 | const bool cache = cost <= imageCache.maxCost();
|
---|
1117 | QDirectFBScreen *screen = QDirectFBScreen::instance();
|
---|
1118 | const QImage::Format format = (img.format() == screen->alphaPixmapFormat() || QDirectFBPixmapData::hasAlphaChannel(img)
|
---|
1119 | ? screen->alphaPixmapFormat() : screen->pixelFormat());
|
---|
1120 |
|
---|
1121 | IDirectFBSurface *surface = screen->createDFBSurface(img, format,
|
---|
1122 | cache
|
---|
1123 | ? QDirectFBScreen::TrackSurface
|
---|
1124 | : QDirectFBScreen::DontTrackSurface);
|
---|
1125 | if (cache) {
|
---|
1126 | CachedImage *cachedImage = new CachedImage;
|
---|
1127 | const_cast<QImage&>(img).data_ptr()->is_cached = true;
|
---|
1128 | cachedImage->surface = surface;
|
---|
1129 | imageCache.insert(key, cachedImage, cost);
|
---|
1130 | } else {
|
---|
1131 | *release = true;
|
---|
1132 | }
|
---|
1133 | return surface;
|
---|
1134 | #endif
|
---|
1135 | }
|
---|
1136 |
|
---|
1137 |
|
---|
1138 | void QDirectFBPaintEnginePrivate::blit(const QRectF &dest, IDirectFBSurface *s, const QRectF &src)
|
---|
1139 | {
|
---|
1140 | const QRect sr = src.toRect();
|
---|
1141 | const QRect dr = q->state()->matrix.mapRect(dest).toRect();
|
---|
1142 | if (dr.isEmpty())
|
---|
1143 | return;
|
---|
1144 | const DFBRectangle sRect = { sr.x(), sr.y(), sr.width(), sr.height() };
|
---|
1145 | DFBResult result;
|
---|
1146 |
|
---|
1147 | if (dr.size() == sr.size()) {
|
---|
1148 | result = surface->Blit(surface, s, &sRect, dr.x(), dr.y());
|
---|
1149 | } else {
|
---|
1150 | Q_ASSERT(supportsStretchBlit());
|
---|
1151 | const DFBRectangle dRect = { dr.x(), dr.y(), dr.width(), dr.height() };
|
---|
1152 | result = surface->StretchBlit(surface, s, &sRect, &dRect);
|
---|
1153 | }
|
---|
1154 | if (result != DFB_OK)
|
---|
1155 | DirectFBError("QDirectFBPaintEngine::drawPixmap()", result);
|
---|
1156 | }
|
---|
1157 |
|
---|
1158 | static inline qreal fixCoord(qreal rect_pos, qreal pixmapSize, qreal offset)
|
---|
1159 | {
|
---|
1160 | qreal pos = rect_pos - offset;
|
---|
1161 | while (pos > rect_pos)
|
---|
1162 | pos -= pixmapSize;
|
---|
1163 | while (pos + pixmapSize < rect_pos)
|
---|
1164 | pos += pixmapSize;
|
---|
1165 | return pos;
|
---|
1166 | }
|
---|
1167 |
|
---|
1168 | void QDirectFBPaintEnginePrivate::drawTiledPixmap(const QRectF &dest, const QPixmap &pixmap,
|
---|
1169 | const QPointF &off, const QTransform &pixmapTransform)
|
---|
1170 | {
|
---|
1171 | const QTransform &transform = q->state()->matrix;
|
---|
1172 | Q_ASSERT(!(getTransformationType(transform) & Matrix_BlitsUnsupported) &&
|
---|
1173 | !(getTransformationType(pixmapTransform) & Matrix_BlitsUnsupported));
|
---|
1174 | const QRect destinationRect = transform.mapRect(dest).toRect().normalized();
|
---|
1175 | QRect newClip = destinationRect;
|
---|
1176 | if (!currentClip.isEmpty())
|
---|
1177 | newClip &= currentClip;
|
---|
1178 |
|
---|
1179 | if (newClip.isNull())
|
---|
1180 | return;
|
---|
1181 |
|
---|
1182 | const DFBRegion clip = {
|
---|
1183 | newClip.x(),
|
---|
1184 | newClip.y(),
|
---|
1185 | newClip.right(),
|
---|
1186 | newClip.bottom()
|
---|
1187 | };
|
---|
1188 | surface->SetClip(surface, &clip);
|
---|
1189 |
|
---|
1190 | QPointF offset = pixmapTransform.inverted().map(off);
|
---|
1191 | Q_ASSERT(transform.type() <= QTransform::TxScale);
|
---|
1192 | QPixmapData *data = pixmap.pixmapData();
|
---|
1193 | Q_ASSERT(data->classId() == QPixmapData::DirectFBClass);
|
---|
1194 | QDirectFBPixmapData *dfbData = static_cast<QDirectFBPixmapData*>(data);
|
---|
1195 | IDirectFBSurface *sourceSurface = dfbData->directFBSurface();
|
---|
1196 | uint blitFlags = 0;
|
---|
1197 | if (dfbData->hasAlphaChannel())
|
---|
1198 | blitFlags |= HasAlpha;
|
---|
1199 | if (QDirectFBScreen::isPremultiplied(dfbData->pixelFormat()))
|
---|
1200 | blitFlags |= Premultiplied;
|
---|
1201 | prepareForBlit(blitFlags);
|
---|
1202 | QDirectFBPaintEnginePrivate::unlock(dfbData);
|
---|
1203 | const QSize pixmapSize = dfbData->size();
|
---|
1204 | if (transform.isScaling() || pixmapTransform.isScaling()) {
|
---|
1205 | Q_ASSERT(supportsStretchBlit());
|
---|
1206 | Q_ASSERT(qMin(transform.m11(), transform.m22()) >= 0);
|
---|
1207 | offset.rx() *= transform.m11();
|
---|
1208 | offset.ry() *= transform.m22();
|
---|
1209 |
|
---|
1210 | const QSizeF mappedSize(pixmapSize.width() * pixmapTransform.m11(), pixmapSize.height() * pixmapTransform.m22());
|
---|
1211 | qreal y = fixCoord(destinationRect.y(), mappedSize.height(), offset.y());
|
---|
1212 | const qreal startX = fixCoord(destinationRect.x(), mappedSize.width(), offset.x());
|
---|
1213 | while (y <= destinationRect.bottom()) {
|
---|
1214 | qreal x = startX;
|
---|
1215 | while (x <= destinationRect.right()) {
|
---|
1216 | const DFBRectangle destination = { qRound(x), qRound(y), mappedSize.width(), mappedSize.height() };
|
---|
1217 | surface->StretchBlit(surface, sourceSurface, 0, &destination);
|
---|
1218 | x += mappedSize.width();
|
---|
1219 | }
|
---|
1220 | y += mappedSize.height();
|
---|
1221 | }
|
---|
1222 | } else {
|
---|
1223 | qreal y = fixCoord(destinationRect.y(), pixmapSize.height(), offset.y());
|
---|
1224 | const qreal startX = fixCoord(destinationRect.x(), pixmapSize.width(), offset.x());
|
---|
1225 | int horizontal = qMax(1, destinationRect.width() / pixmapSize.width()) + 1;
|
---|
1226 | if (startX != destinationRect.x())
|
---|
1227 | ++horizontal;
|
---|
1228 | int vertical = qMax(1, destinationRect.height() / pixmapSize.height()) + 1;
|
---|
1229 | if (y != destinationRect.y())
|
---|
1230 | ++vertical;
|
---|
1231 |
|
---|
1232 | const int maxCount = (vertical * horizontal);
|
---|
1233 | QVarLengthArray<DFBRectangle, 16> sourceRects(maxCount);
|
---|
1234 | QVarLengthArray<DFBPoint, 16> points(maxCount);
|
---|
1235 |
|
---|
1236 | int i = 0;
|
---|
1237 | while (y <= destinationRect.bottom()) {
|
---|
1238 | Q_ASSERT(i < maxCount);
|
---|
1239 | qreal x = startX;
|
---|
1240 | while (x <= destinationRect.right()) {
|
---|
1241 | points[i].x = qRound(x);
|
---|
1242 | points[i].y = qRound(y);
|
---|
1243 | sourceRects[i].x = 0;
|
---|
1244 | sourceRects[i].y = 0;
|
---|
1245 | sourceRects[i].w = int(pixmapSize.width());
|
---|
1246 | sourceRects[i].h = int(pixmapSize.height());
|
---|
1247 | x += pixmapSize.width();
|
---|
1248 | ++i;
|
---|
1249 | }
|
---|
1250 | y += pixmapSize.height();
|
---|
1251 | }
|
---|
1252 | surface->BatchBlit(surface, sourceSurface, sourceRects.constData(), points.constData(), i);
|
---|
1253 | }
|
---|
1254 |
|
---|
1255 | if (currentClip.isEmpty()) {
|
---|
1256 | surface->SetClip(surface, 0);
|
---|
1257 | } else {
|
---|
1258 | const DFBRegion clip = {
|
---|
1259 | currentClip.x(),
|
---|
1260 | currentClip.y(),
|
---|
1261 | currentClip.right(),
|
---|
1262 | currentClip.bottom()
|
---|
1263 | };
|
---|
1264 | surface->SetClip(surface, &clip);
|
---|
1265 | }
|
---|
1266 | }
|
---|
1267 |
|
---|
1268 | void QDirectFBPaintEnginePrivate::updateClip()
|
---|
1269 | {
|
---|
1270 | Q_ASSERT(surface);
|
---|
1271 | currentClip = QRect();
|
---|
1272 | const QClipData *clipData = clip();
|
---|
1273 | if (!clipData || !clipData->enabled) {
|
---|
1274 | surface->SetClip(surface, NULL);
|
---|
1275 | clipType = NoClip;
|
---|
1276 | } else if (clipData->hasRectClip) {
|
---|
1277 | const DFBRegion r = {
|
---|
1278 | clipData->clipRect.x(),
|
---|
1279 | clipData->clipRect.y(),
|
---|
1280 | clipData->clipRect.right(),
|
---|
1281 | clipData->clipRect.bottom()
|
---|
1282 | };
|
---|
1283 | surface->SetClip(surface, &r);
|
---|
1284 | currentClip = clipData->clipRect.normalized();
|
---|
1285 | // ### is this guaranteed to always be normalized?
|
---|
1286 | clipType = RectClip;
|
---|
1287 | } else if (clipData->hasRegionClip) {
|
---|
1288 | clipType = RegionClip;
|
---|
1289 | } else {
|
---|
1290 | clipType = ComplexClip;
|
---|
1291 | }
|
---|
1292 | }
|
---|
1293 |
|
---|
1294 | bool QDirectFBPaintEnginePrivate::supportsStretchBlit() const
|
---|
1295 | {
|
---|
1296 | #ifdef QT_DIRECTFB_STRETCHBLIT
|
---|
1297 | return !(q->state()->renderHints & QPainter::SmoothPixmapTransform);
|
---|
1298 | #else
|
---|
1299 | return false;
|
---|
1300 | #endif
|
---|
1301 | }
|
---|
1302 |
|
---|
1303 |
|
---|
1304 | void QDirectFBPaintEnginePrivate::systemStateChanged()
|
---|
1305 | {
|
---|
1306 | QRasterPaintEnginePrivate::systemStateChanged();
|
---|
1307 | updateClip();
|
---|
1308 | }
|
---|
1309 |
|
---|
1310 | IDirectFBSurface *SurfaceCache::getSurface(const uint *buf, int size)
|
---|
1311 | {
|
---|
1312 | if (buffer == buf && bufsize == size)
|
---|
1313 | return surface;
|
---|
1314 |
|
---|
1315 | clear();
|
---|
1316 |
|
---|
1317 | const DFBSurfaceDescription description = QDirectFBScreen::getSurfaceDescription(buf, size);
|
---|
1318 | surface = QDirectFBScreen::instance()->createDFBSurface(description, QDirectFBScreen::TrackSurface, 0);
|
---|
1319 | if (!surface)
|
---|
1320 | qWarning("QDirectFBPaintEngine: SurfaceCache: Unable to create surface");
|
---|
1321 |
|
---|
1322 | buffer = const_cast<uint*>(buf);
|
---|
1323 | bufsize = size;
|
---|
1324 |
|
---|
1325 | return surface;
|
---|
1326 | }
|
---|
1327 |
|
---|
1328 | void SurfaceCache::clear()
|
---|
1329 | {
|
---|
1330 | if (surface && QDirectFBScreen::instance())
|
---|
1331 | QDirectFBScreen::instance()->releaseDFBSurface(surface);
|
---|
1332 | surface = 0;
|
---|
1333 | buffer = 0;
|
---|
1334 | bufsize = 0;
|
---|
1335 | }
|
---|
1336 |
|
---|
1337 |
|
---|
1338 | static inline QRect mapRect(const QTransform &transform, const QRect &rect) { return transform.mapRect(rect); }
|
---|
1339 | static inline QRect mapRect(const QTransform &transform, const QRectF &rect) { return transform.mapRect(rect).toRect(); }
|
---|
1340 | static inline QLine map(const QTransform &transform, const QLine &line) { return transform.map(line); }
|
---|
1341 | static inline QLine map(const QTransform &transform, const QLineF &line) { return transform.map(line).toLine(); }
|
---|
1342 | template <class T>
|
---|
1343 | static inline void drawLines(const T *lines, int n, const QTransform &transform, IDirectFBSurface *surface)
|
---|
1344 | {
|
---|
1345 | if (n == 1) {
|
---|
1346 | const QLine l = map(transform, lines[0]);
|
---|
1347 | surface->DrawLine(surface, l.x1(), l.y1(), l.x2(), l.y2());
|
---|
1348 | } else {
|
---|
1349 | QVarLengthArray<DFBRegion, 32> lineArray(n);
|
---|
1350 | for (int i=0; i<n; ++i) {
|
---|
1351 | const QLine l = map(transform, lines[i]);
|
---|
1352 | lineArray[i].x1 = l.x1();
|
---|
1353 | lineArray[i].y1 = l.y1();
|
---|
1354 | lineArray[i].x2 = l.x2();
|
---|
1355 | lineArray[i].y2 = l.y2();
|
---|
1356 | }
|
---|
1357 | surface->DrawLines(surface, lineArray.constData(), n);
|
---|
1358 | }
|
---|
1359 | }
|
---|
1360 |
|
---|
1361 | template <class T>
|
---|
1362 | static inline void fillRects(const T *rects, int n, const QTransform &transform, IDirectFBSurface *surface)
|
---|
1363 | {
|
---|
1364 | if (n == 1) {
|
---|
1365 | const QRect r = mapRect(transform, rects[0]);
|
---|
1366 | surface->FillRectangle(surface, r.x(), r.y(), r.width(), r.height());
|
---|
1367 | } else {
|
---|
1368 | QVarLengthArray<DFBRectangle, 32> rectArray(n);
|
---|
1369 | for (int i=0; i<n; ++i) {
|
---|
1370 | const QRect r = mapRect(transform, rects[i]);
|
---|
1371 | rectArray[i].x = r.x();
|
---|
1372 | rectArray[i].y = r.y();
|
---|
1373 | rectArray[i].w = r.width();
|
---|
1374 | rectArray[i].h = r.height();
|
---|
1375 | }
|
---|
1376 | surface->FillRectangles(surface, rectArray.constData(), n);
|
---|
1377 | }
|
---|
1378 | }
|
---|
1379 |
|
---|
1380 | template <class T>
|
---|
1381 | static inline void drawRects(const T *rects, int n, const QTransform &transform, IDirectFBSurface *surface)
|
---|
1382 | {
|
---|
1383 | for (int i=0; i<n; ++i) {
|
---|
1384 | const QRect r = mapRect(transform, rects[i]);
|
---|
1385 | surface->DrawRectangle(surface, r.x(), r.y(), r.width(), r.height());
|
---|
1386 | }
|
---|
1387 | }
|
---|
1388 |
|
---|
1389 | template <typename T> inline const T *ptr(const T &t) { return &t; }
|
---|
1390 | template <> inline const bool* ptr<bool>(const bool &) { return 0; }
|
---|
1391 | template <typename device, typename T1, typename T2, typename T3>
|
---|
1392 | static void rasterFallbackWarn(const char *msg, const char *func, const device *dev,
|
---|
1393 | uint transformationType, bool simplePen,
|
---|
1394 | uint clipType, uint compositionModeStatus,
|
---|
1395 | const char *nameOne, const T1 &one,
|
---|
1396 | const char *nameTwo, const T2 &two,
|
---|
1397 | const char *nameThree, const T3 &three)
|
---|
1398 | {
|
---|
1399 | QString out;
|
---|
1400 | QDebug dbg(&out);
|
---|
1401 | dbg << msg << (QByteArray(func) + "()") << "painting on";
|
---|
1402 | if (dev->devType() == QInternal::Widget) {
|
---|
1403 | dbg << static_cast<const QWidget*>(dev);
|
---|
1404 | } else {
|
---|
1405 | dbg << dev << "of type" << dev->devType();
|
---|
1406 | }
|
---|
1407 |
|
---|
1408 | dbg << QString::fromLatin1("transformationType 0x%1").arg(transformationType, 3, 16, QLatin1Char('0'))
|
---|
1409 | << "simplePen" << simplePen
|
---|
1410 | << "clipType" << clipType
|
---|
1411 | << "compositionModeStatus" << compositionModeStatus;
|
---|
1412 |
|
---|
1413 | const T1 *t1 = ptr(one);
|
---|
1414 | const T2 *t2 = ptr(two);
|
---|
1415 | const T3 *t3 = ptr(three);
|
---|
1416 |
|
---|
1417 | if (t1) {
|
---|
1418 | dbg << nameOne << *t1;
|
---|
1419 | if (t2) {
|
---|
1420 | dbg << nameTwo << *t2;
|
---|
1421 | if (t3) {
|
---|
1422 | dbg << nameThree << *t3;
|
---|
1423 | }
|
---|
1424 | }
|
---|
1425 | }
|
---|
1426 | qWarning("%s", qPrintable(out));
|
---|
1427 | }
|
---|
1428 |
|
---|
1429 | QT_END_NAMESPACE
|
---|
1430 |
|
---|
1431 | #endif // QT_NO_QWS_DIRECTFB
|
---|