summaryrefslogtreecommitdiffstats
path: root/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp')
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp1329
1 files changed, 708 insertions, 621 deletions
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp
index d9346fd..989a37a 100644
--- a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp
+++ b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp
@@ -43,7 +43,7 @@
#ifndef QT_NO_DIRECTFB
-#include "qdirectfbsurface.h"
+#include "qdirectfbwindowsurface.h"
#include "qdirectfbscreen.h"
#include "qdirectfbpixmap.h"
#include <directfb.h>
@@ -54,6 +54,98 @@
#include <private/qpixmapdata_p.h>
#include <private/qpixmap_raster_p.h>
+#if defined QT_DIRECTFB_WARN_ON_RASTERFALLBACKS || defined QT_DIRECTFB_DISABLE_RASTERFALLBACKS
+#define VOID_ARG() static_cast<bool>(false)
+enum PaintOperation {
+ DRAW_RECTS = 0x0001,
+ DRAW_LINES = 0x0002,
+ DRAW_IMAGE = 0x0004,
+ DRAW_PIXMAP = 0x0008,
+ DRAW_TILED_PIXMAP = 0x0010,
+ STROKE_PATH = 0x0020,
+ DRAW_PATH = 0x0040,
+ DRAW_POINTS = 0x0080,
+ DRAW_ELLIPSE = 0x0100,
+ DRAW_POLYGON = 0x0200,
+ DRAW_TEXT = 0x0400,
+ FILL_PATH = 0x0800,
+ FILL_RECT = 0x1000,
+ DRAW_COLORSPANS = 0x2000,
+ ALL = 0xffff
+};
+#endif
+
+#ifdef QT_DIRECTFB_WARN_ON_RASTERFALLBACKS
+template <typename T> inline const T *ptr(const T &t) { return &t; }
+template <> inline const bool* ptr<bool>(const bool &) { return 0; }
+template <typename device, typename T1, typename T2, typename T3>
+static void rasterFallbackWarn(const char *msg, const char *func, const device *dev,
+ int scale, bool matrixRotShear, bool simplePen,
+ bool dfbHandledClip, bool forceRasterPrimitives,
+ const char *nameOne, const T1 &one,
+ const char *nameTwo, const T2 &two,
+ const char *nameThree, const T3 &three)
+{
+ QString out;
+ QDebug dbg(&out);
+ dbg << msg << (QByteArray(func) + "()") << "painting on";
+ if (dev->devType() == QInternal::Widget) {
+ dbg << static_cast<const QWidget*>(dev);
+ } else {
+ dbg << dev << "of type" << dev->devType();
+ }
+
+ dbg << "scale" << scale
+ << "matrixRotShear" << matrixRotShear
+ << "simplePen" << simplePen
+ << "dfbHandledClip" << dfbHandledClip
+ << "forceRasterPrimitives" << forceRasterPrimitives;
+
+ const T1 *t1 = ptr(one);
+ const T2 *t2 = ptr(two);
+ const T3 *t3 = ptr(three);
+
+ if (t1) {
+ dbg << nameOne << *t1;
+ if (t2) {
+ dbg << nameTwo << *t2;
+ if (t3) {
+ dbg << nameThree << *t3;
+ }
+ }
+ }
+ qWarning("%s", qPrintable(out));
+}
+#endif
+
+#if defined QT_DIRECTFB_WARN_ON_RASTERFALLBACKS && defined QT_DIRECTFB_DISABLE_RASTERFALLBACKS
+#define RASTERFALLBACK(op, one, two, three) \
+ if (op & (QT_DIRECTFB_WARN_ON_RASTERFALLBACKS)) \
+ rasterFallbackWarn("Disabled raster engine operation", \
+ __FUNCTION__, state()->painter->device(), \
+ d_func()->scale, d_func()->matrixRotShear, \
+ d_func()->simplePen, d_func()->dfbCanHandleClip(), \
+ d_func()->forceRasterPrimitives, \
+ #one, one, #two, two, #three, three); \
+ if (op & (QT_DIRECTFB_DISABLE_RASTERFALLBACKS)) \
+ return;
+#elif defined QT_DIRECTFB_DISABLE_RASTERFALLBACKS
+#define RASTERFALLBACK(op, one, two, three) \
+ if (op & (QT_DIRECTFB_DISABLE_RASTERFALLBACKS)) \
+ return;
+#elif defined QT_DIRECTFB_WARN_ON_RASTERFALLBACKS
+#define RASTERFALLBACK(op, one, two, three) \
+ if (op & (QT_DIRECTFB_WARN_ON_RASTERFALLBACKS)) \
+ rasterFallbackWarn("Falling back to raster engine for", \
+ __FUNCTION__, state()->painter->device(), \
+ d_func()->scale, d_func()->matrixRotShear, \
+ d_func()->simplePen, d_func()->dfbCanHandleClip(), \
+ d_func()->forceRasterPrimitives, \
+ #one, one, #two, two, #three, three);
+#else
+#define RASTERFALLBACK(op, one, two, three)
+#endif
+
static inline uint ALPHA_MUL(uint x, uint a)
{
uint t = x * a;
@@ -64,137 +156,68 @@ static inline uint ALPHA_MUL(uint x, uint a)
class SurfaceCache
{
public:
- SurfaceCache();
- ~SurfaceCache();
-
- inline IDirectFBSurface *getSurface(const uint *buffer, int size);
- inline void clear();
-
-private:
- IDirectFBSurface *surface;
- uint *buffer;
- int bufsize;
-};
+ SurfaceCache() : surface(0), buffer(0), bufsize(0) {}
+ ~SurfaceCache() { clear(); }
-SurfaceCache::SurfaceCache()
- : surface(0), buffer(0), bufsize(0)
-{
-}
-class CachedImage
-{
-public:
- CachedImage(const QImage &image);
- ~CachedImage();
+ IDirectFBSurface *getSurface(const uint *buf, int size)
+ {
+ if (buffer == buf && bufsize == size)
+ return surface;
- IDirectFBSurface *surface() { return s; }
+ clear();
-private:
- IDirectFBSurface *s;
-};
+ const DFBSurfaceDescription description = QDirectFBScreen::getSurfaceDescription(buf, size);
+ surface = QDirectFBScreen::instance()->createDFBSurface(description, QDirectFBScreen::TrackSurface);
+ if (!surface)
+ qWarning("QDirectFBPaintEngine: SurfaceCache: Unable to create surface");
-CachedImage::CachedImage(const QImage &image)
- : s(0)
-{
- IDirectFBSurface *tmpSurface = 0;
- DFBSurfaceDescription description;
- description = QDirectFBScreen::getSurfaceDescription(image);
- QDirectFBScreen* screen = QDirectFBScreen::instance();
+ buffer = const_cast<uint*>(buf);
+ bufsize = size;
- tmpSurface = screen->createDFBSurface(&description, QDirectFBScreen::TrackSurface);
- if (!tmpSurface) {
- qWarning("CachedImage CreateSurface failed!");
- return;
+ return surface;
}
-#ifndef QT_NO_DIRECTFB_PALETTE
- QDirectFBScreen::setSurfaceColorTable(tmpSurface, image);
-#endif
-
- description.flags = DFBSurfaceDescriptionFlags(description.flags & ~DSDESC_PREALLOCATED);
-
- s = screen->createDFBSurface(&description, QDirectFBScreen::TrackSurface);
- if (!s)
- qWarning("QDirectFBPaintEngine failed caching image");
-
-#ifndef QT_NO_DIRECTFB_PALETTE
- QDirectFBScreen::setSurfaceColorTable(s, image);
-#endif
-
- if (s) {
- s->SetBlittingFlags(s, DSBLIT_NOFX);
- s->Blit(s, tmpSurface, 0, 0, 0);
- s->ReleaseSource(s);
+ void clear()
+ {
+ if (surface && QDirectFBScreen::instance())
+ QDirectFBScreen::instance()->releaseDFBSurface(surface);
+ surface = 0;
+ buffer = 0;
+ bufsize = 0;
}
- if (tmpSurface)
- screen->releaseDFBSurface(tmpSurface);
-}
-
-CachedImage::~CachedImage()
-{
- if (s && QDirectFBScreen::instance())
- QDirectFBScreen::instance()->releaseDFBSurface(s);
-}
-
-static QCache<qint64, CachedImage> imageCache(4*1024*1024); // 4 MB
-
-IDirectFBSurface* SurfaceCache::getSurface(const uint *buf, int size)
-{
- if (buffer == buf && bufsize == size)
- return surface;
-
- clear();
-
- DFBSurfaceDescription description;
- description = QDirectFBScreen::getSurfaceDescription(buf, size);
-
- surface = QDirectFBScreen::instance()->createDFBSurface(&description, QDirectFBScreen::TrackSurface);
- if (!surface)
- qWarning("QDirectFBPaintEngine: SurfaceCache: Unable to create surface");
-
- buffer = const_cast<uint*>(buf);
- bufsize = size;
-
- return surface;
-}
+private:
+ IDirectFBSurface *surface;
+ uint *buffer;
+ int bufsize;
+};
-void SurfaceCache::clear()
-{
- if (surface)
- QDirectFBScreen::instance()->releaseDFBSurface(surface);
- surface = 0;
- buffer = 0;
- bufsize = 0;
-}
-SurfaceCache::~SurfaceCache()
+#ifdef QT_DIRECTFB_IMAGECACHE
+#include <private/qimage_p.h>
+struct CachedImage
{
- clear();
-}
+ IDirectFBSurface *surface;
+ ~CachedImage()
+ {
+ if (surface && QDirectFBScreen::instance()) {
+ QDirectFBScreen::instance()->releaseDFBSurface(surface);
+ }
+ }
+};
+static QCache<qint64, CachedImage> imageCache(4*1024*1024); // 4 MB
+#endif
class QDirectFBPaintEnginePrivate : public QRasterPaintEnginePrivate
{
public:
+ enum Scale { NoScale, Scaled, NegativeScale };
+
QDirectFBPaintEnginePrivate(QDirectFBPaintEngine *p);
~QDirectFBPaintEnginePrivate();
- IDirectFBSurface *surface;
-
- QPen pen;
- QBrush brush;
-
- bool antialiased;
- bool forceRasterPrimitives;
-
- bool simplePen;
- bool simpleBrush;
-
- bool matrixRotShear;
- bool matrixScale;
-
void setTransform(const QTransform &m);
void setPen(const QPen &pen);
- void setBrush(const QBrush &brush);
void setCompositionMode(QPainter::CompositionMode mode);
void setOpacity(quint8 value);
void setRenderHints(QPainter::RenderHints hints);
@@ -207,35 +230,51 @@ public:
inline bool dfbCanHandleClip(const QRect &rect) const;
inline bool dfbCanHandleClip(const QRectF &rect) const;
inline bool dfbCanHandleClip() const;
+ inline bool isSimpleBrush(const QBrush &brush) const;
- void drawLines(const QLine *lines, int count) const;
- void drawLines(const QLineF *lines, int count) const;
+ void drawLines(const QLine *lines, int count);
+ void drawLines(const QLineF *lines, int count);
- void fillRegion(const QRegion &r) const;
- void fillRects(const QRect *rects, int count) const;
- void drawRects(const QRect *rects, int count) const;
- void fillRects(const QRectF *rects, int count) const;
- void drawRects(const QRectF *rects, int count) const;
+ void fillRegion(const QRegion &r);
+ void fillRects(const QRect *rects, int count);
+ void drawRects(const QRect *rects, int count);
+ void fillRects(const QRectF *rects, int count);
+ void drawRects(const QRectF *rects, int count);
- void drawPixmap(const QRectF &dest,
- const QPixmap &pixmap, const QRectF &src);
void drawTiledPixmap(const QRectF &dest, const QPixmap &pixmap);
- void drawImage(const QRectF &dest, const QImage &image, const QRectF &src);
+ void blit(const QRectF &dest, IDirectFBSurface *surface, const QRectF &src);
inline void updateClip();
- inline void setClipDirty();
void systemStateChanged();
void begin(QPaintDevice *device);
void end();
+ static IDirectFBSurface *getSurface(const QImage &img, bool *release);
+
+#ifdef QT_DIRECTFB_IMAGECACHE
+ static inline int cacheCost(const QImage &img) { return img.width() * img.height() * img.depth() / 8; }
+#endif
+
void prepareForBlit(bool alpha);
+private:
+ IDirectFBSurface *surface;
+
+ QPen pen;
+
+ bool antialiased;
+ bool forceRasterPrimitives;
+
+ bool simplePen;
+
+ bool matrixRotShear;
+ Scale scale;
+
SurfaceCache *surfaceCache;
QTransform transform;
int lastLockedHeight;
-private:
+
IDirectFB *fb;
- DFBSurfaceDescription fbDescription;
int fbWidth;
int fbHeight;
@@ -246,470 +285,14 @@ private:
bool dirtyClip;
bool dfbHandledClip;
+ bool ignoreSystemClip;
QDirectFBPaintDevice *dfbDevice;
+ void *lockedMemory;
QDirectFBPaintEngine *q;
+ friend class QDirectFBPaintEngine;
};
-QDirectFBPaintEnginePrivate::QDirectFBPaintEnginePrivate(QDirectFBPaintEngine *p)
- : surface(0), antialiased(false), forceRasterPrimitives(false), simplePen(false),
- simpleBrush(false), matrixRotShear(false), matrixScale(false), lastLockedHeight(-1),
- fbWidth(-1), fbHeight(-1), opacity(255), drawFlagsFromCompositionMode(0),
- blitFlagsFromCompositionMode(0), porterDuffRule(DSPD_SRC_OVER), dirtyClip(true),
- dfbHandledClip(false), dfbDevice(0), q(p)
-{
- fb = QDirectFBScreen::instance()->dfb();
- surfaceCache = new SurfaceCache;
- static int cacheLimit = qgetenv("QT_DIRECTFB_IMAGECACHE").toInt();
- if (cacheLimit > 0)
- imageCache.setMaxCost(cacheLimit * 1024);
-}
-
-QDirectFBPaintEnginePrivate::~QDirectFBPaintEnginePrivate()
-{
- delete surfaceCache;
-}
-
-bool QDirectFBPaintEnginePrivate::dfbCanHandleClip(const QRect &rect) const
-{
- // TODO: Check to see if DirectFB can handle the clip for the given rect
- return dfbHandledClip;
-}
-
-bool QDirectFBPaintEnginePrivate::dfbCanHandleClip(const QRectF &rect) const
-{
- // TODO: Check to see if DirectFB can handle the clip for the given rect
- return dfbHandledClip;
-}
-
-bool QDirectFBPaintEnginePrivate::dfbCanHandleClip() const
-{
- return dfbHandledClip;
-}
-
-void QDirectFBPaintEnginePrivate::setClipDirty()
-{
- dirtyClip = true;
-}
-
-void QDirectFBPaintEnginePrivate::lock()
-{
- // We will potentially get a new pointer to the buffer after a
- // lock so we need to call the base implementation of prepare so
- // it updates its rasterBuffer to point to the new buffer address.
- lastLockedHeight = dfbDevice->height();
-
- Q_ASSERT(dfbDevice);
- prepare(dfbDevice);
-}
-
-void QDirectFBPaintEnginePrivate::unlock()
-{
- Q_ASSERT(dfbDevice);
- dfbDevice->unlockDirectFB();
-}
-
-void QDirectFBPaintEnginePrivate::setTransform(const QTransform &m)
-{
- transform = m;
- matrixRotShear = (transform.m12() != 0 || transform.m21() != 0);
- matrixScale = (transform.m11() != 1 || transform.m22() != 1);
-}
-
-void QDirectFBPaintEnginePrivate::begin(QPaintDevice *device)
-{
- lastLockedHeight = -1;
- if (device->devType() == QInternal::CustomRaster)
- dfbDevice = static_cast<QDirectFBPaintDevice*>(device);
- else if (device->devType() == QInternal::Pixmap) {
- QPixmapData *data = static_cast<QPixmap*>(device)->pixmapData();
- Q_ASSERT(data->classId() == QPixmapData::DirectFBClass);
- QDirectFBPixmapData* dfbPixmapData = static_cast<QDirectFBPixmapData*>(data);
- dfbDevice = static_cast<QDirectFBPaintDevice*>(dfbPixmapData);
- }
-
- if (dfbDevice)
- surface = dfbDevice->directFBSurface();
-
- if (!surface) {
- qFatal("QDirectFBPaintEngine used on an invalid device: 0x%x",
- device->devType());
- }
- forceRasterPrimitives = dfbDevice->forceRasterPrimitives();
-
- surface->GetSize(surface, &fbWidth, &fbHeight);
-
- setTransform(QTransform());
- antialiased = false;
- opacity = 255;
- setCompositionMode(q->state()->compositionMode());
- dirtyClip = true;
- setPen(q->state()->pen);
- setDFBColor(pen.color());
-}
-
-void QDirectFBPaintEnginePrivate::end()
-{
- dfbDevice = 0;
- surface->ReleaseSource(surface);
- surface->SetClip(surface, NULL);
- surface = 0;
-}
-
-void QDirectFBPaintEnginePrivate::setPen(const QPen &p)
-{
- pen = p;
- simplePen = (pen.style() == Qt::NoPen) ||
- (pen.style() == Qt::SolidLine
- && !antialiased
- && (pen.brush().style() == Qt::SolidPattern)
- && (pen.widthF() <= 1 && !matrixScale));
-}
-
-void QDirectFBPaintEnginePrivate::setBrush(const QBrush &b)
-{
- brush = b;
- simpleBrush = (brush.style() == Qt::NoBrush) ||
- (brush.style() == Qt::SolidPattern && !antialiased);
-}
-
-void QDirectFBPaintEnginePrivate::setCompositionMode(QPainter::CompositionMode mode)
-{
- blitFlagsFromCompositionMode = DSBLIT_NOFX;
- drawFlagsFromCompositionMode = DSDRAW_NOFX;
-
- bool blend = true;
- switch (mode) {
- case QPainter::CompositionMode_SourceOver:
- porterDuffRule = DSPD_SRC_OVER;
- break;
- case QPainter::CompositionMode_DestinationOver:
- porterDuffRule = DSPD_DST_OVER;
- break;
- case QPainter::CompositionMode_Clear:
- porterDuffRule = DSPD_CLEAR;
- blend = false;
- break;
- case QPainter::CompositionMode_Source:
- porterDuffRule = DSPD_SRC;
- blend = false;
- break;
- case QPainter::CompositionMode_Destination:
- porterDuffRule = DSPD_NONE; // ### need to double check this
- blend = false;
- return;
- case QPainter::CompositionMode_SourceIn:
- porterDuffRule = DSPD_SRC_IN;
- break;
- case QPainter::CompositionMode_DestinationIn:
- porterDuffRule = DSPD_DST_IN;
- break;
- case QPainter::CompositionMode_SourceOut:
- porterDuffRule = DSPD_SRC_OUT;
- break;
- case QPainter::CompositionMode_DestinationOut:
- porterDuffRule = DSPD_DST_OUT;
- break;
- case QPainter::CompositionMode_Xor:
- porterDuffRule = DSPD_XOR;
- blitFlagsFromCompositionMode |= DSBLIT_XOR;
- drawFlagsFromCompositionMode |= DSDRAW_XOR;
- break;
-// case QPainter::CompositionMode_Plus: // ???
-// porterDuffRule = DSPD_ADD;
-// break;
- default:
- qWarning("QDirectFBPaintEnginePrivate::setCompositionMode(): "
- "mode %d not implemented", mode);
- return;
- }
- // intentially not comparing with current porterDuffRule. surface might have changed.
- if (blend) {
- blitFlagsFromCompositionMode |= DSBLIT_BLEND_ALPHACHANNEL;
- drawFlagsFromCompositionMode |= DSDRAW_BLEND;
- }
- if (opacity != 255) {
- setOpacity(opacity);
- }
-}
-
-void QDirectFBPaintEnginePrivate::setOpacity(quint8 op)
-{
- opacity = op;
- if (opacity == 255) {
- blitFlagsFromCompositionMode &= ~DSBLIT_BLEND_COLORALPHA;
- } else {
- blitFlagsFromCompositionMode |= DSBLIT_BLEND_COLORALPHA;
- }
-}
-
-void QDirectFBPaintEnginePrivate::setRenderHints(QPainter::RenderHints hints)
-{
- const bool old = antialiased;
- antialiased = bool(hints & QPainter::Antialiasing);
- if (old != antialiased) {
- setPen(q->state()->pen);
- }
-}
-
-void QDirectFBPaintEnginePrivate::prepareForBlit(bool alpha)
-{
- quint32 blittingFlags = blitFlagsFromCompositionMode;
- if (alpha) {
- surface->SetPorterDuff(surface,
- (blittingFlags & DSBLIT_BLEND_COLORALPHA)
- ? DSPD_NONE
- : porterDuffRule);
- } else {
- blittingFlags &= ~DSBLIT_BLEND_ALPHACHANNEL;
- surface->SetPorterDuff(surface, DSPD_NONE);
- }
- surface->SetColor(surface, 0xff, 0xff, 0xff, opacity);
- surface->SetBlittingFlags(surface, DFBSurfaceBlittingFlags(blittingFlags));
-}
-
-void QDirectFBPaintEnginePrivate::setDFBColor(const QColor &color)
-{
- Q_ASSERT(surface);
- const quint8 alpha = (opacity == 255 ?
- color.alpha() : ALPHA_MUL(color.alpha(), opacity));
- surface->SetColor(surface,
- color.red(), color.green(), color.blue(), alpha);
- quint32 drawingFlags = drawFlagsFromCompositionMode;
- if (alpha == 255) {
- drawingFlags &= ~DSDRAW_BLEND;
- }
- surface->SetPorterDuff(surface, DSPD_NONE);
- // PorterDuff messes up alpha values for primitives
- surface->SetDrawingFlags(surface, DFBSurfaceDrawingFlags(drawingFlags));
-}
-
-void QDirectFBPaintEnginePrivate::drawLines(const QLine *lines, int n) const
-{
- for (int i = 0; i < n; ++i) {
- const QLine l = transform.map(lines[i]);
- surface->DrawLine(surface, l.x1(), l.y1(), l.x2(), l.y2());
- }
-}
-
-void QDirectFBPaintEnginePrivate::drawLines(const QLineF *lines, int n) const
-{
- for (int i = 0; i < n; ++i) {
- const QLine l = transform.map(lines[i]).toLine();
- surface->DrawLine(surface, l.x1(), l.y1(), l.x2(), l.y2());
- }
-}
-
-void QDirectFBPaintEnginePrivate::fillRegion(const QRegion &region) const
-{
- const QVector<QRect> rects = region.rects();
- const int n = rects.size();
- fillRects(rects.constData(), n);
-}
-
-void QDirectFBPaintEnginePrivate::fillRects(const QRect *rects, int n) const
-{
- for (int i = 0; i < n; ++i) {
- const QRect r = transform.mapRect(rects[i]);
- surface->FillRectangle(surface, r.x(), r.y(),
- r.width(), r.height());
- }
-}
-
-void QDirectFBPaintEnginePrivate::fillRects(const QRectF *rects, int n) const
-{
- for (int i = 0; i < n; ++i) {
- const QRect r = transform.mapRect(rects[i]).toRect();
- surface->FillRectangle(surface, r.x(), r.y(),
- r.width(), r.height());
- }
-}
-
-void QDirectFBPaintEnginePrivate::drawRects(const QRect *rects, int n) const
-{
- for (int i = 0; i < n; ++i) {
- const QRect r = transform.mapRect(rects[i]);
- surface->DrawRectangle(surface, r.x(), r.y(),
- r.width() + 1, r.height() + 1);
- }
-}
-
-void QDirectFBPaintEnginePrivate::drawRects(const QRectF *rects, int n) const
-{
- for (int i = 0; i < n; ++i) {
- const QRect r = transform.mapRect(rects[i]).toRect();
- surface->DrawRectangle(surface, r.x(), r.y(),
- r.width() + 1, r.height() + 1);
- }
-}
-
-void QDirectFBPaintEnginePrivate::drawPixmap(const QRectF &dest,
- const QPixmap &pixmap,
- const QRectF &src)
-{
- prepareForBlit(pixmap.hasAlphaChannel());
- QPixmapData *data = pixmap.pixmapData();
- Q_ASSERT(data->classId() == QPixmapData::DirectFBClass);
- QDirectFBPixmapData *dfbData = static_cast<QDirectFBPixmapData*>(data);
- IDirectFBSurface *s = dfbData->directFBSurface();
- const QRect sr = src.toRect();
- const QRect dr = transform.mapRect(dest).toRect();
- const DFBRectangle sRect = { sr.x(), sr.y(), sr.width(), sr.height() };
- DFBResult result;
-
- if (dr.size() == sr.size()) {
- result = surface->Blit(surface, s, &sRect, dr.x(), dr.y());
- } else {
- const DFBRectangle dRect = { dr.x(), dr.y(), dr.width(), dr.height() };
- result = surface->StretchBlit(surface, s, &sRect, &dRect);
- }
- if (result != DFB_OK)
- DirectFBError("QDirectFBPaintEngine::drawPixmap()", result);
-}
-
-void QDirectFBPaintEnginePrivate::drawTiledPixmap(const QRectF &dest,
- const QPixmap &pixmap)
-{
- prepareForBlit(pixmap.hasAlphaChannel());
- QPixmapData *data = pixmap.pixmapData();
- Q_ASSERT(data->classId() == QPixmapData::DirectFBClass);
- QDirectFBPixmapData *dfbData = static_cast<QDirectFBPixmapData*>(data);
- IDirectFBSurface *s = dfbData->directFBSurface();
- const QRect dr = transform.mapRect(dest).toRect();
- DFBResult result = DFB_OK;
-
- if (!matrixScale && dr == QRect(0, 0, fbWidth, fbHeight)) {
- result = surface->TileBlit(surface, s, 0, 0, 0);
- } else if (!matrixScale) {
- const int dx = pixmap.width();
- const int dy = pixmap.height();
- const DFBRectangle rect = { 0, 0, dx, dy };
- QVarLengthArray<DFBRectangle> rects;
- QVarLengthArray<DFBPoint> points;
-
- for (int y = dr.y(); y <= dr.bottom(); y += dy) {
- for (int x = dr.x(); x <= dr.right(); x += dx) {
- rects.append(rect);
- const DFBPoint point = { x, y };
- points.append(point);
- }
- }
- result = surface->BatchBlit(surface, s, rects.constData(),
- points.constData(), points.size());
- } else {
- const QRect sr = transform.mapRect(QRect(0, 0, pixmap.width(), pixmap.height()));
- const int dx = sr.width();
- const int dy = sr.height();
- const DFBRectangle sRect = { 0, 0, dx, dy };
-
- for (int y = dr.y(); y <= dr.bottom(); y += dy) {
- for (int x = dr.x(); x <= dr.right(); x += dx) {
- const DFBRectangle dRect = { x, y, dx, dy };
- result = surface->StretchBlit(surface, s, &sRect, &dRect);
- if (result != DFB_OK) {
- y = dr.bottom() + 1;
- break;
- }
- }
- }
- }
-
- if (result != DFB_OK)
- DirectFBError("QDirectFBPaintEngine::drawTiledPixmap()", result);
-}
-
-void QDirectFBPaintEnginePrivate::drawImage(const QRectF &dest,
- const QImage &image,
- const QRectF &src)
-{
- Q_ASSERT(QDirectFBScreen::getSurfacePixelFormat(image.format()) != DSPF_UNKNOWN);
- CachedImage *img = imageCache[image.cacheKey()];
- IDirectFBSurface *imgSurface = 0;
- bool doRelease = false;
-
- if (img) {
- imgSurface = img->surface();
- } else {
- const int cost = image.width() * image.height() * image.depth() / 8;
- if (cost <= imageCache.maxCost()) {
- img = new CachedImage(image);
- imgSurface = img->surface();
- if (imgSurface) {
- imageCache.insert(image.cacheKey(), img, cost);
- } else {
- delete img;
- img = 0;
- }
- }
-
- if (!imgSurface) {
- DFBSurfaceDescription description;
-
- description = QDirectFBScreen::getSurfaceDescription(image);
- imgSurface = QDirectFBScreen::instance()->createDFBSurface(&description,
- QDirectFBScreen::DontTrackSurface);
- if (!imgSurface) {
- qWarning("QDirectFBPaintEnginePrivate::drawImage");
- return;
- }
-
-#ifndef QT_NO_DIRECTFB_PALETTE
- QDirectFBScreen::setSurfaceColorTable(surface, image);
-#endif
- doRelease = (imgSurface != 0);
- }
- }
-
- const QRect sr = src.toRect();
- const QRect dr = transform.mapRect(dest).toRect();
- const DFBRectangle sRect = { sr.x(), sr.y(), sr.width(), sr.height() };
-
- prepareForBlit(image.hasAlphaChannel());
- if (dr.size() == sr.size()) {
- surface->Blit(surface, imgSurface, &sRect, dr.x(), dr.y());
- } else {
- const DFBRectangle dRect = { dr.x(), dr.y(),
- dr.width(), dr.height() };
- surface->StretchBlit(surface, imgSurface, &sRect, &dRect);
- }
- if (doRelease) {
- surface->ReleaseSource(surface);
- imgSurface->Release(imgSurface);
- }
-}
-
-void QDirectFBPaintEnginePrivate::updateClip()
-{
- if (!dirtyClip)
- return;
-
- if (!clip() || !clip()->enabled) {
- surface->SetClip(surface, NULL);
- dfbHandledClip = true;
- }
- else if (clip()->hasRectClip) {
- const DFBRegion r = {
- clip()->clipRect.x(),
- clip()->clipRect.y(),
- clip()->clipRect.x() + clip()->clipRect.width(),
- clip()->clipRect.y() + clip()->clipRect.height()
- };
- surface->SetClip(surface, &r);
-
- dfbHandledClip = true;
- }
- else
- dfbHandledClip = false;
-
- dirtyClip = false;
-}
-
-void QDirectFBPaintEnginePrivate::systemStateChanged()
-{
- setClipDirty();
- QRasterPaintEnginePrivate::systemStateChanged();
-}
-
QDirectFBPaintEngine::QDirectFBPaintEngine(QPaintDevice *device)
: QRasterPaintEngine(*(new QDirectFBPaintEnginePrivate(this)), device)
{
@@ -738,12 +321,10 @@ bool QDirectFBPaintEngine::end()
return QRasterPaintEngine::end();
}
-
-
void QDirectFBPaintEngine::clipEnabledChanged()
{
Q_D(QDirectFBPaintEngine);
- d->setClipDirty();
+ d->dirtyClip = true;
QRasterPaintEngine::clipEnabledChanged();
}
@@ -755,14 +336,6 @@ void QDirectFBPaintEngine::penChanged()
QRasterPaintEngine::penChanged();
}
-void QDirectFBPaintEngine::brushChanged()
-{
- Q_D(QDirectFBPaintEngine);
- d->setBrush(state()->brush);
-
- QRasterPaintEngine::brushChanged();
-}
-
void QDirectFBPaintEngine::opacityChanged()
{
Q_D(QDirectFBPaintEngine);
@@ -787,9 +360,9 @@ void QDirectFBPaintEngine::renderHintsChanged()
void QDirectFBPaintEngine::transformChanged()
{
Q_D(QDirectFBPaintEngine);
- const bool old = d->matrixScale;
+ const QDirectFBPaintEnginePrivate::Scale old = d->scale;
d->setTransform(state()->transform());
- if (d->matrixScale != old) {
+ if (d->scale != old) {
d->setPen(state()->pen);
}
QRasterPaintEngine::transformChanged();
@@ -799,9 +372,8 @@ void QDirectFBPaintEngine::setState(QPainterState *s)
{
Q_D(QDirectFBPaintEngine);
QRasterPaintEngine::setState(s);
- d->setClipDirty();
+ d->dirtyClip = true;
d->setPen(state()->pen);
- d->setBrush(state()->brush);
d->setOpacity(quint8(state()->opacity * 255));
d->setCompositionMode(state()->compositionMode());
d->setTransform(state()->transform());
@@ -810,7 +382,7 @@ void QDirectFBPaintEngine::setState(QPainterState *s)
void QDirectFBPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op)
{
Q_D(QDirectFBPaintEngine);
- d->setClipDirty();
+ d->dirtyClip = true;
const QPoint bottom = d->transform.map(QPoint(0, path.controlPointRect().y2));
if (bottom.y() >= d->lastLockedHeight)
d->lock();
@@ -820,8 +392,8 @@ void QDirectFBPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op)
void QDirectFBPaintEngine::clip(const QRect &rect, Qt::ClipOperation op)
{
Q_D(QDirectFBPaintEngine);
- d->setClipDirty();
- if (!d->clip()->hasRectClip && d->clip()->enabled) {
+ d->dirtyClip = true;
+ if (d->clip() && !d->clip()->hasRectClip && d->clip()->enabled) {
const QPoint bottom = d->transform.map(QPoint(0, rect.bottom()));
if (bottom.y() >= d->lastLockedHeight)
d->lock();
@@ -834,8 +406,11 @@ void QDirectFBPaintEngine::drawRects(const QRect *rects, int rectCount)
{
Q_D(QDirectFBPaintEngine);
d->updateClip();
- if (!d->dfbCanHandleClip() || d->matrixRotShear || !d->simpleBrush
- || !d->simplePen || d->forceRasterPrimitives) {
+ const QBrush &brush = state()->brush;
+ if (!d->dfbCanHandleClip() || d->matrixRotShear
+ || !d->simplePen || d->forceRasterPrimitives
+ || !d->isSimpleBrush(brush)) {
+ RASTERFALLBACK(DRAW_RECTS, rectCount, VOID_ARG(), VOID_ARG());
d->lock();
QRasterPaintEngine::drawRects(rects, rectCount);
return;
@@ -843,8 +418,8 @@ void QDirectFBPaintEngine::drawRects(const QRect *rects, int rectCount)
d->unlock();
- if (d->brush != Qt::NoBrush) {
- d->setDFBColor(d->brush.color());
+ if (brush != Qt::NoBrush) {
+ d->setDFBColor(brush.color());
d->fillRects(rects, rectCount);
}
if (d->pen != Qt::NoPen) {
@@ -857,8 +432,11 @@ void QDirectFBPaintEngine::drawRects(const QRectF *rects, int rectCount)
{
Q_D(QDirectFBPaintEngine);
d->updateClip();
- if (!d->dfbCanHandleClip() || d->matrixRotShear || !d->simpleBrush
- || !d->simplePen || d->forceRasterPrimitives) {
+ const QBrush &brush = state()->brush;
+ if (!d->dfbCanHandleClip() || d->matrixRotShear
+ || !d->simplePen || d->forceRasterPrimitives
+ || !d->isSimpleBrush(brush)) {
+ RASTERFALLBACK(DRAW_RECTS, rectCount, VOID_ARG(), VOID_ARG());
d->lock();
QRasterPaintEngine::drawRects(rects, rectCount);
return;
@@ -866,8 +444,8 @@ void QDirectFBPaintEngine::drawRects(const QRectF *rects, int rectCount)
d->unlock();
- if (d->brush != Qt::NoBrush) {
- d->setDFBColor(d->brush.color());
+ if (brush != Qt::NoBrush) {
+ d->setDFBColor(brush.color());
d->fillRects(rects, rectCount);
}
if (d->pen != Qt::NoPen) {
@@ -881,6 +459,7 @@ void QDirectFBPaintEngine::drawLines(const QLine *lines, int lineCount)
Q_D(QDirectFBPaintEngine);
d->updateClip();
if (!d->simplePen || !d->dfbCanHandleClip() || d->forceRasterPrimitives) {
+ RASTERFALLBACK(DRAW_LINES, lineCount, VOID_ARG(), VOID_ARG());
d->lock();
QRasterPaintEngine::drawLines(lines, lineCount);
return;
@@ -898,6 +477,7 @@ void QDirectFBPaintEngine::drawLines(const QLineF *lines, int lineCount)
Q_D(QDirectFBPaintEngine);
d->updateClip();
if (!d->simplePen || !d->dfbCanHandleClip() || d->forceRasterPrimitives) {
+ RASTERFALLBACK(DRAW_LINES, lineCount, VOID_ARG(), VOID_ARG());
d->lock();
QRasterPaintEngine::drawLines(lines, lineCount);
return;
@@ -915,22 +495,53 @@ void QDirectFBPaintEngine::drawImage(const QRectF &r, const QImage &image,
Qt::ImageConversionFlags flags)
{
Q_D(QDirectFBPaintEngine);
- Q_UNUSED(flags); // XXX
+ Q_UNUSED(flags);
+
+ /* This is hard to read. The way it works is like this:
+
+ - If you do not have support for preallocated surfaces and do not use an
+ image cache we always fall back to raster engine.
+
+ - If it's rotated/sheared/mirrored (negative scale) or we can't
+ clip it we fall back to raster engine.
+
+ - If we don't cache the image, but we do have support for
+ preallocated surfaces we fall back to the raster engine if the
+ image is in a format DirectFB can't handle.
+
+ - If we do cache the image but don't have support for preallocated
+ images and the cost of caching the image (bytes used) is higher
+ than the max image cache size we fall back to raster engine.
+ */
-#ifndef QT_NO_DIRECTFB_PREALLOCATED
d->updateClip();
- if (!d->dfbCanHandleClip(r) || d->matrixRotShear
- || QDirectFBScreen::getSurfacePixelFormat(image.format()) == DSPF_UNKNOWN)
+#if !defined QT_NO_DIRECTFB_PREALLOCATED || defined QT_DIRECTFB_IMAGECACHE
+ if (d->matrixRotShear
+ || d->scale == QDirectFBPaintEnginePrivate::NegativeScale
+ || !d->dfbCanHandleClip(r)
+#ifndef QT_DIRECTFB_IMAGECACHE
+ || QDirectFBScreen::getSurfacePixelFormat(image.format()) == DSPF_UNKNOWN
+#elif defined QT_NO_DIRECTFB_PREALLOCATED
+ || QDirectFBPaintEnginePrivate::cacheCost(image) > imageCache.maxCost()
+#endif
+ )
#endif
{
+ RASTERFALLBACK(DRAW_IMAGE, r, image.size(), sr);
d->lock();
QRasterPaintEngine::drawImage(r, image, sr, flags);
return;
}
-
-#ifndef QT_NO_DIRECTFB_PREALLOCATED
+#if !defined QT_NO_DIRECTFB_PREALLOCATED || defined QT_DIRECTFB_IMAGECACHE
d->unlock();
- d->drawImage(r, image, sr);
+ bool release;
+ IDirectFBSurface *imgSurface = d->getSurface(image, &release);
+ d->prepareForBlit(QDirectFBScreen::hasAlpha(imgSurface));
+ d->blit(r, imgSurface, sr);
+ if (release) {
+ imgSurface->ReleaseSource(imgSurface);
+ imgSurface->Release(imgSurface);
+ }
#endif
}
@@ -946,15 +557,23 @@ void QDirectFBPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pixmap,
d->updateClip();
if (pixmap.pixmapData()->classId() != QPixmapData::DirectFBClass) {
+ RASTERFALLBACK(DRAW_PIXMAP, r, pixmap.size(), sr);
d->lock();
QRasterPaintEngine::drawPixmap(r, pixmap, sr);
- } else if (!d->dfbCanHandleClip(r) || d->matrixRotShear) {
- const QImage *img = static_cast<QDirectFBPixmapData*>(pixmap.pixmapData())->buffer();
+ } else if (!d->dfbCanHandleClip(r) || d->matrixRotShear
+ || d->scale == QDirectFBPaintEnginePrivate::NegativeScale) {
+ RASTERFALLBACK(DRAW_PIXMAP, r, pixmap.size(), sr);
+ const QImage *img = static_cast<QDirectFBPixmapData*>(pixmap.pixmapData())->buffer(DSLF_READ);
d->lock();
QRasterPaintEngine::drawImage(r, *img, sr);
} else {
d->unlock();
- d->drawPixmap(r, pixmap, sr);
+ d->prepareForBlit(pixmap.hasAlphaChannel());
+ QPixmapData *data = pixmap.pixmapData();
+ Q_ASSERT(data->classId() == QPixmapData::DirectFBClass);
+ QDirectFBPixmapData *dfbData = static_cast<QDirectFBPixmapData*>(data);
+ IDirectFBSurface *s = dfbData->directFBSurface();
+ d->blit(r, s, sr);
}
}
@@ -970,10 +589,13 @@ void QDirectFBPaintEngine::drawTiledPixmap(const QRectF &r,
Q_D(QDirectFBPaintEngine);
d->updateClip();
if (pixmap.pixmapData()->classId() != QPixmapData::DirectFBClass) {
+ RASTERFALLBACK(DRAW_TILED_PIXMAP, r, pixmap.size(), sp);
d->lock();
QRasterPaintEngine::drawTiledPixmap(r, pixmap, sp);
- } else if (!d->dfbCanHandleClip(r) || d->matrixRotShear || !sp.isNull()) {
- const QImage *img = static_cast<QDirectFBPixmapData*>(pixmap.pixmapData())->buffer();
+ } else if (!d->dfbCanHandleClip(r) || d->matrixRotShear || !sp.isNull()
+ || d->scale == QDirectFBPaintEnginePrivate::NegativeScale) {
+ RASTERFALLBACK(DRAW_TILED_PIXMAP, r, pixmap.size(), sp);
+ const QImage *img = static_cast<QDirectFBPixmapData*>(pixmap.pixmapData())->buffer(DSLF_READ);
d->lock();
QRasterPixmapData *data = new QRasterPixmapData(QPixmapData::PixmapType);
data->fromImage(*img, Qt::AutoColor);
@@ -988,6 +610,7 @@ void QDirectFBPaintEngine::drawTiledPixmap(const QRectF &r,
void QDirectFBPaintEngine::stroke(const QVectorPath &path, const QPen &pen)
{
+ RASTERFALLBACK(STROKE_PATH, path, VOID_ARG(), VOID_ARG());
Q_D(QDirectFBPaintEngine);
d->lock();
QRasterPaintEngine::stroke(path, pen);
@@ -995,6 +618,7 @@ void QDirectFBPaintEngine::stroke(const QVectorPath &path, const QPen &pen)
void QDirectFBPaintEngine::drawPath(const QPainterPath &path)
{
+ RASTERFALLBACK(DRAW_PATH, path, VOID_ARG(), VOID_ARG());
Q_D(QDirectFBPaintEngine);
d->lock();
QRasterPaintEngine::drawPath(path);
@@ -1002,6 +626,7 @@ void QDirectFBPaintEngine::drawPath(const QPainterPath &path)
void QDirectFBPaintEngine::drawPoints(const QPointF *points, int pointCount)
{
+ RASTERFALLBACK(DRAW_POINTS, pointCount, VOID_ARG(), VOID_ARG());
Q_D(QDirectFBPaintEngine);
d->lock();
QRasterPaintEngine::drawPoints(points, pointCount);
@@ -1009,6 +634,7 @@ void QDirectFBPaintEngine::drawPoints(const QPointF *points, int pointCount)
void QDirectFBPaintEngine::drawPoints(const QPoint *points, int pointCount)
{
+ RASTERFALLBACK(DRAW_POINTS, pointCount, VOID_ARG(), VOID_ARG());
Q_D(QDirectFBPaintEngine);
d->lock();
QRasterPaintEngine::drawPoints(points, pointCount);
@@ -1016,6 +642,7 @@ void QDirectFBPaintEngine::drawPoints(const QPoint *points, int pointCount)
void QDirectFBPaintEngine::drawEllipse(const QRectF &rect)
{
+ RASTERFALLBACK(DRAW_ELLIPSE, rect, VOID_ARG(), VOID_ARG());
Q_D(QDirectFBPaintEngine);
d->lock();
QRasterPaintEngine::drawEllipse(rect);
@@ -1024,6 +651,7 @@ void QDirectFBPaintEngine::drawEllipse(const QRectF &rect)
void QDirectFBPaintEngine::drawPolygon(const QPointF *points, int pointCount,
PolygonDrawMode mode)
{
+ RASTERFALLBACK(DRAW_POLYGON, pointCount, mode, VOID_ARG());
Q_D(QDirectFBPaintEngine);
d->lock();
QRasterPaintEngine::drawPolygon(points, pointCount, mode);
@@ -1032,6 +660,7 @@ void QDirectFBPaintEngine::drawPolygon(const QPointF *points, int pointCount,
void QDirectFBPaintEngine::drawPolygon(const QPoint *points, int pointCount,
PolygonDrawMode mode)
{
+ RASTERFALLBACK(DRAW_POLYGON, pointCount, mode, VOID_ARG());
Q_D(QDirectFBPaintEngine);
d->lock();
QRasterPaintEngine::drawPolygon(points, pointCount, mode);
@@ -1040,6 +669,7 @@ void QDirectFBPaintEngine::drawPolygon(const QPoint *points, int pointCount,
void QDirectFBPaintEngine::drawTextItem(const QPointF &p,
const QTextItem &textItem)
{
+ RASTERFALLBACK(DRAW_TEXT, p, textItem.text(), VOID_ARG());
Q_D(QDirectFBPaintEngine);
d->lock();
QRasterPaintEngine::drawTextItem(p, textItem);
@@ -1047,6 +677,7 @@ void QDirectFBPaintEngine::drawTextItem(const QPointF &p,
void QDirectFBPaintEngine::fill(const QVectorPath &path, const QBrush &brush)
{
+ RASTERFALLBACK(FILL_PATH, path, brush, VOID_ARG());
Q_D(QDirectFBPaintEngine);
d->lock();
QRasterPaintEngine::fill(path, brush);
@@ -1080,6 +711,7 @@ void QDirectFBPaintEngine::fillRect(const QRectF &rect, const QBrush &brush)
break;
}
}
+ RASTERFALLBACK(FILL_RECT, rect, brush, VOID_ARG());
d->lock();
QRasterPaintEngine::fillRect(rect, brush);
}
@@ -1089,6 +721,7 @@ void QDirectFBPaintEngine::fillRect(const QRectF &rect, const QColor &color)
Q_D(QDirectFBPaintEngine);
d->updateClip();
if (!d->dfbCanHandleClip() || d->matrixRotShear || d->forceRasterPrimitives) {
+ RASTERFALLBACK(FILL_RECT, rect, color, VOID_ARG());
d->lock();
QRasterPaintEngine::fillRect(rect, color);
} else {
@@ -1105,6 +738,7 @@ void QDirectFBPaintEngine::drawColorSpans(const QSpan *spans, int count,
{
Q_D(QDirectFBPaintEngine);
if (d->forceRasterPrimitives) {
+ RASTERFALLBACK(DRAW_COLORSPANS, count, color, VOID_ARG());
d->lock();
QRasterPaintEngine::drawColorSpans(spans, count, color);
} else {
@@ -1149,4 +783,457 @@ void QDirectFBPaintEngine::drawBufferSpan(const uint *buffer, int bufsize,
d->surface->Blit(d->surface, src, &rect, x, y);
}
+#ifdef QT_DIRECTFB_IMAGECACHE
+static void cachedImageCleanupHook(qint64 key)
+{
+ delete imageCache.take(key);
+}
+void QDirectFBPaintEngine::initImageCache(int size)
+{
+ Q_ASSERT(size >= 0);
+ imageCache.setMaxCost(size);
+ typedef void (*_qt_image_cleanup_hook_64)(qint64);
+ extern Q_GUI_EXPORT _qt_image_cleanup_hook_64 qt_image_cleanup_hook_64;
+ qt_image_cleanup_hook_64 = ::cachedImageCleanupHook;
+}
+
+#endif // QT_DIRECTFB_IMAGECACHE
+
+// ---- QDirectFBPaintEnginePrivate ----
+
+
+QDirectFBPaintEnginePrivate::QDirectFBPaintEnginePrivate(QDirectFBPaintEngine *p)
+ : surface(0), antialiased(false), forceRasterPrimitives(false), simplePen(false),
+ matrixRotShear(false), scale(NoScale), lastLockedHeight(-1),
+ fbWidth(-1), fbHeight(-1), opacity(255), drawFlagsFromCompositionMode(0),
+ blitFlagsFromCompositionMode(0), porterDuffRule(DSPD_SRC_OVER), dirtyClip(true),
+ dfbHandledClip(false), dfbDevice(0), lockedMemory(0), q(p)
+{
+ fb = QDirectFBScreen::instance()->dfb();
+ ignoreSystemClip = QDirectFBScreen::instance()->directFBFlags() & QDirectFBScreen::IgnoreSystemClip;
+ surfaceCache = new SurfaceCache;
+}
+
+QDirectFBPaintEnginePrivate::~QDirectFBPaintEnginePrivate()
+{
+ delete surfaceCache;
+}
+
+bool QDirectFBPaintEnginePrivate::dfbCanHandleClip(const QRect &rect) const
+{
+ // TODO: Check to see if DirectFB can handle the clip for the given rect
+ return dfbHandledClip;
+}
+
+bool QDirectFBPaintEnginePrivate::dfbCanHandleClip(const QRectF &rect) const
+{
+ // TODO: Check to see if DirectFB can handle the clip for the given rect
+ return dfbHandledClip;
+}
+
+bool QDirectFBPaintEnginePrivate::dfbCanHandleClip() const
+{
+ return dfbHandledClip;
+}
+
+bool QDirectFBPaintEnginePrivate::isSimpleBrush(const QBrush &brush) const
+{
+ return (brush.style() == Qt::NoBrush) || (brush.style() == Qt::SolidPattern && !antialiased);
+}
+
+void QDirectFBPaintEnginePrivate::lock()
+{
+ // We will potentially get a new pointer to the buffer after a
+ // lock so we need to call the base implementation of prepare so
+ // it updates its rasterBuffer to point to the new buffer address.
+ Q_ASSERT(dfbDevice);
+ if (dfbDevice->lockFlags() != (DSLF_WRITE|DSLF_READ)
+ || dfbDevice->height() != lastLockedHeight
+ || dfbDevice->memory() != lockedMemory) {
+ prepare(dfbDevice);
+ lastLockedHeight = dfbDevice->height();
+ lockedMemory = dfbDevice->memory();
+ }
+}
+
+void QDirectFBPaintEnginePrivate::unlock()
+{
+ Q_ASSERT(dfbDevice);
+ dfbDevice->unlockDirectFB();
+ lockedMemory = 0;
+}
+
+void QDirectFBPaintEnginePrivate::setTransform(const QTransform &m)
+{
+ transform = m;
+ matrixRotShear = (transform.m12() != 0 || transform.m21() != 0);
+ if (qMin(transform.m11(), transform.m22()) < 0) {
+ scale = NegativeScale;
+ } else if (transform.m11() != 1 || transform.m22() != 1) {
+ scale = Scaled;
+ } else {
+ scale = NoScale;
+ }
+}
+
+void QDirectFBPaintEnginePrivate::begin(QPaintDevice *device)
+{
+ lastLockedHeight = -1;
+ if (device->devType() == QInternal::CustomRaster)
+ dfbDevice = static_cast<QDirectFBPaintDevice*>(device);
+ else if (device->devType() == QInternal::Pixmap) {
+ QPixmapData *data = static_cast<QPixmap*>(device)->pixmapData();
+ Q_ASSERT(data->classId() == QPixmapData::DirectFBClass);
+ QDirectFBPixmapData* dfbPixmapData = static_cast<QDirectFBPixmapData*>(data);
+ dfbDevice = static_cast<QDirectFBPaintDevice*>(dfbPixmapData);
+ }
+
+ if (dfbDevice)
+ surface = dfbDevice->directFBSurface();
+
+ if (!surface) {
+ qFatal("QDirectFBPaintEngine used on an invalid device: 0x%x",
+ device->devType());
+ }
+ lockedMemory = 0;
+ forceRasterPrimitives = dfbDevice->forceRasterPrimitives();
+
+ surface->GetSize(surface, &fbWidth, &fbHeight);
+
+ setTransform(QTransform());
+ antialiased = false;
+ opacity = 255;
+ setCompositionMode(q->state()->compositionMode());
+ dirtyClip = true;
+ setPen(q->state()->pen);
+ setDFBColor(pen.color());
+}
+
+void QDirectFBPaintEnginePrivate::end()
+{
+ lockedMemory = 0;
+ dfbDevice = 0;
+ surface->ReleaseSource(surface);
+ surface->SetClip(surface, NULL);
+ surface = 0;
+}
+
+void QDirectFBPaintEnginePrivate::setPen(const QPen &p)
+{
+ pen = p;
+ simplePen = (pen.style() == Qt::NoPen) ||
+ (pen.style() == Qt::SolidLine
+ && !antialiased
+ && (pen.brush().style() == Qt::SolidPattern)
+ && (pen.widthF() <= 1 && scale != NoScale));
+}
+
+void QDirectFBPaintEnginePrivate::setCompositionMode(QPainter::CompositionMode mode)
+{
+ blitFlagsFromCompositionMode = DSBLIT_NOFX;
+ drawFlagsFromCompositionMode = DSDRAW_NOFX;
+
+ bool blend = true;
+ switch (mode) {
+ case QPainter::CompositionMode_SourceOver:
+ porterDuffRule = DSPD_SRC_OVER;
+ break;
+ case QPainter::CompositionMode_DestinationOver:
+ porterDuffRule = DSPD_DST_OVER;
+ break;
+ case QPainter::CompositionMode_Clear:
+ porterDuffRule = DSPD_CLEAR;
+ blend = false;
+ break;
+ case QPainter::CompositionMode_Source:
+ porterDuffRule = DSPD_SRC;
+ blend = false;
+ break;
+ case QPainter::CompositionMode_Destination:
+ porterDuffRule = DSPD_NONE; // ### need to double check this
+ blend = false;
+ return;
+ case QPainter::CompositionMode_SourceIn:
+ porterDuffRule = DSPD_SRC_IN;
+ break;
+ case QPainter::CompositionMode_DestinationIn:
+ porterDuffRule = DSPD_DST_IN;
+ break;
+ case QPainter::CompositionMode_SourceOut:
+ porterDuffRule = DSPD_SRC_OUT;
+ break;
+ case QPainter::CompositionMode_DestinationOut:
+ porterDuffRule = DSPD_DST_OUT;
+ break;
+ case QPainter::CompositionMode_Xor:
+ porterDuffRule = DSPD_XOR;
+ blitFlagsFromCompositionMode |= DSBLIT_XOR;
+ drawFlagsFromCompositionMode |= DSDRAW_XOR;
+ break;
+// case QPainter::CompositionMode_Plus: // ???
+// porterDuffRule = DSPD_ADD;
+// break;
+ default:
+ qWarning("QDirectFBPaintEnginePrivate::setCompositionMode(): "
+ "mode %d not implemented", mode);
+ return;
+ }
+ // intentially not comparing with current porterDuffRule. surface might have changed.
+ if (blend) {
+ blitFlagsFromCompositionMode |= DSBLIT_BLEND_ALPHACHANNEL;
+ drawFlagsFromCompositionMode |= DSDRAW_BLEND;
+ }
+ if (opacity != 255) {
+ setOpacity(opacity);
+ }
+}
+
+void QDirectFBPaintEnginePrivate::setOpacity(quint8 op)
+{
+ opacity = op;
+ if (opacity == 255) {
+ blitFlagsFromCompositionMode &= ~DSBLIT_BLEND_COLORALPHA;
+ } else {
+ blitFlagsFromCompositionMode |= DSBLIT_BLEND_COLORALPHA;
+ }
+}
+
+void QDirectFBPaintEnginePrivate::setRenderHints(QPainter::RenderHints hints)
+{
+ const bool old = antialiased;
+ antialiased = bool(hints & QPainter::Antialiasing);
+ if (old != antialiased) {
+ setPen(q->state()->pen);
+ }
+}
+
+void QDirectFBPaintEnginePrivate::prepareForBlit(bool alpha)
+{
+ quint32 blittingFlags = blitFlagsFromCompositionMode;
+ if (alpha) {
+ surface->SetPorterDuff(surface,
+ (blittingFlags & DSBLIT_BLEND_COLORALPHA)
+ ? DSPD_NONE
+ : porterDuffRule);
+ } else {
+ blittingFlags &= ~DSBLIT_BLEND_ALPHACHANNEL;
+ surface->SetPorterDuff(surface, DSPD_NONE);
+ }
+ surface->SetColor(surface, 0xff, 0xff, 0xff, opacity);
+ surface->SetBlittingFlags(surface, DFBSurfaceBlittingFlags(blittingFlags));
+}
+
+void QDirectFBPaintEnginePrivate::setDFBColor(const QColor &color)
+{
+ Q_ASSERT(surface);
+ const quint8 alpha = (opacity == 255 ?
+ color.alpha() : ALPHA_MUL(color.alpha(), opacity));
+ surface->SetColor(surface,
+ color.red(), color.green(), color.blue(), alpha);
+ quint32 drawingFlags = drawFlagsFromCompositionMode;
+ if (alpha == 255) {
+ drawingFlags &= ~DSDRAW_BLEND;
+ }
+ surface->SetPorterDuff(surface, DSPD_NONE);
+ // PorterDuff messes up alpha values for primitives
+ surface->SetDrawingFlags(surface, DFBSurfaceDrawingFlags(drawingFlags));
+}
+
+void QDirectFBPaintEnginePrivate::drawLines(const QLine *lines, int n)
+{
+ for (int i = 0; i < n; ++i) {
+ const QLine l = transform.map(lines[i]);
+ surface->DrawLine(surface, l.x1(), l.y1(), l.x2(), l.y2());
+ }
+}
+
+void QDirectFBPaintEnginePrivate::drawLines(const QLineF *lines, int n)
+{
+ for (int i = 0; i < n; ++i) {
+ const QLine l = transform.map(lines[i]).toLine();
+ surface->DrawLine(surface, l.x1(), l.y1(), l.x2(), l.y2());
+ }
+}
+
+void QDirectFBPaintEnginePrivate::fillRegion(const QRegion &region)
+{
+ Q_ASSERT(isSimpleBrush(q->state()->brush));
+ setDFBColor(q->state()->brush.color());
+ const QVector<QRect> rects = region.rects();
+ const int n = rects.size();
+ fillRects(rects.constData(), n);
+}
+
+void QDirectFBPaintEnginePrivate::fillRects(const QRect *rects, int n)
+{
+ for (int i = 0; i < n; ++i) {
+ const QRect r = transform.mapRect(rects[i]);
+ surface->FillRectangle(surface, r.x(), r.y(),
+ r.width(), r.height());
+ }
+}
+
+void QDirectFBPaintEnginePrivate::fillRects(const QRectF *rects, int n)
+{
+ for (int i = 0; i < n; ++i) {
+ const QRect r = transform.mapRect(rects[i]).toRect();
+ surface->FillRectangle(surface, r.x(), r.y(),
+ r.width(), r.height());
+ }
+}
+
+void QDirectFBPaintEnginePrivate::drawRects(const QRect *rects, int n)
+{
+ for (int i = 0; i < n; ++i) {
+ const QRect r = transform.mapRect(rects[i]);
+ surface->DrawRectangle(surface, r.x(), r.y(),
+ r.width() + 1, r.height() + 1);
+ }
+}
+
+void QDirectFBPaintEnginePrivate::drawRects(const QRectF *rects, int n)
+{
+ for (int i = 0; i < n; ++i) {
+ const QRect r = transform.mapRect(rects[i]).toRect();
+ surface->DrawRectangle(surface, r.x(), r.y(),
+ r.width() + 1, r.height() + 1);
+ }
+}
+
+IDirectFBSurface *QDirectFBPaintEnginePrivate::getSurface(const QImage &img, bool *release)
+{
+#ifndef QT_DIRECTFB_IMAGECACHE
+ *release = true;
+ return QDirectFBScreen::instance()->createDFBSurface(img, QDirectFBScreen::DontTrackSurface);
+#else
+ const qint64 key = img.cacheKey();
+ *release = false;
+ if (imageCache.contains(key)) {
+ return imageCache[key]->surface;
+ }
+
+ const int cost = cacheCost(img);
+ const bool cache = cost <= imageCache.maxCost();
+ QDirectFBScreen *screen = QDirectFBScreen::instance();
+ const QImage::Format format = (img.format() == screen->alphaPixmapFormat() || QDirectFBPixmapData::hasAlphaChannel(img)
+ ? screen->alphaPixmapFormat() : screen->pixelFormat());
+
+ IDirectFBSurface *surface = screen->copyToDFBSurface(img, format,
+ cache
+ ? QDirectFBScreen::TrackSurface
+ : QDirectFBScreen::DontTrackSurface);
+ if (cache) {
+ CachedImage *cachedImage = new CachedImage;
+ const_cast<QImage&>(img).data_ptr()->is_cached = true;
+ cachedImage->surface = surface;
+ imageCache.insert(key, cachedImage, cost);
+ } else {
+ *release = true;
+ }
+ return surface;
+#endif
+}
+
+
+void QDirectFBPaintEnginePrivate::blit(const QRectF &dest, IDirectFBSurface *s, const QRectF &src)
+{
+ const QRect sr = src.toRect();
+ const QRect dr = transform.mapRect(dest).toRect();
+ const DFBRectangle sRect = { sr.x(), sr.y(), sr.width(), sr.height() };
+ DFBResult result;
+
+ if (dr.size() == sr.size()) {
+ result = surface->Blit(surface, s, &sRect, dr.x(), dr.y());
+ } else {
+ const DFBRectangle dRect = { dr.x(), dr.y(), dr.width(), dr.height() };
+ result = surface->StretchBlit(surface, s, &sRect, &dRect);
+ }
+ if (result != DFB_OK)
+ DirectFBError("QDirectFBPaintEngine::drawPixmap()", result);
+}
+
+void QDirectFBPaintEnginePrivate::drawTiledPixmap(const QRectF &dest,
+ const QPixmap &pixmap)
+{
+ prepareForBlit(pixmap.hasAlphaChannel());
+ QPixmapData *data = pixmap.pixmapData();
+ Q_ASSERT(data->classId() == QPixmapData::DirectFBClass);
+ QDirectFBPixmapData *dfbData = static_cast<QDirectFBPixmapData*>(data);
+ IDirectFBSurface *s = dfbData->directFBSurface();
+ const QRect dr = transform.mapRect(dest).toRect();
+ DFBResult result = DFB_OK;
+
+ if (scale == NoScale && dr == QRect(0, 0, fbWidth, fbHeight)) {
+ result = surface->TileBlit(surface, s, 0, 0, 0);
+ } else if (scale == NoScale) {
+ const int dx = pixmap.width();
+ const int dy = pixmap.height();
+ const DFBRectangle rect = { 0, 0, dx, dy };
+ QVarLengthArray<DFBRectangle> rects;
+ QVarLengthArray<DFBPoint> points;
+
+ for (int y = dr.y(); y <= dr.bottom(); y += dy) {
+ for (int x = dr.x(); x <= dr.right(); x += dx) {
+ rects.append(rect);
+ const DFBPoint point = { x, y };
+ points.append(point);
+ }
+ }
+ result = surface->BatchBlit(surface, s, rects.constData(),
+ points.constData(), points.size());
+ } else {
+ const QRect sr = transform.mapRect(QRect(0, 0, pixmap.width(), pixmap.height()));
+ const int dx = sr.width();
+ const int dy = sr.height();
+ const DFBRectangle sRect = { 0, 0, dx, dy };
+
+ for (int y = dr.y(); y <= dr.bottom(); y += dy) {
+ for (int x = dr.x(); x <= dr.right(); x += dx) {
+ const DFBRectangle dRect = { x, y, dx, dy };
+ result = surface->StretchBlit(surface, s, &sRect, &dRect);
+ if (result != DFB_OK) {
+ y = dr.bottom() + 1;
+ break;
+ }
+ }
+ }
+ }
+
+ if (result != DFB_OK)
+ DirectFBError("QDirectFBPaintEngine::drawTiledPixmap()", result);
+}
+
+void QDirectFBPaintEnginePrivate::updateClip()
+{
+ if (!dirtyClip)
+ return;
+
+ const QClipData *clipData = clip();
+ if (!clipData || !clipData->enabled) {
+ surface->SetClip(surface, NULL);
+ dfbHandledClip = true;
+ } else if (clipData->hasRectClip) {
+ const DFBRegion r = {
+ clipData->clipRect.x(),
+ clipData->clipRect.y(),
+ clipData->clipRect.x() + clipData->clipRect.width(),
+ clipData->clipRect.y() + clipData->clipRect.height()
+ };
+ surface->SetClip(surface, &r);
+ dfbHandledClip = true;
+ } else if (clipData->hasRegionClip && ignoreSystemClip && clipData->clipRegion == systemClip) {
+ dfbHandledClip = true;
+ } else {
+ dfbHandledClip = false;
+ }
+
+ dirtyClip = false;
+}
+
+void QDirectFBPaintEnginePrivate::systemStateChanged()
+{
+ dirtyClip = true;
+ QRasterPaintEnginePrivate::systemStateChanged();
+}
+
#endif // QT_NO_DIRECTFB