summaryrefslogtreecommitdiffstats
path: root/src/plugins
diff options
context:
space:
mode:
authorAnders Bakken <anders.bakken@nokia.com>2009-03-26 06:09:15 (GMT)
committerTom Cooksey <thomas.cooksey@nokia.com>2009-03-27 15:43:51 (GMT)
commit43c5656d834739e86f2895cfbf3d539bb8c7c498 (patch)
treeb52da52c77fd0b87913012bc6b5a0c3378dabe63 /src/plugins
parent062c476d378022a49307aca136cb9aab381e0814 (diff)
downloadQt-43c5656d834739e86f2895cfbf3d539bb8c7c498.zip
Qt-43c5656d834739e86f2895cfbf3d539bb8c7c498.tar.gz
Qt-43c5656d834739e86f2895cfbf3d539bb8c7c498.tar.bz2
Major surface related fix
Make sure all QDirectFBPaintDevice surfaces always are created with a format that is either QScreen::pixelFormat() or QDirectFBScreen::alphaPixmapFormat(). Also, clean up surface creation by providing more high level functions. Fix a bug where we would assume that ARGB means Format_ARGB32_Premultiplied and not Format_ARGB32. Reviewed-by: Tom Cooksey
Diffstat (limited to 'src/plugins')
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.cpp10
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp30
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp171
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp301
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbscreen.h28
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp4
6 files changed, 327 insertions, 217 deletions
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.cpp
index 8a30ad4..8dbad53 100644
--- a/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.cpp
+++ b/src/plugins/gfxdrivers/directfb/qdirectfbpaintdevice.cpp
@@ -64,8 +64,6 @@ void QDirectFBPaintDevice::lockDirectFB() {
void *mem;
int w, h;
- DFBSurfacePixelFormat format;
-
DFBResult result = dfbSurface->Lock(dfbSurface, DSLF_WRITE, &mem, &bpl);
if (result != DFB_OK || !mem) {
DirectFBError("QDirectFBPixmapData::buffer()", result);
@@ -73,10 +71,8 @@ void QDirectFBPaintDevice::lockDirectFB() {
}
dfbSurface->GetSize(dfbSurface, &w, &h);
- dfbSurface->GetPixelFormat(dfbSurface, &format);
-
lockedImage = new QImage(static_cast<uchar*>(mem), w, h, bpl,
- QDirectFBScreen::getImageFormat(format));
+ QDirectFBScreen::getImageFormat(dfbSurface));
}
@@ -102,9 +98,7 @@ void* QDirectFBPaintDevice::memory() const
QImage::Format QDirectFBPaintDevice::format() const
{
- DFBSurfacePixelFormat dfbFormat;
- dfbSurface->GetPixelFormat(dfbSurface, &dfbFormat);
- return QDirectFBScreen::getImageFormat(dfbFormat);
+ return QDirectFBScreen::getImageFormat(dfbSurface);
}
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp
index 86357e6..84a92d8 100644
--- a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp
+++ b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp
@@ -112,7 +112,7 @@ CachedImage::CachedImage(const QImage &image)
description = QDirectFBScreen::getSurfaceDescription(image);
QDirectFBScreen* screen = QDirectFBScreen::instance();
- tmpSurface = screen->createDFBSurface(&description);
+ tmpSurface = screen->createDFBSurface(&description, QDirectFBScreen::TrackSurface);
if (!tmpSurface) {
qWarning("CachedImage CreateSurface failed!");
return;
@@ -124,7 +124,7 @@ CachedImage::CachedImage(const QImage &image)
description.flags = DFBSurfaceDescriptionFlags(description.flags & ~DSDESC_PREALLOCATED);
- s = screen->createDFBSurface(&description);
+ s = screen->createDFBSurface(&description, QDirectFBScreen::TrackSurface);
if (!s)
qWarning("QDirectFBPaintEngine failed caching image");
@@ -159,7 +159,7 @@ IDirectFBSurface* SurfaceCache::getSurface(const uint *buf, int size)
DFBSurfaceDescription description;
description = QDirectFBScreen::getSurfaceDescription(buf, size);
- surface = QDirectFBScreen::instance()->createDFBSurface(&description);
+ surface = QDirectFBScreen::instance()->createDFBSurface(&description, QDirectFBScreen::TrackSurface);
if (!surface)
qWarning("QDirectFBPaintEngine: SurfaceCache: Unable to create surface");
@@ -724,13 +724,10 @@ void QDirectFBPaintEnginePrivate::drawImage(const QRectF &dest,
const QRectF &src)
{
QImage image = srcImage;
- if (QDirectFBScreen::getSurfacePixelFormat(image) == DSPF_UNKNOWN) {
- QImage::Format format;
- if (image.hasAlphaChannel())
- format = QImage::Format_ARGB32_Premultiplied;
- else
- format = QImage::Format_RGB32;
- image = image.convertToFormat(format);
+ if (QDirectFBScreen::getSurfacePixelFormat(image.format()) == DSPF_UNKNOWN) {
+ image = image.convertToFormat(image.hasAlphaChannel()
+ ? QDirectFBScreen::instance()->alphaPixmapFormat()
+ : QDirectFBScreen::instance()->pixelFormat());
}
CachedImage *img = imageCache[image.cacheKey()];
@@ -756,7 +753,8 @@ void QDirectFBPaintEnginePrivate::drawImage(const QRectF &dest,
DFBSurfaceDescription description;
description = QDirectFBScreen::getSurfaceDescription(image);
- imgSurface = QDirectFBScreen::instance()->createDFBSurface(&description);
+ imgSurface = QDirectFBScreen::instance()->createDFBSurface(&description,
+ QDirectFBScreen::DontTrackSurface);
if (!imgSurface) {
qWarning("QDirectFBPaintEnginePrivate::drawImage");
return;
@@ -790,8 +788,10 @@ void QDirectFBPaintEnginePrivate::drawImage(const QRectF &dest,
}
if (changeFlags)
surface->SetBlittingFlags(surface, DFBSurfaceBlittingFlags(blitFlags));
- if (doRelease)
- QDirectFBScreen::instance()->releaseDFBSurface(imgSurface);
+ if (doRelease) {
+ surface->ReleaseSource(surface);
+ imgSurface->Release(imgSurface);
+ }
}
void QDirectFBPaintEnginePrivate::updateClip()
@@ -1092,11 +1092,11 @@ void QDirectFBPaintEngine::drawTiledPixmap(const QRectF &r,
QRasterPaintEngine::drawTiledPixmap(r, pixmap, sp);
}
else if (!d->dfbCanHandleClip(r) || d->matrixRotShear || !sp.isNull()) {
- QImage* img = static_cast<QDirectFBPixmapData*>(pixmap.pixmapData())->buffer();
+ const QImage *img = static_cast<QDirectFBPixmapData*>(pixmap.pixmapData())->buffer();
+ d->lock();
QRasterPixmapData *data = new QRasterPixmapData(QPixmapData::PixmapType);
data->fromImage(*img, Qt::AutoColor);
const QPixmap pix(data);
- d->lock();
QRasterPaintEngine::drawTiledPixmap(r, pix, sp);
}
else {
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp
index 6352652..6d942a4 100644
--- a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp
+++ b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp
@@ -72,14 +72,19 @@ void QDirectFBPixmapData::resize(int width, int height)
}
DFBSurfaceDescription description;
- description.flags = DFBSurfaceDescriptionFlags(DSDESC_WIDTH |
- DSDESC_HEIGHT);
+ description.flags = DFBSurfaceDescriptionFlags(DSDESC_WIDTH
+ | DSDESC_HEIGHT
+ | DSDESC_PIXELFORMAT);
+ QDirectFBScreen::initSurfaceDescriptionPixelFormat(&description, screen->pixelFormat());
description.width = width;
description.height = height;
- dfbSurface = screen->createDFBSurface(&description);
- if (!dfbSurface)
- qCritical("QDirectFBPixmapData::resize(): Unable to allocate surface");
+ dfbSurface = screen->createDFBSurface(&description, QDirectFBScreen::TrackSurface);
+ if (!dfbSurface) {
+ setSerialNumber(0);
+ qWarning("QDirectFBPixmapData::resize(): Unable to allocate surface");
+ return;
+ }
setSerialNumber(++global_ser_no);
}
@@ -87,61 +92,15 @@ void QDirectFBPixmapData::resize(int width, int height)
void QDirectFBPixmapData::fromImage(const QImage &img,
Qt::ImageConversionFlags)
{
- QImage image;
- if (QDirectFBScreen::getSurfacePixelFormat(img) == DSPF_UNKNOWN)
- image = img.convertToFormat(QImage::Format_ARGB32_Premultiplied);
- else
- image = img;
-
- DFBSurfaceDescription description;
- description = QDirectFBScreen::getSurfaceDescription(image);
-
-#ifndef QT_NO_DIRECTFB_PREALLOCATED
- IDirectFBSurface *imgSurface;
- imgSurface = screen->createDFBSurface(&description);
- if (!imgSurface) {
- qWarning("QDirectFBPixmapData::fromImage()");
- setSerialNumber(0);
- return;
- }
-#ifndef QT_NO_DIRECTFB_PALETTE
- QDirectFBScreen::setSurfaceColorTable(imgSurface, image);
-#endif
-#endif // QT_NO_DIRECTFB_PREALLOCATED
-
- description.flags = DFBSurfaceDescriptionFlags(description.flags
- & ~DSDESC_PREALLOCATED);
- dfbSurface = screen->createDFBSurface(&description);
+ dfbSurface = screen->copyToDFBSurface(img,
+ img.hasAlphaChannel() ? screen->alphaPixmapFormat()
+ : screen->pixelFormat(),
+ QDirectFBScreen::TrackSurface);
if (!dfbSurface) {
qWarning("QDirectFBPixmapData::fromImage()");
setSerialNumber(0);
return;
}
-
-#ifndef QT_NO_DIRECTFB_PALETTE
- QDirectFBScreen::setSurfaceColorTable(dfbSurface, image);
-#endif
-
-#ifdef QT_NO_DIRECTFB_PREALLOCATED
- char *mem;
- surface->Lock(surface, DSLF_WRITE, (void**)&mem, &bpl);
- const int w = image.width() * image.depth() / 8;
- for (int i = 0; i < image.height(); ++i) {
- memcpy(mem, image.scanLine(i), w);
- mem += bpl;
- }
- surface->Unlock(surface);
-#else
- DFBResult result;
- dfbSurface->SetBlittingFlags(dfbSurface, DSBLIT_NOFX);
- result = dfbSurface->Blit(dfbSurface, imgSurface, 0, 0, 0);
- if (result != DFB_OK)
- DirectFBError("QDirectFBPixmapData::fromImage()", result);
- dfbSurface->Flip(dfbSurface, 0, DSFLIP_NONE);
- dfbSurface->ReleaseSource(dfbSurface);
- screen->releaseDFBSurface(imgSurface);
-#endif // QT_NO_DIRECTFB_PREALLOCATED
-
setSerialNumber(++global_ser_no);
}
@@ -161,30 +120,24 @@ void QDirectFBPixmapData::copy(const QPixmapData *data, const QRect &rect)
description.width = rect.width();
description.height = rect.height();
src->GetPixelFormat(src, &description.pixelformat);
+ src->GetCapabilities(src, &description.caps);
- dfbSurface = screen->createDFBSurface(&description);
+ dfbSurface = screen->createDFBSurface(&description, QDirectFBScreen::TrackSurface);
if (!dfbSurface) {
qWarning("QDirectFBPixmapData::copy()");
setSerialNumber(0);
return;
}
- DFBResult result;
-#ifndef QT_NO_DIRECTFB_PALETTE
- IDirectFBPalette *palette;
- result = src->GetPalette(src, &palette);
- if (result == DFB_OK) {
- dfbSurface->SetPalette(dfbSurface, palette);
- palette->Release(palette);
- }
-#endif
-
dfbSurface->SetBlittingFlags(dfbSurface, DSBLIT_NOFX);
const DFBRectangle blitRect = { rect.x(), rect.y(),
rect.width(), rect.height() };
- result = dfbSurface->Blit(dfbSurface, src, &blitRect, 0, 0);
- if (result != DFB_OK)
+ DFBResult result = dfbSurface->Blit(dfbSurface, src, &blitRect, 0, 0);
+ if (result != DFB_OK) {
DirectFBError("QDirectFBPixmapData::copy()", result);
+ setSerialNumber(0);
+ return;
+ }
setSerialNumber(++global_ser_no);
}
@@ -198,37 +151,16 @@ void QDirectFBPixmapData::fill(const QColor &color)
Q_ASSERT(dfbSurface);
if (color.alpha() < 255 && !hasAlphaChannel()) {
- // convert to surface supporting alpha channel
- DFBSurfacePixelFormat format;
- dfbSurface->GetPixelFormat(dfbSurface, &format);
- switch (format) {
- case DSPF_YUY2:
- case DSPF_UYVY:
- format = DSPF_AYUV;
- break;
-#if (Q_DIRECTFB_VERSION >= 0x010100)
- case DSPF_RGB444:
- format = DSPF_ARGB4444;
- break;
- case DSPF_RGB555:
-#endif
- case DSPF_RGB18:
- format = DSPF_ARGB6666;
- break;
- default:
- format = DSPF_ARGB;
- break;
- }
-
DFBSurfaceDescription description;
description.flags = DFBSurfaceDescriptionFlags(DSDESC_WIDTH |
DSDESC_HEIGHT |
DSDESC_PIXELFORMAT);
dfbSurface->GetSize(dfbSurface, &description.width, &description.height);
- description.pixelformat = format;
+ QDirectFBScreen::initSurfaceDescriptionPixelFormat(&description, screen->alphaPixmapFormat());
screen->releaseDFBSurface(dfbSurface); // release old surface
- dfbSurface = screen->createDFBSurface(&description);
+ dfbSurface = screen->createDFBSurface(&description, QDirectFBScreen::TrackSurface);
+ setSerialNumber(++global_ser_no);
if (!dfbSurface) {
qWarning("QDirectFBPixmapData::fill()");
setSerialNumber(0);
@@ -245,6 +177,10 @@ bool QDirectFBPixmapData::hasAlphaChannel() const
if (!serialNumber())
return false;
+ // We don't need to ask DFB for this really. Can just keep track
+ // of what image format this has. It should always have either
+ // QDirectFBScreen::alphaPixmapFormat() or QScreen::pixelFormat()
+
DFBSurfacePixelFormat format;
dfbSurface->GetPixelFormat(dfbSurface, &format);
switch (format) {
@@ -274,14 +210,12 @@ QPixmap QDirectFBPixmapData::transformed(const QTransform &transform,
{
QDirectFBPixmapData *that = const_cast<QDirectFBPixmapData*>(this);
const QImage *image = that->buffer();
- if (image) { // avoid deep copy
- const QImage transformed = image->transformed(transform, mode);
- that->unlockDirectFB();
- QDirectFBPixmapData *data = new QDirectFBPixmapData(pixelType());
- data->fromImage(transformed, Qt::AutoColor);
- return QPixmap(data);
- }
- return QPixmapData::transformed(transform, mode);
+ Q_ASSERT(image);
+ const QImage transformed = image->transformed(transform, mode);
+ that->unlockDirectFB();
+ QDirectFBPixmapData *data = new QDirectFBPixmapData(QPixmapData::PixmapType);
+ data->fromImage(transformed, Qt::AutoColor);
+ return QPixmap(data);
}
int w, h;
@@ -291,15 +225,14 @@ QPixmap QDirectFBPixmapData::transformed(const QTransform &transform,
if (size.isEmpty())
return QPixmap();
- QDirectFBPixmapData *data = new QDirectFBPixmapData(pixelType());
+ QDirectFBPixmapData *data = new QDirectFBPixmapData(QPixmapData::PixmapType);
data->resize(size.width(), size.height());
IDirectFBSurface *dest = data->dfbSurface;
dest->SetBlittingFlags(dest, DSBLIT_NOFX);
- const DFBRectangle srcRect = { 0, 0, w, h };
const DFBRectangle destRect = { 0, 0, size.width(), size.height() };
- dest->StretchBlit(dest, dfbSurface, &srcRect, &destRect);
+ dest->StretchBlit(dest, dfbSurface, 0, &destRect);
return QPixmap(data);
}
@@ -309,39 +242,9 @@ QImage QDirectFBPixmapData::toImage() const
if (!dfbSurface)
return QImage();
-#ifdef QT_NO_DIRECTFB_PREALLOCATED
QDirectFBPixmapData *that = const_cast<QDirectFBPixmapData*>(this);
const QImage *img = that->buffer();
- const QImage copied = img->copy();
- that->unlockDirectFB();
- return copied;
-#else
-
- int w, h;
- dfbSurface->GetSize(dfbSurface, &w, &h);
-
- // Always convert to ARGB32:
- QImage image(w, h, QImage::Format_ARGB32);
-
- DFBSurfaceDescription description;
- description = QDirectFBScreen::getSurfaceDescription(image);
-
- IDirectFBSurface *imgSurface = screen->createDFBSurface(&description);
- if (!imgSurface) {
- qWarning("QDirectFBPixmapData::toImage()");
- return QImage();
- }
-
- imgSurface->SetBlittingFlags(imgSurface, DSBLIT_NOFX);
- DFBResult result = imgSurface->Blit(imgSurface, dfbSurface, 0, 0, 0);
- if (result != DFB_OK) {
- DirectFBError("QDirectFBPixmapData::toImage() blit failed", result);
- return QImage();
- }
- screen->releaseDFBSurface(imgSurface);
-
- return image;
-#endif // QT_NO_DIRECTFB_PREALLOCATED
+ return img->copy();
}
QPaintEngine* QDirectFBPixmapData::paintEngine() const
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp
index 26c023f..db9672a 100644
--- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp
+++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp
@@ -81,6 +81,7 @@ public:
QDirectFBKeyboardHandler *keyboard;
#endif
bool videoonly;
+ QImage::Format alphaPixmapFormat;
};
QDirectFBScreenPrivate::QDirectFBScreenPrivate(QDirectFBScreen* screen)
@@ -96,6 +97,7 @@ QDirectFBScreenPrivate::QDirectFBScreenPrivate(QDirectFBScreen* screen)
, keyboard(0)
#endif
, videoonly(false)
+ , alphaPixmapFormat(QImage::Format_Invalid)
{
#ifndef QT_NO_QWS_SIGNALHANDLER
QWSSignalHandler::instance()->addObject(this);
@@ -130,7 +132,80 @@ QDirectFBScreenPrivate::~QDirectFBScreenPrivate()
dfb->Release(dfb);
}
-IDirectFBSurface* QDirectFBScreen::createDFBSurface(const DFBSurfaceDescription* desc, bool track)
+
+
+// creates a preallocated surface with the same format as the image if
+// possible.
+
+IDirectFBSurface* QDirectFBScreen::createDFBSurface(const QImage &img, SurfaceCreationOptions options)
+{
+ if (img.isNull()) // assert?
+ return 0;
+ if (QDirectFBScreen::getSurfacePixelFormat(img.format()) == DSPF_UNKNOWN) {
+ QImage image = img.convertToFormat(img.hasAlphaChannel()
+ ? d_ptr->alphaPixmapFormat
+ : pixelFormat());
+ IDirectFBSurface *tmp = createDFBSurface(image, false);
+ if (!tmp) {
+ qWarning("Couldn't create surface createDFBSurface(QImage, bool)");
+ return 0;
+ }
+ IDirectFBSurface *surface = copyDFBSurface(tmp, image.format(), options);
+ tmp->Release(tmp);
+ return surface;
+ }
+
+ DFBSurfaceDescription desc = QDirectFBScreen::getSurfaceDescription(img);
+ IDirectFBSurface *surface = createDFBSurface(&desc, options);
+#ifdef QT_NO_DIRECTFB_PREALLOCATED
+ if (surface) {
+ char *mem;
+ int bpl;
+ surface->Lock(dfbSurface, DSLF_WRITE, (void**)&mem, &bpl);
+ const int h = img.height();
+ for (int i = 0; i < h; ++i) {
+ memcpy(mem, img.scanLine(i), bpl);
+ mem += bpl;
+ }
+ surface->Unlock(ret);
+ }
+#endif
+#ifndef QT_NO_DIRECTFB_PALETTE
+ if (img.numColors() != 0)
+ QDirectFBScreen::setSurfaceColorTable(surface, img);
+#endif
+ return surface;
+}
+
+IDirectFBSurface *QDirectFBScreen::copyDFBSurface(IDirectFBSurface *src,
+ QImage::Format format,
+ SurfaceCreationOptions options)
+{
+ Q_ASSERT(src);
+ QSize size;
+ src->GetSize(src, &size.rwidth(), &size.rheight());
+ IDirectFBSurface *surface = createDFBSurface(size, format, options);
+ surface->SetBlittingFlags(surface, DSBLIT_NOFX);
+ surface->Blit(surface, src, 0, 0, 0);
+ surface->ReleaseSource(surface); // ??? Is this always right?
+ return surface;
+}
+
+IDirectFBSurface *QDirectFBScreen::createDFBSurface(const QSize &size,
+ QImage::Format format,
+ SurfaceCreationOptions options)
+{
+ DFBSurfaceDescription desc;
+ desc.flags = DFBSurfaceDescriptionFlags(DSDESC_WIDTH|DSDESC_HEIGHT);
+ if (!QDirectFBScreen::initSurfaceDescriptionPixelFormat(&desc, format))
+ return 0;
+ desc.width = size.width();
+ desc.height = size.height();
+ return createDFBSurface(&desc, options);
+}
+
+
+IDirectFBSurface* QDirectFBScreen::createDFBSurface(const DFBSurfaceDescription *desc, SurfaceCreationOptions options)
{
DFBResult result;
IDirectFBSurface* newSurface = 0;
@@ -152,13 +227,18 @@ IDirectFBSurface* QDirectFBScreen::createDFBSurface(const DFBSurfaceDescription*
result = d_ptr->dfb->CreateSurface(d_ptr->dfb, desc, &newSurface);
if (result != DFB_OK) {
- DirectFBError("QDirectFBScreen::createDFBSurface", result);
+ qWarning("QDirectFBScreen::createDFBSurface() Failed!\n"
+ " Flags %0x Caps %0x width %d height %d pixelformat %0x %d preallocated %p %d\n%s",
+ desc->flags, desc->caps, desc->width, desc->height,
+ desc->pixelformat, DFB_PIXELFORMAT_INDEX(desc->pixelformat),
+ desc->preallocated[0].data, desc->preallocated[0].pitch,
+ DirectFBErrorString(result));
return 0;
}
Q_ASSERT(newSurface);
- if (track) {
+ if (options & TrackSurface) {
d_ptr->allocatedSurfaces.insert(newSurface);
//qDebug("Created a new DirectFB surface at %p. New count = %d",
@@ -168,8 +248,63 @@ IDirectFBSurface* QDirectFBScreen::createDFBSurface(const DFBSurfaceDescription*
return newSurface;
}
-void QDirectFBScreen::releaseDFBSurface(IDirectFBSurface* surface)
+IDirectFBSurface *QDirectFBScreen::copyToDFBSurface(const QImage &img,
+ QImage::Format format,
+ SurfaceCreationOptions options)
{
+ QImage image = img;
+ const QImage::Format pixmapFormat = image.hasAlphaChannel()
+ ? QDirectFBScreen::alphaPixmapFormat()
+ : QDirectFBScreen::pixelFormat();
+
+ if (QDirectFBScreen::getSurfacePixelFormat(image.format()) == DSPF_UNKNOWN
+#ifdef QT_NO_DIRECTFB_PREALLOCATED
+ || image.format() != pixmapFormat
+#endif
+ ) {
+ image = image.convertToFormat(pixmapFormat);
+ }
+
+
+ IDirectFBSurface *dfbSurface = createDFBSurface(img.size(), format, options);
+ if (!dfbSurface) {
+ qWarning("QDirectFBPixmapData::fromImage() Couldn't create surface");
+ return 0;
+ }
+
+#ifndef QT_NO_DIRECTFB_PREALLOCATED
+ IDirectFBSurface *imgSurface = createDFBSurface(img, DontTrackSurface);
+ if (!imgSurface) {
+ qWarning("QDirectFBPixmapData::fromImage()");
+ QDirectFBScreen::releaseDFBSurface(dfbSurface);
+ return 0;
+ }
+ Q_ASSERT(imgSurface);
+ DFBResult result;
+ dfbSurface->SetBlittingFlags(dfbSurface, DSBLIT_NOFX);
+ result = dfbSurface->Blit(dfbSurface, imgSurface, 0, 0, 0);
+ if (result != DFB_OK)
+ DirectFBError("QDirectFBPixmapData::fromImage()", result);
+ dfbSurface->ReleaseSource(dfbSurface);
+ imgSurface->Release(imgSurface);
+#else // QT_NO_DIRECTFB_PREALLOCATED
+ Q_ASSERT(image.format() == pixmapFormat);
+ char *mem;
+ int bpl;
+ dfbSurface->Lock(dfbSurface, DSLF_WRITE, (void**)&mem, &bpl);
+ const int w = image.width() * image.depth() / 8;
+ for (int i = 0; i < image.height(); ++i) {
+ memcpy(mem, image.scanLine(i), w);
+ mem += bpl;
+ }
+ dfbSurface->Unlock(dfbSurface);
+#endif
+ return dfbSurface;
+}
+
+void QDirectFBScreen::releaseDFBSurface(IDirectFBSurface *surface)
+{
+ Q_ASSERT(QDirectFBScreen::instance());
Q_ASSERT(surface);
surface->Release(surface);
if (!d_ptr->allocatedSurfaces.remove(surface))
@@ -200,9 +335,9 @@ IDirectFBDisplayLayer* QDirectFBScreen::dfbDisplayLayer()
}
#endif
-DFBSurfacePixelFormat QDirectFBScreen::getSurfacePixelFormat(const QImage &image)
+DFBSurfacePixelFormat QDirectFBScreen::getSurfacePixelFormat(QImage::Format format)
{
- switch (image.format()) {
+ switch (format) {
#ifndef QT_NO_DIRECTFB_PALETTE
case QImage::Format_Indexed8:
return DSPF_LUT8;
@@ -233,8 +368,21 @@ DFBSurfacePixelFormat QDirectFBScreen::getSurfacePixelFormat(const QImage &image
};
}
-QImage::Format QDirectFBScreen::getImageFormat(DFBSurfacePixelFormat format)
+static inline bool isPremultiplied(IDirectFBSurface *surface)
+{
+ Q_ASSERT(surface);
+ DFBSurfaceCapabilities caps;
+ const DFBResult result = surface->GetCapabilities(surface, &caps);
+ Q_ASSERT(result == DFB_OK);
+ Q_UNUSED(result);
+ return caps & DSCAPS_PREMULTIPLIED;
+}
+
+QImage::Format QDirectFBScreen::getImageFormat(IDirectFBSurface *surface)
{
+ DFBSurfacePixelFormat format;
+ surface->GetPixelFormat(surface, &format);
+
switch (format) {
case DSPF_LUT8:
return QImage::Format_Indexed8;
@@ -257,8 +405,14 @@ QImage::Format QDirectFBScreen::getImageFormat(DFBSurfacePixelFormat format)
return QImage::Format_RGB666;
case DSPF_RGB32:
return QImage::Format_RGB32;
- case DSPF_ARGB:
- return QImage::Format_ARGB32_Premultiplied;
+ case DSPF_ARGB: {
+ DFBSurfaceCapabilities caps;
+ const DFBResult result = surface->GetCapabilities(surface, &caps);
+ Q_ASSERT(result == DFB_OK);
+ Q_UNUSED(result);
+ return (caps & DSCAPS_PREMULTIPLIED
+ ? QImage::Format_ARGB32_Premultiplied
+ : QImage::Format_ARGB32); }
default:
break;
}
@@ -268,38 +422,32 @@ QImage::Format QDirectFBScreen::getImageFormat(DFBSurfacePixelFormat format)
DFBSurfaceDescription QDirectFBScreen::getSurfaceDescription(const QImage &image)
{
DFBSurfaceDescription description;
- DFBSurfacePixelFormat format = getSurfacePixelFormat(image);
+
+ const DFBSurfacePixelFormat format = getSurfacePixelFormat(image.format());
if (format == DSPF_UNKNOWN || image.isNull()) {
description.flags = DFBSurfaceDescriptionFlags(0);
return description;
}
- description.flags = DFBSurfaceDescriptionFlags(DSDESC_CAPS
- | DSDESC_WIDTH
+ description.flags = DFBSurfaceDescriptionFlags(DSDESC_WIDTH
| DSDESC_HEIGHT
- | DSDESC_PIXELFORMAT
- | DSDESC_PREALLOCATED);
-
- description.caps = DSCAPS_NONE;
+#ifndef QT_NO_DIRECTFB_PREALLOCATED
+ | DSDESC_PREALLOCATED
+#endif
+ | DSDESC_PIXELFORMAT);
+ QDirectFBScreen::initSurfaceDescriptionPixelFormat(&description, image.format());
description.width = image.width();
description.height = image.height();
- description.pixelformat = format;
+#ifndef QT_NO_DIRECTFB_PREALLOCATED
description.preallocated[0].data = (void*)(image.bits());
description.preallocated[0].pitch = image.bytesPerLine();
description.preallocated[1].data = 0;
description.preallocated[1].pitch = 0;
+#endif
- switch (image.format()) {
- case QImage::Format_ARGB32_Premultiplied:
- case QImage::Format_ARGB8565_Premultiplied:
- case QImage::Format_ARGB6666_Premultiplied:
- case QImage::Format_ARGB8555_Premultiplied:
- case QImage::Format_ARGB4444_Premultiplied:
+ if (QDirectFBScreen::isPremultiplied(image.format()))
description.caps = DSCAPS_PREMULTIPLIED;
- default:
- break;
- }
return description;
}
@@ -337,7 +485,7 @@ void QDirectFBScreen::setSurfaceColorTable(IDirectFBSurface *surface,
if (numColors == 0)
return;
- QVarLengthArray<DFBColor> colors(numColors);
+ QVarLengthArray<DFBColor, 256> colors(numColors);
for (int i = 0; i < numColors; ++i) {
QRgb c = image.color(i);
colors[i].a = qAlpha(c);
@@ -461,18 +609,10 @@ void QDirectFBScreenCursor::set(const QImage &image, int hotx, int hoty)
} else if (!image.isNull() && implicitHide) {
show();
}
+ cursor = image.convertToFormat(QDirectFBScreen::instance()->alphaPixmapFormat());
if (!image.isNull()) {
-#ifdef QT_NO_DIRECTFB_PALETTE
- if (image.numColors() > 0)
- cursor = image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
- else
-#endif
- if (image.format() == QImage::Format_Indexed8) {
- cursor = image.convertToFormat(QImage::Format_ARGB32_Premultiplied);
- } else {
- cursor = image;
- }
+ Q_ASSERT(cursor.numColors() == 0);
size = cursor.size();
hotspot = QPoint(hotx, hoty);
@@ -480,15 +620,12 @@ void QDirectFBScreenCursor::set(const QImage &image, int hotx, int hoty)
description = QDirectFBScreen::getSurfaceDescription(cursor);
IDirectFBSurface *surface;
- surface = QDirectFBScreen::instance()->createDFBSurface(&description);
+ surface = QDirectFBScreen::instance()->createDFBSurface(&description,
+ QDirectFBScreen::TrackSurface);
if (!surface) {
qWarning("QDirectFBScreenCursor::set: Unable to create surface");
return;
}
-#ifndef QT_NO_DIRECTFB_PALETTE
- QDirectFBScreen::setSurfaceColorTable(surface, cursor);
-#endif
-
DFBResult result = layer->SetCooperativeLevel(layer, DLSCL_ADMINISTRATIVE);
if (result != DFB_OK) {
DirectFBError("QDirectFBScreenCursor::set: "
@@ -636,7 +773,7 @@ bool QDirectFBScreen::connect(const QString &displaySpec)
}
const QStringList displayArgs = displaySpec.split(QLatin1Char(':'),
- QString::SkipEmptyParts);
+ QString::SkipEmptyParts);
d_ptr->setFlipFlags(displayArgs);
@@ -663,6 +800,12 @@ bool QDirectFBScreen::connect(const QString &displaySpec)
description.caps = DFBSurfaceCapabilities(DSCAPS_PRIMARY
| DSCAPS_DOUBLE
| DSCAPS_STATIC_ALLOC);
+ if (displayArgs.contains(QLatin1String("forcepremultiplied"),
+ Qt::CaseInsensitive)) {
+ description.caps = DFBSurfaceCapabilities(description.caps
+ | DSCAPS_PREMULTIPLIED);
+ }
+
if (!(d_ptr->flipFlags & DSFLIP_BLIT)) {
description.caps = DFBSurfaceCapabilities(description.caps
| DSCAPS_DOUBLE
@@ -671,12 +814,43 @@ bool QDirectFBScreen::connect(const QString &displaySpec)
// We don't track the primary surface as it's released in disconnect
- d_ptr->dfbSurface = createDFBSurface(&description, false);
+ d_ptr->dfbSurface = createDFBSurface(&description, DontTrackSurface);
if (!d_ptr->dfbSurface) {
DirectFBError("QDirectFBScreen: error creating primary surface",
result);
return false;
}
+
+ // Work out what format we're going to use for surfaces with an alpha channel
+ d_ptr->alphaPixmapFormat = QDirectFBScreen::getImageFormat(d_ptr->dfbSurface);
+ setPixelFormat(d_ptr->alphaPixmapFormat);
+ switch (d_ptr->alphaPixmapFormat) {
+ case QImage::Format_RGB666:
+ d_ptr->alphaPixmapFormat = QImage::Format_ARGB6666_Premultiplied;
+ break;
+ case QImage::Format_RGB444:
+ d_ptr->alphaPixmapFormat = QImage::Format_ARGB4444_Premultiplied;
+ break;
+ case QImage::NImageFormats:
+ case QImage::Format_Invalid:
+ case QImage::Format_Mono:
+ case QImage::Format_MonoLSB:
+ case QImage::Format_Indexed8:
+ case QImage::Format_RGB32:
+ case QImage::Format_RGB888:
+ case QImage::Format_RGB16:
+ case QImage::Format_RGB555:
+ d_ptr->alphaPixmapFormat = QImage::Format_ARGB32_Premultiplied;
+ break;
+ case QImage::Format_ARGB32:
+ case QImage::Format_ARGB32_Premultiplied:
+ case QImage::Format_ARGB4444_Premultiplied:
+ case QImage::Format_ARGB8555_Premultiplied:
+ case QImage::Format_ARGB8565_Premultiplied:
+ case QImage::Format_ARGB6666_Premultiplied:
+ // works already
+ break;
+ }
d_ptr->dfbSurface->GetSize(d_ptr->dfbSurface, &w, &h);
data = 0;
@@ -692,7 +866,7 @@ bool QDirectFBScreen::connect(const QString &displaySpec)
else
DirectFBError("QDirectFBScreen: error getting surface format", result);
- setPixelFormat(getImageFormat(format));
+ setPixelFormat(getImageFormat(d_ptr->dfbSurface));
physWidth = physHeight = -1;
QRegExp mmWidthRx(QLatin1String("mmWidth=?(\\d+)"));
@@ -954,21 +1128,14 @@ void QDirectFBScreen::exposeRegion(QRegion r, int changing)
void QDirectFBScreen::blit(const QImage &img, const QPoint &topLeft,
const QRegion &reg)
{
- IDirectFBSurface *src = 0;
- DFBSurfaceDescription description = getSurfaceDescription(img);
-
- src = createDFBSurface(&description);
+ IDirectFBSurface *src = createDFBSurface(img, QDirectFBScreen::DontTrackSurface);
if (!src) {
qWarning("QDirectFBScreen::blit(): Error creating surface");
return;
}
-#ifndef QT_NO_DIRECTFB_PALETTE
- setSurfaceColorTable(d_ptr->dfbSurface, img);
-#endif
-
blit(src, topLeft, reg);
-
- releaseDFBSurface(src);
+ d_ptr->dfbSurface->ReleaseSource(d_ptr->dfbSurface);
+ src->Release(src);
}
void QDirectFBScreen::blit(IDirectFBSurface *src, const QPoint &topLeft,
@@ -1021,3 +1188,27 @@ void QDirectFBScreen::solidFill(const QColor &color, const QRegion &region)
dfbRects.size());
}
+QImage::Format QDirectFBScreen::alphaPixmapFormat() const
+{
+ return d_ptr->alphaPixmapFormat;
+}
+
+
+bool QDirectFBScreen::initSurfaceDescriptionPixelFormat(DFBSurfaceDescription *description,
+ QImage::Format format)
+{
+ const DFBSurfacePixelFormat pixelformat = QDirectFBScreen::getSurfacePixelFormat(format);
+ if (pixelformat == DSPF_UNKNOWN)
+ return false;
+ description->flags = DFBSurfaceDescriptionFlags(description->flags | DSDESC_PIXELFORMAT);
+ description->pixelformat = pixelformat;
+ if (QDirectFBScreen::isPremultiplied(format)) {
+ if (!(description->flags & DSDESC_CAPS)) {
+ description->caps = DSCAPS_PREMULTIPLIED;
+ description->flags = DFBSurfaceDescriptionFlags(description->flags | DSDESC_CAPS);
+ } else {
+ description->caps = DFBSurfaceCapabilities(description->caps | DSCAPS_PREMULTIPLIED);
+ }
+ }
+ return true;
+}
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h
index 35dea0d..a1e93c6 100644
--- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h
+++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h
@@ -88,18 +88,38 @@ public:
#endif
// Track surface creation/release so we can release all on exit
- IDirectFBSurface* createDFBSurface(const DFBSurfaceDescription* desc, bool track = true);
+ enum SurfaceCreationOption {
+ DontTrackSurface = 0,
+ TrackSurface = 1
+ };
+ Q_DECLARE_FLAGS(SurfaceCreationOptions, SurfaceCreationOption);
+ IDirectFBSurface *createDFBSurface(const DFBSurfaceDescription *desc,
+ SurfaceCreationOptions options);
+ IDirectFBSurface *createDFBSurface(const QImage &image,
+ SurfaceCreationOptions options);
+ IDirectFBSurface *createDFBSurface(const QSize &size,
+ QImage::Format format,
+ SurfaceCreationOptions options);
+ IDirectFBSurface *copyDFBSurface(IDirectFBSurface *src,
+ QImage::Format format,
+ SurfaceCreationOptions options);
+ IDirectFBSurface *copyToDFBSurface(const QImage &image,
+ QImage::Format format,
+ SurfaceCreationOptions options);
void releaseDFBSurface(IDirectFBSurface* surface);
+
bool preferVideoOnly() const;
static int depth(DFBSurfacePixelFormat format);
- static DFBSurfacePixelFormat getSurfacePixelFormat(const QImage &image);
+ static DFBSurfacePixelFormat getSurfacePixelFormat(QImage::Format format);
static DFBSurfaceDescription getSurfaceDescription(const QImage &image);
static DFBSurfaceDescription getSurfaceDescription(const uint *buffer,
int length);
- static QImage::Format getImageFormat(DFBSurfacePixelFormat format);
+ static QImage::Format getImageFormat(IDirectFBSurface *surface);
+ static bool initSurfaceDescriptionPixelFormat(DFBSurfaceDescription *description, QImage::Format format);
static inline bool isPremultiplied(QImage::Format format);
+ QImage::Format alphaPixmapFormat() const;
#ifndef QT_NO_DIRECTFB_PALETTE
static void setSurfaceColorTable(IDirectFBSurface *surface,
@@ -114,6 +134,8 @@ private:
QDirectFBScreenPrivate *d_ptr;
};
+Q_DECLARE_OPERATORS_FOR_FLAGS(QDirectFBScreen::SurfaceCreationOptions);
+
inline bool QDirectFBScreen::isPremultiplied(QImage::Format format)
{
switch (format) {
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp
index ce026ea..00d1781 100644
--- a/src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp
+++ b/src/plugins/gfxdrivers/directfb/qdirectfbsurface.cpp
@@ -153,8 +153,8 @@ void QDirectFBSurface::setGeometry(const QRect &rect, const QRegion &mask)
DSDESC_PIXELFORMAT);
description.width = rect.width();
description.height = rect.height();
- description.pixelformat = DSPF_ARGB;
-
+ QDirectFBScreen::initSurfaceDescriptionPixelFormat(&description,
+ QDirectFBSurface::instance()->pixelFormat());
dfbSurface = QDirectFBScreen::instance()->createDFBSurface(&description, false);
} else {
Q_ASSERT(dfbSurface);