diff options
author | Bradley T. Hughes <bradley.hughes@nokia.com> | 2009-05-08 08:47:27 (GMT) |
---|---|---|
committer | Bradley T. Hughes <bradley.hughes@nokia.com> | 2009-05-08 08:47:27 (GMT) |
commit | f17c21cec25f40991865343c5f9c3e838e13d5d3 (patch) | |
tree | 616d8582e9817c96d98bf1a645aee76bd4b21598 /src/plugins/gfxdrivers | |
parent | 0822e845b2678ab626cd5fe9919364188c06a70e (diff) | |
parent | 04975e4a594af999600e175f65869f615f5e9740 (diff) | |
download | Qt-f17c21cec25f40991865343c5f9c3e838e13d5d3.zip Qt-f17c21cec25f40991865343c5f9c3e838e13d5d3.tar.gz Qt-f17c21cec25f40991865343c5f9c3e838e13d5d3.tar.bz2 |
Merge branch 'master' of git@scm.dev.nokia.troll.no:qt/qt into windows-7-multitouch
Diffstat (limited to 'src/plugins/gfxdrivers')
15 files changed, 752 insertions, 713 deletions
diff --git a/src/plugins/gfxdrivers/directfb/directfb.pro b/src/plugins/gfxdrivers/directfb/directfb.pro index 67f5d61..5c60b2f 100644 --- a/src/plugins/gfxdrivers/directfb/directfb.pro +++ b/src/plugins/gfxdrivers/directfb/directfb.pro @@ -6,6 +6,7 @@ QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/gfxdrivers # These defines might be necessary if your DirectFB driver doesn't # support all of the DirectFB API. # +#DEFINES += QT_DIRECTFB_IMAGECACHE #DEFINES += QT_NO_DIRECTFB_WM #DEFINES += QT_NO_DIRECTFB_LAYER #DEFINES += QT_NO_DIRECTFB_PALETTE @@ -22,7 +23,7 @@ target.path = $$[QT_INSTALL_PLUGINS]/gfxdrivers INSTALLS += target HEADERS = qdirectfbscreen.h \ - qdirectfbsurface.h \ + qdirectfbwindowsurface.h \ qdirectfbpaintengine.h \ qdirectfbpaintdevice.h \ qdirectfbpixmap.h \ @@ -31,7 +32,7 @@ HEADERS = qdirectfbscreen.h \ SOURCES = qdirectfbscreen.cpp \ qdirectfbscreenplugin.cpp \ - qdirectfbsurface.cpp \ + qdirectfbwindowsurface.cpp \ qdirectfbpaintengine.cpp \ qdirectfbpaintdevice.cpp \ qdirectfbpixmap.cpp \ @@ -40,4 +41,4 @@ SOURCES = qdirectfbscreen.cpp \ QMAKE_CXXFLAGS += $$QT_CFLAGS_DIRECTFB LIBS += $$QT_LIBS_DIRECTFB - +DEFINES += $$QT_DEFINES_DIRECTFB diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.cpp index 924090c..72e0ce5 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.cpp @@ -56,15 +56,20 @@ IDirectFBSurface *QDirectFBPaintDevice::directFBSurface() const } -void QDirectFBPaintDevice::lockDirectFB() +void QDirectFBPaintDevice::lockDirectFB(uint flags) { - if (lockedImage) - return; // Already locked - - if (uchar *mem = QDirectFBScreen::lockSurface(dfbSurface, DSLF_WRITE, &bpl)) { - const QSize s = size(); - lockedImage = new QImage(mem, s.width(), s.height(), bpl, - QDirectFBScreen::getImageFormat(dfbSurface)); + 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; + } } } @@ -77,15 +82,19 @@ void QDirectFBPaintDevice::unlockDirectFB() dfbSurface->Unlock(dfbSurface); delete lockedImage; lockedImage = 0; + mem = 0; + lock = 0; } -void* QDirectFBPaintDevice::memory() const +void *QDirectFBPaintDevice::memory() const { - QDirectFBPaintDevice* that = const_cast<QDirectFBPaintDevice*>(this); - that->lockDirectFB(); - Q_ASSERT(that->lockedImage); - return that->lockedImage->bits(); + if (lock != (DSLF_READ|DSLF_WRITE)) { + QDirectFBPaintDevice *that = const_cast<QDirectFBPaintDevice*>(this); + that->lockDirectFB(DSLF_READ|DSLF_WRITE); + Q_ASSERT(that->lockedImage); + } + return mem; } @@ -101,7 +110,7 @@ int QDirectFBPaintDevice::bytesPerLine() const // Can only get the stride when we lock the surface Q_ASSERT(!lockedImage); QDirectFBPaintDevice* that = const_cast<QDirectFBPaintDevice*>(this); - that->lockDirectFB(); + that->lockDirectFB(DSLF_READ); Q_ASSERT(bpl != -1); } return bpl; diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.h b/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.h index a11064b..13f0a8f 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.h +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.h @@ -58,7 +58,7 @@ public: IDirectFBSurface *directFBSurface() const; - void lockDirectFB(); + void lockDirectFB(uint flags); void unlockDirectFB(); inline bool forceRasterPrimitives() const { return forceRaster; } @@ -69,6 +69,7 @@ public: int bytesPerLine() const; QSize size() const; int metric(QPaintDevice::PaintDeviceMetric metric) const; + uint lockFlags() const { return lock; } protected: // Shouldn't create QDirectFBPaintDevice by itself but only sub-class it: QDirectFBPaintDevice(QDirectFBScreen *scr = QDirectFBScreen::instance()) @@ -76,7 +77,10 @@ protected: dfbSurface(0), lockedImage(0), screen(scr), - forceRaster(false) {} + forceRaster(false), + lock(0), + mem(0) + {} inline int dotsPerMeterX() const { @@ -92,6 +96,8 @@ protected: QDirectFBScreen *screen; int bpl; bool forceRaster; + uint lock; + uchar *mem; private: Q_DISABLE_COPY(QDirectFBPaintDevice) }; diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp index 14d2146..91a60e7 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp @@ -43,7 +43,7 @@ #ifndef QT_NO_DIRECTFB -#include "qdirectfbsurface.h" +#include "qdirectfbwindowsurface.h" #include "qdirectfbscreen.h" #include "qdirectfbpixmap.h" #include <directfb.h> @@ -80,7 +80,7 @@ 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, - bool matrixScale, bool matrixRotShear, bool simplePen, + int scale, bool matrixRotShear, bool simplePen, bool dfbHandledClip, bool forceRasterPrimitives, const char *nameOne, const T1 &one, const char *nameTwo, const T2 &two, @@ -95,7 +95,7 @@ static void rasterFallbackWarn(const char *msg, const char *func, const device * dbg << dev << "of type" << dev->devType(); } - dbg << "matrixScale" << matrixScale + dbg << "scale" << scale << "matrixRotShear" << matrixRotShear << "simplePen" << simplePen << "dfbHandledClip" << dfbHandledClip @@ -123,7 +123,7 @@ static void rasterFallbackWarn(const char *msg, const char *func, const device * if (op & (QT_DIRECTFB_WARN_ON_RASTERFALLBACKS)) \ rasterFallbackWarn("Disabled raster engine operation", \ __FUNCTION__, state()->painter->device(), \ - d_func()->matrixScale, d_func()->matrixRotShear, \ + d_func()->scale, d_func()->matrixRotShear, \ d_func()->simplePen, d_func()->dfbCanHandleClip(), \ d_func()->forceRasterPrimitives, \ #one, one, #two, two, #three, three); \ @@ -138,7 +138,7 @@ static void rasterFallbackWarn(const char *msg, const char *func, const device * if (op & (QT_DIRECTFB_WARN_ON_RASTERFALLBACKS)) \ rasterFallbackWarn("Falling back to raster engine for", \ __FUNCTION__, state()->painter->device(), \ - d_func()->matrixScale, d_func()->matrixRotShear, \ + d_func()->scale, d_func()->matrixRotShear, \ d_func()->simplePen, d_func()->dfbCanHandleClip(), \ d_func()->forceRasterPrimitives, \ #one, one, #two, two, #three, three); @@ -156,129 +156,66 @@ static inline uint ALPHA_MUL(uint x, uint a) class SurfaceCache { public: - SurfaceCache(); - ~SurfaceCache(); + SurfaceCache() : surface(0), buffer(0), bufsize(0) {} + ~SurfaceCache() { clear(); } - inline IDirectFBSurface *getSurface(const uint *buffer, int size); - inline void clear(); -private: - IDirectFBSurface *surface; - uint *buffer; - int bufsize; -}; - -SurfaceCache::SurfaceCache() - : surface(0), buffer(0), bufsize(0) -{ -} + IDirectFBSurface *getSurface(const uint *buf, int size) + { + if (buffer == buf && bufsize == size) + return surface; -class CachedImage -{ -public: - CachedImage(const QImage &image); - ~CachedImage(); + clear(); - IDirectFBSurface *surface() { return s; } + const DFBSurfaceDescription description = QDirectFBScreen::getSurfaceDescription(buf, size); + surface = QDirectFBScreen::instance()->createDFBSurface(description, QDirectFBScreen::TrackSurface); + if (!surface) + qWarning("QDirectFBPaintEngine: SurfaceCache: Unable to create surface"); -private: - IDirectFBSurface *s; -}; - -CachedImage::CachedImage(const QImage &image) - : s(0) -{ - IDirectFBSurface *tmpSurface = 0; - DFBSurfaceDescription description = QDirectFBScreen::getSurfaceDescription(image); - QDirectFBScreen* screen = QDirectFBScreen::instance(); + buffer = const_cast<uint*>(buf); + bufsize = size; - tmpSurface = screen->createDFBSurface(description, QDirectFBScreen::TrackSurface); - if (!tmpSurface) { - qWarning("CachedImage CreateSurface failed!"); - return; + return surface; } -#ifndef QT_NO_DIRECTFB_PALETTE - QDirectFBScreen::setSurfaceColorTable(tmpSurface, image); -#endif - - description.flags = DFBSurfaceDescriptionFlags(description.flags & ~DSDESC_PREALLOCATED); - - s = screen->createDFBSurface(description, QDirectFBScreen::TrackSurface); - if (!s) - qWarning("QDirectFBPaintEngine failed caching image"); - -#ifndef QT_NO_DIRECTFB_PALETTE - QDirectFBScreen::setSurfaceColorTable(s, image); -#endif - - if (s) { - s->SetBlittingFlags(s, DSBLIT_NOFX); - s->Blit(s, tmpSurface, 0, 0, 0); - s->ReleaseSource(s); + void clear() + { + if (surface && QDirectFBScreen::instance()) + QDirectFBScreen::instance()->releaseDFBSurface(surface); + surface = 0; + buffer = 0; + bufsize = 0; } - if (tmpSurface) - screen->releaseDFBSurface(tmpSurface); -} - -CachedImage::~CachedImage() -{ - if (s && QDirectFBScreen::instance()) - QDirectFBScreen::instance()->releaseDFBSurface(s); -} - -static QCache<qint64, CachedImage> imageCache(4*1024*1024); // 4 MB - -IDirectFBSurface* SurfaceCache::getSurface(const uint *buf, int size) -{ - if (buffer == buf && bufsize == size) - return surface; - - clear(); - - 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; -} +private: + IDirectFBSurface *surface; + uint *buffer; + int bufsize; +}; -void SurfaceCache::clear() -{ - if (surface) - QDirectFBScreen::instance()->releaseDFBSurface(surface); - surface = 0; - buffer = 0; - bufsize = 0; -} -SurfaceCache::~SurfaceCache() +#ifdef QT_DIRECTFB_IMAGECACHE +#include <private/qimage_p.h> +struct CachedImage { - clear(); -} + IDirectFBSurface *surface; + ~CachedImage() + { + if (surface && QDirectFBScreen::instance()) { + QDirectFBScreen::instance()->releaseDFBSurface(surface); + } + } +}; +static QCache<qint64, CachedImage> imageCache(4*1024*1024); // 4 MB +#endif class QDirectFBPaintEnginePrivate : public QRasterPaintEnginePrivate { public: + enum Scale { NoScale, Scaled, NegativeScale }; + QDirectFBPaintEnginePrivate(QDirectFBPaintEngine *p); ~QDirectFBPaintEnginePrivate(); - IDirectFBSurface *surface; - - QPen pen; - - bool antialiased; - bool forceRasterPrimitives; - - bool simplePen; - - bool matrixRotShear; - bool matrixScale; - void setTransform(const QTransform &m); void setPen(const QPen &pen); void setCompositionMode(QPainter::CompositionMode mode); @@ -304,24 +241,39 @@ public: void fillRects(const QRectF *rects, int count); void drawRects(const QRectF *rects, int count); - - void drawPixmap(const QRectF &dest, - const QPixmap &pixmap, const QRectF &src); void drawTiledPixmap(const QRectF &dest, const QPixmap &pixmap); - void drawImage(const QRectF &dest, const QImage &image, const QRectF &src); + void blit(const QRectF &dest, IDirectFBSurface *surface, const QRectF &src); inline void updateClip(); - inline void setClipDirty(); void systemStateChanged(); void begin(QPaintDevice *device); void end(); + static IDirectFBSurface *getSurface(const QImage &img, bool *release); + +#ifdef QT_DIRECTFB_IMAGECACHE + static inline int cacheCost(const QImage &img) { return img.width() * img.height() * img.depth() / 8; } +#endif + void prepareForBlit(bool alpha); +private: + IDirectFBSurface *surface; + + QPen pen; + + bool antialiased; + bool forceRasterPrimitives; + + bool simplePen; + + bool matrixRotShear; + Scale scale; + SurfaceCache *surfaceCache; QTransform transform; int lastLockedHeight; -private: + IDirectFB *fb; DFBSurfaceDescription fbDescription; int fbWidth; @@ -336,469 +288,12 @@ private: bool dfbHandledClip; bool ignoreSystemClip; QDirectFBPaintDevice *dfbDevice; + void *lockedMemory; QDirectFBPaintEngine *q; + friend class QDirectFBPaintEngine; }; -QDirectFBPaintEnginePrivate::QDirectFBPaintEnginePrivate(QDirectFBPaintEngine *p) - : surface(0), antialiased(false), forceRasterPrimitives(false), simplePen(false), - matrixRotShear(false), matrixScale(false), lastLockedHeight(-1), - fbWidth(-1), fbHeight(-1), opacity(255), drawFlagsFromCompositionMode(0), - blitFlagsFromCompositionMode(0), porterDuffRule(DSPD_SRC_OVER), dirtyClip(true), - dfbHandledClip(false), dfbDevice(0), q(p) -{ - fb = QDirectFBScreen::instance()->dfb(); - ignoreSystemClip = QDirectFBScreen::instance()->directFBFlags() & QDirectFBScreen::IgnoreSystemClip; - surfaceCache = new SurfaceCache; - static int cacheLimit = qgetenv("QT_DIRECTFB_IMAGECACHE").toInt(); - if (cacheLimit > 0) - imageCache.setMaxCost(cacheLimit * 1024); -} - -QDirectFBPaintEnginePrivate::~QDirectFBPaintEnginePrivate() -{ - delete surfaceCache; -} - -bool QDirectFBPaintEnginePrivate::dfbCanHandleClip(const QRect &rect) const -{ - // TODO: Check to see if DirectFB can handle the clip for the given rect - return dfbHandledClip; -} - -bool QDirectFBPaintEnginePrivate::dfbCanHandleClip(const QRectF &rect) const -{ - // TODO: Check to see if DirectFB can handle the clip for the given rect - return dfbHandledClip; -} - -bool QDirectFBPaintEnginePrivate::dfbCanHandleClip() const -{ - return dfbHandledClip; -} - -bool QDirectFBPaintEnginePrivate::isSimpleBrush(const QBrush &brush) const -{ - return (brush.style() == Qt::NoBrush) || (brush.style() == Qt::SolidPattern && !antialiased); -} - -void QDirectFBPaintEnginePrivate::setClipDirty() -{ - dirtyClip = true; -} - -void QDirectFBPaintEnginePrivate::lock() -{ - // We will potentially get a new pointer to the buffer after a - // lock so we need to call the base implementation of prepare so - // it updates its rasterBuffer to point to the new buffer address. - lastLockedHeight = dfbDevice->height(); - - Q_ASSERT(dfbDevice); - prepare(dfbDevice); -} - -void QDirectFBPaintEnginePrivate::unlock() -{ - Q_ASSERT(dfbDevice); - dfbDevice->unlockDirectFB(); -} - -void QDirectFBPaintEnginePrivate::setTransform(const QTransform &m) -{ - transform = m; - matrixRotShear = (transform.m12() != 0 || transform.m21() != 0); - matrixScale = (transform.m11() != 1 || transform.m22() != 1); -} - -void QDirectFBPaintEnginePrivate::begin(QPaintDevice *device) -{ - lastLockedHeight = -1; - if (device->devType() == QInternal::CustomRaster) - dfbDevice = static_cast<QDirectFBPaintDevice*>(device); - else if (device->devType() == QInternal::Pixmap) { - QPixmapData *data = static_cast<QPixmap*>(device)->pixmapData(); - Q_ASSERT(data->classId() == QPixmapData::DirectFBClass); - QDirectFBPixmapData* dfbPixmapData = static_cast<QDirectFBPixmapData*>(data); - dfbDevice = static_cast<QDirectFBPaintDevice*>(dfbPixmapData); - } - - if (dfbDevice) - surface = dfbDevice->directFBSurface(); - - if (!surface) { - qFatal("QDirectFBPaintEngine used on an invalid device: 0x%x", - device->devType()); - } - forceRasterPrimitives = dfbDevice->forceRasterPrimitives(); - - surface->GetSize(surface, &fbWidth, &fbHeight); - - setTransform(QTransform()); - antialiased = false; - opacity = 255; - setCompositionMode(q->state()->compositionMode()); - dirtyClip = true; - setPen(q->state()->pen); - setDFBColor(pen.color()); -} - -void QDirectFBPaintEnginePrivate::end() -{ - dfbDevice = 0; - surface->ReleaseSource(surface); - surface->SetClip(surface, NULL); - surface = 0; -} - -void QDirectFBPaintEnginePrivate::setPen(const QPen &p) -{ - pen = p; - simplePen = (pen.style() == Qt::NoPen) || - (pen.style() == Qt::SolidLine - && !antialiased - && (pen.brush().style() == Qt::SolidPattern) - && (pen.widthF() <= 1 && !matrixScale)); -} - -void QDirectFBPaintEnginePrivate::setCompositionMode(QPainter::CompositionMode mode) -{ - blitFlagsFromCompositionMode = DSBLIT_NOFX; - drawFlagsFromCompositionMode = DSDRAW_NOFX; - - bool blend = true; - switch (mode) { - case QPainter::CompositionMode_SourceOver: - porterDuffRule = DSPD_SRC_OVER; - break; - case QPainter::CompositionMode_DestinationOver: - porterDuffRule = DSPD_DST_OVER; - break; - case QPainter::CompositionMode_Clear: - porterDuffRule = DSPD_CLEAR; - blend = false; - break; - case QPainter::CompositionMode_Source: - porterDuffRule = DSPD_SRC; - blend = false; - break; - case QPainter::CompositionMode_Destination: - porterDuffRule = DSPD_NONE; // ### need to double check this - blend = false; - return; - case QPainter::CompositionMode_SourceIn: - porterDuffRule = DSPD_SRC_IN; - break; - case QPainter::CompositionMode_DestinationIn: - porterDuffRule = DSPD_DST_IN; - break; - case QPainter::CompositionMode_SourceOut: - porterDuffRule = DSPD_SRC_OUT; - break; - case QPainter::CompositionMode_DestinationOut: - porterDuffRule = DSPD_DST_OUT; - break; - case QPainter::CompositionMode_Xor: - porterDuffRule = DSPD_XOR; - blitFlagsFromCompositionMode |= DSBLIT_XOR; - drawFlagsFromCompositionMode |= DSDRAW_XOR; - break; -// case QPainter::CompositionMode_Plus: // ??? -// porterDuffRule = DSPD_ADD; -// break; - default: - qWarning("QDirectFBPaintEnginePrivate::setCompositionMode(): " - "mode %d not implemented", mode); - return; - } - // intentially not comparing with current porterDuffRule. surface might have changed. - if (blend) { - blitFlagsFromCompositionMode |= DSBLIT_BLEND_ALPHACHANNEL; - drawFlagsFromCompositionMode |= DSDRAW_BLEND; - } - if (opacity != 255) { - setOpacity(opacity); - } -} - -void QDirectFBPaintEnginePrivate::setOpacity(quint8 op) -{ - opacity = op; - if (opacity == 255) { - blitFlagsFromCompositionMode &= ~DSBLIT_BLEND_COLORALPHA; - } else { - blitFlagsFromCompositionMode |= DSBLIT_BLEND_COLORALPHA; - } -} - -void QDirectFBPaintEnginePrivate::setRenderHints(QPainter::RenderHints hints) -{ - const bool old = antialiased; - antialiased = bool(hints & QPainter::Antialiasing); - if (old != antialiased) { - setPen(q->state()->pen); - } -} - -void QDirectFBPaintEnginePrivate::prepareForBlit(bool alpha) -{ - quint32 blittingFlags = blitFlagsFromCompositionMode; - if (alpha) { - surface->SetPorterDuff(surface, - (blittingFlags & DSBLIT_BLEND_COLORALPHA) - ? DSPD_NONE - : porterDuffRule); - } else { - blittingFlags &= ~DSBLIT_BLEND_ALPHACHANNEL; - surface->SetPorterDuff(surface, DSPD_NONE); - } - surface->SetColor(surface, 0xff, 0xff, 0xff, opacity); - surface->SetBlittingFlags(surface, DFBSurfaceBlittingFlags(blittingFlags)); -} - -void QDirectFBPaintEnginePrivate::setDFBColor(const QColor &color) -{ - Q_ASSERT(surface); - const quint8 alpha = (opacity == 255 ? - color.alpha() : ALPHA_MUL(color.alpha(), opacity)); - surface->SetColor(surface, - color.red(), color.green(), color.blue(), alpha); - quint32 drawingFlags = drawFlagsFromCompositionMode; - if (alpha == 255) { - drawingFlags &= ~DSDRAW_BLEND; - } - surface->SetPorterDuff(surface, DSPD_NONE); - // PorterDuff messes up alpha values for primitives - surface->SetDrawingFlags(surface, DFBSurfaceDrawingFlags(drawingFlags)); -} - -void QDirectFBPaintEnginePrivate::drawLines(const QLine *lines, int n) -{ - for (int i = 0; i < n; ++i) { - const QLine l = transform.map(lines[i]); - surface->DrawLine(surface, l.x1(), l.y1(), l.x2(), l.y2()); - } -} - -void QDirectFBPaintEnginePrivate::drawLines(const QLineF *lines, int n) -{ - for (int i = 0; i < n; ++i) { - const QLine l = transform.map(lines[i]).toLine(); - surface->DrawLine(surface, l.x1(), l.y1(), l.x2(), l.y2()); - } -} - -void QDirectFBPaintEnginePrivate::fillRegion(const QRegion ®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); - } -} - -void QDirectFBPaintEnginePrivate::drawPixmap(const QRectF &dest, - const QPixmap &pixmap, - const QRectF &src) -{ - prepareForBlit(pixmap.hasAlphaChannel()); - QPixmapData *data = pixmap.pixmapData(); - Q_ASSERT(data->classId() == QPixmapData::DirectFBClass); - QDirectFBPixmapData *dfbData = static_cast<QDirectFBPixmapData*>(data); - IDirectFBSurface *s = dfbData->directFBSurface(); - const QRect sr = src.toRect(); - const QRect dr = transform.mapRect(dest).toRect(); - const DFBRectangle sRect = { sr.x(), sr.y(), sr.width(), sr.height() }; - DFBResult result; - - if (dr.size() == sr.size()) { - result = surface->Blit(surface, s, &sRect, dr.x(), dr.y()); - } else { - const DFBRectangle dRect = { dr.x(), dr.y(), dr.width(), dr.height() }; - result = surface->StretchBlit(surface, s, &sRect, &dRect); - } - if (result != DFB_OK) - DirectFBError("QDirectFBPaintEngine::drawPixmap()", result); -} - -void QDirectFBPaintEnginePrivate::drawTiledPixmap(const QRectF &dest, - const QPixmap &pixmap) -{ - prepareForBlit(pixmap.hasAlphaChannel()); - QPixmapData *data = pixmap.pixmapData(); - Q_ASSERT(data->classId() == QPixmapData::DirectFBClass); - QDirectFBPixmapData *dfbData = static_cast<QDirectFBPixmapData*>(data); - IDirectFBSurface *s = dfbData->directFBSurface(); - const QRect dr = transform.mapRect(dest).toRect(); - DFBResult result = DFB_OK; - - if (!matrixScale && dr == QRect(0, 0, fbWidth, fbHeight)) { - result = surface->TileBlit(surface, s, 0, 0, 0); - } else if (!matrixScale) { - const int dx = pixmap.width(); - const int dy = pixmap.height(); - const DFBRectangle rect = { 0, 0, dx, dy }; - QVarLengthArray<DFBRectangle> rects; - QVarLengthArray<DFBPoint> points; - - for (int y = dr.y(); y <= dr.bottom(); y += dy) { - for (int x = dr.x(); x <= dr.right(); x += dx) { - rects.append(rect); - const DFBPoint point = { x, y }; - points.append(point); - } - } - result = surface->BatchBlit(surface, s, rects.constData(), - points.constData(), points.size()); - } else { - const QRect sr = transform.mapRect(QRect(0, 0, pixmap.width(), pixmap.height())); - const int dx = sr.width(); - const int dy = sr.height(); - const DFBRectangle sRect = { 0, 0, dx, dy }; - - for (int y = dr.y(); y <= dr.bottom(); y += dy) { - for (int x = dr.x(); x <= dr.right(); x += dx) { - const DFBRectangle dRect = { x, y, dx, dy }; - result = surface->StretchBlit(surface, s, &sRect, &dRect); - if (result != DFB_OK) { - y = dr.bottom() + 1; - break; - } - } - } - } - - if (result != DFB_OK) - DirectFBError("QDirectFBPaintEngine::drawTiledPixmap()", result); -} - -void QDirectFBPaintEnginePrivate::drawImage(const QRectF &dest, - const QImage &image, - const QRectF &src) -{ - Q_ASSERT(QDirectFBScreen::getSurfacePixelFormat(image.format()) != DSPF_UNKNOWN); - CachedImage *img = imageCache[image.cacheKey()]; - IDirectFBSurface *imgSurface = 0; - bool doRelease = false; - - if (img) { - imgSurface = img->surface(); - } else { - const int cost = image.width() * image.height() * image.depth() / 8; - if (cost <= imageCache.maxCost()) { - img = new CachedImage(image); - imgSurface = img->surface(); - if (imgSurface) { - imageCache.insert(image.cacheKey(), img, cost); - } else { - delete img; - img = 0; - } - } - - if (!imgSurface) { - DFBSurfaceDescription description = QDirectFBScreen::getSurfaceDescription(image); - imgSurface = QDirectFBScreen::instance()->createDFBSurface(description, - QDirectFBScreen::DontTrackSurface); - if (!imgSurface) { - qWarning("QDirectFBPaintEnginePrivate::drawImage"); - return; - } - -#ifndef QT_NO_DIRECTFB_PALETTE - QDirectFBScreen::setSurfaceColorTable(surface, image); -#endif - doRelease = (imgSurface != 0); - } - } - - const QRect sr = src.toRect(); - const QRect dr = transform.mapRect(dest).toRect(); - const DFBRectangle sRect = { sr.x(), sr.y(), sr.width(), sr.height() }; - - prepareForBlit(image.hasAlphaChannel()); - if (dr.size() == sr.size()) { - surface->Blit(surface, imgSurface, &sRect, dr.x(), dr.y()); - } else { - const DFBRectangle dRect = { dr.x(), dr.y(), - dr.width(), dr.height() }; - surface->StretchBlit(surface, imgSurface, &sRect, &dRect); - } - if (doRelease) { - surface->ReleaseSource(surface); - imgSurface->Release(imgSurface); - } -} - -void QDirectFBPaintEnginePrivate::updateClip() -{ - if (!dirtyClip) - return; - - const QClipData *clipData = clip(); - if (!clipData || !clipData->enabled) { - surface->SetClip(surface, NULL); - dfbHandledClip = true; - } else if (clipData->hasRectClip) { - const DFBRegion r = { - clipData->clipRect.x(), - clipData->clipRect.y(), - clipData->clipRect.x() + clipData->clipRect.width(), - clipData->clipRect.y() + clipData->clipRect.height() - }; - surface->SetClip(surface, &r); - dfbHandledClip = true; - } else if (clipData->hasRegionClip && ignoreSystemClip && clipData->clipRegion == systemClip) { - dfbHandledClip = true; - } else { - dfbHandledClip = false; - } - - dirtyClip = false; -} - -void QDirectFBPaintEnginePrivate::systemStateChanged() -{ - setClipDirty(); - QRasterPaintEnginePrivate::systemStateChanged(); -} - QDirectFBPaintEngine::QDirectFBPaintEngine(QPaintDevice *device) : QRasterPaintEngine(*(new QDirectFBPaintEnginePrivate(this)), device) { @@ -827,12 +322,10 @@ bool QDirectFBPaintEngine::end() return QRasterPaintEngine::end(); } - - void QDirectFBPaintEngine::clipEnabledChanged() { Q_D(QDirectFBPaintEngine); - d->setClipDirty(); + d->dirtyClip = true; QRasterPaintEngine::clipEnabledChanged(); } @@ -868,9 +361,9 @@ void QDirectFBPaintEngine::renderHintsChanged() void QDirectFBPaintEngine::transformChanged() { Q_D(QDirectFBPaintEngine); - const bool old = d->matrixScale; + const QDirectFBPaintEnginePrivate::Scale old = d->scale; d->setTransform(state()->transform()); - if (d->matrixScale != old) { + if (d->scale != old) { d->setPen(state()->pen); } QRasterPaintEngine::transformChanged(); @@ -880,7 +373,7 @@ void QDirectFBPaintEngine::setState(QPainterState *s) { Q_D(QDirectFBPaintEngine); QRasterPaintEngine::setState(s); - d->setClipDirty(); + d->dirtyClip = true; d->setPen(state()->pen); d->setOpacity(quint8(state()->opacity * 255)); d->setCompositionMode(state()->compositionMode()); @@ -890,7 +383,7 @@ void QDirectFBPaintEngine::setState(QPainterState *s) void QDirectFBPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op) { Q_D(QDirectFBPaintEngine); - d->setClipDirty(); + d->dirtyClip = true; const QPoint bottom = d->transform.map(QPoint(0, path.controlPointRect().y2)); if (bottom.y() >= d->lastLockedHeight) d->lock(); @@ -900,7 +393,7 @@ void QDirectFBPaintEngine::clip(const QVectorPath &path, Qt::ClipOperation op) void QDirectFBPaintEngine::clip(const QRect &rect, Qt::ClipOperation op) { Q_D(QDirectFBPaintEngine); - d->setClipDirty(); + 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) @@ -1003,12 +496,36 @@ void QDirectFBPaintEngine::drawImage(const QRectF &r, const QImage &image, Qt::ImageConversionFlags flags) { Q_D(QDirectFBPaintEngine); - Q_UNUSED(flags); // XXX + Q_UNUSED(flags); + + /* This is hard to read. The way it works is like this: + + - If you do not have support for preallocated surfaces and do not use an + image cache we always fall back to raster engine. + + - If it's rotated/sheared/mirrored (negative scale) or we can't + clip it we fall back to raster engine. + + - If we don't cache the image, but we do have support for + preallocated surfaces we fall back to the raster engine if the + image is in a format DirectFB can't handle. + + - If we do cache the image but don't have support for preallocated + images and the cost of caching the image (bytes used) is higher + than the max image cache size we fall back to raster engine. + */ -#ifndef QT_NO_DIRECTFB_PREALLOCATED d->updateClip(); - if (!d->dfbCanHandleClip(r) || d->matrixRotShear - || QDirectFBScreen::getSurfacePixelFormat(image.format()) == DSPF_UNKNOWN) +#if !defined QT_NO_DIRECTFB_PREALLOCATED || defined QT_DIRECTFB_IMAGECACHE + if (d->matrixRotShear + || d->scale == QDirectFBPaintEnginePrivate::NegativeScale + || !d->dfbCanHandleClip(r) +#ifndef QT_DIRECTFB_IMAGECACHE + || QDirectFBScreen::getSurfacePixelFormat(image.format()) == DSPF_UNKNOWN +#elif defined QT_NO_DIRECTFB_PREALLOCATED + || QDirectFBPaintEnginePrivate::cacheCost(image) > imageCache.maxCost() +#endif + ) #endif { RASTERFALLBACK(DRAW_IMAGE, r, image.size(), sr); @@ -1016,10 +533,16 @@ void QDirectFBPaintEngine::drawImage(const QRectF &r, const QImage &image, QRasterPaintEngine::drawImage(r, image, sr, flags); return; } - -#ifndef QT_NO_DIRECTFB_PREALLOCATED +#if !defined QT_NO_DIRECTFB_PREALLOCATED || defined QT_DIRECTFB_IMAGECACHE d->unlock(); - d->drawImage(r, image, sr); + bool release; + IDirectFBSurface *imgSurface = d->getSurface(image, &release); + d->prepareForBlit(QDirectFBScreen::hasAlpha(imgSurface)); + d->blit(r, imgSurface, sr); + if (release) { + imgSurface->ReleaseSource(imgSurface); + imgSurface->Release(imgSurface); + } #endif } @@ -1038,14 +561,20 @@ 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->dfbCanHandleClip(r) || d->matrixRotShear) { + } else if (!d->dfbCanHandleClip(r) || d->matrixRotShear + || d->scale == QDirectFBPaintEnginePrivate::NegativeScale) { RASTERFALLBACK(DRAW_PIXMAP, r, pixmap.size(), sr); - const QImage *img = static_cast<QDirectFBPixmapData*>(pixmap.pixmapData())->buffer(); + const QImage *img = static_cast<QDirectFBPixmapData*>(pixmap.pixmapData())->buffer(DSLF_READ); d->lock(); QRasterPaintEngine::drawImage(r, *img, sr); } else { d->unlock(); - d->drawPixmap(r, pixmap, sr); + d->prepareForBlit(pixmap.hasAlphaChannel()); + QPixmapData *data = pixmap.pixmapData(); + Q_ASSERT(data->classId() == QPixmapData::DirectFBClass); + QDirectFBPixmapData *dfbData = static_cast<QDirectFBPixmapData*>(data); + IDirectFBSurface *s = dfbData->directFBSurface(); + d->blit(r, s, sr); } } @@ -1064,9 +593,10 @@ void QDirectFBPaintEngine::drawTiledPixmap(const QRectF &r, RASTERFALLBACK(DRAW_TILED_PIXMAP, r, pixmap.size(), sp); d->lock(); QRasterPaintEngine::drawTiledPixmap(r, pixmap, sp); - } else if (!d->dfbCanHandleClip(r) || d->matrixRotShear || !sp.isNull()) { + } else if (!d->dfbCanHandleClip(r) || d->matrixRotShear || !sp.isNull() + || d->scale == QDirectFBPaintEnginePrivate::NegativeScale) { RASTERFALLBACK(DRAW_TILED_PIXMAP, r, pixmap.size(), sp); - const QImage *img = static_cast<QDirectFBPixmapData*>(pixmap.pixmapData())->buffer(); + const QImage *img = static_cast<QDirectFBPixmapData*>(pixmap.pixmapData())->buffer(DSLF_READ); d->lock(); QRasterPixmapData *data = new QRasterPixmapData(QPixmapData::PixmapType); data->fromImage(*img, Qt::AutoColor); @@ -1254,4 +784,457 @@ void QDirectFBPaintEngine::drawBufferSpan(const uint *buffer, int bufsize, d->surface->Blit(d->surface, src, &rect, x, y); } +#ifdef QT_DIRECTFB_IMAGECACHE +static void cachedImageCleanupHook(qint64 key) +{ + delete imageCache.take(key); +} +void QDirectFBPaintEngine::initImageCache(int size) +{ + Q_ASSERT(size >= 0); + imageCache.setMaxCost(size); + typedef void (*_qt_image_cleanup_hook_64)(qint64); + extern Q_GUI_EXPORT _qt_image_cleanup_hook_64 qt_image_cleanup_hook_64; + qt_image_cleanup_hook_64 = ::cachedImageCleanupHook; +} + +#endif // QT_DIRECTFB_IMAGECACHE + +// ---- QDirectFBPaintEnginePrivate ---- + + +QDirectFBPaintEnginePrivate::QDirectFBPaintEnginePrivate(QDirectFBPaintEngine *p) + : surface(0), antialiased(false), forceRasterPrimitives(false), simplePen(false), + matrixRotShear(false), scale(NoScale), lastLockedHeight(-1), + fbWidth(-1), fbHeight(-1), opacity(255), drawFlagsFromCompositionMode(0), + blitFlagsFromCompositionMode(0), porterDuffRule(DSPD_SRC_OVER), dirtyClip(true), + dfbHandledClip(false), dfbDevice(0), lockedMemory(0), q(p) +{ + fb = QDirectFBScreen::instance()->dfb(); + ignoreSystemClip = QDirectFBScreen::instance()->directFBFlags() & QDirectFBScreen::IgnoreSystemClip; + surfaceCache = new SurfaceCache; +} + +QDirectFBPaintEnginePrivate::~QDirectFBPaintEnginePrivate() +{ + delete surfaceCache; +} + +bool QDirectFBPaintEnginePrivate::dfbCanHandleClip(const QRect &rect) const +{ + // TODO: Check to see if DirectFB can handle the clip for the given rect + return dfbHandledClip; +} + +bool QDirectFBPaintEnginePrivate::dfbCanHandleClip(const QRectF &rect) const +{ + // TODO: Check to see if DirectFB can handle the clip for the given rect + return dfbHandledClip; +} + +bool QDirectFBPaintEnginePrivate::dfbCanHandleClip() const +{ + return dfbHandledClip; +} + +bool QDirectFBPaintEnginePrivate::isSimpleBrush(const QBrush &brush) const +{ + return (brush.style() == Qt::NoBrush) || (brush.style() == Qt::SolidPattern && !antialiased); +} + +void QDirectFBPaintEnginePrivate::lock() +{ + // We will potentially get a new pointer to the buffer after a + // lock so we need to call the base implementation of prepare so + // it updates its rasterBuffer to point to the new buffer address. + Q_ASSERT(dfbDevice); + if (dfbDevice->lockFlags() != (DSLF_WRITE|DSLF_READ) + || dfbDevice->height() != lastLockedHeight + || dfbDevice->memory() != lockedMemory) { + prepare(dfbDevice); + lastLockedHeight = dfbDevice->height(); + lockedMemory = dfbDevice->memory(); + } +} + +void QDirectFBPaintEnginePrivate::unlock() +{ + Q_ASSERT(dfbDevice); + dfbDevice->unlockDirectFB(); + lockedMemory = 0; +} + +void QDirectFBPaintEnginePrivate::setTransform(const QTransform &m) +{ + transform = m; + matrixRotShear = (transform.m12() != 0 || transform.m21() != 0); + if (qMin(transform.m11(), transform.m22()) < 0) { + scale = NegativeScale; + } else if (transform.m11() != 1 || transform.m22() != 1) { + scale = Scaled; + } else { + scale = NoScale; + } +} + +void QDirectFBPaintEnginePrivate::begin(QPaintDevice *device) +{ + lastLockedHeight = -1; + if (device->devType() == QInternal::CustomRaster) + dfbDevice = static_cast<QDirectFBPaintDevice*>(device); + else if (device->devType() == QInternal::Pixmap) { + QPixmapData *data = static_cast<QPixmap*>(device)->pixmapData(); + Q_ASSERT(data->classId() == QPixmapData::DirectFBClass); + QDirectFBPixmapData* dfbPixmapData = static_cast<QDirectFBPixmapData*>(data); + dfbDevice = static_cast<QDirectFBPaintDevice*>(dfbPixmapData); + } + + if (dfbDevice) + surface = dfbDevice->directFBSurface(); + + if (!surface) { + qFatal("QDirectFBPaintEngine used on an invalid device: 0x%x", + device->devType()); + } + lockedMemory = 0; + forceRasterPrimitives = dfbDevice->forceRasterPrimitives(); + + surface->GetSize(surface, &fbWidth, &fbHeight); + + setTransform(QTransform()); + antialiased = false; + opacity = 255; + setCompositionMode(q->state()->compositionMode()); + dirtyClip = true; + setPen(q->state()->pen); + setDFBColor(pen.color()); +} + +void QDirectFBPaintEnginePrivate::end() +{ + lockedMemory = 0; + dfbDevice = 0; + surface->ReleaseSource(surface); + surface->SetClip(surface, NULL); + surface = 0; +} + +void QDirectFBPaintEnginePrivate::setPen(const QPen &p) +{ + pen = p; + simplePen = (pen.style() == Qt::NoPen) || + (pen.style() == Qt::SolidLine + && !antialiased + && (pen.brush().style() == Qt::SolidPattern) + && (pen.widthF() <= 1 && scale != NoScale)); +} + +void QDirectFBPaintEnginePrivate::setCompositionMode(QPainter::CompositionMode mode) +{ + blitFlagsFromCompositionMode = DSBLIT_NOFX; + drawFlagsFromCompositionMode = DSDRAW_NOFX; + + bool blend = true; + switch (mode) { + case QPainter::CompositionMode_SourceOver: + porterDuffRule = DSPD_SRC_OVER; + break; + case QPainter::CompositionMode_DestinationOver: + porterDuffRule = DSPD_DST_OVER; + break; + case QPainter::CompositionMode_Clear: + porterDuffRule = DSPD_CLEAR; + blend = false; + break; + case QPainter::CompositionMode_Source: + porterDuffRule = DSPD_SRC; + blend = false; + break; + case QPainter::CompositionMode_Destination: + porterDuffRule = DSPD_NONE; // ### need to double check this + blend = false; + return; + case QPainter::CompositionMode_SourceIn: + porterDuffRule = DSPD_SRC_IN; + break; + case QPainter::CompositionMode_DestinationIn: + porterDuffRule = DSPD_DST_IN; + break; + case QPainter::CompositionMode_SourceOut: + porterDuffRule = DSPD_SRC_OUT; + break; + case QPainter::CompositionMode_DestinationOut: + porterDuffRule = DSPD_DST_OUT; + break; + case QPainter::CompositionMode_Xor: + porterDuffRule = DSPD_XOR; + blitFlagsFromCompositionMode |= DSBLIT_XOR; + drawFlagsFromCompositionMode |= DSDRAW_XOR; + break; +// case QPainter::CompositionMode_Plus: // ??? +// porterDuffRule = DSPD_ADD; +// break; + default: + qWarning("QDirectFBPaintEnginePrivate::setCompositionMode(): " + "mode %d not implemented", mode); + return; + } + // intentially not comparing with current porterDuffRule. surface might have changed. + if (blend) { + blitFlagsFromCompositionMode |= DSBLIT_BLEND_ALPHACHANNEL; + drawFlagsFromCompositionMode |= DSDRAW_BLEND; + } + if (opacity != 255) { + setOpacity(opacity); + } +} + +void QDirectFBPaintEnginePrivate::setOpacity(quint8 op) +{ + opacity = op; + if (opacity == 255) { + blitFlagsFromCompositionMode &= ~DSBLIT_BLEND_COLORALPHA; + } else { + blitFlagsFromCompositionMode |= DSBLIT_BLEND_COLORALPHA; + } +} + +void QDirectFBPaintEnginePrivate::setRenderHints(QPainter::RenderHints hints) +{ + const bool old = antialiased; + antialiased = bool(hints & QPainter::Antialiasing); + if (old != antialiased) { + setPen(q->state()->pen); + } +} + +void QDirectFBPaintEnginePrivate::prepareForBlit(bool alpha) +{ + quint32 blittingFlags = blitFlagsFromCompositionMode; + if (alpha) { + surface->SetPorterDuff(surface, + (blittingFlags & DSBLIT_BLEND_COLORALPHA) + ? DSPD_NONE + : porterDuffRule); + } else { + blittingFlags &= ~DSBLIT_BLEND_ALPHACHANNEL; + surface->SetPorterDuff(surface, DSPD_NONE); + } + surface->SetColor(surface, 0xff, 0xff, 0xff, opacity); + surface->SetBlittingFlags(surface, DFBSurfaceBlittingFlags(blittingFlags)); +} + +void QDirectFBPaintEnginePrivate::setDFBColor(const QColor &color) +{ + Q_ASSERT(surface); + const quint8 alpha = (opacity == 255 ? + color.alpha() : ALPHA_MUL(color.alpha(), opacity)); + surface->SetColor(surface, + color.red(), color.green(), color.blue(), alpha); + quint32 drawingFlags = drawFlagsFromCompositionMode; + if (alpha == 255) { + drawingFlags &= ~DSDRAW_BLEND; + } + surface->SetPorterDuff(surface, DSPD_NONE); + // PorterDuff messes up alpha values for primitives + surface->SetDrawingFlags(surface, DFBSurfaceDrawingFlags(drawingFlags)); +} + +void QDirectFBPaintEnginePrivate::drawLines(const QLine *lines, int n) +{ + for (int i = 0; i < n; ++i) { + const QLine l = transform.map(lines[i]); + surface->DrawLine(surface, l.x1(), l.y1(), l.x2(), l.y2()); + } +} + +void QDirectFBPaintEnginePrivate::drawLines(const QLineF *lines, int n) +{ + for (int i = 0; i < n; ++i) { + const QLine l = transform.map(lines[i]).toLine(); + surface->DrawLine(surface, l.x1(), l.y1(), l.x2(), l.y2()); + } +} + +void QDirectFBPaintEnginePrivate::fillRegion(const QRegion ®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 + *release = true; + return QDirectFBScreen::instance()->createDFBSurface(img, QDirectFBScreen::DontTrackSurface); +#else + const qint64 key = img.cacheKey(); + *release = false; + if (imageCache.contains(key)) { + return imageCache[key]->surface; + } + + const int cost = cacheCost(img); + const bool cache = cost <= imageCache.maxCost(); + QDirectFBScreen *screen = QDirectFBScreen::instance(); + const QImage::Format format = (img.format() == screen->alphaPixmapFormat() || QDirectFBPixmapData::hasAlphaChannel(img) + ? screen->alphaPixmapFormat() : screen->pixelFormat()); + + IDirectFBSurface *surface = screen->copyToDFBSurface(img, format, + cache + ? QDirectFBScreen::TrackSurface + : QDirectFBScreen::DontTrackSurface); + if (cache) { + CachedImage *cachedImage = new CachedImage; + const_cast<QImage&>(img).data_ptr()->is_cached = true; + cachedImage->surface = surface; + imageCache.insert(key, cachedImage, cost); + } else { + *release = true; + } + return surface; +#endif +} + + +void QDirectFBPaintEnginePrivate::blit(const QRectF &dest, IDirectFBSurface *s, const QRectF &src) +{ + const QRect sr = src.toRect(); + const QRect dr = transform.mapRect(dest).toRect(); + const DFBRectangle sRect = { sr.x(), sr.y(), sr.width(), sr.height() }; + DFBResult result; + + if (dr.size() == sr.size()) { + result = surface->Blit(surface, s, &sRect, dr.x(), dr.y()); + } else { + const DFBRectangle dRect = { dr.x(), dr.y(), dr.width(), dr.height() }; + result = surface->StretchBlit(surface, s, &sRect, &dRect); + } + if (result != DFB_OK) + DirectFBError("QDirectFBPaintEngine::drawPixmap()", result); +} + +void QDirectFBPaintEnginePrivate::drawTiledPixmap(const QRectF &dest, + const QPixmap &pixmap) +{ + prepareForBlit(pixmap.hasAlphaChannel()); + QPixmapData *data = pixmap.pixmapData(); + Q_ASSERT(data->classId() == QPixmapData::DirectFBClass); + QDirectFBPixmapData *dfbData = static_cast<QDirectFBPixmapData*>(data); + IDirectFBSurface *s = dfbData->directFBSurface(); + const QRect dr = transform.mapRect(dest).toRect(); + DFBResult result = DFB_OK; + + if (scale == NoScale && dr == QRect(0, 0, fbWidth, fbHeight)) { + result = surface->TileBlit(surface, s, 0, 0, 0); + } else if (scale == NoScale) { + const int dx = pixmap.width(); + const int dy = pixmap.height(); + const DFBRectangle rect = { 0, 0, dx, dy }; + QVarLengthArray<DFBRectangle> rects; + QVarLengthArray<DFBPoint> points; + + for (int y = dr.y(); y <= dr.bottom(); y += dy) { + for (int x = dr.x(); x <= dr.right(); x += dx) { + rects.append(rect); + const DFBPoint point = { x, y }; + points.append(point); + } + } + result = surface->BatchBlit(surface, s, rects.constData(), + points.constData(), points.size()); + } else { + const QRect sr = transform.mapRect(QRect(0, 0, pixmap.width(), pixmap.height())); + const int dx = sr.width(); + const int dy = sr.height(); + const DFBRectangle sRect = { 0, 0, dx, dy }; + + for (int y = dr.y(); y <= dr.bottom(); y += dy) { + for (int x = dr.x(); x <= dr.right(); x += dx) { + const DFBRectangle dRect = { x, y, dx, dy }; + result = surface->StretchBlit(surface, s, &sRect, &dRect); + if (result != DFB_OK) { + y = dr.bottom() + 1; + break; + } + } + } + } + + if (result != DFB_OK) + DirectFBError("QDirectFBPaintEngine::drawTiledPixmap()", result); +} + +void QDirectFBPaintEnginePrivate::updateClip() +{ + if (!dirtyClip) + return; + + const QClipData *clipData = clip(); + if (!clipData || !clipData->enabled) { + surface->SetClip(surface, NULL); + dfbHandledClip = true; + } else if (clipData->hasRectClip) { + const DFBRegion r = { + clipData->clipRect.x(), + clipData->clipRect.y(), + clipData->clipRect.x() + clipData->clipRect.width(), + clipData->clipRect.y() + clipData->clipRect.height() + }; + surface->SetClip(surface, &r); + dfbHandledClip = true; + } else if (clipData->hasRegionClip && ignoreSystemClip && clipData->clipRegion == systemClip) { + dfbHandledClip = true; + } else { + dfbHandledClip = false; + } + + dirtyClip = false; +} + +void QDirectFBPaintEnginePrivate::systemStateChanged() +{ + dirtyClip = true; + QRasterPaintEnginePrivate::systemStateChanged(); +} + #endif // QT_NO_DIRECTFB diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.h b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.h index e79ec61..d33255b 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.h +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.h @@ -106,6 +106,7 @@ public: virtual void clip(const QVectorPath &path, Qt::ClipOperation op); virtual void clip(const QRect &rect, Qt::ClipOperation op); + static void initImageCache(int size); }; QT_END_HEADER diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp index ea9bb3a..7297a99 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp @@ -157,6 +157,16 @@ static bool checkForAlphaPixels(const QImage &img) return false; } +bool QDirectFBPixmapData::hasAlphaChannel(const QImage &img) +{ +#ifndef QT_NO_DIRECTFB_OPAQUE_DETECTION + return ::checkForAlphaPixels(img); +#else + return img.hasAlphaChannel(); +#endif +} + + void QDirectFBPixmapData::fromImage(const QImage &i, Qt::ImageConversionFlags flags) { @@ -166,7 +176,7 @@ void QDirectFBPixmapData::fromImage(const QImage &i, const QImage img = (i.depth() == 1 ? i.convertToFormat(screen->alphaPixmapFormat()) : i); if (img.hasAlphaChannel() #ifndef QT_NO_DIRECTFB_OPAQUE_DETECTION - && (flags & Qt::NoOpaqueDetection || ::checkForAlphaPixels(img)) + && (flags & Qt::NoOpaqueDetection || QDirectFBPixmapData::hasAlphaChannel(img)) #endif ) { alpha = true; @@ -357,7 +367,7 @@ QImage QDirectFBPixmapData::toImage() const return img->copy(); } -QPaintEngine* QDirectFBPixmapData::paintEngine() const +QPaintEngine *QDirectFBPixmapData::paintEngine() const { if (!engine) { // QDirectFBPixmapData is also a QCustomRasterPaintDevice, so pass @@ -368,10 +378,15 @@ QPaintEngine* QDirectFBPixmapData::paintEngine() const return engine; } +QImage *QDirectFBPixmapData::buffer() +{ + lockDirectFB(DSLF_READ|DSLF_WRITE); + return lockedImage; +} -QImage* QDirectFBPixmapData::buffer() +QImage * QDirectFBPixmapData::buffer(uint lockFlags) { - lockDirectFB(); + lockDirectFB(lockFlags); return lockedImage; } @@ -381,3 +396,4 @@ void QDirectFBPixmapData::invalidate() alpha = false; format = QImage::Format_Invalid; } + diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.h b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.h index 6cfafcd..7cd60d6 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.h +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.h @@ -69,11 +69,13 @@ public: Qt::TransformationMode mode) const; QImage toImage() const; QPaintEngine* paintEngine() const; - QImage *buffer(); + virtual QImage *buffer(); + QImage *buffer(uint lockFlags); // Pure virtual in QPixmapData, so re-implement here and delegate to QDirectFBPaintDevice int metric(QPaintDevice::PaintDeviceMetric m) const {return QDirectFBPaintDevice::metric(m);} inline QImage::Format pixelFormat() const { return format; } + static bool hasAlphaChannel(const QImage &img); private: void invalidate(); QDirectFBPaintEngine *engine; diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp index c1b75c5..f571d1b 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp @@ -40,7 +40,7 @@ ****************************************************************************/ #include "qdirectfbscreen.h" -#include "qdirectfbsurface.h" +#include "qdirectfbwindowsurface.h" #include "qdirectfbpixmap.h" #include "qdirectfbmouse.h" #include "qdirectfbkeyboard.h" @@ -113,9 +113,9 @@ QDirectFBScreenPrivate::~QDirectFBScreenPrivate() delete keyboard; #endif - foreach (IDirectFBSurface *surf, allocatedSurfaces) - surf->Release(surf); - allocatedSurfaces.clear(); + for (QSet<IDirectFBSurface*>::const_iterator it = allocatedSurfaces.begin(); it != allocatedSurfaces.end(); ++it) { + (*it)->Release(*it); + } if (dfbSurface) dfbSurface->Release(dfbSurface); @@ -350,6 +350,7 @@ QDirectFBScreen::DirectFBFlags QDirectFBScreen::directFBFlags() const { return d_ptr->directFBFlags; } + IDirectFB *QDirectFBScreen::dfb() { return d_ptr->dfb; @@ -751,43 +752,43 @@ struct FlagDescription { }; static const FlagDescription accelerationDescriptions[] = { - { "DFXL_NONE ", DFXL_NONE }, - { "DFXL_FILLRECTANGLE", DFXL_FILLRECTANGLE }, - { "DFXL_DRAWRECTANGLE", DFXL_DRAWRECTANGLE }, - { "DFXL_DRAWLINE", DFXL_DRAWLINE }, - { "DFXL_FILLTRIANGLE", DFXL_FILLTRIANGLE }, - { "DFXL_BLIT", DFXL_BLIT }, - { "DFXL_STRETCHBLIT", DFXL_STRETCHBLIT }, - { "DFXL_TEXTRIANGLES", DFXL_TEXTRIANGLES }, - { "DFXL_DRAWSTRING", DFXL_DRAWSTRING }, + { " DFXL_NONE ", DFXL_NONE }, + { " DFXL_FILLRECTANGLE", DFXL_FILLRECTANGLE }, + { " DFXL_DRAWRECTANGLE", DFXL_DRAWRECTANGLE }, + { " DFXL_DRAWLINE", DFXL_DRAWLINE }, + { " DFXL_FILLTRIANGLE", DFXL_FILLTRIANGLE }, + { " DFXL_BLIT", DFXL_BLIT }, + { " DFXL_STRETCHBLIT", DFXL_STRETCHBLIT }, + { " DFXL_TEXTRIANGLES", DFXL_TEXTRIANGLES }, + { " DFXL_DRAWSTRING", DFXL_DRAWSTRING }, { 0, 0 } }; static const FlagDescription blitDescriptions[] = { - { "DSBLIT_NOFX", DSBLIT_NOFX }, - { "DSBLIT_BLEND_ALPHACHANNEL", DSBLIT_BLEND_ALPHACHANNEL }, - { "DSBLIT_BLEND_COLORALPHA", DSBLIT_BLEND_COLORALPHA }, - { "DSBLIT_COLORIZE", DSBLIT_COLORIZE }, - { "DSBLIT_SRC_COLORKEY", DSBLIT_SRC_COLORKEY }, - { "DSBLIT_DST_COLORKEY", DSBLIT_DST_COLORKEY }, - { "DSBLIT_SRC_PREMULTIPLY", DSBLIT_SRC_PREMULTIPLY }, - { "DSBLIT_DST_PREMULTIPLY", DSBLIT_DST_PREMULTIPLY }, - { "DSBLIT_DEMULTIPLY", DSBLIT_DEMULTIPLY }, - { "DSBLIT_DEINTERLACE", DSBLIT_DEINTERLACE }, - { "DSBLIT_SRC_PREMULTCOLOR", DSBLIT_SRC_PREMULTCOLOR }, - { "DSBLIT_XOR", DSBLIT_XOR }, - { "DSBLIT_INDEX_TRANSLATION", DSBLIT_INDEX_TRANSLATION }, + { " DSBLIT_NOFX", DSBLIT_NOFX }, + { " DSBLIT_BLEND_ALPHACHANNEL", DSBLIT_BLEND_ALPHACHANNEL }, + { " DSBLIT_BLEND_COLORALPHA", DSBLIT_BLEND_COLORALPHA }, + { " DSBLIT_COLORIZE", DSBLIT_COLORIZE }, + { " DSBLIT_SRC_COLORKEY", DSBLIT_SRC_COLORKEY }, + { " DSBLIT_DST_COLORKEY", DSBLIT_DST_COLORKEY }, + { " DSBLIT_SRC_PREMULTIPLY", DSBLIT_SRC_PREMULTIPLY }, + { " DSBLIT_DST_PREMULTIPLY", DSBLIT_DST_PREMULTIPLY }, + { " DSBLIT_DEMULTIPLY", DSBLIT_DEMULTIPLY }, + { " DSBLIT_DEINTERLACE", DSBLIT_DEINTERLACE }, + { " DSBLIT_SRC_PREMULTCOLOR", DSBLIT_SRC_PREMULTCOLOR }, + { " DSBLIT_XOR", DSBLIT_XOR }, + { " DSBLIT_INDEX_TRANSLATION", DSBLIT_INDEX_TRANSLATION }, { 0, 0 } }; static const FlagDescription drawDescriptions[] = { - { "DSDRAW_NOFX", DSDRAW_NOFX }, - { "DSDRAW_BLEND", DSDRAW_BLEND }, - { "DSDRAW_DST_COLORKEY", DSDRAW_DST_COLORKEY }, - { "DSDRAW_SRC_PREMULTIPLY", DSDRAW_SRC_PREMULTIPLY }, - { "DSDRAW_DST_PREMULTIPLY", DSDRAW_DST_PREMULTIPLY }, - { "DSDRAW_DEMULTIPLY", DSDRAW_DEMULTIPLY }, - { "DSDRAW_XOR", DSDRAW_XOR }, + { " DSDRAW_NOFX", DSDRAW_NOFX }, + { " DSDRAW_BLEND", DSDRAW_BLEND }, + { " DSDRAW_DST_COLORKEY", DSDRAW_DST_COLORKEY }, + { " DSDRAW_SRC_PREMULTIPLY", DSDRAW_SRC_PREMULTIPLY }, + { " DSDRAW_DST_PREMULTIPLY", DSDRAW_DST_PREMULTIPLY }, + { " DSDRAW_DEMULTIPLY", DSDRAW_DEMULTIPLY }, + { " DSDRAW_XOR", DSDRAW_XOR }, { 0, 0 } }; #endif @@ -817,7 +818,7 @@ static const QByteArray flagDescriptions(uint mask, const FlagDescription *flags -static void printDirectFBInfo(IDirectFB *fb) +static void printDirectFBInfo(IDirectFB *fb, IDirectFBSurface *primarySurface) { DFBResult result; DFBGraphicsDeviceDescription dev; @@ -828,10 +829,14 @@ static void printDirectFBInfo(IDirectFB *fb) return; } - qDebug("Device: %s (%s), Driver: %s v%i.%i (%s)\n" - " acceleration: 0x%x%s,\nblit: 0x%x%s,\ndraw: 0x%0x%s\nvideo: %iKB\n", + DFBSurfacePixelFormat pixelFormat; + primarySurface->GetPixelFormat(primarySurface, &pixelFormat); + + qDebug("Device: %s (%s), Driver: %s v%i.%i (%s) Pixelformat: %d (%d)\n" + "acceleration: 0x%x%s\nblit: 0x%x%s\ndraw: 0x%0x%s\nvideo: %iKB\n", dev.name, dev.vendor, dev.driver.name, dev.driver.major, - dev.driver.minor, dev.driver.vendor, dev.acceleration_mask, + dev.driver.minor, dev.driver.vendor, DFB_PIXELFORMAT_INDEX(pixelFormat), + QDirectFBScreen::getImageFormat(primarySurface), dev.acceleration_mask, ::flagDescriptions(dev.acceleration_mask, accelerationDescriptions).constData(), dev.blitting_flags, ::flagDescriptions(dev.blitting_flags, blitDescriptions).constData(), dev.drawing_flags, ::flagDescriptions(dev.drawing_flags, drawDescriptions).constData(), @@ -882,9 +887,6 @@ bool QDirectFBScreen::connect(const QString &displaySpec) return false; } - if (displayArgs.contains(QLatin1String("debug"), Qt::CaseInsensitive)) - printDirectFBInfo(d_ptr->dfb); - if (displayArgs.contains(QLatin1String("videoonly"), Qt::CaseInsensitive)) d_ptr->directFBFlags |= VideoOnly; @@ -900,6 +902,12 @@ bool QDirectFBScreen::connect(const QString &displaySpec) d_ptr->directFBFlags |= BoundingRectFlip; } +#ifdef QT_DIRECTFB_IMAGECACHE + int imageCacheSize = 4 * 1024 * 1024; // 4 MB + ::setIntOption(displayArgs, QLatin1String("imagecachesize"), &imageCacheSize); + QDirectFBPaintEngine::initImageCache(imageCacheSize); +#endif + if (displayArgs.contains(QLatin1String("ignoresystemclip"), Qt::CaseInsensitive)) d_ptr->directFBFlags |= IgnoreSystemClip; @@ -945,6 +953,9 @@ bool QDirectFBScreen::connect(const QString &displaySpec) return false; } + if (displayArgs.contains(QLatin1String("debug"), Qt::CaseInsensitive)) + printDirectFBInfo(d_ptr->dfb, d_ptr->dfbSurface); + // Work out what format we're going to use for surfaces with an alpha channel d_ptr->alphaPixmapFormat = QDirectFBScreen::getImageFormat(d_ptr->dfbSurface); setPixelFormat(d_ptr->alphaPixmapFormat); @@ -1102,19 +1113,19 @@ QWSWindowSurface *QDirectFBScreen::createSurface(QWidget *widget) const { #ifdef QT_NO_DIRECTFB_WM if (QApplication::type() == QApplication::GuiServer) { - return new QDirectFBSurface(d_ptr->flipFlags, const_cast<QDirectFBScreen*>(this), widget); + return new QDirectFBWindowSurface(d_ptr->flipFlags, const_cast<QDirectFBScreen*>(this), widget); } else { return QScreen::createSurface(widget); } #else - return new QDirectFBSurface(d_ptr->flipFlags, const_cast<QDirectFBScreen*>(this), widget); + return new QDirectFBWindowSurface(d_ptr->flipFlags, const_cast<QDirectFBScreen*>(this), widget); #endif } QWSWindowSurface *QDirectFBScreen::createSurface(const QString &key) const { if (key == QLatin1String("directfb")) { - return new QDirectFBSurface(d_ptr->flipFlags, const_cast<QDirectFBScreen*>(this)); + return new QDirectFBWindowSurface(d_ptr->flipFlags, const_cast<QDirectFBScreen*>(this)); } return QScreen::createSurface(key); } @@ -1147,7 +1158,7 @@ void QDirectFBScreen::compose(const QRegion ®ion) const QPoint offset = win->requestedRegion().boundingRect().topLeft(); if (surface->key() == QLatin1String("directfb")) { - QDirectFBSurface *s = static_cast<QDirectFBSurface*>(surface); + QDirectFBWindowSurface *s = static_cast<QDirectFBWindowSurface*>(surface); blit(s->directFBSurface(), offset, r); } else { blit(surface->image(), offset, r); @@ -1196,7 +1207,7 @@ void QDirectFBScreen::compose(const QRegion ®ion) const QPoint offset = win->requestedRegion().boundingRect().topLeft(); if (surface->key() == QLatin1String("directfb")) { - QDirectFBSurface *s = static_cast<QDirectFBSurface*>(surface); + QDirectFBWindowSurface *s = static_cast<QDirectFBWindowSurface*>(surface); blit(s->directFBSurface(), offset, r); } else { blit(surface->image(), offset, r); @@ -1336,12 +1347,12 @@ bool QDirectFBScreen::initSurfaceDescriptionPixelFormat(DFBSurfaceDescription *d return true; } -uchar *QDirectFBScreen::lockSurface(IDirectFBSurface *surface, DFBSurfaceLockFlags flags, int *bpl) +uchar *QDirectFBScreen::lockSurface(IDirectFBSurface *surface, uint flags, int *bpl) { void *mem; - const DFBResult result = surface->Lock(surface, flags, static_cast<void**>(&mem), bpl); + const DFBResult result = surface->Lock(surface, static_cast<DFBSurfaceLockFlags>(flags), static_cast<void**>(&mem), bpl); if (result != DFB_OK) { - DirectFBError("QDirectFBPixmapData::lockSurface()", result); + DirectFBError("QDirectFBScreen::lockSurface()", result); } return reinterpret_cast<uchar*>(mem); diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h index 42d0ebe..84199a2 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h +++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h @@ -105,8 +105,6 @@ public: TrackSurface = 1 }; Q_DECLARE_FLAGS(SurfaceCreationOptions, SurfaceCreationOption); - IDirectFBSurface *createDFBSurface(DFBSurfaceDescription desc, - SurfaceCreationOptions options); IDirectFBSurface *createDFBSurface(const QImage &image, SurfaceCreationOptions options); IDirectFBSurface *createDFBSurface(const QSize &size, @@ -130,6 +128,7 @@ public: static bool initSurfaceDescriptionPixelFormat(DFBSurfaceDescription *description, QImage::Format format); static inline bool isPremultiplied(QImage::Format format); static inline bool hasAlpha(DFBSurfacePixelFormat format); + static inline bool hasAlpha(IDirectFBSurface *surface); QImage::Format alphaPixmapFormat() const; #ifndef QT_NO_DIRECTFB_PALETTE @@ -137,14 +136,17 @@ public: const QImage &image); #endif - static uchar *lockSurface(IDirectFBSurface *surface, DFBSurfaceLockFlags flags, int *bpl = 0); + static uchar *lockSurface(IDirectFBSurface *surface, uint flags, int *bpl = 0); private: + IDirectFBSurface *createDFBSurface(DFBSurfaceDescription desc, + SurfaceCreationOptions options); void compose(const QRegion &r); void blit(IDirectFBSurface *src, const QPoint &topLeft, const QRegion ®ion); QDirectFBScreenPrivate *d_ptr; + friend class SurfaceCache; }; Q_DECLARE_OPERATORS_FOR_FLAGS(QDirectFBScreen::SurfaceCreationOptions); @@ -186,6 +188,14 @@ inline bool QDirectFBScreen::hasAlpha(DFBSurfacePixelFormat format) } } +inline bool QDirectFBScreen::hasAlpha(IDirectFBSurface *surface) +{ + Q_ASSERT(surface); + DFBSurfacePixelFormat format; + surface->GetPixelFormat(surface, &format); + return QDirectFBScreen::hasAlpha(format); +} + QT_END_HEADER #endif // QDIRECTFBSCREEN_H diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp index beb9b5f..cd8796b 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp @@ -39,7 +39,7 @@ ** ****************************************************************************/ -#include "qdirectfbsurface.h" +#include "qdirectfbwindowsurface.h" #include "qdirectfbscreen.h" #include "qdirectfbpaintengine.h" @@ -50,7 +50,7 @@ //#define QT_DIRECTFB_DEBUG_SURFACES 1 -QDirectFBSurface::QDirectFBSurface(DFBSurfaceFlipFlags flip, QDirectFBScreen *scr) +QDirectFBWindowSurface::QDirectFBWindowSurface(DFBSurfaceFlipFlags flip, QDirectFBScreen *scr) : QDirectFBPaintDevice(scr) #ifndef QT_NO_DIRECTFB_WM , dfbWindow(0) @@ -66,7 +66,7 @@ QDirectFBSurface::QDirectFBSurface(DFBSurfaceFlipFlags flip, QDirectFBScreen *sc #endif } -QDirectFBSurface::QDirectFBSurface(DFBSurfaceFlipFlags flip, QDirectFBScreen *scr, QWidget *widget) +QDirectFBWindowSurface::QDirectFBWindowSurface(DFBSurfaceFlipFlags flip, QDirectFBScreen *scr, QWidget *widget) : QWSWindowSurface(widget), QDirectFBPaintDevice(scr) #ifndef QT_NO_DIRECTFB_WM , dfbWindow(0) @@ -86,17 +86,17 @@ QDirectFBSurface::QDirectFBSurface(DFBSurfaceFlipFlags flip, QDirectFBScreen *sc #endif } -QDirectFBSurface::~QDirectFBSurface() +QDirectFBWindowSurface::~QDirectFBWindowSurface() { } -bool QDirectFBSurface::isValid() const +bool QDirectFBWindowSurface::isValid() const { return true; } #ifndef QT_NO_DIRECTFB_WM -void QDirectFBSurface::createWindow() +void QDirectFBWindowSurface::createWindow() { #ifdef QT_NO_DIRECTFB_LAYER #warning QT_NO_DIRECTFB_LAYER requires QT_NO_DIRECTFB_WM @@ -132,7 +132,7 @@ void QDirectFBSurface::createWindow() } #endif // QT_NO_DIRECTFB_WM -void QDirectFBSurface::setGeometry(const QRect &rect, const QRegion &mask) +void QDirectFBWindowSurface::setGeometry(const QRect &rect, const QRegion &mask) { if (rect.isNull()) { #ifndef QT_NO_DIRECTFB_WM @@ -178,15 +178,7 @@ void QDirectFBSurface::setGeometry(const QRect &rect, const QRegion &mask) "Unable to get DirectFB handle!"); } - DFBSurfaceDescription description; - description.flags = DFBSurfaceDescriptionFlags(DSDESC_WIDTH | - DSDESC_HEIGHT | - DSDESC_PIXELFORMAT); - description.width = rect.width(); - description.height = rect.height(); - QDirectFBScreen::initSurfaceDescriptionPixelFormat(&description, - screen->pixelFormat()); - dfbSurface = screen->createDFBSurface(description, false); + dfbSurface = screen->createDFBSurface(rect.size(), screen->pixelFormat(), QDirectFBScreen::DontTrackSurface); forceRaster = (dfbSurface && QDirectFBScreen::getImageFormat(dfbSurface) == QImage::Format_RGB32); } else { Q_ASSERT(dfbSurface); @@ -211,13 +203,13 @@ void QDirectFBSurface::setGeometry(const QRect &rect, const QRegion &mask) } if (result != DFB_OK) - DirectFBErrorFatal("QDirectFBSurface::setGeometry()", result); + DirectFBErrorFatal("QDirectFBWindowSurface::setGeometry()", result); } QWSWindowSurface::setGeometry(rect, mask); } -QByteArray QDirectFBSurface::permanentState() const +QByteArray QDirectFBWindowSurface::permanentState() const { QByteArray array; #ifdef QT_NO_DIRECTFB_WM @@ -236,7 +228,7 @@ QByteArray QDirectFBSurface::permanentState() const return array; } -void QDirectFBSurface::setPermanentState(const QByteArray &state) +void QDirectFBWindowSurface::setPermanentState(const QByteArray &state) { SurfaceFlags flags; const char *ptr = state.constData(); @@ -250,7 +242,7 @@ void QDirectFBSurface::setPermanentState(const QByteArray &state) #endif } -bool QDirectFBSurface::scroll(const QRegion ®ion, int dx, int dy) +bool QDirectFBWindowSurface::scroll(const QRegion ®ion, int dx, int dy) { if (!dfbSurface || !(flipFlags & DSFLIP_BLIT)) return false; @@ -278,7 +270,7 @@ bool QDirectFBSurface::scroll(const QRegion ®ion, int dx, int dy) return true; } -bool QDirectFBSurface::move(const QPoint &offset) +bool QDirectFBWindowSurface::move(const QPoint &offset) { QWSWindowSurface::move(offset); @@ -293,7 +285,7 @@ bool QDirectFBSurface::move(const QPoint &offset) #endif } -QRegion QDirectFBSurface::move(const QPoint &offset, const QRegion &newClip) +QRegion QDirectFBWindowSurface::move(const QPoint &offset, const QRegion &newClip) { #ifdef QT_NO_DIRECTFB_WM return QWSWindowSurface::move(offset, newClip); @@ -306,10 +298,10 @@ QRegion QDirectFBSurface::move(const QPoint &offset, const QRegion &newClip) #endif } -QPaintEngine* QDirectFBSurface::paintEngine() const +QPaintEngine* QDirectFBWindowSurface::paintEngine() const { if (!engine) { - QDirectFBSurface *that = const_cast<QDirectFBSurface*>(this); + QDirectFBWindowSurface *that = const_cast<QDirectFBWindowSurface*>(this); that->engine = new QDirectFBPaintEngine(that); return that->engine; } @@ -339,8 +331,8 @@ inline bool isWidgetOpaque(const QWidget *w) return false; } -void QDirectFBSurface::flush(QWidget *widget, const QRegion ®ion, - const QPoint &offset) +void QDirectFBWindowSurface::flush(QWidget *widget, const QRegion ®ion, + const QPoint &offset) { Q_UNUSED(widget); #ifdef QT_NO_DIRECTFB_WM @@ -402,15 +394,15 @@ void QDirectFBSurface::flush(QWidget *widget, const QRegion ®ion, } -void QDirectFBSurface::beginPaint(const QRegion &) +void QDirectFBWindowSurface::beginPaint(const QRegion &) { } -void QDirectFBSurface::endPaint(const QRegion &) +void QDirectFBWindowSurface::endPaint(const QRegion &) { #ifdef QT_DIRECTFB_DEBUG_SURFACES if (bufferImages.count()) { - qDebug("QDirectFBSurface::endPaint() this=%p", this); + qDebug("QDirectFBWindowSurface::endPaint() this=%p", this); foreach(QImage* bufferImg, bufferImages) qDebug(" Deleting buffer image %p", bufferImg); @@ -423,7 +415,7 @@ void QDirectFBSurface::endPaint(const QRegion &) } -QImage* QDirectFBSurface::buffer(const QWidget *widget) +QImage *QDirectFBWindowSurface::buffer(const QWidget *widget) { if (!lockedImage) return 0; @@ -441,7 +433,7 @@ QImage* QDirectFBSurface::buffer(const QWidget *widget) bufferImages.append(img); #ifdef QT_DIRECTFB_DEBUG_SURFACES - qDebug("QDirectFBSurface::buffer() Created & returned %p", img); + qDebug("QDirectFBWindowSurface::buffer() Created & returned %p", img); #endif return img; diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbsurface.h b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.h index 54c14a5..75998c4 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbsurface.h +++ b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.h @@ -58,12 +58,12 @@ QT_BEGIN_HEADER QT_MODULE(Gui) -class QDirectFBSurface: public QWSWindowSurface, public QDirectFBPaintDevice +class QDirectFBWindowSurface : public QWSWindowSurface, public QDirectFBPaintDevice { public: - QDirectFBSurface(DFBSurfaceFlipFlags flipFlags, QDirectFBScreen* scr); - QDirectFBSurface(DFBSurfaceFlipFlags flipFlags, QDirectFBScreen* scr, QWidget *widget); - ~QDirectFBSurface(); + QDirectFBWindowSurface(DFBSurfaceFlipFlags flipFlags, QDirectFBScreen* scr); + QDirectFBWindowSurface(DFBSurfaceFlipFlags flipFlags, QDirectFBScreen* scr, QWidget *widget); + ~QDirectFBWindowSurface(); bool isValid() const; @@ -79,15 +79,15 @@ public: QRegion move(const QPoint &offset, const QRegion &newClip); QImage image() const { return QImage(); } - QPaintDevice* paintDevice() { return this; } - QPaintEngine* paintEngine() const; + QPaintDevice *paintDevice() { return this; } + QPaintEngine *paintEngine() const; void flush(QWidget *widget, const QRegion ®ion, const QPoint &offset); void beginPaint(const QRegion &); void endPaint(const QRegion &); - QImage* buffer(const QWidget *widget); + QImage *buffer(const QWidget *widget); private: #ifndef QT_NO_DIRECTFB_WM diff --git a/src/plugins/gfxdrivers/powervr/QWSWSEGL/QWSWSEGL.pro b/src/plugins/gfxdrivers/powervr/QWSWSEGL/QWSWSEGL.pro index b62894d..9331d0a 100644 --- a/src/plugins/gfxdrivers/powervr/QWSWSEGL/QWSWSEGL.pro +++ b/src/plugins/gfxdrivers/powervr/QWSWSEGL/QWSWSEGL.pro @@ -22,3 +22,5 @@ LIBS += -lpvr2d DESTDIR = $$QMAKE_LIBDIR_QT target.path = $$[QT_INSTALL_LIBS] INSTALLS += target + +include(../powervr.pri)
\ No newline at end of file diff --git a/src/plugins/gfxdrivers/powervr/README b/src/plugins/gfxdrivers/powervr/README index ec02efb..4dce87f 100644 --- a/src/plugins/gfxdrivers/powervr/README +++ b/src/plugins/gfxdrivers/powervr/README @@ -29,12 +29,13 @@ strictly Unix-style markers. *************************************************************************** * IMPORTANT: To build the QScreen plugin and the WSEGL library it depends * -* on, the pvr2d.h, wsegl.h headers for your platform are required. These * -* can be obtained either through your platform provider or directly from * -* Imagination Technologies. * +* on, the pvr2d.h, wsegl.h headers for your platform are required. You * +* can find a copy of these headers in src/3rdparty/powervr for SGX based * +* platforms like the TI OMAP3xxx. They may also work on MBX platforms too * +* depending on how old your libEGL is. You can tell Qt where to find * +* these headers by setting QMAKE_INCDIR_POWERVR in the mkspec. * *************************************************************************** - When you start a Qt/Embedded application, you should modify the QWS_DISPLAY environment variable to use the "powervr" driver instead of "LinuxFb". For example, if your original QWS_DISPLAY variable was: diff --git a/src/plugins/gfxdrivers/powervr/powervr.pri b/src/plugins/gfxdrivers/powervr/powervr.pri new file mode 100644 index 0000000..9df8c0e --- /dev/null +++ b/src/plugins/gfxdrivers/powervr/powervr.pri @@ -0,0 +1,2 @@ + +INCLUDEPATH += $$QMAKE_INCDIR_POWERVR diff --git a/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.pro b/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.pro index 691cd2d..675be85 100644 --- a/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.pro +++ b/src/plugins/gfxdrivers/powervr/pvreglscreen/pvreglscreen.pro @@ -9,9 +9,10 @@ DEFINES += QT_QWS_CLIENTBLIT INCLUDEPATH += ../QWSWSEGL + HEADERS = \ - pvreglscreen.h \ - pvreglwindowsurface.h + pvreglscreen.h \ + pvreglwindowsurface.h SOURCES = \ pvreglscreenplugin.cpp \ @@ -22,3 +23,5 @@ QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/gfxdrivers target.path = $$[QT_INSTALL_PLUGINS]/gfxdrivers INSTALLS += target + +include(../powervr.pri)
\ No newline at end of file |