diff options
author | Anders Bakken <anders.bakken@nokia.com> | 2009-08-24 15:19:07 (GMT) |
---|---|---|
committer | Anders Bakken <anders.bakken@nokia.com> | 2009-08-25 18:25:09 (GMT) |
commit | dc4e9f4bb91237b26b82e27310eda6808786ce36 (patch) | |
tree | 4071cdf55469fc28d004fa877093cf859f620837 /src/plugins | |
parent | 9dc0914b30a3266be586e1dece931bcdb2f21e49 (diff) | |
download | Qt-dc4e9f4bb91237b26b82e27310eda6808786ce36.zip Qt-dc4e9f4bb91237b26b82e27310eda6808786ce36.tar.gz Qt-dc4e9f4bb91237b26b82e27310eda6808786ce36.tar.bz2 |
Implement support for DirectFB image providers
Reimplement QPixmapData::fromFile/fromData to load images using
IDirectFBImage providers. This functionality might be accelerated on
embedded boards and could have potentially large performance
enhancements.
Reviewed-by: Donald Carr <donald.carr@nokia.com>
Diffstat (limited to 'src/plugins')
-rw-r--r-- | src/plugins/gfxdrivers/directfb/directfb.pro | 1 | ||||
-rw-r--r-- | src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp | 155 | ||||
-rw-r--r-- | src/plugins/gfxdrivers/directfb/qdirectfbpixmap.h | 9 | ||||
-rw-r--r-- | src/plugins/gfxdrivers/directfb/qdirectfbscreen.h | 11 |
4 files changed, 172 insertions, 4 deletions
diff --git a/src/plugins/gfxdrivers/directfb/directfb.pro b/src/plugins/gfxdrivers/directfb/directfb.pro index 5c60b2f..f01d8b1 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_IMAGEPROVIDER #DEFINES += QT_DIRECTFB_IMAGECACHE #DEFINES += QT_NO_DIRECTFB_WM #DEFINES += QT_NO_DIRECTFB_LAYER diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp index 7231dd5..caa973f 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp @@ -45,6 +45,7 @@ #include "qdirectfbpaintengine.h" #include <QtGui/qbitmap.h> +#include <QtCore/qfile.h> #include <directfb.h> static int global_ser_no = 0; @@ -167,6 +168,160 @@ bool QDirectFBPixmapData::hasAlphaChannel(const QImage &img) #endif } +#ifdef QT_DIRECTFB_IMAGEPROVIDER +bool QDirectFBPixmapData::fromFile(const QString &filename, const char *format, + Qt::ImageConversionFlags flags) +{ + if (flags == Qt::AutoColor) { + if (filename.startsWith(QLatin1Char(':'))) { // resource + QFile file(filename); + if (!file.open(QIODevice::ReadOnly)) + return false; + const QByteArray data = file.readAll(); + file.close(); + return fromData(reinterpret_cast<const uchar*>(data.constData()), data.size(), format, flags); + } else { + DFBDataBufferDescription description; + description.flags = DBDESC_FILE; + const QByteArray fileNameData = filename.toLocal8Bit(); + description.file = fileNameData.constData(); + if (fromDataBufferDescription(description)) { + return true; + } + // fall back to Qt + } + } + return QPixmapData::fromFile(filename, format, flags); +} + +bool QDirectFBPixmapData::fromData(const uchar *buffer, uint len, const char *format, + Qt::ImageConversionFlags flags) +{ + if (flags == Qt::AutoColor) { + DFBDataBufferDescription description; + description.flags = DBDESC_MEMORY; + description.memory.data = buffer; + description.memory.length = len; + if (fromDataBufferDescription(description)) + return true; + // fall back to Qt + } + return QPixmapData::fromData(buffer, len, format, flags); +} + +template <typename T> class QDirectFBPointer +{ +public: + QDirectFBPointer(T *tt = 0) : t(tt) {} + ~QDirectFBPointer() { if (t) t->Release(t); } + + inline T* operator->() { return t; } + inline operator T*() { return t; } + + inline T** operator&() { return &t; } + inline bool operator!() const { return !t; } + inline T *data() { return t; } + inline const T *data() const { return t; } + + T *t; +}; + +bool QDirectFBPixmapData::fromDataBufferDescription(const DFBDataBufferDescription &dataBufferDescription) +{ + IDirectFB *dfb = screen->dfb(); + Q_ASSERT(dfb); + QDirectFBPointer<IDirectFBDataBuffer> dataBuffer; + DFBResult result = DFB_OK; + if ((result = dfb->CreateDataBuffer(dfb, &dataBufferDescription, &dataBuffer)) != DFB_OK) { + DirectFBError("QDirectFBPixmapData::fromDataBufferDescription()", result); + return false; + } + + QDirectFBPointer<IDirectFBImageProvider> provider; + if ((result = dataBuffer->CreateImageProvider(dataBuffer, &provider)) != DFB_OK) { + DirectFBError("QDirectFBPixmapData::fromDataBufferDescription(): Can't create image provider", result); + return false; + } + + DFBSurfaceDescription surfaceDescription; + if ((result = provider->GetSurfaceDescription(provider, &surfaceDescription)) != DFB_OK) { + DirectFBError("QDirectFBPixmapData::fromDataBufferDescription(): Can't get surface description", result); + return false; + } + + QDirectFBPointer<IDirectFBSurface> surfaceFromDescription = screen->createDFBSurface(surfaceDescription, QDirectFBScreen::DontTrackSurface, &result); + if (!surfaceFromDescription) { + DirectFBError("QDirectFBPixmapData::fromSurfaceDescription(): Can't create surface", result); + return false; + } + + result = provider->RenderTo(provider, surfaceFromDescription, 0); + if (result != DFB_OK) { + DirectFBError("QDirectFBPixmapData::fromSurfaceDescription(): Can't render to surface", result); + return false; + } + + DFBImageDescription imageDescription; + result = provider->GetImageDescription(provider, &imageDescription); + if (result != DFB_OK) { + DirectFBError("QDirectFBPixmapData::fromSurfaceDescription(): Can't get image description", result); + return false; + } + + alpha = imageDescription.caps & (DICAPS_ALPHACHANNEL|DICAPS_COLORKEY); + imageFormat = alpha ? screen->alphaPixmapFormat() : screen->pixelFormat(); + + dfbSurface = screen->createDFBSurface(QSize(surfaceDescription.width, surfaceDescription.height), + imageFormat, QDirectFBScreen::TrackSurface); + if (alpha) + dfbSurface->Clear(dfbSurface, 0, 0, 0, 0); + + DFBSurfaceBlittingFlags blittingFlags = DSBLIT_NOFX; + if (imageDescription.caps & DICAPS_COLORKEY) { + blittingFlags |= DSBLIT_SRC_COLORKEY; + result = surfaceFromDescription->SetSrcColorKey(surfaceFromDescription, + imageDescription.colorkey_r, + imageDescription.colorkey_g, + imageDescription.colorkey_b); + if (result != DFB_OK) { + DirectFBError("QDirectFBPixmapData::fromSurfaceDescription: Can't set src color key", result); + invalidate(); // release dfbSurface + return false; + } + } + if (imageDescription.caps & DICAPS_ALPHACHANNEL) { + blittingFlags |= DSBLIT_BLEND_ALPHACHANNEL; + } + result = dfbSurface->SetBlittingFlags(dfbSurface, blittingFlags); + if (result != DFB_OK) { + DirectFBError("QDirectFBPixmapData::fromSurfaceDescription: Can't set blitting flags", result); + invalidate(); // release dfbSurface + return false; + } + + result = dfbSurface->Blit(dfbSurface, surfaceFromDescription, 0, 0, 0); + if (result != DFB_OK) { + DirectFBError("QDirectFBPixmapData::fromSurfaceDescription: Can't blit to surface", result); + invalidate(); // release dfbSurface + return false; + } + if (blittingFlags != DSBLIT_NOFX) { + dfbSurface->SetBlittingFlags(dfbSurface, DSBLIT_NOFX); + } + + + w = surfaceDescription.width; + h = surfaceDescription.height; + is_null = (w <= 0 || h <= 0); + d = QDirectFBScreen::depth(imageFormat); + setSerialNumber(++global_ser_no); +#if (Q_DIRECTFB_VERSION >= 0x010000) + dfbSurface->ReleaseSource(dfbSurface); +#endif + return true; +} + +#endif void QDirectFBPixmapData::fromImage(const QImage &image, Qt::ImageConversionFlags flags) diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.h b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.h index c8dda0c..f0ae2f8 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.h +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.h @@ -62,6 +62,12 @@ public: // Re-implemented from QPixmapData: virtual void resize(int width, int height); virtual void fromImage(const QImage &image, Qt::ImageConversionFlags flags); +#ifdef QT_DIRECTFB_IMAGEPROVIDER + virtual bool fromFile(const QString &filename, const char *format, + Qt::ImageConversionFlags flags); + virtual bool fromData(const uchar *buffer, uint len, const char *format, + Qt::ImageConversionFlags flags); +#endif virtual void copy(const QPixmapData *data, const QRect &rect); virtual void fill(const QColor &color); virtual QPixmap transformed(const QTransform &matrix, @@ -78,6 +84,9 @@ public: static bool hasAlphaChannel(const QImage &img); inline bool hasAlphaChannel() const { return alpha; } private: +#ifdef QT_DIRECTFB_IMAGEPROVIDER + bool fromDataBufferDescription(const DFBDataBufferDescription &dataBuffer); +#endif void invalidate(); bool alpha; }; diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h index e8da283..c61cde7 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h +++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h @@ -59,6 +59,9 @@ QT_MODULE(Gui) #if !defined QT_DIRECTFB_IMAGECACHE && !defined QT_NO_DIRECTFB_IMAGECACHE #define QT_NO_DIRECTFB_IMAGECACHE #endif +#if !defined QT_DIRECTFB_IMAGEPROVIDER && !defined QT_NO_DIRECTFB_IMAGEPROVIDER +#define QT_NO_DIRECTFB_IMAGEPROVIDER +#endif #if !defined QT_NO_DIRECTFB_PALETTE && !defined QT_DIRECTFB_PALETTE #define QT_DIRECTFB_PALETTE #endif @@ -162,6 +165,10 @@ public: QImage::Format format, SurfaceCreationOptions options, DFBResult *result = 0); + IDirectFBSurface *createDFBSurface(DFBSurfaceDescription desc, + SurfaceCreationOptions options, + DFBResult *result); + void flipSurface(IDirectFBSurface *surface, DFBSurfaceFlipFlags flipFlags, const QRegion ®ion, const QPoint &offset); void releaseDFBSurface(IDirectFBSurface *surface); @@ -188,11 +195,7 @@ public: static uchar *lockSurface(IDirectFBSurface *surface, uint flags, int *bpl = 0); private: - IDirectFBSurface *createDFBSurface(DFBSurfaceDescription desc, - SurfaceCreationOptions options, - DFBResult *result); QDirectFBScreenPrivate *d_ptr; - friend class SurfaceCache; }; Q_DECLARE_OPERATORS_FOR_FLAGS(QDirectFBScreen::SurfaceCreationOptions); |