diff options
Diffstat (limited to 'src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp')
-rw-r--r-- | src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp | 485 |
1 files changed, 338 insertions, 147 deletions
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp index 0486e400b4..3e54e7f57d 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp @@ -81,10 +81,11 @@ public: QDirectFBKeyboardHandler *keyboard; #endif bool videoonly; + QImage::Format alphaPixmapFormat; }; QDirectFBScreenPrivate::QDirectFBScreenPrivate(QDirectFBScreen* screen) - : QWSGraphicsSystem(screen), dfb(0), dfbSurface(0), flipFlags(DSFLIP_BLIT) + : QWSGraphicsSystem(screen), dfb(0), dfbSurface(0), flipFlags(DSFLIP_NONE) #ifndef QT_NO_DIRECTFB_LAYER , dfbLayer(0) #endif @@ -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,90 @@ 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) { + int bpl; + uchar *mem = QDirectFBScreen::lockSurface(surface, DSLF_WRITE, &bpl); + if (mem) { + const int h = img.height(); + const int w = img.width() * img.depth() / 8; + for (int i = 0; i < h; ++i) { + memcpy(mem, img.scanLine(i), w); + mem += bpl; + } + surface->Unlock(surface); + } + } +#endif +#ifndef QT_NO_DIRECTFB_PALETTE + if (img.numColors() != 0 && surface) + 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); + DFBSurfacePixelFormat dspf; + src->GetPixelFormat(src, &dspf); + DFBSurfaceBlittingFlags flags = QDirectFBScreen::hasAlpha(dspf) + ? DSBLIT_BLEND_ALPHACHANNEL + : DSBLIT_NOFX; + if (flags & DSBLIT_BLEND_ALPHACHANNEL) + surface->Clear(surface, 0, 0, 0, 0); + + surface->SetBlittingFlags(surface, flags); + surface->Blit(surface, src, 0, 0, 0); + surface->ReleaseSource(surface); + 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; @@ -143,22 +228,43 @@ IDirectFBSurface* QDirectFBScreen::createDFBSurface(const DFBSurfaceDescription* if (d_ptr->videoonly && !(desc->flags & DSDESC_PREALLOCATED)) { // Add the video only capability. This means the surface will be created in video ram DFBSurfaceDescription voDesc = *desc; - voDesc.caps = DFBSurfaceCapabilities(voDesc.caps | DSCAPS_VIDEOONLY); - voDesc.flags = DFBSurfaceDescriptionFlags(voDesc.flags | DSDESC_CAPS); + if (!(voDesc.flags & DSDESC_CAPS)) { + voDesc.caps = DSCAPS_VIDEOONLY; + voDesc.flags = DFBSurfaceDescriptionFlags(voDesc.flags | DSDESC_CAPS); + } else { + voDesc.caps = DFBSurfaceCapabilities(voDesc.caps | DSCAPS_VIDEOONLY); + } result = d_ptr->dfb->CreateSurface(d_ptr->dfb, &voDesc, &newSurface); + if (result != DFB_OK +#ifdef QT_NO_DEBUG + && (desc->flags & DSDESC_CAPS) && (desc->caps & DSCAPS_PRIMARY) +#endif + ) { + qWarning("QDirectFBScreen::createDFBSurface() Failed to create surface in video memory!\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)); + } } if (!newSurface) 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 +274,69 @@ IDirectFBSurface* QDirectFBScreen::createDFBSurface(const DFBSurfaceDescription* return newSurface; } -void QDirectFBScreen::releaseDFBSurface(IDirectFBSurface* surface) +IDirectFBSurface *QDirectFBScreen::copyToDFBSurface(const QImage &img, + QImage::Format pixmapFormat, + SurfaceCreationOptions options) +{ + QImage image = img; + if (QDirectFBScreen::getSurfacePixelFormat(image.format()) == DSPF_UNKNOWN +#ifdef QT_NO_DIRECTFB_PREALLOCATED + || image.format() != pixmapFormat +#endif +#ifdef QT_NO_DIRECTFB_PALETTE + || image.numColors() != 0 +#endif + ) { + image = image.convertToFormat(pixmapFormat); + } + + IDirectFBSurface *dfbSurface = createDFBSurface(image.size(), pixmapFormat, options); + if (!dfbSurface) { + qWarning("QDirectFBPixmapData::fromImage() Couldn't create surface"); + return 0; + } + +#ifndef QT_NO_DIRECTFB_PREALLOCATED + IDirectFBSurface *imgSurface = createDFBSurface(image, DontTrackSurface); + if (!imgSurface) { + qWarning("QDirectFBPixmapData::fromImage()"); + QDirectFBScreen::releaseDFBSurface(dfbSurface); + return 0; + } + + Q_ASSERT(imgSurface); + DFBSurfaceBlittingFlags flags = img.hasAlphaChannel() + ? DSBLIT_BLEND_ALPHACHANNEL + : DSBLIT_NOFX; + if (flags & DSBLIT_BLEND_ALPHACHANNEL) + dfbSurface->Clear(dfbSurface, 0, 0, 0, 0); + + dfbSurface->SetBlittingFlags(dfbSurface, flags); + DFBResult 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); + int bpl; + uchar *mem = QDirectFBScreen::lockSurface(dfbSurface, DSLF_WRITE, &bpl); + if (mem) { + const int h = image.height(); + const int w = image.width() * image.depth() / 8; + for (int i=0; i<h; ++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 +367,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 +400,11 @@ DFBSurfacePixelFormat QDirectFBScreen::getSurfacePixelFormat(const QImage &image }; } -QImage::Format QDirectFBScreen::getImageFormat(DFBSurfacePixelFormat format) +QImage::Format QDirectFBScreen::getImageFormat(IDirectFBSurface *surface) { + DFBSurfacePixelFormat format; + surface->GetPixelFormat(surface, &format); + switch (format) { case DSPF_LUT8: return QImage::Format_Indexed8; @@ -257,8 +427,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 +444,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 +507,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); @@ -362,50 +532,6 @@ void QDirectFBScreen::setSurfaceColorTable(IDirectFBSurface *surface, palette->Release(palette); } -void QDirectFBScreen::setImageColorTable(QImage *image, IDirectFBSurface *surface) -{ - if (!image || !surface || image->depth() > 8) - return; - - IDirectFBPalette *palette = 0; - unsigned int numColors = 0; - DFBResult result; - do { - result = surface->GetPalette(surface, &palette); - if (result != DFB_OK) { - DirectFBError("QDirectFBScreen::setImageColorTable GetPalette", result); - break; - } - - result = palette->GetSize(palette, &numColors); - if (result != DFB_OK) { - DirectFBError("QDirectFBScreen::setImageColorTable GetPalette", result); - break; - } - - if (numColors == 0) - break; - - QVarLengthArray<DFBColor> dfbColors(numColors); - result = palette->GetEntries(palette, dfbColors.data(), numColors, 0); - if (result != DFB_OK) { - DirectFBError("QDirectFBScreen::setImageColorTable GetPalette", result); - break; - } - - QVector<QRgb> qtColors(numColors); - for (unsigned int i=0; i<numColors; ++i) { - const DFBColor &col = dfbColors[i]; - qtColors[i] = qRgba(col.r, col.g, col.b, col.a); - } - image->setColorTable(qtColors); - - } while (0); - - if (palette) - palette->Release(palette); -} - #endif // QT_NO_DIRECTFB_PALETTE #if !defined(QT_NO_DIRECTFB_LAYER) && !defined(QT_NO_QWS_CURSOR) @@ -505,18 +631,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); @@ -524,15 +642,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: " @@ -611,7 +726,7 @@ int QDirectFBScreen::depth(DFBSurfacePixelFormat format) void QDirectFBScreenPrivate::setFlipFlags(const QStringList &args) { - QRegExp flipRegexp(QLatin1String("^flip=([\\w,]+)$")); + QRegExp flipRegexp(QLatin1String("^flip=([\\w,]*)$")); int index = args.indexOf(flipRegexp); if (index >= 0) { const QStringList flips = flipRegexp.cap(1).split(QLatin1Char(','), @@ -630,6 +745,8 @@ void QDirectFBScreenPrivate::setFlipFlags(const QStringList &args) qWarning("QDirectFBScreen: Unknown flip argument: %s", qPrintable(flip)); } + } else { + flipFlags = DFBSurfaceFlipFlags(DSFLIP_BLIT); } } @@ -659,6 +776,18 @@ static void printDirectFBInfo(IDirectFB *fb) dev.blitting_flags, dev.drawing_flags, dev.video_memory); } +static inline bool setIntOption(const QStringList &arguments, const QString &variable, int *value) +{ + Q_ASSERT(value); + QRegExp rx(QString("%1=?(\\d+)").arg(variable)); + rx.setCaseSensitivity(Qt::CaseInsensitive); + if (arguments.indexOf(rx) != -1) { + *value = rx.cap(1).toInt(); + return true; + } + return false; +} + bool QDirectFBScreen::connect(const QString &displaySpec) { DFBResult result = DFB_OK; @@ -680,7 +809,7 @@ bool QDirectFBScreen::connect(const QString &displaySpec) } const QStringList displayArgs = displaySpec.split(QLatin1Char(':'), - QString::SkipEmptyParts); + QString::SkipEmptyParts); d_ptr->setFlipFlags(displayArgs); @@ -704,23 +833,57 @@ bool QDirectFBScreen::connect(const QString &displaySpec) DFBSurfaceDescription description; description.flags = DFBSurfaceDescriptionFlags(DSDESC_CAPS); - description.caps = DFBSurfaceCapabilities(DSCAPS_PRIMARY - | DSCAPS_DOUBLE - | DSCAPS_STATIC_ALLOC); - if (!(d_ptr->flipFlags & DSFLIP_BLIT)) { - description.caps = DFBSurfaceCapabilities(description.caps - | DSCAPS_DOUBLE - | DSCAPS_TRIPLE); + if (::setIntOption(displayArgs, QLatin1String("width"), &description.width)) + description.flags = DFBSurfaceDescriptionFlags(description.flags | DSDESC_WIDTH); + if (::setIntOption(displayArgs, QLatin1String("height"), &description.height)) + description.flags = DFBSurfaceDescriptionFlags(description.flags | DSDESC_HEIGHT); + uint caps = DSCAPS_PRIMARY|DSCAPS_DOUBLE; + if (displayArgs.contains(QLatin1String("static_alloc"))) + caps |= DSCAPS_STATIC_ALLOC; + + if (displayArgs.contains(QLatin1String("forcepremultiplied"), Qt::CaseInsensitive)) { + caps |= DSCAPS_PREMULTIPLIED; } - + description.caps = DFBSurfaceCapabilities(caps); // 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; @@ -736,21 +899,11 @@ 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+)")); - int dimIdxW = displayArgs.indexOf(mmWidthRx); - if (dimIdxW >= 0) { - mmWidthRx.exactMatch(displayArgs.at(dimIdxW)); - physWidth = mmWidthRx.cap(1).toInt(); - } - QRegExp mmHeightRx(QLatin1String("mmHeight=?(\\d+)")); - int dimIdxH = displayArgs.indexOf(mmHeightRx); - if (dimIdxH >= 0) { - mmHeightRx.exactMatch(displayArgs.at(dimIdxH)); - physHeight = mmHeightRx.cap(1).toInt(); - } + ::setIntOption(displayArgs, QLatin1String("mmWidth"), &physWidth); + ::setIntOption(displayArgs, QLatin1String("mmHeight"), &physHeight); const int dpi = 72; if (physWidth < 0) physWidth = qRound(dw * 25.4 / dpi); @@ -803,16 +956,15 @@ void QDirectFBScreen::disconnect() bool QDirectFBScreen::initDevice() { - QWSServer *server = QWSServer::instance(); #ifndef QT_NO_DIRECTFB_MOUSE if (qgetenv("QWS_MOUSE_PROTO").isEmpty()) { - server->setDefaultMouse("None"); + QWSServer::instance()->setDefaultMouse("None"); d_ptr->mouse = new QDirectFBMouseHandler; } #endif #ifndef QT_NO_DIRECTFB_KEYBOARD if (qgetenv("QWS_KEYBOARD").isEmpty()) { - server->setDefaultKeyboard("None"); + QWSServer::instance()->setDefaultKeyboard("None"); d_ptr->keyboard = new QDirectFBKeyboardHandler(QString()); } #endif @@ -858,19 +1010,21 @@ void QDirectFBScreen::blank(bool on) QWSWindowSurface* QDirectFBScreen::createSurface(QWidget *widget) const { #ifdef QT_NO_DIRECTFB_WM - if (QApplication::type() == QApplication::GuiServer) - return new QDirectFBSurface(const_cast<QDirectFBScreen*>(this), widget); - else + if (QApplication::type() == QApplication::GuiServer) { + return new QDirectFBSurface(d_ptr->flipFlags, const_cast<QDirectFBScreen*>(this), widget); + } else { return QScreen::createSurface(widget); + } #else - return new QDirectFBSurface(const_cast<QDirectFBScreen*>(this), widget); + return new QDirectFBSurface(d_ptr->flipFlags, const_cast<QDirectFBScreen*>(this), widget); #endif } QWSWindowSurface* QDirectFBScreen::createSurface(const QString &key) const { - if (key == QLatin1String("directfb")) - return new QDirectFBSurface(const_cast<QDirectFBScreen*>(this)); + if (key == QLatin1String("directfb")) { + return new QDirectFBSurface(d_ptr->flipFlags, const_cast<QDirectFBScreen*>(this)); + } return QScreen::createSurface(key); } @@ -903,7 +1057,7 @@ void QDirectFBScreen::compose(const QRegion ®ion) if (surface->key() == QLatin1String("directfb")) { QDirectFBSurface *s = static_cast<QDirectFBSurface*>(surface); - blit(s->directFbSurface(), offset, r); + blit(s->directFBSurface(), offset, r); } else { blit(surface->image(), offset, r); } @@ -952,11 +1106,12 @@ void QDirectFBScreen::compose(const QRegion ®ion) if (surface->key() == QLatin1String("directfb")) { QDirectFBSurface *s = static_cast<QDirectFBSurface*>(surface); - blit(s->directFbSurface(), offset, r); + blit(s->directFBSurface(), offset, r); } else { blit(surface->image(), offset, r); } } + d_ptr->dfbSurface->ReleaseSource(d_ptr->dfbSurface); } // Normally, when using DirectFB to compose the windows (I.e. when @@ -998,21 +1153,14 @@ void QDirectFBScreen::exposeRegion(QRegion r, int changing) void QDirectFBScreen::blit(const QImage &img, const QPoint &topLeft, const QRegion ®) { - 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, @@ -1043,25 +1191,68 @@ void QDirectFBScreen::blit(IDirectFBSurface *src, const QPoint &topLeft, points.data(), n); } +// This function is only ever called by QScreen::drawBackground which +// is only ever called by QScreen::compose which is never called with +// DirectFB so it's really a noop. void QDirectFBScreen::solidFill(const QColor &color, const QRegion ®ion) { if (region.isEmpty()) return; - const QVector<QRect> rects = region.rects(); - QVarLengthArray<DFBRectangle> dfbRects(rects.size()); - for (int i = 0; i < rects.size(); ++i) { - const QRect r = rects.at(i); - dfbRects[i].x = r.x(); - dfbRects[i].y = r.y(); - dfbRects[i].w = r.width(); - dfbRects[i].h = r.height(); + if (QDirectFBScreen::getImageFormat(d_ptr->dfbSurface) == QImage::Format_RGB32) { + data = QDirectFBScreen::lockSurface(d_ptr->dfbSurface, DSLF_WRITE, &lstep); + if (!data) + return; + + QScreen::solidFill(color, region); + d_ptr->dfbSurface->Unlock(d_ptr->dfbSurface); + data = 0; + lstep = 0; + } else { + d_ptr->dfbSurface->SetColor(d_ptr->dfbSurface, + color.red(), color.green(), color.blue(), + color.alpha()); + const QVector<QRect> rects = region.rects(); + for (int i=0; i<rects.size(); ++i) { + const QRect &r = rects.at(i); + d_ptr->dfbSurface->FillRectangle(d_ptr->dfbSurface, + r.x(), r.y(), r.width(), r.height()); + } + } +} + +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; +} + +uchar *QDirectFBScreen::lockSurface(IDirectFBSurface *surface, DFBSurfaceLockFlags flags, int *bpl) +{ + void *mem; + const DFBResult result = surface->Lock(surface, flags, static_cast<void**>(&mem), bpl); + if (result != DFB_OK) { + DirectFBError("QDirectFBPixmapData::lockSurface()", result); } - d_ptr->dfbSurface->SetColor(d_ptr->dfbSurface, - color.red(), color.green(), color.blue(), - color.alpha()); - d_ptr->dfbSurface->FillRectangles(d_ptr->dfbSurface, dfbRects.data(), - dfbRects.size()); + return reinterpret_cast<uchar*>(mem); } |