Update copyright year in license headers.
[profile/ivi/qtbase.git] / src / plugins / platforms / directfb / qdirectfbblitter.cpp
index 86a8bf7..bb5fa0b 100644 (file)
@@ -1,6 +1,6 @@
 /****************************************************************************
 **
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
 ** All rights reserved.
 ** Contact: Nokia Corporation (qt-info@nokia.com)
 **
 #include <QtGui/private/qpixmap_blitter_p.h>
 
 #include <QDebug>
+#include <QFile>
 
 #include <directfb.h>
 
+QT_BEGIN_NAMESPACE
+
+static QBlittable::Capabilities dfb_blitter_capabilities()
+{
+    return QBlittable::Capabilities(QBlittable::SolidRectCapability
+                                    |QBlittable::SourcePixmapCapability
+                                    |QBlittable::SourceOverPixmapCapability
+                                    |QBlittable::SourceOverScaledPixmapCapability);
+}
+
 QDirectFbBlitter::QDirectFbBlitter(const QSize &rect, IDirectFBSurface *surface)
-        : QBlittable(rect, QBlittable::Capabilities(QBlittable::SolidRectCapability
-                                                          |QBlittable::SourcePixmapCapability
-                                                          |QBlittable::SourceOverPixmapCapability
-                                                          |QBlittable::SourceOverScaledPixmapCapability))
+    : QBlittable(rect, dfb_blitter_capabilities())
+        , m_surface(surface)
 {
-    if (surface) {
-        m_surface = surface;
-    } else {
-        DFBSurfaceDescription surfaceDesc;
-        memset(&surfaceDesc,0,sizeof(DFBSurfaceDescription));
-        surfaceDesc.width = rect.width();
-        surfaceDesc.height = rect.height();
+        m_surface->AddRef(m_surface.data());
+}
+
+QDirectFbBlitter::QDirectFbBlitter(const QSize &rect, bool alpha)
+    : QBlittable(rect, dfb_blitter_capabilities())
+{
+    DFBSurfaceDescription surfaceDesc;
+    memset(&surfaceDesc,0,sizeof(DFBSurfaceDescription));
+    surfaceDesc.width = rect.width();
+    surfaceDesc.height = rect.height();
+
+    if (alpha) {
         surfaceDesc.caps = DSCAPS_PREMULTIPLIED;
-        surfaceDesc.pixelformat = DSPF_ARGB;
+        surfaceDesc.pixelformat = QDirectFbBlitter::alphaPixmapFormat();
         surfaceDesc.flags = DFBSurfaceDescriptionFlags(DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_CAPS | DSDESC_PIXELFORMAT);
-
-        IDirectFB *dfb = QDirectFbConvenience::dfbInterface();
-        dfb->CreateSurface(dfb,&surfaceDesc, &m_surface);
-        m_surface->Clear(m_surface,0,0,0,0);
+    } else {
+        surfaceDesc.flags = DFBSurfaceDescriptionFlags(DSDESC_WIDTH | DSDESC_HEIGHT | DSDESC_PIXELFORMAT);
+        surfaceDesc.pixelformat = QDirectFbBlitter::pixmapFormat();
     }
 
+
+    IDirectFB *dfb = QDirectFbConvenience::dfbInterface();
+    dfb->CreateSurface(dfb , &surfaceDesc, m_surface.outPtr());
+    m_surface->Clear(m_surface.data(), 0, 0, 0, 0);
 }
 
 QDirectFbBlitter::~QDirectFbBlitter()
 {
     unlock();
-    m_surface->Release(m_surface);
+}
+
+DFBSurfacePixelFormat QDirectFbBlitter::alphaPixmapFormat()
+{
+    return DSPF_ARGB;
+}
+
+DFBSurfacePixelFormat QDirectFbBlitter::pixmapFormat()
+{
+    return DSPF_RGB32;
+}
+
+DFBSurfacePixelFormat QDirectFbBlitter::selectPixmapFormat(bool withAlpha)
+{
+    return withAlpha ? alphaPixmapFormat() : pixmapFormat();
 }
 
 void QDirectFbBlitter::fillRect(const QRectF &rect, const QColor &color)
 {
-    m_surface->SetColor(m_surface, color.red(), color.green(), color.blue(), color.alpha());
+    m_surface->SetColor(m_surface.data(), color.red(), color.green(), color.blue(), color.alpha());
 //    When the blitter api supports non opaque blits, also remember to change
 //    qpixmap_blitter.cpp::fill
 //    DFBSurfaceDrawingFlags drawingFlags = color.alpha() ? DSDRAW_BLEND : DSDRAW_NOFX;
 //    m_surface->SetDrawingFlags(m_surface, drawingFlags);
-    m_surface->SetDrawingFlags(m_surface, DSDRAW_NOFX);
-    m_surface->FillRectangle(m_surface, rect.x(), rect.y(),
+    m_surface->SetDrawingFlags(m_surface.data(), DSDRAW_NOFX);
+    m_surface->FillRectangle(m_surface.data(), rect.x(), rect.y(),
                               rect.width(), rect.height());
 }
 
 void QDirectFbBlitter::drawPixmap(const QRectF &rect, const QPixmap &pixmap, const QRectF &srcRect)
 {
-    QPixmapData *data = pixmap.pixmapData();
+    QPlatformPixmap *data = pixmap.handle();
     Q_ASSERT(data->width() && data->height());
-    Q_ASSERT(data->classId() == QPixmapData::BlitterClass);
-    QBlittablePixmapData *blitPm = static_cast<QBlittablePixmapData*>(data);
+    Q_ASSERT(data->classId() == QPlatformPixmap::BlitterClass);
+    QBlittablePlatformPixmap *blitPm = static_cast<QBlittablePlatformPixmap*>(data);
     QDirectFbBlitter *dfbBlitter = static_cast<QDirectFbBlitter *>(blitPm->blittable());
     dfbBlitter->unlock();
 
-    IDirectFBSurface *s = dfbBlitter->m_surface;
+    IDirectFBSurface *s = dfbBlitter->m_surface.data();
 
     DFBSurfaceBlittingFlags blittingFlags = DSBLIT_NOFX;
     DFBSurfacePorterDuffRule porterDuff = DSPD_SRC;
@@ -108,18 +139,18 @@ void QDirectFbBlitter::drawPixmap(const QRectF &rect, const QPixmap &pixmap, con
         porterDuff = DSPD_SRC_OVER;
     }
 
-    m_surface->SetBlittingFlags(m_surface, DFBSurfaceBlittingFlags(blittingFlags));
-    m_surface->SetPorterDuff(m_surface,porterDuff);
-    m_surface->SetDstBlendFunction(m_surface,DSBF_INVSRCALPHA);
+    m_surface->SetBlittingFlags(m_surface.data(), DFBSurfaceBlittingFlags(blittingFlags));
+    m_surface->SetPorterDuff(m_surface.data(), porterDuff);
+    m_surface->SetDstBlendFunction(m_surface.data(), DSBF_INVSRCALPHA);
 
     const DFBRectangle sRect = { srcRect.x(), srcRect.y(), srcRect.width(), srcRect.height() };
 
     DFBResult result;
     if (rect.width() == srcRect.width() && rect.height() == srcRect.height())
-        result = m_surface->Blit(m_surface, s, &sRect, rect.x(), rect.y());
+        result = m_surface->Blit(m_surface.data(), s, &sRect, rect.x(), rect.y());
     else {
         const DFBRectangle dRect = { rect.x(), rect.y(), rect.width(), rect.height() };
-        result = m_surface->StretchBlit(m_surface, s, &sRect, &dRect);
+        result = m_surface->StretchBlit(m_surface.data(), s, &sRect, &dRect);
     }
     if (result != DFB_OK)
         DirectFBError("QDirectFBBlitter::drawPixmap()", result);
@@ -132,15 +163,15 @@ QImage *QDirectFbBlitter::doLock()
 
     void *mem;
     int bpl;
-    const DFBResult result = m_surface->Lock(m_surface, DFBSurfaceLockFlags(DSLF_WRITE|DSLF_READ), static_cast<void**>(&mem), &bpl);
+    const DFBResult result = m_surface->Lock(m_surface.data(), DFBSurfaceLockFlags(DSLF_WRITE|DSLF_READ), static_cast<void**>(&mem), &bpl);
     if (result == DFB_OK) {
         DFBSurfacePixelFormat dfbFormat;
         DFBSurfaceCapabilities dfbCaps;
-        m_surface->GetPixelFormat(m_surface,&dfbFormat);
-        m_surface->GetCapabilities(m_surface,&dfbCaps);
+        m_surface->GetPixelFormat(m_surface.data(), &dfbFormat);
+        m_surface->GetCapabilities(m_surface.data(), &dfbCaps);
         QImage::Format format = QDirectFbConvenience::imageFormatFromSurfaceFormat(dfbFormat, dfbCaps);
         int w, h;
-        m_surface->GetSize(m_surface,&w,&h);
+        m_surface->GetSize(m_surface.data(), &w, &h);
         m_image = QImage(static_cast<uchar *>(mem),w,h,bpl,format);
     } else {
         DirectFBError("Failed to lock image", result);
@@ -149,7 +180,97 @@ QImage *QDirectFbBlitter::doLock()
     return &m_image;
 }
 
+bool QDirectFbBlitterPlatformPixmap::fromDataBufferDescription(const DFBDataBufferDescription &dataBufferDescription)
+{
+    DFBResult result;
+    IDirectFB *dfb = QDirectFbConvenience::dfbInterface();
+
+    // Create a data buffer
+    QDirectFBPointer<IDirectFBDataBuffer> dataBuffer;
+    result = dfb->CreateDataBuffer(dfb, &dataBufferDescription, dataBuffer.outPtr());
+    if (result != DFB_OK) {
+        DirectFBError(QDFB_PRETTY, result);
+        return false;
+    }
+
+    // Create the image provider
+    QDirectFBPointer<IDirectFBImageProvider> provider;
+    result = dataBuffer->CreateImageProvider(dataBuffer.data(), provider.outPtr());
+    if (result != DFB_OK) {
+        DirectFBError(QDFB_PRETTY, result);
+        return false;
+    }
+
+    // Extract image information
+    DFBImageDescription imageDescription;
+    result = provider->GetImageDescription(provider.data(), &imageDescription);
+    if (result != DFB_OK) {
+        DirectFBError(QDFB_PRETTY, result);
+        return false;
+    }
+
+    // Can we handle this directlu?
+    if (imageDescription.caps & DICAPS_COLORKEY)
+        return false;
+
+    DFBSurfaceDescription surfaceDescription;
+    result = provider->GetSurfaceDescription(provider.data(), &surfaceDescription);
+    if (result != DFB_OK) {
+        DirectFBError(QDFB_PRETTY, result);
+        return false;
+    }
+
+    m_alpha = imageDescription.caps & DICAPS_ALPHACHANNEL;
+    resize(surfaceDescription.width, surfaceDescription.height);
+    // TODO: FIXME; update d
+
+
+    result = provider->RenderTo(provider.data(), dfbBlitter()->dfbSurface(), 0);
+    if (result != DFB_OK) {
+        DirectFBError(QDFB_PRETTY, result);
+        return false;
+    }
+
+    return true;
+}
+
+bool QDirectFbBlitterPlatformPixmap::fromFile(const QString &filename, const char *format,
+                                              Qt::ImageConversionFlags flags)
+{
+    // If we can't find the file, pass it on to the base class as it is
+    // trying harder by appending various extensions to the path.
+    if (!QFile::exists(filename))
+        return QBlittablePlatformPixmap::fromFile(filename, format, flags);
+
+    // Stop if there is a requirement for colors
+    if (flags != Qt::AutoColor)
+        return QBlittablePlatformPixmap::fromFile(filename, format, flags);
+
+    // Deal with resources
+    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);
+    }
+
+    // Try to use directfb to load it.
+    DFBDataBufferDescription description;
+    description.flags = DBDESC_FILE;
+    const QByteArray fileNameData = filename.toLocal8Bit();
+    description.file = fileNameData.constData();
+    if (fromDataBufferDescription(description))
+        return true;
+
+    // Fallback
+    return QBlittablePlatformPixmap::fromFile(filename, format, flags);
+}
+
 void QDirectFbBlitter::doUnlock()
 {
-    m_surface->Unlock(m_surface);
+    m_surface->Unlock(m_surface.data());
 }
+
+QT_END_NAMESPACE