/****************************************************************************
**
-** 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;
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);
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);
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