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/gfxdrivers/directfb/qdirectfbpixmap.cpp | |
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/gfxdrivers/directfb/qdirectfbpixmap.cpp')
-rw-r--r-- | src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp | 155 |
1 files changed, 155 insertions, 0 deletions
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) |