diff options
Diffstat (limited to 'src/plugins/gfxdrivers/directfb')
11 files changed, 510 insertions, 528 deletions
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbkeyboard.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbkeyboard.cpp index ed59db8..b5376b1 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbkeyboard.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbkeyboard.cpp @@ -78,7 +78,7 @@ private: DFBEvent event; int bytesRead; -private slots: +private Q_SLOTS: void readKeyboardData(); }; diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbmouse.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbmouse.cpp index 15fb6f4..142993d 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbmouse.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbmouse.cpp @@ -71,7 +71,7 @@ private: DFBEvent event; uint bytesRead; -private slots: +private Q_SLOTS: void readMouseData(); }; @@ -101,7 +101,7 @@ QDirectFBMouseHandlerPrivate::QDirectFBMouseHandlerPrivate(QDirectFBMouseHandler #endif DFBInputDeviceCapabilities caps; - caps = DFBInputDeviceCapabilities(DICAPS_BUTTONS | DICAPS_AXES); + caps = DICAPS_BUTTONS | DICAPS_AXES; result = fb->CreateInputEventBuffer(fb, caps, DFB_TRUE, &eventBuffer); if (result != DFB_OK) { DirectFBError("QDirectFBMouseHandler: " diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.cpp index 905fec3..86e92f7 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.cpp @@ -56,20 +56,17 @@ IDirectFBSurface *QDirectFBPaintDevice::directFBSurface() const } -void QDirectFBPaintDevice::lockDirectFB(uint flags) +void QDirectFBPaintDevice::lockDirectFB(DFBSurfaceLockFlags flags) { if (!(lock & flags)) { if (lock) unlockDirectFB(); - if ((mem = QDirectFBScreen::lockSurface(dfbSurface, flags, &bpl))) { - const QSize s = size(); - lockedImage = new QImage(mem, s.width(), s.height(), bpl, - QDirectFBScreen::getImageFormat(dfbSurface)); - lock = flags; - Q_ASSERT(mem); - } else { - lock = 0; - } + mem = QDirectFBScreen::lockSurface(dfbSurface, flags, &bpl); + Q_ASSERT(mem); + const QSize s = size(); + lockedImage = new QImage(mem, s.width(), s.height(), bpl, + QDirectFBScreen::getImageFormat(dfbSurface)); + lock = flags; } } @@ -83,17 +80,12 @@ void QDirectFBPaintDevice::unlockDirectFB() delete lockedImage; lockedImage = 0; mem = 0; - lock = 0; + lock = DFBSurfaceLockFlags(0); } void *QDirectFBPaintDevice::memory() const { - if (lock != (DSLF_READ|DSLF_WRITE)) { - QDirectFBPaintDevice *that = const_cast<QDirectFBPaintDevice*>(this); - that->lockDirectFB(DSLF_READ|DSLF_WRITE); - Q_ASSERT(that->lockedImage); - } return mem; } diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.h b/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.h index 32c49bb..248a15b 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.h +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.h @@ -51,14 +51,14 @@ QT_BEGIN_HEADER QT_MODULE(Gui) // Inherited by both window surface and pixmap -class QDirectFBPaintDevice : public QCustomRasterPaintDevice + class QDirectFBPaintDevice : public QCustomRasterPaintDevice { public: ~QDirectFBPaintDevice(); IDirectFBSurface *directFBSurface() const; - void lockDirectFB(uint flags); + void lockDirectFB(DFBSurfaceLockFlags lock); void unlockDirectFB(); // Reimplemented from QCustomRasterPaintDevice: @@ -67,16 +67,12 @@ public: int bytesPerLine() const; QSize size() const; int metric(QPaintDevice::PaintDeviceMetric metric) const; - uint lockFlags() const { return lock; } + DFBSurfaceLockFlags lockFlags() const { return lock; } protected: // Shouldn't create QDirectFBPaintDevice by itself but only sub-class it: QDirectFBPaintDevice(QDirectFBScreen *scr = QDirectFBScreen::instance()) - : QCustomRasterPaintDevice(0), - dfbSurface(0), - lockedImage(0), - screen(scr), - lock(0), - mem(0) + : QCustomRasterPaintDevice(0), dfbSurface(0), lockedImage(0), screen(scr), + lock(DFBSurfaceLockFlags(0)), mem(0) {} inline int dotsPerMeterX() const @@ -92,11 +88,11 @@ protected: QImage *lockedImage; QDirectFBScreen *screen; int bpl; - uint lock; + DFBSurfaceLockFlags lock; uchar *mem; private: Q_DISABLE_COPY(QDirectFBPaintDevice) -}; + }; QT_END_HEADER 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 ®ion) -{ - 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 diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.h b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.h index 8c5877b..6148b14 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.h +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.h @@ -56,43 +56,40 @@ class QDirectFBPaintEngine : public QRasterPaintEngine Q_DECLARE_PRIVATE(QDirectFBPaintEngine) public: QDirectFBPaintEngine(QPaintDevice *device); - ~QDirectFBPaintEngine(); + virtual ~QDirectFBPaintEngine(); - bool begin(QPaintDevice *device); - bool end(); + virtual bool begin(QPaintDevice *device); + virtual bool end(); - void drawRects(const QRect *rects, int rectCount); - void drawRects(const QRectF *rects, int rectCount); + virtual void drawRects(const QRect *rects, int rectCount); + virtual void drawRects(const QRectF *rects, int rectCount); - void fillRect(const QRectF &r, const QBrush &brush); - void fillRect(const QRectF &r, const QColor &color); + virtual void fillRect(const QRectF &r, const QBrush &brush); + virtual void fillRect(const QRectF &r, const QColor &color); - void drawLines(const QLine *line, int lineCount); - void drawLines(const QLineF *line, int lineCount); + virtual void drawLines(const QLine *line, int lineCount); + virtual void drawLines(const QLineF *line, int lineCount); - void drawImage(const QPointF &p, const QImage &img); - void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr, - Qt::ImageConversionFlags falgs = Qt::AutoColor); + virtual void drawImage(const QPointF &p, const QImage &img); + virtual void drawImage(const QRectF &r, const QImage &pm, const QRectF &sr, + Qt::ImageConversionFlags falgs = Qt::AutoColor); - void drawPixmap(const QPointF &p, const QPixmap &pm); - void drawPixmap(const QRectF &r, const QPixmap &pixmap, const QRectF &sr); - void drawTiledPixmap(const QRectF &r, const QPixmap &pm, const QPointF &sr); + virtual void drawPixmap(const QPointF &p, const QPixmap &pm); + virtual void drawPixmap(const QRectF &r, const QPixmap &pixmap, const QRectF &sr); + virtual void drawTiledPixmap(const QRectF &r, const QPixmap &pm, const QPointF &sr); - void drawColorSpans(const QSpan *spans, int count, uint color); - void drawBufferSpan(const uint *buffer, int bufsize, - int x, int y, int length, uint const_alpha); + virtual void drawBufferSpan(const uint *buffer, int bufsize, + int x, int y, int length, uint const_alpha); - - // The following methods simply lock the surface & call the base implementation - void stroke(const QVectorPath &path, const QPen &pen); - void drawPath(const QPainterPath &path); - void drawPoints(const QPointF *points, int pointCount); - void drawPoints(const QPoint *points, int pointCount); - void drawEllipse(const QRectF &rect); - void drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode); - void drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode); - void drawTextItem(const QPointF &p, const QTextItem &textItem); - void fill(const QVectorPath &path, const QBrush &brush); + virtual void stroke(const QVectorPath &path, const QPen &pen); + virtual void drawPath(const QPainterPath &path); + virtual void drawPoints(const QPointF *points, int pointCount); + virtual void drawPoints(const QPoint *points, int pointCount); + virtual void drawEllipse(const QRectF &rect); + virtual void drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode); + virtual void drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode); + virtual void drawTextItem(const QPointF &p, const QTextItem &textItem); + virtual void fill(const QVectorPath &path, const QBrush &brush); virtual void clipEnabledChanged(); virtual void penChanged(); diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp index c9d5d7c..52e85ba 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp @@ -345,6 +345,10 @@ QImage QDirectFBPixmapData::toImage() const if (!dfbSurface) return QImage(); +#if 0 + // In later versions of DirectFB one can set a flag to tell + // DirectFB not to move the surface to videomemory. When that + // happens we can use this (hopefully faster) codepath #ifndef QT_NO_DIRECTFB_PREALLOCATED QImage ret(w, h, QDirectFBScreen::getImageFormat(dfbSurface)); if (IDirectFBSurface *imgSurface = screen->createDFBSurface(ret, QDirectFBScreen::DontTrackSurface)) { @@ -362,6 +366,7 @@ QImage QDirectFBPixmapData::toImage() const return ret; } #endif +#endif QDirectFBPixmapData *that = const_cast<QDirectFBPixmapData*>(this); const QImage *img = that->buffer(); @@ -385,7 +390,7 @@ QImage *QDirectFBPixmapData::buffer() return lockedImage; } -QImage * QDirectFBPixmapData::buffer(uint lockFlags) +QImage * QDirectFBPixmapData::buffer(DFBSurfaceLockFlags lockFlags) { lockDirectFB(lockFlags); return lockedImage; diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.h b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.h index e81aef4..0204061 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.h +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.h @@ -71,7 +71,7 @@ public: virtual QImage *buffer(); virtual int metric(QPaintDevice::PaintDeviceMetric m) const {return QDirectFBPaintDevice::metric(m);} - QImage *buffer(uint lockFlags); + QImage *buffer(DFBSurfaceLockFlags lockFlags); // Pure virtual in QPixmapData, so re-implement here and delegate to QDirectFBPaintDevice inline QImage::Format pixelFormat() const { return format; } diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp index 76064ad..0928643 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp @@ -208,7 +208,7 @@ IDirectFBSurface *QDirectFBScreen::createDFBSurface(const QSize &size, { DFBSurfaceDescription desc; memset(&desc, 0, sizeof(DFBSurfaceDescription)); - desc.flags = DFBSurfaceDescriptionFlags(DSDESC_WIDTH|DSDESC_HEIGHT); + desc.flags |= DSDESC_WIDTH|DSDESC_HEIGHT; if (!QDirectFBScreen::initSurfaceDescriptionPixelFormat(&desc, format)) return 0; desc.width = size.width(); @@ -226,13 +226,15 @@ IDirectFBSurface *QDirectFBScreen::createDFBSurface(DFBSurfaceDescription desc, return 0; } - if (d_ptr->directFBFlags & VideoOnly && !(desc.flags & DSDESC_PREALLOCATED)) { + if (d_ptr->directFBFlags & VideoOnly + && !(desc.flags & DSDESC_PREALLOCATED) + && (!(desc.flags & DSDESC_CAPS) || !(desc.caps & DSCAPS_SYSTEMONLY))) { // Add the video only capability. This means the surface will be created in video ram if (!(desc.flags & DSDESC_CAPS)) { desc.caps = DSCAPS_VIDEOONLY; - desc.flags = DFBSurfaceDescriptionFlags(desc.flags | DSDESC_CAPS); + desc.flags |= DSDESC_CAPS; } else { - desc.caps = DFBSurfaceCapabilities(desc.caps | DSCAPS_VIDEOONLY); + desc.caps |= DSCAPS_VIDEOONLY; } result = d_ptr->dfb->CreateSurface(d_ptr->dfb, &desc, &newSurface); if (result != DFB_OK @@ -247,11 +249,11 @@ IDirectFBSurface *QDirectFBScreen::createDFBSurface(DFBSurfaceDescription desc, desc.preallocated[0].data, desc.preallocated[0].pitch, DirectFBErrorString(result)); } - desc.caps = DFBSurfaceCapabilities(desc.caps & ~DSCAPS_VIDEOONLY); + desc.caps &= ~DSCAPS_VIDEOONLY; } if (d_ptr->directFBFlags & SystemOnly) - desc.caps = DFBSurfaceCapabilities(desc.caps | DSCAPS_SYSTEMONLY); + desc.caps |= DSCAPS_SYSTEMONLY; if (!newSurface) result = d_ptr->dfb->CreateSurface(d_ptr->dfb, &desc, &newSurface); @@ -459,20 +461,16 @@ DFBSurfaceDescription QDirectFBScreen::getSurfaceDescription(const QImage &image const DFBSurfacePixelFormat format = getSurfacePixelFormat(image.format()); if (format == DSPF_UNKNOWN || image.isNull()) { - description.flags = DFBSurfaceDescriptionFlags(0); + description.flags = DSDESC_NONE; return description; } - description.flags = DFBSurfaceDescriptionFlags(DSDESC_WIDTH - | DSDESC_HEIGHT -#ifndef QT_NO_DIRECTFB_PREALLOCATED - | DSDESC_PREALLOCATED -#endif - | DSDESC_PIXELFORMAT); + description.flags = DSDESC_WIDTH|DSDESC_HEIGHT|DSDESC_PIXELFORMAT; QDirectFBScreen::initSurfaceDescriptionPixelFormat(&description, image.format()); description.width = image.width(); description.height = image.height(); #ifndef QT_NO_DIRECTFB_PREALLOCATED + description.flags |= DSDESC_PREALLOCATED; description.preallocated[0].data = (void*)(image.bits()); description.preallocated[0].pitch = image.bytesPerLine(); description.preallocated[1].data = 0; @@ -491,11 +489,7 @@ DFBSurfaceDescription QDirectFBScreen::getSurfaceDescription(const uint *buffer, DFBSurfaceDescription description; memset(&description, 0, sizeof(DFBSurfaceDescription)); - description.flags = DFBSurfaceDescriptionFlags(DSDESC_CAPS - | DSDESC_WIDTH - | DSDESC_HEIGHT - | DSDESC_PIXELFORMAT - | DSDESC_PREALLOCATED); + description.flags = DSDESC_CAPS|DSDESC_WIDTH|DSDESC_HEIGHT|DSDESC_PIXELFORMAT|DSDESC_PREALLOCATED; description.caps = DSCAPS_PREMULTIPLIED; description.width = length; description.height = 1; @@ -504,8 +498,7 @@ DFBSurfaceDescription QDirectFBScreen::getSurfaceDescription(const uint *buffer, description.preallocated[0].pitch = length * sizeof(uint); description.preallocated[1].data = 0; description.preallocated[1].pitch = 0; - - return description; +return description; } #ifndef QT_NO_DIRECTFB_PALETTE @@ -727,19 +720,19 @@ void QDirectFBScreenPrivate::setFlipFlags(const QStringList &args) flipFlags = DSFLIP_NONE; foreach(const QString &flip, flips) { if (flip == QLatin1String("wait")) - flipFlags = DFBSurfaceFlipFlags(flipFlags | DSFLIP_WAIT); + flipFlags |= DSFLIP_WAIT; else if (flip == QLatin1String("blit")) - flipFlags = DFBSurfaceFlipFlags(flipFlags | DSFLIP_BLIT); + flipFlags |= DSFLIP_BLIT; else if (flip == QLatin1String("onsync")) - flipFlags = DFBSurfaceFlipFlags(flipFlags | DSFLIP_ONSYNC); + flipFlags |= DSFLIP_ONSYNC; else if (flip == QLatin1String("pipeline")) - flipFlags = DFBSurfaceFlipFlags(flipFlags | DSFLIP_PIPELINE); + flipFlags |= DSFLIP_PIPELINE; else qWarning("QDirectFBScreen: Unknown flip argument: %s", qPrintable(flip)); } } else { - flipFlags = DFBSurfaceFlipFlags(DSFLIP_BLIT); + flipFlags = DSFLIP_BLIT; } } @@ -751,7 +744,12 @@ QPixmapData *QDirectFBScreenPrivate::createPixmapData(QPixmapData::PixelType typ return new QDirectFBPixmapData(type); } -#ifndef QT_NO_DEBUG +#ifdef QT_NO_DEBUG +struct FlagDescription; +static const FlagDescription *accelerationDescriptions = 0; +static const FlagDescription *blitDescriptions = 0; +static const FlagDescription *drawDescriptions = 0; +#else struct FlagDescription { const char *name; uint flag; @@ -928,13 +926,13 @@ bool QDirectFBScreen::connect(const QString &displaySpec) DFBSurfaceDescription description; memset(&description, 0, sizeof(DFBSurfaceDescription)); - description.flags = DFBSurfaceDescriptionFlags(DSDESC_CAPS); + description.flags = DSDESC_CAPS; if (::setIntOption(displayArgs, QLatin1String("width"), &description.width)) - description.flags = DFBSurfaceDescriptionFlags(description.flags | DSDESC_WIDTH); + description.flags |= DSDESC_WIDTH; if (::setIntOption(displayArgs, QLatin1String("height"), &description.height)) - description.flags = DFBSurfaceDescriptionFlags(description.flags | DSDESC_HEIGHT); + description.flags |= DSDESC_HEIGHT; - uint caps = DSCAPS_PRIMARY|DSCAPS_DOUBLE; + description.caps = DSCAPS_PRIMARY|DSCAPS_DOUBLE; struct { const char *name; const DFBSurfaceCapabilities cap; @@ -948,14 +946,13 @@ bool QDirectFBScreen::connect(const QString &displaySpec) }; for (int i=0; capabilities[i].name; ++i) { if (displayArgs.contains(QString::fromLatin1(capabilities[i].name), Qt::CaseInsensitive)) - caps |= capabilities[i].cap; + description.caps |= capabilities[i].cap; } if (displayArgs.contains(QLatin1String("forcepremultiplied"), Qt::CaseInsensitive)) { - caps |= DSCAPS_PREMULTIPLIED; + description.caps |= DSCAPS_PREMULTIPLIED; } - description.caps = DFBSurfaceCapabilities(caps); // We don't track the primary surface as it's released in disconnect d_ptr->dfbSurface = createDFBSurface(description, DontTrackSurface); if (!d_ptr->dfbSurface) { @@ -1213,10 +1210,10 @@ void QDirectFBScreen::compose(const QRegion ®ion) DFBSurfaceBlittingFlags flags = DSBLIT_NOFX; if (!win->isOpaque()) { - flags = DFBSurfaceBlittingFlags(flags | DSBLIT_BLEND_ALPHACHANNEL); + flags |= DSBLIT_BLEND_ALPHACHANNEL; const uint opacity = win->opacity(); if (opacity < 255) { - flags = DFBSurfaceBlittingFlags(flags | DSBLIT_BLEND_COLORALPHA); + flags |= DSBLIT_BLEND_COLORALPHA; d_ptr->dfbSurface->SetColor(d_ptr->dfbSurface, 0xff, 0xff, 0xff, opacity); } } @@ -1356,14 +1353,14 @@ bool QDirectFBScreen::initSurfaceDescriptionPixelFormat(DFBSurfaceDescription *d const DFBSurfacePixelFormat pixelformat = QDirectFBScreen::getSurfacePixelFormat(format); if (pixelformat == DSPF_UNKNOWN) return false; - description->flags = DFBSurfaceDescriptionFlags(description->flags | DSDESC_PIXELFORMAT); + description->flags |= DSDESC_PIXELFORMAT; description->pixelformat = pixelformat; if (QDirectFBScreen::isPremultiplied(format)) { if (!(description->flags & DSDESC_CAPS)) { description->caps = DSCAPS_PREMULTIPLIED; - description->flags = DFBSurfaceDescriptionFlags(description->flags | DSDESC_CAPS); + description->flags |= DSDESC_CAPS; } else { - description->caps = DFBSurfaceCapabilities(description->caps | DSCAPS_PREMULTIPLIED); + description->caps |= DSCAPS_PREMULTIPLIED; } } return true; diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h index 4239156..69b09e9 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h +++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h @@ -44,6 +44,7 @@ #include <QtGui/qscreen_qws.h> #include <directfb.h> +#include <directfb_version.h> QT_BEGIN_HEADER @@ -51,8 +52,24 @@ QT_MODULE(Gui) #define Q_DIRECTFB_VERSION ((DIRECTFB_MAJOR_VERSION << 16) | (DIRECTFB_MINOR_VERION << 8) | DIRECTFB_MICRO_VERSION) -class QDirectFBScreenPrivate; +#include <QDebug> +#define DIRECTFB_DECLARE_OPERATORS_FOR_FLAGS(F) \ + static inline F operator~(F f) { return F(~int(f)); } \ + static inline F operator&(F left, F right) { return F(int(left) & int(right)); } \ + static inline F operator|(F left, F right) { return F(int(left) | int(right)); } \ + static inline F &operator|=(F &left, F right) { left = (left | right); return left; } \ + static inline F &operator&=(F &left, F right) { left = (left & right); return left; } + +DIRECTFB_DECLARE_OPERATORS_FOR_FLAGS(DFBInputDeviceCapabilities); +DIRECTFB_DECLARE_OPERATORS_FOR_FLAGS(DFBWindowDescriptionFlags); +DIRECTFB_DECLARE_OPERATORS_FOR_FLAGS(DFBSurfaceDescriptionFlags); +DIRECTFB_DECLARE_OPERATORS_FOR_FLAGS(DFBSurfaceCapabilities); +DIRECTFB_DECLARE_OPERATORS_FOR_FLAGS(DFBSurfaceLockFlags); +DIRECTFB_DECLARE_OPERATORS_FOR_FLAGS(DFBSurfaceBlittingFlags); +DIRECTFB_DECLARE_OPERATORS_FOR_FLAGS(DFBSurfaceDrawingFlags); +DIRECTFB_DECLARE_OPERATORS_FOR_FLAGS(DFBSurfaceFlipFlags); +class QDirectFBScreenPrivate; class Q_GUI_EXPORT QDirectFBScreen : public QScreen { public: diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp index 86ee62c..7dcf398 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp @@ -106,18 +106,16 @@ void QDirectFBWindowSurface::createWindow() qFatal("QDirectFBWindowSurface: Unable to get primary display layer!"); DFBWindowDescription description; - description.caps = DFBWindowCapabilities(DWCAPS_NODECORATION); - description.flags = DFBWindowDescriptionFlags(DWDESC_CAPS - |DWDESC_SURFACE_CAPS - |DWDESC_PIXELFORMAT); + description.caps = DWCAPS_NODECORATION; + description.flags = DWDESC_CAPS|DWDESC_SURFACE_CAPS|DWDESC_PIXELFORMAT; description.surface_caps = DSCAPS_NONE; if (screen->directFBFlags() & QDirectFBScreen::VideoOnly) - description.surface_caps = DFBSurfaceCapabilities(description.surface_caps|DSCAPS_VIDEOONLY); + description.surface_caps |= DSCAPS_VIDEOONLY; const QImage::Format format = screen->pixelFormat(); description.pixelformat = QDirectFBScreen::getSurfacePixelFormat(format); if (QDirectFBScreen::isPremultiplied(format)) - description.surface_caps = DFBSurfaceCapabilities(DSCAPS_PREMULTIPLIED|description.caps); + description.surface_caps = DSCAPS_PREMULTIPLIED; DFBResult result = layer->CreateWindow(layer, &description, &dfbWindow); if (result != DFB_OK) @@ -370,7 +368,7 @@ void QDirectFBWindowSurface::flush(QWidget *widget, const QRegion ®ion, } else { if (!boundingRectFlip && region.numRects() > 1) { const QVector<QRect> rects = region.rects(); - const DFBSurfaceFlipFlags nonWaitFlags = DFBSurfaceFlipFlags(flipFlags & ~DSFLIP_WAIT); + const DFBSurfaceFlipFlags nonWaitFlags = flipFlags & ~DSFLIP_WAIT; for (int i=0; i<rects.size(); ++i) { const QRect &r = rects.at(i); const DFBRegion dfbReg = { r.x() + offset.x(), r.y() + offset.y(), |