summaryrefslogtreecommitdiffstats
path: root/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp
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/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp
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/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp')
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp155
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)