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.cpp171
1 files changed, 134 insertions, 37 deletions
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpixmap.cpp
index 35ab859..0a1696a 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;
}
}
@@ -184,19 +283,6 @@ 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()
-}
-
QPixmap QDirectFBPixmapData::transformed(const QTransform &transform,
Qt::TransformationMode mode) const
{
@@ -221,11 +307,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,
@@ -250,7 +335,12 @@ QImage QDirectFBPixmapData::toImage() const
#ifndef QT_NO_DIRECTFB_PREALLOCATED
QImage ret(size(), QDirectFBScreen::getImageFormat(dfbSurface));
if (IDirectFBSurface *imgSurface = screen->createDFBSurface(ret, QDirectFBScreen::DontTrackSurface)) {
- imgSurface->SetBlittingFlags(imgSurface, hasAlphaChannel() ? DSBLIT_BLEND_ALPHACHANNEL : DSBLIT_NOFX);
+ if (hasAlphaChannel()) {
+ imgSurface->SetBlittingFlags(imgSurface, DSBLIT_BLEND_ALPHACHANNEL);
+ imgSurface->Clear(imgSurface, 0, 0, 0, 0);
+ } else {
+ imgSurface->SetBlittingFlags(imgSurface, DSBLIT_NOFX);
+ }
imgSurface->Blit(imgSurface, dfbSurface, 0, 0, 0);
imgSurface->ReleaseSource(imgSurface);
imgSurface->Release(imgSurface);
@@ -280,3 +370,10 @@ QImage* QDirectFBPixmapData::buffer()
lockDirectFB();
return lockedImage;
}
+
+void QDirectFBPixmapData::invalidate()
+{
+ setSerialNumber(0);
+ alpha = false;
+ format = QImage::Format_Invalid;
+}