summaryrefslogtreecommitdiffstats
path: root/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp')
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp272
1 files changed, 217 insertions, 55 deletions
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp
index 0afb8a8..ce9a55c 100644
--- a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp
+++ b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp
@@ -1,6 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the plugins of the Qt Toolkit.
@@ -9,8 +10,8 @@
** No Commercial Usage
** This file contains pre-release code and may not be distributed.
** You may use this file in accordance with the terms and conditions
-** contained in the either Technology Preview License Agreement or the
-** Beta Release License Agreement.
+** contained in the Technology Preview License Agreement accompanying
+** this package.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
@@ -20,47 +21,49 @@
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
-** In addition, as a special exception, Nokia gives you certain
-** additional rights. These rights are described in the Nokia Qt LGPL
-** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
-** package.
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** If you have questions regarding the use of this file, please contact
+** Nokia at qt-info@nokia.com.
+**
+**
+**
+**
+**
+**
**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 3.0 as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU General Public License version 3.0 requirements will be
-** met: http://www.gnu.org/copyleft/gpl.html.
**
-** If you are unsure which license is appropriate for your use, please
-** contact the sales department at http://qt.nokia.com/contact.
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qdirectfbpixmap.h"
+#ifndef QT_NO_QWS_DIRECTFB
+
#include "qdirectfbscreen.h"
#include "qdirectfbpaintengine.h"
#include <QtGui/qbitmap.h>
+#include <QtCore/qfile.h>
#include <directfb.h>
+
+QT_BEGIN_NAMESPACE
+
static int global_ser_no = 0;
QDirectFBPixmapData::QDirectFBPixmapData(QDirectFBScreen *screen, PixelType pixelType)
: QPixmapData(pixelType, DirectFBClass), QDirectFBPaintDevice(screen),
- format(QImage::Format_Invalid), alpha(false)
+ alpha(false)
{
setSerialNumber(0);
}
QDirectFBPixmapData::~QDirectFBPixmapData()
{
- unlockDirectFB();
- if (dfbSurface && QDirectFBScreen::instance())
- screen->releaseDFBSurface(dfbSurface);
}
void QDirectFBPixmapData::resize(int width, int height)
@@ -70,11 +73,11 @@ void QDirectFBPixmapData::resize(int width, int height)
return;
}
- format = screen->pixelFormat();
+ imageFormat = screen->pixelFormat();
dfbSurface = screen->createDFBSurface(QSize(width, height),
- format,
+ imageFormat,
QDirectFBScreen::TrackSurface);
- d = screen->depth();
+ d = QDirectFBScreen::depth(imageFormat);
alpha = false;
if (!dfbSurface) {
invalidate();
@@ -85,7 +88,6 @@ void QDirectFBPixmapData::resize(int width, int height)
w = width;
h = height;
is_null = (w <= 0 || h <= 0);
- d = metric(QPaintDevice::PdmDepth);
setSerialNumber(++global_ser_no);
}
@@ -162,43 +164,185 @@ static bool checkForAlphaPixels(const QImage &img)
bool QDirectFBPixmapData::hasAlphaChannel(const QImage &img)
{
#ifndef QT_NO_DIRECTFB_OPAQUE_DETECTION
- return ::checkForAlphaPixels(img);
+ return checkForAlphaPixels(img);
#else
return img.hasAlphaChannel();
#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);
+}
-void QDirectFBPixmapData::fromImage(const QImage &i,
- Qt::ImageConversionFlags flags)
+bool QDirectFBPixmapData::fromData(const uchar *buffer, uint len, const char *format,
+ Qt::ImageConversionFlags flags)
{
-#ifdef QT_NO_DIRECTFB_OPAQUE_DETECTION
- Q_UNUSED(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> struct QDirectFBInterfaceCleanupHandler
+{
+ static void cleanup(T *t) { if (t) t->Release(t); }
+};
+
+template <typename T>
+class QDirectFBPointer : public QScopedPointer<T, QDirectFBInterfaceCleanupHandler<T> >
+{
+public:
+ QDirectFBPointer(T *t = 0)
+ : QScopedPointer<T, QDirectFBInterfaceCleanupHandler<T> >(t)
+ {}
+};
+
+bool QDirectFBPixmapData::fromDataBufferDescription(const DFBDataBufferDescription &dataBufferDescription)
+{
+ IDirectFB *dfb = screen->dfb();
+ Q_ASSERT(dfb);
+ DFBResult result = DFB_OK;
+ IDirectFBDataBuffer *dataBufferPtr;
+ if ((result = dfb->CreateDataBuffer(dfb, &dataBufferDescription, &dataBufferPtr)) != DFB_OK) {
+ DirectFBError("QDirectFBPixmapData::fromDataBufferDescription()", result);
+ return false;
+ }
+ QDirectFBPointer<IDirectFBDataBuffer> dataBuffer(dataBufferPtr);
+
+ IDirectFBImageProvider *providerPtr;
+ if ((result = dataBuffer->CreateImageProvider(dataBuffer.data(), &providerPtr)) != DFB_OK) {
+ DirectFBError("QDirectFBPixmapData::fromDataBufferDescription(): Can't create image provider", result);
+ return false;
+ }
+ QDirectFBPointer<IDirectFBImageProvider> provider(providerPtr);
+
+ DFBSurfaceDescription surfaceDescription;
+ if ((result = provider->GetSurfaceDescription(provider.data(), &surfaceDescription)) != DFB_OK) {
+ DirectFBError("QDirectFBPixmapData::fromDataBufferDescription(): Can't get surface description", result);
+ return false;
+ }
+
+ DFBImageDescription imageDescription;
+ result = provider->GetImageDescription(provider.data(), &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);
+
+ result = provider->RenderTo(provider.data(), dfbSurface, 0);
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBPixmapData::fromSurfaceDescription(): Can't render to surface", result);
+ return false;
+ }
+
+ w = surfaceDescription.width;
+ h = surfaceDescription.height;
+ is_null = (w <= 0 || h <= 0);
+ d = QDirectFBScreen::depth(imageFormat);
+ setSerialNumber(++global_ser_no);
+
+#if defined QT_DIRECTFB_IMAGEPROVIDER_KEEPALIVE
+ screen->setDirectFBImageProvider(providerPtr);
+ provider.take();
+#endif
+
+ return true;
+}
+
#endif
- const QImage img = (i.depth() == 1 ? i.convertToFormat(screen->alphaPixmapFormat()) : i);
+
+void QDirectFBPixmapData::fromImage(const QImage &img,
+ Qt::ImageConversionFlags flags)
+{
+ if (img.depth() == 1) {
+ fromImage(img.convertToFormat(screen->alphaPixmapFormat()), flags);
+ return;
+ }
+
if (img.hasAlphaChannel()
#ifndef QT_NO_DIRECTFB_OPAQUE_DETECTION
&& (flags & Qt::NoOpaqueDetection || QDirectFBPixmapData::hasAlphaChannel(img))
#endif
) {
alpha = true;
- format = screen->alphaPixmapFormat();
+ imageFormat = screen->alphaPixmapFormat();
} else {
alpha = false;
- format = screen->pixelFormat();
+ imageFormat = screen->pixelFormat();
}
- dfbSurface = screen->copyToDFBSurface(img, format,
- QDirectFBScreen::TrackSurface);
+ QImage image;
+ if (flags != Qt::AutoColor) {
+ image = img.convertToFormat(imageFormat, flags);
+ flags = Qt::AutoColor;
+ } else {
+ image = img;
+ }
+
+ IDirectFBSurface *imageSurface = screen->createDFBSurface(image, image.format(), QDirectFBScreen::DontTrackSurface);
+ if (!imageSurface) {
+ qWarning("QDirectFBPixmapData::fromImage()");
+ invalidate();
+ return;
+ }
+
+ dfbSurface = screen->createDFBSurface(image.size(), imageFormat, QDirectFBScreen::TrackSurface);
if (!dfbSurface) {
qWarning("QDirectFBPixmapData::fromImage()");
invalidate();
return;
}
- w = img.width();
- h = img.height();
+
+ if (image.hasAlphaChannel()) {
+ dfbSurface->Clear(dfbSurface, 0, 0, 0, 0);
+ dfbSurface->SetBlittingFlags(dfbSurface, DSBLIT_BLEND_ALPHACHANNEL);
+ } else {
+ dfbSurface->SetBlittingFlags(dfbSurface, DSBLIT_NOFX);
+ }
+ dfbSurface->Blit(dfbSurface, imageSurface, 0, 0, 0);
+ imageSurface->Release(imageSurface);
+
+ w = image.width();
+ h = image.height();
is_null = (w <= 0 || h <= 0);
- d = metric(QPaintDevice::PdmDepth);
+ d = QDirectFBScreen::depth(imageFormat);
setSerialNumber(++global_ser_no);
+#ifdef QT_NO_DIRECTFB_OPAQUE_DETECTION
+ Q_UNUSED(flags);
+#endif
}
void QDirectFBPixmapData::copy(const QPixmapData *data, const QRect &rect)
@@ -207,17 +351,21 @@ void QDirectFBPixmapData::copy(const QPixmapData *data, const QRect &rect)
QPixmapData::copy(data, rect);
return;
}
- unlockDirectFB();
const QDirectFBPixmapData *otherData = static_cast<const QDirectFBPixmapData*>(data);
+#ifdef QT_NO_DIRECTFB_SUBSURFACE
+ if (otherData->lockFlags()) {
+ const_cast<QDirectFBPixmapData*>(otherData)->unlockSurface();
+ }
+#endif
IDirectFBSurface *src = otherData->directFBSurface();
alpha = data->hasAlphaChannel();
- format = (alpha
- ? QDirectFBScreen::instance()->alphaPixmapFormat()
- : QDirectFBScreen::instance()->pixelFormat());
+ imageFormat = (alpha
+ ? QDirectFBScreen::instance()->alphaPixmapFormat()
+ : QDirectFBScreen::instance()->pixelFormat());
- dfbSurface = screen->createDFBSurface(rect.size(), format,
+ dfbSurface = screen->createDFBSurface(rect.size(), imageFormat,
QDirectFBScreen::TrackSurface);
if (!dfbSurface) {
qWarning("QDirectFBPixmapData::copy()");
@@ -237,6 +385,7 @@ void QDirectFBPixmapData::copy(const QPixmapData *data, const QRect &rect)
h = rect.height();
d = otherData->d;
is_null = (w <= 0 || h <= 0);
+ unlockSurface();
DFBResult result = dfbSurface->Blit(dfbSurface, src, &blitRect, 0, 0);
#if (Q_DIRECTFB_VERSION >= 0x010000)
dfbSurface->ReleaseSource(dfbSurface);
@@ -275,11 +424,12 @@ void QDirectFBPixmapData::fill(const QColor &color)
alpha = (color.alpha() < 255);
- if (alpha && ::isOpaqueFormat(format)) {
+ if (alpha && isOpaqueFormat(imageFormat)) {
QSize size;
dfbSurface->GetSize(dfbSurface, &size.rwidth(), &size.rheight());
screen->releaseDFBSurface(dfbSurface);
- format = screen->alphaPixmapFormat();
+ imageFormat = screen->alphaPixmapFormat();
+ d = QDirectFBScreen::depth(imageFormat);
dfbSurface = screen->createDFBSurface(size, screen->alphaPixmapFormat(), QDirectFBScreen::TrackSurface);
setSerialNumber(++global_ser_no);
if (!dfbSurface) {
@@ -296,18 +446,21 @@ QPixmap QDirectFBPixmapData::transformed(const QTransform &transform,
Qt::TransformationMode mode) const
{
QDirectFBPixmapData *that = const_cast<QDirectFBPixmapData*>(this);
+#ifdef QT_NO_DIRECTFB_SUBSURFACE
+ if (lockFlags())
+ that->unlockSurface();
+#endif
+
if (!dfbSurface || transform.type() != QTransform::TxScale
|| mode != Qt::FastTransformation)
{
const QImage *image = that->buffer();
Q_ASSERT(image);
const QImage transformed = image->transformed(transform, mode);
- that->unlockDirectFB();
QDirectFBPixmapData *data = new QDirectFBPixmapData(screen, QPixmapData::PixmapType);
data->fromImage(transformed, Qt::AutoColor);
return QPixmap(data);
}
- that->unlockDirectFB();
const QSize size = transform.mapRect(QRect(0, 0, w, h)).size();
if (size.isEmpty())
@@ -320,7 +473,7 @@ QPixmap QDirectFBPixmapData::transformed(const QTransform &transform,
flags = DSBLIT_BLEND_ALPHACHANNEL;
}
data->dfbSurface = screen->createDFBSurface(size,
- format,
+ imageFormat,
QDirectFBScreen::TrackSurface);
if (flags & DSBLIT_BLEND_ALPHACHANNEL) {
data->dfbSurface->Clear(data->dfbSurface, 0, 0, 0, 0);
@@ -387,21 +540,30 @@ QPaintEngine *QDirectFBPixmapData::paintEngine() const
QImage *QDirectFBPixmapData::buffer()
{
- lockDirectFB(DSLF_READ|DSLF_WRITE);
- return lockedImage;
-}
-
-QImage * QDirectFBPixmapData::buffer(DFBSurfaceLockFlags lockFlags)
-{
- lockDirectFB(lockFlags);
- return lockedImage;
+ if (!lockFlgs) {
+ lockSurface(DSLF_READ|DSLF_WRITE);
+ }
+ Q_ASSERT(lockFlgs);
+ Q_ASSERT(!lockedImage.isNull());
+ return &lockedImage;
}
void QDirectFBPixmapData::invalidate()
{
+ if (dfbSurface) {
+ screen->releaseDFBSurface(dfbSurface);
+ dfbSurface = 0;
+ }
setSerialNumber(0);
alpha = false;
d = w = h = 0;
- format = QImage::Format_Invalid;
+ is_null = true;
+ imageFormat = QImage::Format_Invalid;
}
+QT_END_NAMESPACE
+
+#endif // QT_NO_QWS_DIRECTFB
+
+
+