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