changeset 7 | f7bc934e204c |
parent 3 | 41300fa6a67c |
3:41300fa6a67c | 7:f7bc934e204c |
---|---|
1 /**************************************************************************** |
1 /**************************************************************************** |
2 ** |
2 ** |
3 ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). |
3 ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). |
4 ** All rights reserved. |
4 ** All rights reserved. |
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
5 ** Contact: Nokia Corporation (qt-info@nokia.com) |
6 ** |
6 ** |
7 ** This file is part of the plugins of the Qt Toolkit. |
7 ** This file is part of the plugins of the Qt Toolkit. |
8 ** |
8 ** |
66 Matrix_RectsUnsupported = (QTransform::TxRotate|QTransform::TxShear|QTransform::TxProject), |
66 Matrix_RectsUnsupported = (QTransform::TxRotate|QTransform::TxShear|QTransform::TxProject), |
67 Matrix_BlitsUnsupported = (Matrix_NegativeScale|Matrix_RectsUnsupported) |
67 Matrix_BlitsUnsupported = (Matrix_NegativeScale|Matrix_RectsUnsupported) |
68 }; |
68 }; |
69 |
69 |
70 enum CompositionModeStatus { |
70 enum CompositionModeStatus { |
71 PorterDuff_None = 0x00, |
71 PorterDuff_None = 0x0, |
72 PorterDuff_SupportedBlits = 0x01, |
72 PorterDuff_Supported = 0x1, |
73 PorterDuff_SupportedPrimitives = 0x02, |
73 PorterDuff_PremultiplyColors = 0x2, |
74 PorterDuff_SupportedOpaquePrimitives = 0x04, |
74 PorterDuff_AlwaysBlend = 0x4 |
75 PorterDuff_Dirty = 0x10 |
|
76 }; |
75 }; |
77 |
76 |
78 enum ClipType { |
77 enum ClipType { |
79 ClipUnset, |
78 ClipUnset, |
80 NoClip, |
79 NoClip, |
95 |
94 |
96 inline void lock(); |
95 inline void lock(); |
97 inline void unlock(); |
96 inline void unlock(); |
98 static inline void unlock(QDirectFBPaintDevice *device); |
97 static inline void unlock(QDirectFBPaintDevice *device); |
99 |
98 |
100 inline bool testCompositionMode(const QPen *pen, const QBrush *brush, const QColor *color = 0) const; |
|
101 inline bool isSimpleBrush(const QBrush &brush) const; |
99 inline bool isSimpleBrush(const QBrush &brush) const; |
102 |
100 |
103 void drawTiledPixmap(const QRectF &dest, const QPixmap &pixmap, const QPointF &pos); |
101 void drawTiledPixmap(const QRectF &dest, const QPixmap &pixmap, const QPointF &pos); |
104 void blit(const QRectF &dest, IDirectFBSurface *surface, const QRectF &src); |
102 void blit(const QRectF &dest, IDirectFBSurface *surface, const QRectF &src); |
103 |
|
104 inline bool supportsStretchBlit() const; |
|
105 |
105 |
106 inline void updateClip(); |
106 inline void updateClip(); |
107 virtual void systemStateChanged(); |
107 virtual void systemStateChanged(); |
108 |
108 |
109 static IDirectFBSurface *getSurface(const QImage &img, bool *release); |
109 static IDirectFBSurface *getSurface(const QImage &img, bool *release); |
126 quint8 opacity; |
126 quint8 opacity; |
127 |
127 |
128 ClipType clipType; |
128 ClipType clipType; |
129 QDirectFBPaintDevice *dfbDevice; |
129 QDirectFBPaintDevice *dfbDevice; |
130 uint compositionModeStatus; |
130 uint compositionModeStatus; |
131 bool isPremultiplied; |
|
131 |
132 |
132 bool inClip; |
133 bool inClip; |
133 QRect currentClip; |
134 QRect currentClip; |
134 |
135 |
135 QDirectFBPaintEngine *q; |
136 QDirectFBPaintEngine *q; |
164 } |
165 } |
165 }; |
166 }; |
166 static QCache<qint64, CachedImage> imageCache(4*1024*1024); // 4 MB |
167 static QCache<qint64, CachedImage> imageCache(4*1024*1024); // 4 MB |
167 #endif |
168 #endif |
168 |
169 |
169 #if defined QT_DIRECTFB_WARN_ON_RASTERFALLBACKS || defined QT_DIRECTFB_DISABLE_RASTERFALLBACKS |
170 #if defined QT_DIRECTFB_WARN_ON_RASTERFALLBACKS || defined QT_DIRECTFB_DISABLE_RASTERFALLBACKS || defined QT_DEBUG |
170 #define VOID_ARG() static_cast<bool>(false) |
171 #define VOID_ARG() static_cast<bool>(false) |
171 enum PaintOperation { |
172 enum PaintOperation { |
172 DRAW_RECTS = 0x0001, DRAW_LINES = 0x0002, DRAW_IMAGE = 0x0004, |
173 DRAW_RECTS = 0x0001, DRAW_LINES = 0x0002, DRAW_IMAGE = 0x0004, |
173 DRAW_PIXMAP = 0x0008, DRAW_TILED_PIXMAP = 0x0010, STROKE_PATH = 0x0020, |
174 DRAW_PIXMAP = 0x0008, DRAW_TILED_PIXMAP = 0x0010, STROKE_PATH = 0x0020, |
174 DRAW_PATH = 0x0040, DRAW_POINTS = 0x0080, DRAW_ELLIPSE = 0x0100, |
175 DRAW_PATH = 0x0040, DRAW_POINTS = 0x0080, DRAW_ELLIPSE = 0x0100, |
175 DRAW_POLYGON = 0x0200, DRAW_TEXT = 0x0400, FILL_PATH = 0x0800, |
176 DRAW_POLYGON = 0x0200, DRAW_TEXT = 0x0400, FILL_PATH = 0x0800, |
176 FILL_RECT = 0x1000, DRAW_COLORSPANS = 0x2000, DRAW_ROUNDED_RECT = 0x4000, |
177 FILL_RECT = 0x1000, DRAW_COLORSPANS = 0x2000, DRAW_ROUNDED_RECT = 0x4000, |
177 ALL = 0xffff |
178 ALL = 0xffff |
178 }; |
179 }; |
179 #endif |
180 |
180 |
181 #ifdef QT_DEBUG |
182 static void initRasterFallbacksMasks(int *warningMask, int *disableMask) |
|
183 { |
|
184 struct { |
|
185 const char *name; |
|
186 PaintOperation operation; |
|
187 } const operations[] = { |
|
188 { "DRAW_RECTS", DRAW_RECTS }, |
|
189 { "DRAW_LINES", DRAW_LINES }, |
|
190 { "DRAW_IMAGE", DRAW_IMAGE }, |
|
191 { "DRAW_PIXMAP", DRAW_PIXMAP }, |
|
192 { "DRAW_TILED_PIXMAP", DRAW_TILED_PIXMAP }, |
|
193 { "STROKE_PATH", STROKE_PATH }, |
|
194 { "DRAW_PATH", DRAW_PATH }, |
|
195 { "DRAW_POINTS", DRAW_POINTS }, |
|
196 { "DRAW_ELLIPSE", DRAW_ELLIPSE }, |
|
197 { "DRAW_POLYGON", DRAW_POLYGON }, |
|
198 { "DRAW_TEXT", DRAW_TEXT }, |
|
199 { "FILL_PATH", FILL_PATH }, |
|
200 { "FILL_RECT", FILL_RECT }, |
|
201 { "DRAW_COLORSPANS", DRAW_COLORSPANS }, |
|
202 { "DRAW_ROUNDED_RECT", DRAW_ROUNDED_RECT }, |
|
203 { "ALL", ALL }, |
|
204 { 0, ALL } |
|
205 }; |
|
206 |
|
207 QStringList warning = QString::fromLatin1(qgetenv("QT_DIRECTFB_WARN_ON_RASTERFALLBACKS")).toUpper().split(QLatin1Char('|'), |
|
208 QString::SkipEmptyParts); |
|
209 QStringList disable = QString::fromLatin1(qgetenv("QT_DIRECTFB_DISABLE_RASTERFALLBACKS")).toUpper().split(QLatin1Char('|'), |
|
210 QString::SkipEmptyParts); |
|
211 *warningMask = 0; |
|
212 *disableMask = 0; |
|
213 if (!warning.isEmpty() || !disable.isEmpty()) { |
|
214 for (int i=0; operations[i].name; ++i) { |
|
215 const QString name = QString::fromLatin1(operations[i].name); |
|
216 int idx = warning.indexOf(name); |
|
217 if (idx != -1) { |
|
218 *warningMask |= operations[i].operation; |
|
219 warning.erase(warning.begin() + idx); |
|
220 } |
|
221 idx = disable.indexOf(name); |
|
222 if (idx != -1) { |
|
223 *disableMask |= operations[i].operation; |
|
224 disable.erase(disable.begin() + idx); |
|
225 } |
|
226 } |
|
227 } |
|
228 if (!warning.isEmpty()) { |
|
229 qWarning("QDirectFBPaintEngine QT_DIRECTFB_WARN_ON_RASTERFALLBACKS Unknown operation(s): %s", |
|
230 qPrintable(warning.join(QLatin1String("|")))); |
|
231 } |
|
232 if (!disable.isEmpty()) { |
|
233 qWarning("QDirectFBPaintEngine QT_DIRECTFB_DISABLE_RASTERFALLBACKS Unknown operation(s): %s", |
|
234 qPrintable(disable.join(QLatin1String("|")))); |
|
235 } |
|
236 |
|
237 } |
|
238 #endif |
|
239 |
|
240 static inline int rasterFallbacksMask(bool warn) |
|
241 { |
|
181 #ifdef QT_DIRECTFB_WARN_ON_RASTERFALLBACKS |
242 #ifdef QT_DIRECTFB_WARN_ON_RASTERFALLBACKS |
243 if (warn) |
|
244 return QT_DIRECTFB_WARN_ON_RASTERFALLBACKS; |
|
245 #endif |
|
246 #ifdef QT_DIRECTFB_DISABLE_RASTERFALLBACKS |
|
247 if (!warn) |
|
248 return QT_DIRECTFB_DISABLE_RASTERFALLBACKS; |
|
249 #endif |
|
250 #ifndef QT_DEBUG |
|
251 return 0; |
|
252 #else |
|
253 static int warnMask = -1; |
|
254 static int disableMask = -1; |
|
255 if (warnMask == -1) |
|
256 initRasterFallbacksMasks(&warnMask, &disableMask); |
|
257 return warn ? warnMask : disableMask; |
|
258 #endif |
|
259 } |
|
260 #endif |
|
261 |
|
262 #if defined QT_DIRECTFB_WARN_ON_RASTERFALLBACKS || defined QT_DEBUG |
|
182 template <typename device, typename T1, typename T2, typename T3> |
263 template <typename device, typename T1, typename T2, typename T3> |
183 static void rasterFallbackWarn(const char *msg, const char *func, const device *dev, |
264 static void rasterFallbackWarn(const char *msg, const char *func, const device *dev, |
184 uint transformationType, bool simplePen, |
265 uint transformationType, bool simplePen, |
185 uint clipType, uint compositionModeStatus, |
266 uint clipType, uint compositionModeStatus, |
186 const char *nameOne, const T1 &one, |
267 const char *nameOne, const T1 &one, |
187 const char *nameTwo, const T2 &two, |
268 const char *nameTwo, const T2 &two, |
188 const char *nameThree, const T3 &three); |
269 const char *nameThree, const T3 &three); |
189 #endif |
270 #endif |
190 |
271 |
191 #if defined QT_DIRECTFB_WARN_ON_RASTERFALLBACKS && defined QT_DIRECTFB_DISABLE_RASTERFALLBACKS |
272 #if defined QT_DEBUG || (defined QT_DIRECTFB_WARN_ON_RASTERFALLBACKS && defined QT_DIRECTFB_DISABLE_RASTERFALLBACKS) |
192 #define RASTERFALLBACK(op, one, two, three) \ |
273 #define RASTERFALLBACK(op, one, two, three) \ |
193 if (op & (QT_DIRECTFB_WARN_ON_RASTERFALLBACKS)) \ |
274 { \ |
194 rasterFallbackWarn("Disabled raster engine operation", \ |
275 const bool disable = op & rasterFallbacksMask(false); \ |
195 __FUNCTION__, state()->painter->device(), \ |
276 if (op & rasterFallbacksMask(true)) \ |
196 d_func()->transformationType, \ |
277 rasterFallbackWarn(disable \ |
197 d_func()->simplePen, \ |
278 ? "Disabled raster engine operation" \ |
198 d_func()->clipType, \ |
279 : "Falling back to raster engine for", \ |
199 d_func()->compositionModeStatus, \ |
280 __FUNCTION__, \ |
200 #one, one, #two, two, #three, three); \ |
281 state()->painter->device(), \ |
201 if (op & (QT_DIRECTFB_DISABLE_RASTERFALLBACKS)) \ |
282 d_func()->transformationType, \ |
202 return; |
283 d_func()->simplePen, \ |
284 d_func()->clipType, \ |
|
285 d_func()->compositionModeStatus, \ |
|
286 #one, one, #two, two, #three, three); \ |
|
287 if (disable) \ |
|
288 return; \ |
|
289 } |
|
203 #elif defined QT_DIRECTFB_DISABLE_RASTERFALLBACKS |
290 #elif defined QT_DIRECTFB_DISABLE_RASTERFALLBACKS |
204 #define RASTERFALLBACK(op, one, two, three) \ |
291 #define RASTERFALLBACK(op, one, two, three) \ |
205 if (op & (QT_DIRECTFB_DISABLE_RASTERFALLBACKS)) \ |
292 if (op & rasterFallbacksMask(false)) \ |
206 return; |
293 return; |
207 #elif defined QT_DIRECTFB_WARN_ON_RASTERFALLBACKS |
294 #elif defined QT_DIRECTFB_WARN_ON_RASTERFALLBACKS |
208 #define RASTERFALLBACK(op, one, two, three) \ |
295 #define RASTERFALLBACK(op, one, two, three) \ |
209 if (op & (QT_DIRECTFB_WARN_ON_RASTERFALLBACKS)) \ |
296 if (op & rasterFallbacksMask(true)) \ |
210 rasterFallbackWarn("Falling back to raster engine for", \ |
297 rasterFallbackWarn("Falling back to raster engine for", \ |
211 __FUNCTION__, state()->painter->device(), \ |
298 __FUNCTION__, state()->painter->device(), \ |
212 d_func()->transformationType, \ |
299 d_func()->transformationType, \ |
213 d_func()->simplePen, \ |
300 d_func()->simplePen, \ |
214 d_func()->clipType, \ |
301 d_func()->clipType, \ |
283 |
370 |
284 if (!d->surface) { |
371 if (!d->surface) { |
285 qFatal("QDirectFBPaintEngine used on an invalid device: 0x%x", |
372 qFatal("QDirectFBPaintEngine used on an invalid device: 0x%x", |
286 device->devType()); |
373 device->devType()); |
287 } |
374 } |
375 d->isPremultiplied = QDirectFBScreen::isPremultiplied(d->dfbDevice->format()); |
|
288 |
376 |
289 d->prepare(d->dfbDevice); |
377 d->prepare(d->dfbDevice); |
290 gccaps = AllFeatures; |
378 gccaps = AllFeatures; |
291 d->setCompositionMode(state()->composition_mode); |
379 d->setCompositionMode(state()->composition_mode); |
292 |
380 |
409 |
497 |
410 if ((d->transformationType & QDirectFBPaintEnginePrivate::Matrix_RectsUnsupported) |
498 if ((d->transformationType & QDirectFBPaintEnginePrivate::Matrix_RectsUnsupported) |
411 || !d->simplePen |
499 || !d->simplePen |
412 || d->clipType == QDirectFBPaintEnginePrivate::ComplexClip |
500 || d->clipType == QDirectFBPaintEnginePrivate::ComplexClip |
413 || !d->isSimpleBrush(brush) |
501 || !d->isSimpleBrush(brush) |
414 || !d->testCompositionMode(&pen, &brush)) { |
502 || !(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported)) { |
415 RASTERFALLBACK(DRAW_RECTS, rectCount, VOID_ARG(), VOID_ARG()); |
503 RASTERFALLBACK(DRAW_RECTS, rectCount, VOID_ARG(), VOID_ARG()); |
416 d->lock(); |
504 d->lock(); |
417 QRasterPaintEngine::drawRects(rects, rectCount); |
505 QRasterPaintEngine::drawRects(rects, rectCount); |
418 return; |
506 return; |
419 } |
507 } |
439 |
527 |
440 if ((d->transformationType & QDirectFBPaintEnginePrivate::Matrix_RectsUnsupported) |
528 if ((d->transformationType & QDirectFBPaintEnginePrivate::Matrix_RectsUnsupported) |
441 || !d->simplePen |
529 || !d->simplePen |
442 || d->clipType == QDirectFBPaintEnginePrivate::ComplexClip |
530 || d->clipType == QDirectFBPaintEnginePrivate::ComplexClip |
443 || !d->isSimpleBrush(brush) |
531 || !d->isSimpleBrush(brush) |
444 || !d->testCompositionMode(&pen, &brush)) { |
532 || !(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported)) { |
445 RASTERFALLBACK(DRAW_RECTS, rectCount, VOID_ARG(), VOID_ARG()); |
533 RASTERFALLBACK(DRAW_RECTS, rectCount, VOID_ARG(), VOID_ARG()); |
446 d->lock(); |
534 d->lock(); |
447 QRasterPaintEngine::drawRects(rects, rectCount); |
535 QRasterPaintEngine::drawRects(rects, rectCount); |
448 return; |
536 return; |
449 } |
537 } |
464 Q_D(QDirectFBPaintEngine); |
552 Q_D(QDirectFBPaintEngine); |
465 |
553 |
466 const QPen &pen = state()->pen; |
554 const QPen &pen = state()->pen; |
467 if (!d->simplePen |
555 if (!d->simplePen |
468 || d->clipType == QDirectFBPaintEnginePrivate::ComplexClip |
556 || d->clipType == QDirectFBPaintEnginePrivate::ComplexClip |
469 || !d->testCompositionMode(&pen, 0)) { |
557 || !(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported)) { |
470 RASTERFALLBACK(DRAW_LINES, lineCount, VOID_ARG(), VOID_ARG()); |
558 RASTERFALLBACK(DRAW_LINES, lineCount, VOID_ARG(), VOID_ARG()); |
471 d->lock(); |
559 d->lock(); |
472 QRasterPaintEngine::drawLines(lines, lineCount); |
560 QRasterPaintEngine::drawLines(lines, lineCount); |
473 return; |
561 return; |
474 } |
562 } |
484 Q_D(QDirectFBPaintEngine); |
572 Q_D(QDirectFBPaintEngine); |
485 |
573 |
486 const QPen &pen = state()->pen; |
574 const QPen &pen = state()->pen; |
487 if (!d->simplePen |
575 if (!d->simplePen |
488 || d->clipType == QDirectFBPaintEnginePrivate::ComplexClip |
576 || d->clipType == QDirectFBPaintEnginePrivate::ComplexClip |
489 || !d->testCompositionMode(&pen, 0)) { |
577 || !(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported)) { |
490 RASTERFALLBACK(DRAW_LINES, lineCount, VOID_ARG(), VOID_ARG()); |
578 RASTERFALLBACK(DRAW_LINES, lineCount, VOID_ARG(), VOID_ARG()); |
491 d->lock(); |
579 d->lock(); |
492 QRasterPaintEngine::drawLines(lines, lineCount); |
580 QRasterPaintEngine::drawLines(lines, lineCount); |
493 return; |
581 return; |
494 } |
582 } |
522 images and the cost of caching the image (bytes used) is higher |
610 images and the cost of caching the image (bytes used) is higher |
523 than the max image cache size we fall back to raster engine. |
611 than the max image cache size we fall back to raster engine. |
524 */ |
612 */ |
525 |
613 |
526 #if !defined QT_NO_DIRECTFB_PREALLOCATED || defined QT_DIRECTFB_IMAGECACHE |
614 #if !defined QT_NO_DIRECTFB_PREALLOCATED || defined QT_DIRECTFB_IMAGECACHE |
527 if (!(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_SupportedBlits) |
615 if (!(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported) |
528 || (d->transformationType & QDirectFBPaintEnginePrivate::Matrix_BlitsUnsupported) |
616 || (d->transformationType & QDirectFBPaintEnginePrivate::Matrix_BlitsUnsupported) |
529 || d->clipType == QDirectFBPaintEnginePrivate::ComplexClip |
617 || (d->clipType == QDirectFBPaintEnginePrivate::ComplexClip) |
618 || (!d->supportsStretchBlit() && state()->matrix.mapRect(r).size() != sr.size()) |
|
530 #ifndef QT_DIRECTFB_IMAGECACHE |
619 #ifndef QT_DIRECTFB_IMAGECACHE |
531 || QDirectFBScreen::getSurfacePixelFormat(image.format()) == DSPF_UNKNOWN |
620 || (QDirectFBScreen::getSurfacePixelFormat(image.format()) == DSPF_UNKNOWN) |
532 #elif defined QT_NO_DIRECTFB_PREALLOCATED |
621 #elif defined QT_NO_DIRECTFB_PREALLOCATED |
533 || QDirectFBPaintEnginePrivate::cacheCost(image) > imageCache.maxCost() |
622 || (QDirectFBPaintEnginePrivate::cacheCost(image) > imageCache.maxCost()) |
534 #endif |
623 #endif |
535 ) |
624 ) |
536 #endif |
625 #endif |
537 { |
626 { |
538 RASTERFALLBACK(DRAW_IMAGE, r, image.size(), sr); |
627 RASTERFALLBACK(DRAW_IMAGE, r, image.size(), sr); |
570 QRasterPaintEngine::drawPixmap(r, pixmap, sr); |
659 QRasterPaintEngine::drawPixmap(r, pixmap, sr); |
571 } else { |
660 } else { |
572 QPixmapData *data = pixmap.pixmapData(); |
661 QPixmapData *data = pixmap.pixmapData(); |
573 Q_ASSERT(data->classId() == QPixmapData::DirectFBClass); |
662 Q_ASSERT(data->classId() == QPixmapData::DirectFBClass); |
574 QDirectFBPixmapData *dfbData = static_cast<QDirectFBPixmapData*>(data); |
663 QDirectFBPixmapData *dfbData = static_cast<QDirectFBPixmapData*>(data); |
575 if (!(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_SupportedBlits) |
664 if (!(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported) |
576 || (d->transformationType & QDirectFBPaintEnginePrivate::Matrix_BlitsUnsupported) |
665 || (d->transformationType & QDirectFBPaintEnginePrivate::Matrix_BlitsUnsupported) |
577 || d->clipType == QDirectFBPaintEnginePrivate::ComplexClip |
666 || (d->clipType == QDirectFBPaintEnginePrivate::ComplexClip) |
578 || (state()->renderHints & QPainter::SmoothPixmapTransform |
667 || (!d->supportsStretchBlit() && state()->matrix.mapRect(r).size() != sr.size())) { |
579 && state()->matrix.mapRect(r).size() != sr.size())) { |
|
580 RASTERFALLBACK(DRAW_PIXMAP, r, pixmap.size(), sr); |
668 RASTERFALLBACK(DRAW_PIXMAP, r, pixmap.size(), sr); |
581 const QImage *img = dfbData->buffer(); |
669 const QImage *img = dfbData->buffer(); |
582 d->lock(); |
670 d->lock(); |
583 QRasterPaintEngine::drawImage(r, *img, sr); |
671 QRasterPaintEngine::drawImage(r, *img, sr); |
584 } else { |
672 } else { |
602 Q_D(QDirectFBPaintEngine); |
690 Q_D(QDirectFBPaintEngine); |
603 if (pixmap.pixmapData()->classId() != QPixmapData::DirectFBClass) { |
691 if (pixmap.pixmapData()->classId() != QPixmapData::DirectFBClass) { |
604 RASTERFALLBACK(DRAW_TILED_PIXMAP, r, pixmap.size(), offset); |
692 RASTERFALLBACK(DRAW_TILED_PIXMAP, r, pixmap.size(), offset); |
605 d->lock(); |
693 d->lock(); |
606 QRasterPaintEngine::drawTiledPixmap(r, pixmap, offset); |
694 QRasterPaintEngine::drawTiledPixmap(r, pixmap, offset); |
607 } else if (!(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_SupportedBlits) |
695 } else if (!(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported) |
608 || (d->transformationType & QDirectFBPaintEnginePrivate::Matrix_BlitsUnsupported) |
696 || (d->transformationType & QDirectFBPaintEnginePrivate::Matrix_BlitsUnsupported) |
609 || d->clipType == QDirectFBPaintEnginePrivate::ComplexClip |
697 || (d->clipType == QDirectFBPaintEnginePrivate::ComplexClip) |
610 || (state()->renderHints & QPainter::SmoothPixmapTransform && state()->matrix.isScaling())) { |
698 || (!d->supportsStretchBlit() && state()->matrix.isScaling())) { |
611 RASTERFALLBACK(DRAW_TILED_PIXMAP, r, pixmap.size(), offset); |
699 RASTERFALLBACK(DRAW_TILED_PIXMAP, r, pixmap.size(), offset); |
612 QPixmapData *pixmapData = pixmap.pixmapData(); |
700 QPixmapData *pixmapData = pixmap.pixmapData(); |
613 Q_ASSERT(pixmapData->classId() == QPixmapData::DirectFBClass); |
701 Q_ASSERT(pixmapData->classId() == QPixmapData::DirectFBClass); |
614 QDirectFBPixmapData *dfbData = static_cast<QDirectFBPixmapData*>(pixmapData); |
702 QDirectFBPixmapData *dfbData = static_cast<QDirectFBPixmapData*>(pixmapData); |
615 const QImage *img = dfbData->buffer(); |
703 const QImage *img = dfbData->buffer(); |
715 if (brush.style() == Qt::NoBrush) |
803 if (brush.style() == Qt::NoBrush) |
716 return; |
804 return; |
717 if (d->clipType != QDirectFBPaintEnginePrivate::ComplexClip) { |
805 if (d->clipType != QDirectFBPaintEnginePrivate::ComplexClip) { |
718 switch (brush.style()) { |
806 switch (brush.style()) { |
719 case Qt::SolidPattern: { |
807 case Qt::SolidPattern: { |
720 if (d->transformationType & QDirectFBPaintEnginePrivate::Matrix_RectsUnsupported |
|
721 || !d->testCompositionMode(0, &brush)) { |
|
722 break; |
|
723 } |
|
724 const QColor color = brush.color(); |
808 const QColor color = brush.color(); |
725 if (!color.isValid()) |
809 if (!color.isValid()) |
726 return; |
810 return; |
811 |
|
812 if (d->transformationType & QDirectFBPaintEnginePrivate::Matrix_RectsUnsupported |
|
813 || !(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported)) { |
|
814 break; |
|
815 } |
|
727 d->setDFBColor(color); |
816 d->setDFBColor(color); |
728 const QRect r = state()->matrix.mapRect(rect).toRect(); |
817 const QRect r = state()->matrix.mapRect(rect).toRect(); |
729 CLIPPED_PAINT(d->surface->FillRectangle(d->surface, r.x(), r.y(), r.width(), r.height())); |
818 CLIPPED_PAINT(d->surface->FillRectangle(d->surface, r.x(), r.y(), r.width(), r.height())); |
730 return; } |
819 return; } |
731 |
820 |
732 case Qt::TexturePattern: { |
821 case Qt::TexturePattern: { |
733 if (!(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_SupportedBlits) |
822 if (!(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported) |
734 || (d->transformationType & QDirectFBPaintEnginePrivate::Matrix_BlitsUnsupported) |
823 || (d->transformationType & QDirectFBPaintEnginePrivate::Matrix_BlitsUnsupported) |
735 || (state()->renderHints & QPainter::SmoothPixmapTransform && state()->matrix.isScaling())) { |
824 || (!d->supportsStretchBlit() && state()->matrix.isScaling())) { |
736 break; |
825 break; |
737 } |
826 } |
738 |
827 |
739 const QPixmap texture = brush.texture(); |
828 const QPixmap texture = brush.texture(); |
740 if (texture.pixmapData()->classId() != QPixmapData::DirectFBClass) |
829 if (texture.pixmapData()->classId() != QPixmapData::DirectFBClass) |
755 { |
844 { |
756 if (!color.isValid()) |
845 if (!color.isValid()) |
757 return; |
846 return; |
758 Q_D(QDirectFBPaintEngine); |
847 Q_D(QDirectFBPaintEngine); |
759 if ((d->transformationType & QDirectFBPaintEnginePrivate::Matrix_RectsUnsupported) |
848 if ((d->transformationType & QDirectFBPaintEnginePrivate::Matrix_RectsUnsupported) |
760 || d->clipType == QDirectFBPaintEnginePrivate::ComplexClip |
849 || (d->clipType == QDirectFBPaintEnginePrivate::ComplexClip) |
761 || !d->testCompositionMode(0, 0, &color)) { |
850 || !(d->compositionModeStatus & QDirectFBPaintEnginePrivate::PorterDuff_Supported)) { |
762 RASTERFALLBACK(FILL_RECT, rect, color, VOID_ARG()); |
851 RASTERFALLBACK(FILL_RECT, rect, color, VOID_ARG()); |
763 d->lock(); |
852 d->lock(); |
764 QRasterPaintEngine::fillRect(rect, color); |
853 QRasterPaintEngine::fillRect(rect, color); |
765 } else { |
854 } else { |
766 d->setDFBColor(color); |
855 d->setDFBColor(color); |
800 |
889 |
801 QDirectFBPaintEnginePrivate::QDirectFBPaintEnginePrivate(QDirectFBPaintEngine *p) |
890 QDirectFBPaintEnginePrivate::QDirectFBPaintEnginePrivate(QDirectFBPaintEngine *p) |
802 : surface(0), antialiased(false), simplePen(false), |
891 : surface(0), antialiased(false), simplePen(false), |
803 transformationType(0), opacity(255), |
892 transformationType(0), opacity(255), |
804 clipType(ClipUnset), dfbDevice(0), |
893 clipType(ClipUnset), dfbDevice(0), |
805 compositionModeStatus(0), inClip(false), q(p) |
894 compositionModeStatus(0), isPremultiplied(false), inClip(false), q(p) |
806 { |
895 { |
807 fb = QDirectFBScreen::instance()->dfb(); |
896 fb = QDirectFBScreen::instance()->dfb(); |
808 surfaceCache = new SurfaceCache; |
897 surfaceCache = new SurfaceCache; |
809 } |
898 } |
810 |
899 |
815 |
904 |
816 bool QDirectFBPaintEnginePrivate::isSimpleBrush(const QBrush &brush) const |
905 bool QDirectFBPaintEnginePrivate::isSimpleBrush(const QBrush &brush) const |
817 { |
906 { |
818 return (brush.style() == Qt::NoBrush) || (brush.style() == Qt::SolidPattern && !antialiased); |
907 return (brush.style() == Qt::NoBrush) || (brush.style() == Qt::SolidPattern && !antialiased); |
819 } |
908 } |
820 |
|
821 bool QDirectFBPaintEnginePrivate::testCompositionMode(const QPen *pen, const QBrush *brush, const QColor *color) const |
|
822 { |
|
823 Q_ASSERT(!pen || pen->style() == Qt::NoPen || pen->style() == Qt::SolidLine); |
|
824 Q_ASSERT(!brush || brush->style() == Qt::NoBrush || brush->style() == Qt::SolidPattern); |
|
825 switch (compositionModeStatus & (QDirectFBPaintEnginePrivate::PorterDuff_SupportedOpaquePrimitives |
|
826 |QDirectFBPaintEnginePrivate::PorterDuff_SupportedPrimitives)) { |
|
827 case QDirectFBPaintEnginePrivate::PorterDuff_SupportedPrimitives: |
|
828 return true; |
|
829 case QDirectFBPaintEnginePrivate::PorterDuff_SupportedOpaquePrimitives: |
|
830 if (pen && pen->style() == Qt::SolidLine && pen->color().alpha() != 255) |
|
831 return false; |
|
832 if (brush) { |
|
833 if (brush->style() == Qt::SolidPattern && brush->color().alpha() != 255) { |
|
834 return false; |
|
835 } |
|
836 } else if (color && color->alpha() != 255) { |
|
837 return false; |
|
838 } |
|
839 return true; |
|
840 case QDirectFBPaintEnginePrivate::PorterDuff_None: |
|
841 return false; |
|
842 default: |
|
843 // ### PorterDuff_SupportedOpaquePrimitives|PorterDuff_SupportedPrimitives can't be combined |
|
844 break; |
|
845 } |
|
846 Q_ASSERT(0); |
|
847 return false; |
|
848 } |
|
849 |
|
850 |
909 |
851 void QDirectFBPaintEnginePrivate::lock() |
910 void QDirectFBPaintEnginePrivate::lock() |
852 { |
911 { |
853 // We will potentially get a new pointer to the buffer after a |
912 // We will potentially get a new pointer to the buffer after a |
854 // lock so we need to call the base implementation of prepare so |
913 // lock so we need to call the base implementation of prepare so |
908 if (!surface) |
967 if (!surface) |
909 return; |
968 return; |
910 |
969 |
911 static const bool forceRasterFallBack = qgetenv("QT_DIRECTFB_FORCE_RASTER").toInt() > 0; |
970 static const bool forceRasterFallBack = qgetenv("QT_DIRECTFB_FORCE_RASTER").toInt() > 0; |
912 if (forceRasterFallBack) { |
971 if (forceRasterFallBack) { |
913 compositionModeStatus = 0; |
972 compositionModeStatus = PorterDuff_None; |
914 return; |
973 return; |
915 } |
974 } |
916 |
975 |
917 compositionModeStatus = PorterDuff_SupportedBlits; |
976 compositionModeStatus = PorterDuff_Supported|PorterDuff_PremultiplyColors|PorterDuff_AlwaysBlend; |
918 switch (mode) { |
977 switch (mode) { |
919 case QPainter::CompositionMode_Clear: |
978 case QPainter::CompositionMode_Clear: |
920 surface->SetPorterDuff(surface, DSPD_CLEAR); |
979 surface->SetPorterDuff(surface, DSPD_CLEAR); |
921 break; |
980 break; |
922 case QPainter::CompositionMode_Source: |
981 case QPainter::CompositionMode_Source: |
923 surface->SetPorterDuff(surface, DSPD_SRC); |
982 surface->SetPorterDuff(surface, DSPD_SRC); |
924 compositionModeStatus |= PorterDuff_SupportedOpaquePrimitives; |
983 compositionModeStatus &= ~PorterDuff_AlwaysBlend; |
984 if (!isPremultiplied) |
|
985 compositionModeStatus &= ~PorterDuff_PremultiplyColors; |
|
925 break; |
986 break; |
926 case QPainter::CompositionMode_SourceOver: |
987 case QPainter::CompositionMode_SourceOver: |
927 compositionModeStatus |= PorterDuff_SupportedPrimitives; |
988 compositionModeStatus &= ~PorterDuff_AlwaysBlend; |
928 surface->SetPorterDuff(surface, DSPD_SRC_OVER); |
989 surface->SetPorterDuff(surface, DSPD_SRC_OVER); |
929 break; |
990 break; |
930 case QPainter::CompositionMode_DestinationOver: |
991 case QPainter::CompositionMode_DestinationOver: |
931 surface->SetPorterDuff(surface, DSPD_DST_OVER); |
992 surface->SetPorterDuff(surface, DSPD_DST_OVER); |
932 break; |
993 break; |
933 case QPainter::CompositionMode_SourceIn: |
994 case QPainter::CompositionMode_SourceIn: |
934 surface->SetPorterDuff(surface, DSPD_SRC_IN); |
995 surface->SetPorterDuff(surface, DSPD_SRC_IN); |
996 if (!isPremultiplied) |
|
997 compositionModeStatus &= ~PorterDuff_PremultiplyColors; |
|
935 break; |
998 break; |
936 case QPainter::CompositionMode_DestinationIn: |
999 case QPainter::CompositionMode_DestinationIn: |
937 surface->SetPorterDuff(surface, DSPD_DST_IN); |
1000 surface->SetPorterDuff(surface, DSPD_DST_IN); |
938 break; |
1001 break; |
939 case QPainter::CompositionMode_SourceOut: |
1002 case QPainter::CompositionMode_SourceOut: |
940 surface->SetPorterDuff(surface, DSPD_SRC_OUT); |
1003 surface->SetPorterDuff(surface, DSPD_SRC_OUT); |
941 break; |
1004 break; |
942 case QPainter::CompositionMode_DestinationOut: |
1005 case QPainter::CompositionMode_DestinationOut: |
943 surface->SetPorterDuff(surface, DSPD_DST_OUT); |
1006 surface->SetPorterDuff(surface, DSPD_DST_OUT); |
944 break; |
1007 break; |
1008 #if (Q_DIRECTFB_VERSION >= 0x010209) |
|
1009 case QPainter::CompositionMode_Destination: |
|
1010 surface->SetPorterDuff(surface, DSPD_DST); |
|
1011 break; |
|
1012 #endif |
|
945 #if (Q_DIRECTFB_VERSION >= 0x010000) |
1013 #if (Q_DIRECTFB_VERSION >= 0x010000) |
946 case QPainter::CompositionMode_SourceAtop: |
1014 case QPainter::CompositionMode_SourceAtop: |
947 surface->SetPorterDuff(surface, DSPD_SRC_ATOP); |
1015 surface->SetPorterDuff(surface, DSPD_SRC_ATOP); |
948 break; |
1016 break; |
949 case QPainter::CompositionMode_DestinationAtop: |
1017 case QPainter::CompositionMode_DestinationAtop: |
955 case QPainter::CompositionMode_Xor: |
1023 case QPainter::CompositionMode_Xor: |
956 surface->SetPorterDuff(surface, DSPD_XOR); |
1024 surface->SetPorterDuff(surface, DSPD_XOR); |
957 break; |
1025 break; |
958 #endif |
1026 #endif |
959 default: |
1027 default: |
960 compositionModeStatus = 0; |
1028 compositionModeStatus = PorterDuff_None; |
961 break; |
1029 break; |
962 } |
1030 } |
963 } |
1031 } |
964 |
1032 |
965 void QDirectFBPaintEnginePrivate::setRenderHints(QPainter::RenderHints hints) |
1033 void QDirectFBPaintEnginePrivate::setRenderHints(QPainter::RenderHints hints) |
977 if (opacity != 255) { |
1045 if (opacity != 255) { |
978 blittingFlags |= DSBLIT_BLEND_COLORALPHA; |
1046 blittingFlags |= DSBLIT_BLEND_COLORALPHA; |
979 } |
1047 } |
980 surface->SetColor(surface, 0xff, 0xff, 0xff, opacity); |
1048 surface->SetColor(surface, 0xff, 0xff, 0xff, opacity); |
981 surface->SetBlittingFlags(surface, blittingFlags); |
1049 surface->SetBlittingFlags(surface, blittingFlags); |
982 if (compositionModeStatus & PorterDuff_Dirty) { |
|
983 setCompositionMode(q->state()->composition_mode); |
|
984 } |
|
985 } |
1050 } |
986 |
1051 |
987 static inline uint ALPHA_MUL(uint x, uint a) |
1052 static inline uint ALPHA_MUL(uint x, uint a) |
988 { |
1053 { |
989 uint t = x * a; |
1054 uint t = x * a; |
992 } |
1057 } |
993 |
1058 |
994 void QDirectFBPaintEnginePrivate::setDFBColor(const QColor &color) |
1059 void QDirectFBPaintEnginePrivate::setDFBColor(const QColor &color) |
995 { |
1060 { |
996 Q_ASSERT(surface); |
1061 Q_ASSERT(surface); |
1062 Q_ASSERT(compositionModeStatus & PorterDuff_Supported); |
|
997 const quint8 alpha = (opacity == 255 ? |
1063 const quint8 alpha = (opacity == 255 ? |
998 color.alpha() : ALPHA_MUL(color.alpha(), opacity)); |
1064 color.alpha() : ALPHA_MUL(color.alpha(), opacity)); |
999 surface->SetColor(surface, color.red(), color.green(), color.blue(), alpha); |
1065 QColor col; |
1000 surface->SetPorterDuff(surface, DSPD_NONE); |
1066 if (compositionModeStatus & PorterDuff_PremultiplyColors) { |
1001 surface->SetDrawingFlags(surface, alpha == 255 ? DSDRAW_NOFX : DSDRAW_BLEND); |
1067 col = QColor(ALPHA_MUL(color.red(), alpha), |
1002 compositionModeStatus |= PorterDuff_Dirty; |
1068 ALPHA_MUL(color.green(), alpha), |
1069 ALPHA_MUL(color.blue(), alpha), |
|
1070 alpha); |
|
1071 } else { |
|
1072 col = QColor(color.red(), color.green(), color.blue(), alpha); |
|
1073 } |
|
1074 surface->SetColor(surface, col.red(), col.green(), col.blue(), col.alpha()); |
|
1075 surface->SetDrawingFlags(surface, alpha == 255 && !(compositionModeStatus & PorterDuff_AlwaysBlend) ? DSDRAW_NOFX : DSDRAW_BLEND); |
|
1003 } |
1076 } |
1004 |
1077 |
1005 IDirectFBSurface *QDirectFBPaintEnginePrivate::getSurface(const QImage &img, bool *release) |
1078 IDirectFBSurface *QDirectFBPaintEnginePrivate::getSurface(const QImage &img, bool *release) |
1006 { |
1079 { |
1007 #ifdef QT_NO_DIRECTFB_IMAGECACHE |
1080 #ifdef QT_NO_DIRECTFB_IMAGECACHE |
1047 DFBResult result; |
1120 DFBResult result; |
1048 |
1121 |
1049 if (dr.size() == sr.size()) { |
1122 if (dr.size() == sr.size()) { |
1050 result = surface->Blit(surface, s, &sRect, dr.x(), dr.y()); |
1123 result = surface->Blit(surface, s, &sRect, dr.x(), dr.y()); |
1051 } else { |
1124 } else { |
1125 Q_ASSERT(supportsStretchBlit()); |
|
1052 const DFBRectangle dRect = { dr.x(), dr.y(), dr.width(), dr.height() }; |
1126 const DFBRectangle dRect = { dr.x(), dr.y(), dr.width(), dr.height() }; |
1053 result = surface->StretchBlit(surface, s, &sRect, &dRect); |
1127 result = surface->StretchBlit(surface, s, &sRect, &dRect); |
1054 } |
1128 } |
1055 if (result != DFB_OK) |
1129 if (result != DFB_OK) |
1056 DirectFBError("QDirectFBPaintEngine::drawPixmap()", result); |
1130 DirectFBError("QDirectFBPaintEngine::drawPixmap()", result); |
1094 QDirectFBPixmapData *dfbData = static_cast<QDirectFBPixmapData*>(data); |
1168 QDirectFBPixmapData *dfbData = static_cast<QDirectFBPixmapData*>(data); |
1095 QDirectFBPaintEnginePrivate::unlock(dfbData); |
1169 QDirectFBPaintEnginePrivate::unlock(dfbData); |
1096 const QSize pixmapSize = dfbData->size(); |
1170 const QSize pixmapSize = dfbData->size(); |
1097 IDirectFBSurface *sourceSurface = dfbData->directFBSurface(); |
1171 IDirectFBSurface *sourceSurface = dfbData->directFBSurface(); |
1098 if (transform.isScaling()) { |
1172 if (transform.isScaling()) { |
1173 Q_ASSERT(supportsStretchBlit()); |
|
1099 Q_ASSERT(qMin(transform.m11(), transform.m22()) >= 0); |
1174 Q_ASSERT(qMin(transform.m11(), transform.m22()) >= 0); |
1100 offset.rx() *= transform.m11(); |
1175 offset.rx() *= transform.m11(); |
1101 offset.ry() *= transform.m22(); |
1176 offset.ry() *= transform.m22(); |
1102 |
1177 |
1103 const QSizeF mappedSize(pixmapSize.width() * transform.m11(), pixmapSize.height() * transform.m22()); |
1178 const QSizeF mappedSize(pixmapSize.width() * transform.m11(), pixmapSize.height() * transform.m22()); |
1182 } else { |
1257 } else { |
1183 clipType = ComplexClip; |
1258 clipType = ComplexClip; |
1184 } |
1259 } |
1185 } |
1260 } |
1186 |
1261 |
1262 bool QDirectFBPaintEnginePrivate::supportsStretchBlit() const |
|
1263 { |
|
1264 #ifdef QT_DIRECTFB_STRETCHBLIT |
|
1265 return !(q->state()->renderHints & QPainter::SmoothPixmapTransform); |
|
1266 #else |
|
1267 return false; |
|
1268 #endif |
|
1269 } |
|
1270 |
|
1271 |
|
1187 void QDirectFBPaintEnginePrivate::systemStateChanged() |
1272 void QDirectFBPaintEnginePrivate::systemStateChanged() |
1188 { |
1273 { |
1189 QRasterPaintEnginePrivate::systemStateChanged(); |
1274 QRasterPaintEnginePrivate::systemStateChanged(); |
1190 updateClip(); |
1275 updateClip(); |
1191 } |
1276 } |
1267 const QRect r = mapRect(transform, rects[i]); |
1352 const QRect r = mapRect(transform, rects[i]); |
1268 surface->DrawRectangle(surface, r.x(), r.y(), r.width(), r.height()); |
1353 surface->DrawRectangle(surface, r.x(), r.y(), r.width(), r.height()); |
1269 } |
1354 } |
1270 } |
1355 } |
1271 |
1356 |
1272 #ifdef QT_DIRECTFB_WARN_ON_RASTERFALLBACKS |
1357 #if defined QT_DIRECTFB_WARN_ON_RASTERFALLBACKS || defined QT_DEBUG |
1273 template <typename T> inline const T *ptr(const T &t) { return &t; } |
1358 template <typename T> inline const T *ptr(const T &t) { return &t; } |
1274 template <> inline const bool* ptr<bool>(const bool &) { return 0; } |
1359 template <> inline const bool* ptr<bool>(const bool &) { return 0; } |
1275 template <typename device, typename T1, typename T2, typename T3> |
1360 template <typename device, typename T1, typename T2, typename T3> |
1276 static void rasterFallbackWarn(const char *msg, const char *func, const device *dev, |
1361 static void rasterFallbackWarn(const char *msg, const char *func, const device *dev, |
1277 uint transformationType, bool simplePen, |
1362 uint transformationType, bool simplePen, |