diff options
Diffstat (limited to 'src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp')
-rw-r--r-- | src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp | 272 |
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 + + + |