summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAnders Bakken <anders.bakken@nokia.com>2009-08-24 15:19:07 (GMT)
committerAnders Bakken <anders.bakken@nokia.com>2009-08-25 18:25:09 (GMT)
commitdc4e9f4bb91237b26b82e27310eda6808786ce36 (patch)
tree4071cdf55469fc28d004fa877093cf859f620837 /src
parent9dc0914b30a3266be586e1dece931bcdb2f21e49 (diff)
downloadQt-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')
-rw-r--r--src/plugins/gfxdrivers/directfb/directfb.pro1
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp155
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbpixmap.h9
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbscreen.h11
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 &region, 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);