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.cpp822
1 files changed, 401 insertions, 421 deletions
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp
index ade8554..94f1aeb 100644
--- a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp
+++ b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp
@@ -54,173 +54,22 @@
#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 unsupportedCompositionMode,
- 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
- << "unsupportedCompositionMode" << unsupportedCompositionMode;
-
- 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()->unsupportedCompositionMode, \
- #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()->unsupportedCompositionMode, \
- #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;
- t = ((t + (t >> 8) + 0x80) >> 8) & 0xff;
- return t;
-}
-
-class SurfaceCache
-{
-public:
- SurfaceCache() : surface(0), buffer(0), bufsize(0) {}
- ~SurfaceCache() { clear(); }
-
-
- IDirectFBSurface *getSurface(const uint *buf, int size)
- {
- if (buffer == buf && bufsize == size)
- return surface;
-
- clear();
-
- const DFBSurfaceDescription 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;
- }
-
- void clear()
- {
- if (surface && QDirectFBScreen::instance())
- QDirectFBScreen::instance()->releaseDFBSurface(surface);
- surface = 0;
- buffer = 0;
- bufsize = 0;
- }
-private:
- IDirectFBSurface *surface;
- uint *buffer;
- int bufsize;
-};
-
-
-#ifdef QT_DIRECTFB_IMAGECACHE
-#include <private/qimage_p.h>
-struct CachedImage
-{
- IDirectFBSurface *surface;
- ~CachedImage()
- {
- if (surface && QDirectFBScreen::instance()) {
- QDirectFBScreen::instance()->releaseDFBSurface(surface);
- }
- }
-};
-static QCache<qint64, CachedImage> imageCache(4*1024*1024); // 4 MB
-#endif
-
+class SurfaceCache;
class QDirectFBPaintEnginePrivate : public QRasterPaintEnginePrivate
{
public:
- enum Scale { NoScale, Scaled, NegativeScale };
-
+ enum TransformationTypeFlags {
+ NegativeScale = 0x100,
+ RectsUnsupported = (QTransform::TxRotate|QTransform::TxShear|QTransform::TxProject),
+ BlitUnsupported = (NegativeScale|RectsUnsupported)
+ };
QDirectFBPaintEnginePrivate(QDirectFBPaintEngine *p);
~QDirectFBPaintEnginePrivate();
- void setTransform(const QTransform &m);
- void setPen(const QPen &pen);
+ inline void setTransform(const QTransform &transforma);
+ inline void setPen(const QPen &pen);
inline void setCompositionMode(QPainter::CompositionMode mode);
- inline void setOpacity(quint8 value);
- void setRenderHints(QPainter::RenderHints hints);
+ inline void setRenderHints(QPainter::RenderHints hints);
inline void setDFBColor(const QColor &color);
@@ -232,20 +81,11 @@ public:
inline bool dfbCanHandleClip() const;
inline bool isSimpleBrush(const QBrush &brush) const;
- void drawLines(const QLine *lines, int count);
- void drawLines(const QLineF *lines, int count);
-
- 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 drawTiledPixmap(const QRectF &dest, const QPixmap &pixmap);
+ void drawTiledPixmap(const QRectF &dest, const QPixmap &pixmap, const QPointF &pos);
void blit(const QRectF &dest, IDirectFBSurface *surface, const QRectF &src);
inline void updateClip();
- void systemStateChanged();
+ virtual void systemStateChanged();
static IDirectFBSurface *getSurface(const QImage &img, bool *release);
@@ -257,22 +97,14 @@ public:
private:
IDirectFBSurface *surface;
- QPen pen;
-
bool antialiased;
-
bool simplePen;
- bool matrixRotShear;
- Scale scale;
+ uint transformationType; // this is QTransform::type() + NegativeScale if qMin(transform.m11(), transform.m22()) < 0
SurfaceCache *surfaceCache;
- QTransform transform;
- int lastLockedHeight;
IDirectFB *fb;
- int fbWidth;
- int fbHeight;
quint8 opacity;
@@ -280,13 +112,97 @@ private:
bool dfbHandledClip;
bool ignoreSystemClip;
QDirectFBPaintDevice *dfbDevice;
- void *lockedMemory;
bool unsupportedCompositionMode;
QDirectFBPaintEngine *q;
+ QRect currentClip;
friend class QDirectFBPaintEngine;
};
+class SurfaceCache
+{
+public:
+ SurfaceCache() : surface(0), buffer(0), bufsize(0) {}
+ ~SurfaceCache() { clear(); }
+ IDirectFBSurface *getSurface(const uint *buf, int size);
+ void clear();
+private:
+ IDirectFBSurface *surface;
+ uint *buffer;
+ int bufsize;
+};
+
+
+#ifdef QT_DIRECTFB_IMAGECACHE
+#include <private/qimage_p.h>
+struct CachedImage
+{
+ IDirectFBSurface *surface;
+ ~CachedImage()
+ {
+ if (surface && QDirectFBScreen::instance()) {
+ QDirectFBScreen::instance()->releaseDFBSurface(surface);
+ }
+ }
+};
+static QCache<qint64, CachedImage> imageCache(4*1024*1024); // 4 MB
+#endif
+
+#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 device, typename T1, typename T2, typename T3>
+static void rasterFallbackWarn(const char *msg, const char *, const device *, uint, bool, bool, bool,
+ const char *, const T1 &, const char *, const T2 &, const char *, const T3 &);
+#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()->transformationType, \
+ d_func()->simplePen, \
+ d_func()->dfbCanHandleClip(), \
+ d_func()->unsupportedCompositionMode, \
+ #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()->transformationType, \
+ d_func()->simplePen, \
+ d_func()->dfbCanHandleClip(), \
+ d_func()->unsupportedCompositionMode, \
+ #one, one, #two, two, #three, three);
+#else
+#define RASTERFALLBACK(op, one, two, three)
+#endif
+
+
+template <class T>
+static inline void drawLines(const T *lines, int n, const QTransform &transform, IDirectFBSurface *surface);
+template <class T>
+static inline void fillRects(const T *rects, int n, const QTransform &transform, IDirectFBSurface *surface);
+template <class T>
+static inline void drawRects(const T *rects, int n, const QTransform &transform, IDirectFBSurface *surface);
+
QDirectFBPaintEngine::QDirectFBPaintEngine(QPaintDevice *device)
: QRasterPaintEngine(*(new QDirectFBPaintEnginePrivate(this)), device)
{
@@ -299,7 +215,6 @@ QDirectFBPaintEngine::~QDirectFBPaintEngine()
bool QDirectFBPaintEngine::begin(QPaintDevice *device)
{
Q_D(QDirectFBPaintEngine);
- d->lastLockedHeight = -1;
if (device->devType() == QInternal::CustomRaster) {
d->dfbDevice = static_cast<QDirectFBPaintDevice*>(device);
} else if (device->devType() == QInternal::Pixmap) {
@@ -316,23 +231,10 @@ bool QDirectFBPaintEngine::begin(QPaintDevice *device)
qFatal("QDirectFBPaintEngine used on an invalid device: 0x%x",
device->devType());
}
- d->lockedMemory = 0;
-
- d->surface->GetSize(d->surface, &d->fbWidth, &d->fbHeight);
-
- d->setTransform(QTransform());
- d->antialiased = false;
- d->setOpacity(255);
- d->setCompositionMode(state()->compositionMode());
- d->dirtyClip = true;
- d->setPen(state()->pen);
-
- const bool status = QRasterPaintEngine::begin(device);
- // XXX: QRasterPaintEngine::begin() resets the capabilities
- gccaps |= PorterDuff;
+ d->prepare(d->dfbDevice);
- return status;
+ return QRasterPaintEngine::begin(device);
}
bool QDirectFBPaintEngine::end()
@@ -343,6 +245,7 @@ bool QDirectFBPaintEngine::end()
#if (Q_DIRECTFB_VERSION >= 0x010000)
d->surface->ReleaseSource(d->surface);
#endif
+ d->currentClip = QRect();
d->surface->SetClip(d->surface, NULL);
d->surface = 0;
return QRasterPaintEngine::end();
@@ -366,7 +269,7 @@ void QDirectFBPaintEngine::penChanged()
void QDirectFBPaintEngine::opacityChanged()
{
Q_D(QDirectFBPaintEngine);
- d->setOpacity(quint8(state()->opacity * 255));
+ d->opacity = quint8(state()->opacity * 255);
QRasterPaintEngine::opacityChanged();
}
@@ -387,32 +290,26 @@ void QDirectFBPaintEngine::renderHintsChanged()
void QDirectFBPaintEngine::transformChanged()
{
Q_D(QDirectFBPaintEngine);
- const QDirectFBPaintEnginePrivate::Scale old = d->scale;
- d->setTransform(state()->transform());
- if (d->scale != old) {
- d->setPen(state()->pen);
- }
+ d->setTransform(state()->matrix);
QRasterPaintEngine::transformChanged();
}
-void QDirectFBPaintEngine::setState(QPainterState *s)
+void QDirectFBPaintEngine::setState(QPainterState *state)
{
Q_D(QDirectFBPaintEngine);
- QRasterPaintEngine::setState(s);
+ QRasterPaintEngine::setState(state);
d->dirtyClip = true;
- d->setPen(state()->pen);
- d->setOpacity(quint8(state()->opacity * 255));
- d->setCompositionMode(state()->compositionMode());
- d->setTransform(state()->transform());
+ d->setPen(state->pen);
+ d->opacity = quint8(state->opacity * 255);
+ d->setCompositionMode(state->compositionMode());
+ d->setTransform(state->transform());
+ d->setRenderHints(state->renderHints);
}
void QDirectFBPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op)
{
Q_D(QDirectFBPaintEngine);
d->dirtyClip = true;
- const QPoint bottom = d->transform.map(QPoint(0, int(path.controlPointRect().bottom())));
- if (bottom.y() > d->lastLockedHeight)
- d->lock();
QRasterPaintEngine::clip(path, op);
}
@@ -420,12 +317,6 @@ void QDirectFBPaintEngine::clip(const QRect &rect, Qt::ClipOperation op)
{
Q_D(QDirectFBPaintEngine);
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();
- }
-
QRasterPaintEngine::clip(rect, op);
}
@@ -434,8 +325,11 @@ void QDirectFBPaintEngine::drawRects(const QRect *rects, int rectCount)
Q_D(QDirectFBPaintEngine);
d->updateClip();
const QBrush &brush = state()->brush;
- if (d->unsupportedCompositionMode || !d->dfbCanHandleClip() || d->matrixRotShear
- || !d->simplePen || !d->isSimpleBrush(brush)) {
+ if (d->unsupportedCompositionMode
+ || (d->transformationType & QDirectFBPaintEnginePrivate::RectsUnsupported)
+ || !d->simplePen
+ || !d->dfbCanHandleClip()
+ || !d->isSimpleBrush(brush)) {
RASTERFALLBACK(DRAW_RECTS, rectCount, VOID_ARG(), VOID_ARG());
d->lock();
QRasterPaintEngine::drawRects(rects, rectCount);
@@ -446,11 +340,12 @@ void QDirectFBPaintEngine::drawRects(const QRect *rects, int rectCount)
if (brush != Qt::NoBrush) {
d->setDFBColor(brush.color());
- d->fillRects(rects, rectCount);
+ ::fillRects<QRect>(rects, rectCount, state()->matrix, d->surface);
}
- if (d->pen != Qt::NoPen) {
- d->setDFBColor(d->pen.color());
- d->drawRects(rects, rectCount);
+ const QPen &pen = state()->pen;
+ if (pen != Qt::NoPen) {
+ d->setDFBColor(pen.color());
+ ::drawRects<QRect>(rects, rectCount, state()->matrix, d->surface);
}
}
@@ -459,8 +354,11 @@ void QDirectFBPaintEngine::drawRects(const QRectF *rects, int rectCount)
Q_D(QDirectFBPaintEngine);
d->updateClip();
const QBrush &brush = state()->brush;
- if (d->unsupportedCompositionMode || !d->dfbCanHandleClip() || d->matrixRotShear
- || !d->simplePen || !d->isSimpleBrush(brush)) {
+ if (d->unsupportedCompositionMode
+ || (d->transformationType & QDirectFBPaintEnginePrivate::RectsUnsupported)
+ || !d->simplePen
+ || !d->dfbCanHandleClip()
+ || !d->isSimpleBrush(brush)) {
RASTERFALLBACK(DRAW_RECTS, rectCount, VOID_ARG(), VOID_ARG());
d->lock();
QRasterPaintEngine::drawRects(rects, rectCount);
@@ -471,11 +369,12 @@ void QDirectFBPaintEngine::drawRects(const QRectF *rects, int rectCount)
if (brush != Qt::NoBrush) {
d->setDFBColor(brush.color());
- d->fillRects(rects, rectCount);
+ ::fillRects<QRectF>(rects, rectCount, state()->matrix, d->surface);
}
- if (d->pen != Qt::NoPen) {
- d->setDFBColor(d->pen.color());
- d->drawRects(rects, rectCount);
+ const QPen &pen = state()->pen;
+ if (pen != Qt::NoPen) {
+ d->setDFBColor(pen.color());
+ ::drawRects<QRectF>(rects, rectCount, state()->matrix, d->surface);
}
}
@@ -490,10 +389,11 @@ void QDirectFBPaintEngine::drawLines(const QLine *lines, int lineCount)
return;
}
- if (d->pen != Qt::NoPen) {
+ const QPen &pen = state()->pen;
+ if (pen != Qt::NoPen) {
d->unlock();
- d->setDFBColor(d->pen.color());
- d->drawLines(lines, lineCount);
+ d->setDFBColor(pen.color());
+ ::drawLines<QLine>(lines, lineCount, state()->matrix, d->surface);
}
}
@@ -508,10 +408,11 @@ void QDirectFBPaintEngine::drawLines(const QLineF *lines, int lineCount)
return;
}
- if (d->pen != Qt::NoPen) {
+ const QPen &pen = state()->pen;
+ if (pen != Qt::NoPen) {
d->unlock();
- d->setDFBColor(d->pen.color());
- d->drawLines(lines, lineCount);
+ d->setDFBColor(pen.color());
+ ::drawLines<QLineF>(lines, lineCount, state()->matrix, d->surface);
}
}
@@ -542,8 +443,7 @@ void QDirectFBPaintEngine::drawImage(const QRectF &r, const QImage &image,
d->updateClip();
#if !defined QT_NO_DIRECTFB_PREALLOCATED || defined QT_DIRECTFB_IMAGECACHE
if (d->unsupportedCompositionMode
- || d->matrixRotShear
- || d->scale == QDirectFBPaintEnginePrivate::NegativeScale
+ || (d->transformationType & QDirectFBPaintEnginePrivate::BlitUnsupported)
|| !d->dfbCanHandleClip(r)
#ifndef QT_DIRECTFB_IMAGECACHE
|| QDirectFBScreen::getSurfacePixelFormat(image.format()) == DSPF_UNKNOWN
@@ -588,8 +488,9 @@ void QDirectFBPaintEngine::drawPixmap(const QRectF &r, const QPixmap &pixmap,
RASTERFALLBACK(DRAW_PIXMAP, r, pixmap.size(), sr);
d->lock();
QRasterPaintEngine::drawPixmap(r, pixmap, sr);
- } else if (d->unsupportedCompositionMode || !d->dfbCanHandleClip(r) || d->matrixRotShear
- || d->scale == QDirectFBPaintEnginePrivate::NegativeScale) {
+ } else if (d->unsupportedCompositionMode
+ || (d->transformationType & QDirectFBPaintEnginePrivate::BlitUnsupported)
+ || !d->dfbCanHandleClip(r)) {
RASTERFALLBACK(DRAW_PIXMAP, r, pixmap.size(), sr);
const QImage *img = static_cast<QDirectFBPixmapData*>(pixmap.pixmapData())->buffer(DSLF_READ);
d->lock();
@@ -613,30 +514,27 @@ void QDirectFBPaintEngine::drawPixmap(const QPointF &p, const QPixmap &pm)
void QDirectFBPaintEngine::drawTiledPixmap(const QRectF &r,
const QPixmap &pixmap,
- const QPointF &sp)
+ const QPointF &offset)
{
Q_D(QDirectFBPaintEngine);
d->updateClip();
if (pixmap.pixmapData()->classId() != QPixmapData::DirectFBClass) {
- RASTERFALLBACK(DRAW_TILED_PIXMAP, r, pixmap.size(), sp);
+ RASTERFALLBACK(DRAW_TILED_PIXMAP, r, pixmap.size(), offset);
d->lock();
- QRasterPaintEngine::drawTiledPixmap(r, pixmap, sp);
- } else if (d->unsupportedCompositionMode || !d->dfbCanHandleClip(r) || d->matrixRotShear || !sp.isNull()
- || d->scale == QDirectFBPaintEnginePrivate::NegativeScale) {
- RASTERFALLBACK(DRAW_TILED_PIXMAP, r, pixmap.size(), sp);
+ QRasterPaintEngine::drawTiledPixmap(r, pixmap, offset);
+ } else if (d->unsupportedCompositionMode
+ || (d->transformationType & QDirectFBPaintEnginePrivate::BlitUnsupported)
+ || !d->dfbCanHandleClip(r)) {
+ RASTERFALLBACK(DRAW_TILED_PIXMAP, r, pixmap.size(), offset);
const QImage *img = static_cast<QDirectFBPixmapData*>(pixmap.pixmapData())->buffer(DSLF_READ);
d->lock();
QRasterPixmapData *data = new QRasterPixmapData(QPixmapData::PixmapType);
data->fromImage(*img, Qt::AutoColor);
const QPixmap pix(data);
- QRasterPaintEngine::drawTiledPixmap(r, pix, sp);
+ QRasterPaintEngine::drawTiledPixmap(r, pix, offset);
} else {
d->unlock();
- QPixmapData *data = pixmap.pixmapData();
- Q_ASSERT(data->classId() == QPixmapData::DirectFBClass);
- QDirectFBPixmapData *dfbData = static_cast<QDirectFBPixmapData*>(data);
- dfbData->unlockDirectFB();
- d->drawTiledPixmap(r, pixmap);
+ d->drawTiledPixmap(r, pixmap, offset);
}
}
@@ -721,7 +619,9 @@ void QDirectFBPaintEngine::fillRect(const QRectF &rect, const QBrush &brush)
{
Q_D(QDirectFBPaintEngine);
d->updateClip();
- if (!d->unsupportedCompositionMode && d->dfbCanHandleClip(rect) && !d->matrixRotShear) {
+ if (!d->unsupportedCompositionMode
+ && !(d->transformationType & (QDirectFBPaintEnginePrivate::RectsUnsupported))
+ && d->dfbCanHandleClip(rect)) {
switch (brush.style()) {
case Qt::SolidPattern: {
const QColor color = brush.color();
@@ -729,18 +629,21 @@ void QDirectFBPaintEngine::fillRect(const QRectF &rect, const QBrush &brush)
return;
d->unlock();
d->setDFBColor(color);
- const QRect r = d->transform.mapRect(rect).toRect();
+ const QRect r = state()->matrix.mapRect(rect).toRect();
d->surface->FillRectangle(d->surface, r.x(), r.y(),
r.width(), r.height());
return; }
- case Qt::TexturePattern:
- if (state()->brushOrigin == QPointF() && brush.transform().isIdentity()) {
- //could handle certain types of brush.transform() E.g. scale
- d->unlock();
- d->drawTiledPixmap(rect, brush.texture());
- return;
- }
- break;
+ case Qt::TexturePattern: {
+ if (d->transformationType & QDirectFBPaintEnginePrivate::NegativeScale)
+ break;
+
+ const QPixmap texture = brush.texture();
+ if (texture.pixmapData()->classId() != QPixmapData::DirectFBClass)
+ break;
+
+ d->unlock();
+ d->drawTiledPixmap(rect, texture, rect.topLeft() - state()->brushOrigin);
+ return; }
default:
break;
}
@@ -756,51 +659,21 @@ void QDirectFBPaintEngine::fillRect(const QRectF &rect, const QColor &color)
return;
Q_D(QDirectFBPaintEngine);
d->updateClip();
- if (d->unsupportedCompositionMode || !d->dfbCanHandleClip() || d->matrixRotShear) {
+ if (d->unsupportedCompositionMode
+ || (d->transformationType & QDirectFBPaintEnginePrivate::RectsUnsupported)
+ || !d->dfbCanHandleClip()) {
RASTERFALLBACK(FILL_RECT, rect, color, VOID_ARG());
d->lock();
QRasterPaintEngine::fillRect(rect, color);
} else {
d->unlock();
d->setDFBColor(color);
- const QRect r = d->transform.mapRect(rect).toRect();
+ const QRect r = state()->matrix.mapRect(rect).toRect();
d->surface->FillRectangle(d->surface, r.x(), r.y(),
r.width(), r.height());
}
}
-void QDirectFBPaintEngine::drawColorSpans(const QSpan *spans, int count,
- uint color)
-{
- Q_D(QDirectFBPaintEngine);
- color = INV_PREMUL(color);
-
- QVarLengthArray<DFBRegion> lines(count);
- int j = 0;
- for (int i = 0; i < count; ++i) {
- if (spans[i].coverage == 255) {
- lines[j].x1 = spans[i].x;
- lines[j].y1 = spans[i].y;
- lines[j].x2 = spans[i].x + spans[i].len - 1;
- lines[j].y2 = spans[i].y;
- ++j;
- } else {
- DFBSpan span = { spans[i].x, spans[i].len };
- uint c = BYTE_MUL(color, spans[i].coverage);
- // ### how does this play with setDFBColor
- d->surface->SetColor(d->surface,
- qRed(c), qGreen(c), qBlue(c), qAlpha(c));
- d->surface->FillSpans(d->surface, spans[i].y, &span, 1);
- }
- }
- if (j > 0) {
- d->surface->SetColor(d->surface,
- qRed(color), qGreen(color), qBlue(color),
- qAlpha(color));
- d->surface->DrawLines(d->surface, lines.data(), j);
- }
-}
-
void QDirectFBPaintEngine::drawBufferSpan(const uint *buffer, int bufsize,
int x, int y, int length,
uint const_alpha)
@@ -834,9 +707,8 @@ void QDirectFBPaintEngine::initImageCache(int size)
QDirectFBPaintEnginePrivate::QDirectFBPaintEnginePrivate(QDirectFBPaintEngine *p)
: surface(0), antialiased(false), simplePen(false),
- matrixRotShear(false), scale(NoScale), lastLockedHeight(-1),
- fbWidth(-1), fbHeight(-1), opacity(255), dirtyClip(true),
- dfbHandledClip(false), dfbDevice(0), lockedMemory(0),
+ transformationType(0), opacity(255), dirtyClip(true),
+ dfbHandledClip(false), dfbDevice(0),
unsupportedCompositionMode(false), q(p)
{
fb = QDirectFBScreen::instance()->dfb();
@@ -877,12 +749,9 @@ void QDirectFBPaintEnginePrivate::lock()
// 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) {
+ if (dfbDevice->lockFlags() != (DSLF_WRITE|DSLF_READ)) {
+ dfbDevice->lockDirectFB(DSLF_READ|DSLF_WRITE);
prepare(dfbDevice);
- lastLockedHeight = dfbDevice->height();
- lockedMemory = dfbDevice->memory();
}
}
@@ -890,32 +759,26 @@ void QDirectFBPaintEnginePrivate::unlock()
{
Q_ASSERT(dfbDevice);
dfbDevice->unlockDirectFB();
- lockedMemory = 0;
}
-void QDirectFBPaintEnginePrivate::setTransform(const QTransform &m)
+void QDirectFBPaintEnginePrivate::setTransform(const QTransform &transform)
{
- transform = m;
- matrixRotShear = (transform.m12() != 0 || transform.m21() != 0);
+ transformationType = transform.type();
if (qMin(transform.m11(), transform.m22()) < 0) {
- scale = NegativeScale;
- } else if (transform.m11() != 1 || transform.m22() != 1) {
- scale = Scaled;
- } else {
- scale = NoScale;
+ transformationType |= QDirectFBPaintEnginePrivate::NegativeScale;
}
+ setPen(q->state()->pen);
}
-void QDirectFBPaintEnginePrivate::setPen(const QPen &p)
+void QDirectFBPaintEnginePrivate::setPen(const QPen &pen)
{
- pen = p;
if (pen.style() == Qt::NoPen) {
simplePen = true;
} else if (pen.style() == Qt::SolidLine
&& !antialiased
&& pen.brush().style() == Qt::SolidPattern
&& pen.widthF() <= 1.0
- && (scale == NoScale || pen.isCosmetic())) {
+ && (transformationType < QTransform::TxScale || pen.isCosmetic())) {
simplePen = true;
} else {
simplePen = false;
@@ -927,12 +790,6 @@ void QDirectFBPaintEnginePrivate::setCompositionMode(QPainter::CompositionMode m
unsupportedCompositionMode = (mode != QPainter::CompositionMode_SourceOver);
}
-
-void QDirectFBPaintEnginePrivate::setOpacity(quint8 op)
-{
- opacity = op;
-}
-
void QDirectFBPaintEnginePrivate::setRenderHints(QPainter::RenderHints hints)
{
const bool old = antialiased;
@@ -952,6 +809,13 @@ void QDirectFBPaintEnginePrivate::prepareForBlit(bool alpha)
surface->SetBlittingFlags(surface, DFBSurfaceBlittingFlags(blittingFlags));
}
+static inline uint ALPHA_MUL(uint x, uint a)
+{
+ uint t = x * a;
+ t = ((t + (t >> 8) + 0x80) >> 8) & 0xff;
+ return t;
+}
+
void QDirectFBPaintEnginePrivate::setDFBColor(const QColor &color)
{
Q_ASSERT(surface);
@@ -962,67 +826,6 @@ void QDirectFBPaintEnginePrivate::setDFBColor(const QColor &color)
surface->SetDrawingFlags(surface, alpha == 255 ? DSDRAW_NOFX : DSDRAW_BLEND);
}
-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
@@ -1061,7 +864,7 @@ IDirectFBSurface *QDirectFBPaintEnginePrivate::getSurface(const QImage &img, boo
void QDirectFBPaintEnginePrivate::blit(const QRectF &dest, IDirectFBSurface *s, const QRectF &src)
{
const QRect sr = src.toRect();
- const QRect dr = transform.mapRect(dest).toRect();
+ const QRect dr = q->state()->matrix.mapRect(dest).toRect();
if (dr.isEmpty())
return;
const DFBRectangle sRect = { sr.x(), sr.y(), sr.width(), sr.height() };
@@ -1077,55 +880,107 @@ void QDirectFBPaintEnginePrivate::blit(const QRectF &dest, IDirectFBSurface *s,
DirectFBError("QDirectFBPaintEngine::drawPixmap()", result);
}
-void QDirectFBPaintEnginePrivate::drawTiledPixmap(const QRectF &dest,
- const QPixmap &pixmap)
+static inline qreal fixCoord(qreal rect_pos, qreal pixmapSize, qreal offset)
+{
+ qreal pos = rect_pos - offset;
+ while (pos > rect_pos)
+ pos -= pixmapSize;
+ while (pos + pixmapSize < rect_pos)
+ pos += pixmapSize;
+ return pos;
+}
+
+void QDirectFBPaintEnginePrivate::drawTiledPixmap(const QRectF &dest, const QPixmap &pixmap, const QPointF &off)
{
+ Q_ASSERT(!dirtyClip);
+ Q_ASSERT(!(transformationType & BlitUnsupported));
+ const QTransform &transform = q->state()->matrix;
+ const QRect destinationRect = transform.mapRect(dest).toRect().normalized();
+ QRect newClip = destinationRect;
+ if (!currentClip.isEmpty())
+ newClip &= currentClip;
+
+ if (newClip.isNull())
+ return;
+
+ const DFBRegion clip = {
+ newClip.x(),
+ newClip.y(),
+ newClip.x() + newClip.width() - 1,
+ newClip.y() + newClip.height() - 1
+ };
+ surface->SetClip(surface, &clip);
+
+ QPointF offset = off;
+ Q_ASSERT(transform.type() <= QTransform::TxScale);
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);
+ dfbData->unlockDirectFB();
+ const QSize pixmapSize = dfbData->size();
+ IDirectFBSurface *sourceSurface = dfbData->directFBSurface();
+ if (transform.isScaling()) {
+ Q_ASSERT(qMin(transform.m11(), transform.m22()) >= 0);
+ offset.rx() *= transform.m11();
+ offset.ry() *= transform.m22();
+
+ const QSizeF mappedSize(pixmapSize.width() * transform.m11(), pixmapSize.height() * transform.m22());
+ qreal y = ::fixCoord(destinationRect.y(), mappedSize.height(), offset.y());
+ const qreal startX = ::fixCoord(destinationRect.x(), mappedSize.width(), offset.x());
+ while (y <= destinationRect.bottom()) {
+ qreal x = startX;
+ while (x <= destinationRect.right()) {
+ const DFBRectangle destination = { qRound(x), qRound(y), mappedSize.width(), mappedSize.height() };
+ surface->StretchBlit(surface, sourceSurface, 0, &destination);
+ x += mappedSize.width();
}
+ y += mappedSize.height();
}
- 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;
- }
+ qreal y = ::fixCoord(destinationRect.y(), pixmapSize.height(), offset.y());
+ const qreal startX = ::fixCoord(destinationRect.x(), pixmapSize.width(), offset.x());
+ int horizontal = qMax(1, destinationRect.width() / pixmapSize.width()) + 1;
+ if (startX != destinationRect.x())
+ ++horizontal;
+ int vertical = qMax(1, destinationRect.height() / pixmapSize.height()) + 1;
+ if (y != destinationRect.y())
+ ++vertical;
+
+ const int maxCount = (vertical * horizontal);
+ QVarLengthArray<DFBRectangle, 16> sourceRects(maxCount);
+ QVarLengthArray<DFBPoint, 16> points(maxCount);
+
+ int i = 0;
+ while (y <= destinationRect.bottom()) {
+ Q_ASSERT(i < maxCount);
+ qreal x = startX;
+ while (x <= destinationRect.right()) {
+ points[i].x = qRound(x);
+ points[i].y = qRound(y);
+ sourceRects[i].x = 0;
+ sourceRects[i].y = 0;
+ sourceRects[i].w = int(pixmapSize.width());
+ sourceRects[i].h = int(pixmapSize.height());
+ x += pixmapSize.width();
+ ++i;
}
+ y += pixmapSize.height();
}
+ surface->BatchBlit(surface, sourceSurface, sourceRects.constData(), points.constData(), i);
}
- if (result != DFB_OK)
- DirectFBError("QDirectFBPaintEngine::drawTiledPixmap()", result);
+ if (currentClip.isEmpty()) {
+ surface->SetClip(surface, 0);
+ } else {
+ const DFBRegion clip = {
+ currentClip.x(),
+ currentClip.y(),
+ currentClip.x() + currentClip.width(),
+ currentClip.y() + currentClip.height()
+ };
+ surface->SetClip(surface, &clip);
+ }
}
void QDirectFBPaintEnginePrivate::updateClip()
@@ -1133,6 +988,7 @@ void QDirectFBPaintEnginePrivate::updateClip()
if (!dirtyClip)
return;
+ currentClip = QRect();
const QClipData *clipData = clip();
if (!clipData || !clipData->enabled) {
surface->SetClip(surface, NULL);
@@ -1145,6 +1001,8 @@ void QDirectFBPaintEnginePrivate::updateClip()
clipData->clipRect.y() + clipData->clipRect.height()
};
surface->SetClip(surface, &r);
+ currentClip = clipData->clipRect.normalized();
+ // ### is this guaranteed to always be normalized?
dfbHandledClip = true;
} else if (clipData->hasRegionClip && ignoreSystemClip && clipData->clipRegion == systemClip) {
dfbHandledClip = true;
@@ -1161,4 +1019,126 @@ void QDirectFBPaintEnginePrivate::systemStateChanged()
QRasterPaintEnginePrivate::systemStateChanged();
}
+IDirectFBSurface *SurfaceCache::getSurface(const uint *buf, int size)
+{
+ if (buffer == buf && bufsize == size)
+ return surface;
+
+ clear();
+
+ const DFBSurfaceDescription 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;
+}
+
+void SurfaceCache::clear()
+{
+ if (surface && QDirectFBScreen::instance())
+ QDirectFBScreen::instance()->releaseDFBSurface(surface);
+ surface = 0;
+ buffer = 0;
+ bufsize = 0;
+}
+
+
+static inline QRect mapRect(const QTransform &transform, const QRect &rect) { return transform.mapRect(rect); }
+static inline QRect mapRect(const QTransform &transform, const QRectF &rect) { return transform.mapRect(rect).toRect(); }
+static inline QLine map(const QTransform &transform, const QLine &line) { return transform.map(line); }
+static inline QLine map(const QTransform &transform, const QLineF &line) { return transform.map(line).toLine(); }
+template <class T>
+static inline void drawLines(const T *lines, int n, const QTransform &transform, IDirectFBSurface *surface)
+{
+ if (n == 1) {
+ const QLine l = ::map(transform, lines[0]);
+ surface->DrawLine(surface, l.x1(), l.y1(), l.x2(), l.y2());
+ } else {
+ QVarLengthArray<DFBRegion, 32> lineArray(n);
+ for (int i=0; i<n; ++i) {
+ const QLine l = ::map(transform, lines[i]);
+ lineArray[i].x1 = l.x1();
+ lineArray[i].y1 = l.y1();
+ lineArray[i].x2 = l.x2();
+ lineArray[i].y2 = l.y2();
+ }
+ surface->DrawLines(surface, lineArray.constData(), n);
+ }
+}
+
+template <class T>
+static inline void fillRects(const T *rects, int n, const QTransform &transform, IDirectFBSurface *surface)
+{
+ if (n == 1) {
+ const QRect r = ::mapRect(transform, rects[0]);
+ surface->FillRectangle(surface, r.x(), r.y(), r.width(), r.height());
+ } else {
+ QVarLengthArray<DFBRectangle, 32> rectArray(n);
+ for (int i=0; i<n; ++i) {
+ const QRect r = ::mapRect(transform, rects[i]);
+ rectArray[i].x = r.x();
+ rectArray[i].y = r.y();
+ rectArray[i].w = r.width();
+ rectArray[i].h = r.height();
+ }
+ surface->FillRectangles(surface, rectArray.constData(), n);
+ }
+}
+
+template <class T>
+static inline void drawRects(const T *rects, int n, const QTransform &transform, IDirectFBSurface *surface)
+{
+ for (int i=0; i<n; ++i) {
+ const QRect r = ::mapRect(transform, rects[i]);
+ surface->DrawRectangle(surface, r.x(), r.y(), r.width(), r.height());
+ }
+}
+
+#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,
+ uint transformationType, bool simplePen,
+ bool dfbHandledClip, bool unsupportedCompositionMode,
+ 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 << QString("transformationType 0x%1").arg(transformationType, 3, 16, QLatin1Char('0'))
+ << "simplePen" << simplePen
+ << "dfbHandledClip" << dfbHandledClip
+ << "unsupportedCompositionMode" << unsupportedCompositionMode;
+
+ 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
+
+
#endif // QT_NO_DIRECTFB