summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAnders Bakken <anders.bakken@nokia.com>2009-04-08 23:49:08 (GMT)
committerAnders Bakken <anders.bakken@nokia.com>2009-04-09 01:23:26 (GMT)
commit6b494c48efa21f4ed3e2367f8bed8e138fd58190 (patch)
treea42d6c2447854b79168463088648cf18bebc4791 /src
parentd8dda2706408e0c9558966e74376834d290dc6e3 (diff)
downloadQt-6b494c48efa21f4ed3e2367f8bed8e138fd58190.zip
Qt-6b494c48efa21f4ed3e2367f8bed8e138fd58190.tar.gz
Qt-6b494c48efa21f4ed3e2367f8bed8e138fd58190.tar.bz2
Be smarter about alpha formats
Try harder to prevent blends by explicitly checking for alpha pixels in the source image (unless asked not to). Can be defined out by #defining QT_NO_DIRECTFB_OPAQUE_DETECTION Reviewed-by: Donald <qt-info@nokia.com>
Diffstat (limited to 'src')
-rw-r--r--src/plugins/gfxdrivers/directfb/directfb.pro1
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp161
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbpixmap.h3
3 files changed, 133 insertions, 32 deletions
diff --git a/src/plugins/gfxdrivers/directfb/directfb.pro b/src/plugins/gfxdrivers/directfb/directfb.pro
index 399044e..89a289c 100644
--- a/src/plugins/gfxdrivers/directfb/directfb.pro
+++ b/src/plugins/gfxdrivers/directfb/directfb.pro
@@ -13,6 +13,7 @@ QTDIR_build:DESTDIR = $$QT_BUILD_TREE/plugins/gfxdrivers
#DEFINES += QT_NO_DIRECTFB_MOUSE
#DEFINES += QT_NO_DIRECTFB_KEYBOARD
#DEFINES += QT_DIRECTFB_TIMING
+#DEFINES += QT_NO_DIRECTFB_OPAQUE_DETECTION
target.path = $$[QT_INSTALL_PLUGINS]/gfxdrivers
INSTALLS += target
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp
index a20b66a..a4e235b 100644
--- a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp
+++ b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp
@@ -51,7 +51,7 @@ static int global_ser_no = 0;
QDirectFBPixmapData::QDirectFBPixmapData(PixelType pixelType)
: QPixmapData(pixelType, DirectFBClass),
- engine(0)
+ engine(0), format(QImage::Format_Invalid), alpha(false)
{
setSerialNumber(0);
}
@@ -67,16 +67,18 @@ QDirectFBPixmapData::~QDirectFBPixmapData()
void QDirectFBPixmapData::resize(int width, int height)
{
if (width <= 0 || height <= 0) {
- setSerialNumber(0);
+ invalidate();
return;
}
- dfbSurface = screen->createDFBSurface(QSize(width, height),
- screen->pixelFormat(),
- QDirectFBScreen::TrackSurface);
- forceRaster = (screen->pixelFormat() == QImage::Format_RGB32);
+ format = screen->pixelFormat();
+ dfbSurface = QDirectFBScreen::instance()->createDFBSurface(QSize(width, height),
+ format,
+ QDirectFBScreen::TrackSurface);
+ alpha = false;
+ forceRaster = (format == QImage::Format_RGB32);
if (!dfbSurface) {
- setSerialNumber(0);
+ invalidate();
qWarning("QDirectFBPixmapData::resize(): Unable to allocate surface");
return;
}
@@ -84,18 +86,98 @@ void QDirectFBPixmapData::resize(int width, int height)
setSerialNumber(++global_ser_no);
}
+
+// mostly duplicated from qimage.cpp (QImageData::checkForAlphaPixels)
+static bool checkForAlphaPixels(const QImage &img)
+{
+ const uchar *bits = img.bits();
+ const int bytes_per_line = img.bytesPerLine();
+ const uchar *end_bits = bits + bytes_per_line;
+ const int width = img.width();
+ const int height = img.height();
+ switch (img.format()) {
+ case QImage::Format_Indexed8:
+ return img.hasAlphaChannel();
+ case QImage::Format_ARGB32:
+ case QImage::Format_ARGB32_Premultiplied:
+ for (int y=0; y<height; ++y) {
+ for (int x=0; x<width; ++x) {
+ if ((((uint *)bits)[x] & 0xff000000) != 0xff000000) {
+ return true;
+ }
+ }
+ bits += bytes_per_line;
+ }
+ break;
+
+ case QImage::Format_ARGB8555_Premultiplied:
+ case QImage::Format_ARGB8565_Premultiplied:
+ for (int y=0; y<height; ++y) {
+ while (bits < end_bits) {
+ if (bits[0] != 0) {
+ return true;
+ }
+ bits += 3;
+ }
+ bits = end_bits;
+ end_bits += bytes_per_line;
+ }
+ break;
+
+ case QImage::Format_ARGB6666_Premultiplied:
+ for (int y=0; y<height; ++y) {
+ while (bits < end_bits) {
+ if ((bits[0] & 0xfc) != 0) {
+ return true;
+ }
+ bits += 3;
+ }
+ bits = end_bits;
+ end_bits += bytes_per_line;
+ }
+ break;
+
+ case QImage::Format_ARGB4444_Premultiplied:
+ for (int y=0; y<height; ++y) {
+ while (bits < end_bits) {
+ if ((bits[0] & 0xf0) != 0) {
+ return true;
+ }
+ bits += 2;
+ }
+ bits = end_bits;
+ end_bits += bytes_per_line;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return false;
+}
+
void QDirectFBPixmapData::fromImage(const QImage &img,
- Qt::ImageConversionFlags)
+ Qt::ImageConversionFlags flags)
{
- const QImage::Format format = img.hasAlphaChannel() ?
- screen->alphaPixmapFormat()
- : screen->pixelFormat();
+ Q_ASSERT(img.depth() != 1); // these should be handled by QRasterPixmapData
+ if (img.hasAlphaChannel()
+#ifndef QT_NO_DIRECTFB_OPAQUE_DETECTION
+ && (flags & Qt::NoOpaqueDetection || ::checkForAlphaPixels(img))
+#endif
+ ) {
+ alpha = true;
+ format = screen->alphaPixmapFormat();
+ } else {
+ alpha = false;
+ format = screen->pixelFormat();
+ }
dfbSurface = screen->copyToDFBSurface(img, format,
QDirectFBScreen::TrackSurface);
forceRaster = (format == QImage::Format_RGB32);
if (!dfbSurface) {
qWarning("QDirectFBPixmapData::fromImage()");
- setSerialNumber(0);
+ invalidate();
return;
}
setSerialNumber(++global_ser_no);
@@ -110,15 +192,15 @@ void QDirectFBPixmapData::copy(const QPixmapData *data, const QRect &rect)
IDirectFBSurface *src = static_cast<const QDirectFBPixmapData*>(data)->directFBSurface();
const bool hasAlpha = data->hasAlphaChannel();
- const QImage::Format format = (hasAlpha
- ? screen->alphaPixmapFormat()
- : screen->pixelFormat());
+ format = (hasAlpha
+ ? QDirectFBScreen::instance()->alphaPixmapFormat()
+ : QDirectFBScreen::instance()->pixelFormat());
dfbSurface = screen->createDFBSurface(rect.size(), format,
QDirectFBScreen::TrackSurface);
if (!dfbSurface) {
qWarning("QDirectFBPixmapData::copy()");
- setSerialNumber(0);
+ invalidate();
return;
}
forceRaster = (format == QImage::Format_RGB32);
@@ -135,13 +217,28 @@ void QDirectFBPixmapData::copy(const QPixmapData *data, const QRect &rect)
dfbSurface->ReleaseSource(dfbSurface);
if (result != DFB_OK) {
DirectFBError("QDirectFBPixmapData::copy()", result);
- setSerialNumber(0);
+ invalidate();
return;
}
setSerialNumber(++global_ser_no);
}
+static inline bool isOpaqueFormat(QImage::Format format)
+{
+ switch (format) {
+ case QImage::Format_RGB32:
+ case QImage::Format_RGB16:
+ case QImage::Format_RGB666:
+ case QImage::Format_RGB555:
+ case QImage::Format_RGB888:
+ case QImage::Format_RGB444:
+ return true;
+ default:
+ break;
+ }
+ return false;
+}
void QDirectFBPixmapData::fill(const QColor &color)
{
@@ -150,17 +247,19 @@ void QDirectFBPixmapData::fill(const QColor &color)
Q_ASSERT(dfbSurface);
- if (color.alpha() < 255 && !hasAlphaChannel()) {
+ alpha = (color.alpha() < 255);
+ if (alpha && ::isOpaqueFormat(format)) {
QSize size;
dfbSurface->GetSize(dfbSurface, &size.rwidth(), &size.rheight());
screen->releaseDFBSurface(dfbSurface);
+ format = screen->alphaPixmapFormat();
dfbSurface = screen->createDFBSurface(size, screen->alphaPixmapFormat(), QDirectFBScreen::TrackSurface);
forceRaster = false;
setSerialNumber(++global_ser_no);
if (!dfbSurface) {
- qWarning("QDirectFBPixmapData::fill()");
- setSerialNumber(0);
+ qWarning("QDirecttFBPixmapData::fill()");
+ invalidate();
return;
}
}
@@ -186,15 +285,7 @@ void QDirectFBPixmapData::fill(const QColor &color)
bool QDirectFBPixmapData::hasAlphaChannel() const
{
- if (!serialNumber())
- return false;
- DFBSurfacePixelFormat format;
- dfbSurface->GetPixelFormat(dfbSurface, &format);
- return QDirectFBScreen::hasAlpha(format);
-
- // 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()
+ return alpha;
}
QPixmap QDirectFBPixmapData::transformed(const QTransform &transform,
@@ -221,11 +312,10 @@ QPixmap QDirectFBPixmapData::transformed(const QTransform &transform,
return QPixmap();
QDirectFBPixmapData *data = new QDirectFBPixmapData(QPixmapData::PixmapType);
- QImage::Format format = screen->pixelFormat();
DFBSurfaceBlittingFlags flags = DSBLIT_NOFX;
- if (hasAlphaChannel()) {
+ data->alpha = alpha;
+ if (alpha) {
flags = DSBLIT_BLEND_ALPHACHANNEL;
- format = screen->alphaPixmapFormat();
}
data->dfbSurface = screen->createDFBSurface(size,
format,
@@ -285,3 +375,10 @@ QImage* QDirectFBPixmapData::buffer()
lockDirectFB();
return lockedImage;
}
+
+void QDirectFBPixmapData::invalidate()
+{
+ setSerialNumber(0);
+ alpha = false;
+ format = QImage::Format_Invalid;
+}
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.h b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.h
index 32676f8..7aa6df8 100644
--- a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.h
+++ b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.h
@@ -75,7 +75,10 @@ public:
int metric(QPaintDevice::PaintDeviceMetric m) const {return QDirectFBPaintDevice::metric(m);}
private:
+ void invalidate();
QDirectFBPaintEngine *engine;
+ QImage::Format format;
+ bool alpha;
};
QT_END_HEADER