From 95baddfc2f5dc719188f52519c95206959983206 Mon Sep 17 00:00:00 2001 From: Anders Bakken Date: Wed, 22 Jul 2009 09:47:19 -0700 Subject: Rewrite QDFBScreen::exposeRegion This code should be a noop in the case where one has a proper dfb cursor and proper dfb window handling. This was the only case it actually worked. This patch makes it work for a screen cursor rendered by Qt and sets exposeRegion up to work for using an offscreen backing store. Since one can't query the background color set by directfb this patch also adds a connect option to set the background color. This is needed for erasing the background when the mouse cursor moves. Reviewed-by: Donald --- .../gfxdrivers/directfb/qdirectfbscreen.cpp | 286 +++++++++------------ src/plugins/gfxdrivers/directfb/qdirectfbscreen.h | 14 +- 2 files changed, 124 insertions(+), 176 deletions(-) diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp index 0928643..88e304c 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp @@ -70,7 +70,6 @@ public: IDirectFBDisplayLayer *dfbLayer; #endif IDirectFBScreen *dfbScreen; - QRegion prevExpose; QSet allocatedSurfaces; @@ -82,6 +81,7 @@ public: #endif QDirectFBScreen::DirectFBFlags directFBFlags; QImage::Format alphaPixmapFormat; + QColor backgroundColor; }; QDirectFBScreenPrivate::QDirectFBScreenPrivate(QDirectFBScreen *screen) @@ -1047,6 +1047,14 @@ bool QDirectFBScreen::connect(const QString &displaySpec) printDirectFBInfo(d_ptr->dfb, d_ptr->dfbSurface); #endif + QRegExp backgroundColorRegExp("bgcolor=?(.+)"); + backgroundColorRegExp.setCaseSensitivity(Qt::CaseInsensitive); + if (displayArgs.indexOf(backgroundColorRegExp) != -1) { + d_ptr->backgroundColor.setNamedColor(backgroundColorRegExp.cap(1)); + } + if (!d_ptr->backgroundColor.isValid()) + d_ptr->backgroundColor = Qt::green; + return true; } @@ -1087,7 +1095,7 @@ bool QDirectFBScreen::initDevice() #endif #ifndef QT_NO_QWS_CURSOR -#ifdef QT_NO_DIRECTFB_LAYER +#ifdef QT_NO_DIRECTFB_WM QScreenCursor::initSoftwareCursor(); #else qt_screencursor = new QDirectFBScreenCursor; @@ -1145,203 +1153,119 @@ QWSWindowSurface *QDirectFBScreen::createSurface(const QString &key) const return QScreen::createSurface(key); } -void QDirectFBScreen::compose(const QRegion ®ion) -{ - const QList windows = QWSServer::instance()->clientWindows(); - - QRegion blitRegion = region; - QRegion blendRegion; - - d_ptr->dfbSurface->SetBlittingFlags(d_ptr->dfbSurface, DSBLIT_NOFX); - - // blit opaque region - for (int i = 0; i < windows.size(); ++i) { - QWSWindow *win = windows.at(i); - QWSWindowSurface *surface = win->windowSurface(); - if (!surface) - continue; - - const QRegion r = win->allocatedRegion() & blitRegion; - if (r.isEmpty()) - continue; - - blitRegion -= r; - - if (surface->isRegionReserved()) { - // nothing - } else if (win->isOpaque()) { - const QPoint offset = win->requestedRegion().boundingRect().topLeft(); - - if (surface->key() == QLatin1String("directfb")) { - QDirectFBWindowSurface *s = static_cast(surface); - blit(s->directFBSurface(), offset, r); - } else { - blit(surface->image(), offset, r); - } - } else { - blendRegion += r; - } - if (blitRegion.isEmpty()) - break; - } - - { // fill background - const QRegion fill = blitRegion + blendRegion; - if (!fill.isEmpty()) { - const QColor color = QWSServer::instance()->backgroundBrush().color(); - solidFill(color, fill); - blitRegion = QRegion(); - } - } - - if (blendRegion.isEmpty()) - return; - - // blend non-opaque region - for (int i = windows.size() - 1; i >= 0; --i) { - QWSWindow *win = windows.at(i); - QWSWindowSurface *surface = win->windowSurface(); - if (!surface) - continue; - - const QRegion r = win->allocatedRegion() & blendRegion; - if (r.isEmpty()) - continue; - - DFBSurfaceBlittingFlags flags = DSBLIT_NOFX; - if (!win->isOpaque()) { - flags |= DSBLIT_BLEND_ALPHACHANNEL; - const uint opacity = win->opacity(); - if (opacity < 255) { - flags |= DSBLIT_BLEND_COLORALPHA; - d_ptr->dfbSurface->SetColor(d_ptr->dfbSurface, 0xff, 0xff, 0xff, opacity); - } - } - d_ptr->dfbSurface->SetBlittingFlags(d_ptr->dfbSurface, flags); - - const QPoint offset = win->requestedRegion().boundingRect().topLeft(); - - if (surface->key() == QLatin1String("directfb")) { - QDirectFBWindowSurface *s = static_cast(surface); - blit(s->directFBSurface(), offset, r); - } else { - blit(surface->image(), offset, r); - } - } -#if (Q_DIRECTFB_VERSION >= 0x010000) - d_ptr->dfbSurface->ReleaseSource(d_ptr->dfbSurface); -#endif -} - // Normally, when using DirectFB to compose the windows (I.e. when // QT_NO_DIRECTFB_WM isn't set), exposeRegion will simply return. If // QT_NO_DIRECTFB_WM is set, exposeRegion will compose only non-directFB // window surfaces. Normal, directFB surfaces are handled by DirectFB. +static inline bool needExposeRegion() +{ +#ifdef QT_NO_DIRECTFB_WM + return true; +#endif +#ifdef QT_NO_DIRECTFB_LAYER +#ifndef QT_NO_QWS_CURSOR + return true; +#endif +#endif + return false; +} + void QDirectFBScreen::exposeRegion(QRegion r, int changing) { + if (!needExposeRegion()) { + return; + } + const QList windows = QWSServer::instance()->clientWindows(); if (changing < 0 || changing >= windows.size()) return; -#ifndef QT_NO_DIRECTFB_WM + QWSWindow *win = windows.at(changing); QWSWindowSurface *s = win->windowSurface(); - if (s && s->key() == QLatin1String("directfb")) - return; -#endif - r &= region(); if (r.isEmpty()) return; - if (d_ptr->flipFlags & DSFLIP_BLIT) { - const QRect brect = r.boundingRect(); - DFBRegion dfbRegion = { brect.left(), brect.top(), - brect.right(), brect.bottom() }; - compose(r); - d_ptr->dfbSurface->Flip(d_ptr->dfbSurface, &dfbRegion, - d_ptr->flipFlags); + const QRect brect = r.boundingRect(); + + if (!s) { + solidFill(d_ptr->backgroundColor, r); } else { - compose(r + d_ptr->prevExpose); - d_ptr->dfbSurface->Flip(d_ptr->dfbSurface, 0, d_ptr->flipFlags); + const QRect windowGeometry = s->geometry(); + const QRegion outsideWindow = r.subtracted(windowGeometry); + if (!outsideWindow.isEmpty()) { + solidFill(d_ptr->backgroundColor, outsideWindow); + } + const QRegion insideWindow = r.intersected(windowGeometry); + if (!insideWindow.isEmpty()) { + QDirectFBWindowSurface *dfbWindowSurface = (s->key() == QLatin1String("directfb")) + ? static_cast(s) : 0; + if (dfbWindowSurface) { + IDirectFBSurface *surface = dfbWindowSurface->directFBSurface(); + if (d_ptr->directFBFlags & BoundingRectFlip || insideWindow.numRects() == 1) { + const QRect source = (insideWindow.boundingRect().intersected(windowGeometry)).translated(-windowGeometry.topLeft()); + const DFBRectangle rect = { + source.x(), source.y(), source.width(), source.height() + }; + d_ptr->dfbSurface->Blit(d_ptr->dfbSurface, surface, &rect, + windowGeometry.x() + source.x(), + windowGeometry.y() + source.y()); + } else { + const QVector rects = insideWindow.rects(); + const int count = rects.size(); + Q_ASSERT(count > 1); + for (int i=0; idfbSurface->Blit(d_ptr->dfbSurface, surface, &rect, + windowGeometry.x() + source.x(), + windowGeometry.y() + source.y()); + } + } + } + } } - d_ptr->prevExpose = r; -} - -void QDirectFBScreen::blit(const QImage &img, const QPoint &topLeft, - const QRegion ®) -{ - IDirectFBSurface *src = createDFBSurface(img, QDirectFBScreen::DontTrackSurface); - if (!src) { - qWarning("QDirectFBScreen::blit(): Error creating surface"); - return; - } - blit(src, topLeft, reg); + if (QScreenCursor *cursor = QScreenCursor::instance()) { + const QRect cursorRectangle = cursor->boundingRect(); + if (cursor->isVisible() && !cursor->isAccelerated() && cursorRectangle.intersects(brect)) { + const QImage image = cursor->image(); + IDirectFBSurface *surface = createDFBSurface(image, QDirectFBScreen::DontTrackSurface); + d_ptr->dfbSurface->SetBlittingFlags(d_ptr->dfbSurface, DSBLIT_BLEND_ALPHACHANNEL); + d_ptr->dfbSurface->Blit(d_ptr->dfbSurface, surface, 0, cursorRectangle.x(), cursorRectangle.y()); + surface->Release(surface); #if (Q_DIRECTFB_VERSION >= 0x010000) - d_ptr->dfbSurface->ReleaseSource(d_ptr->dfbSurface); + d_ptr->dfbSurface->ReleaseSource(d_ptr->dfbSurface); #endif - src->Release(src); -} - -void QDirectFBScreen::blit(IDirectFBSurface *src, const QPoint &topLeft, - const QRegion ®ion) -{ - const QVector rs = region.translated(-offset()).rects(); - const int size = rs.size(); - const QPoint tl = topLeft - offset(); - - QVarLengthArray rects(size); - QVarLengthArray points(size); - - int n = 0; - for (int i = 0; i < size; ++i) { - const QRect r = rs.at(i); - if (!r.isValid()) - continue; - rects[n].x = r.x() - tl.x(); - rects[n].y = r.y() - tl.y(); - rects[n].w = r.width(); - rects[n].h = r.height(); - points[n].x = r.x(); - points[n].y = r.y(); - ++n; + } } - - d_ptr->dfbSurface->BatchBlit(d_ptr->dfbSurface, src, rects.data(), - points.data(), n); + flipSurface(d_ptr->dfbSurface, d_ptr->flipFlags, r, QPoint()); } -// 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; - 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 rects = region.rects(); - for (int i=0; idfbSurface->FillRectangle(d_ptr->dfbSurface, - r.x(), r.y(), r.width(), r.height()); - } + d_ptr->dfbSurface->SetColor(d_ptr->dfbSurface, + color.red(), color.green(), color.blue(), + color.alpha()); + const QVector rects = region.rects(); + for (int i=0; idfbSurface->FillRectangle(d_ptr->dfbSurface, + r.x(), r.y(), r.width(), r.height()); } } +void QDirectFBScreen::erase(const QRegion ®ion) +{ + solidFill(d_ptr->backgroundColor, region); +} + QImage::Format QDirectFBScreen::alphaPixmapFormat() const { return d_ptr->alphaPixmapFormat; @@ -1377,3 +1301,31 @@ uchar *QDirectFBScreen::lockSurface(IDirectFBSurface *surface, uint flags, int * return reinterpret_cast(mem); } + +void QDirectFBScreen::flipSurface(IDirectFBSurface *surface, DFBSurfaceFlipFlags flipFlags, + const QRegion ®ion, const QPoint &offset) +{ + if (!(flipFlags & DSFLIP_BLIT)) { + surface->Flip(surface, 0, flipFlags); + } else { + if (!(d_ptr->directFBFlags & BoundingRectFlip) && region.numRects() > 1) { + const QVector rects = region.rects(); + const DFBSurfaceFlipFlags nonWaitFlags = flipFlags & ~DSFLIP_WAIT; + for (int i=0; iFlip(surface, &dfbReg, i + 1 < rects.size() ? nonWaitFlags : flipFlags); + } + } else { + const QRect r = region.boundingRect(); + const DFBRegion dfbReg = { r.x() + offset.x(), r.y() + offset.y(), + r.x() + r.width() + offset.x(), + r.y() + r.height() + offset.y() }; + surface->Flip(surface, &dfbReg, flipFlags); + } + } +} + + diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h index 090a685..c128932 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h +++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.h @@ -52,7 +52,6 @@ QT_MODULE(Gui) #define Q_DIRECTFB_VERSION ((DIRECTFB_MAJOR_VERSION << 16) | (DIRECTFB_MINOR_VERION << 8) | DIRECTFB_MICRO_VERSION) -#include #define DIRECTFB_DECLARE_OPERATORS_FOR_FLAGS(F) \ static inline F operator~(F f) { return F(~int(f)); } \ static inline F operator&(F left, F right) { return F(int(left) & int(right)); } \ @@ -94,7 +93,6 @@ public: void shutdownDevice(); void exposeRegion(QRegion r, int changing); - void blit(const QImage &img, const QPoint &topLeft, const QRegion ®ion); void scroll(const QRegion ®ion, const QPoint &offset); void solidFill(const QColor &color, const QRegion ®ion); @@ -131,9 +129,12 @@ public: QImage::Format format, SurfaceCreationOptions options); IDirectFBSurface *copyToDFBSurface(const QImage &image, - QImage::Format format, - SurfaceCreationOptions options); + QImage::Format format, + SurfaceCreationOptions options); + void flipSurface(IDirectFBSurface *surface, DFBSurfaceFlipFlags flipFlags, + const QRegion ®ion, const QPoint &offset); void releaseDFBSurface(IDirectFBSurface *surface); + void erase(const QRegion ®ion); static int depth(DFBSurfacePixelFormat format); @@ -154,14 +155,9 @@ public: #endif static uchar *lockSurface(IDirectFBSurface *surface, uint flags, int *bpl = 0); - private: IDirectFBSurface *createDFBSurface(DFBSurfaceDescription desc, SurfaceCreationOptions options); - void compose(const QRegion &r); - void blit(IDirectFBSurface *src, const QPoint &topLeft, - const QRegion ®ion); - QDirectFBScreenPrivate *d_ptr; friend class SurfaceCache; }; -- cgit v0.12