diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/gui/painting/qpaintengine_raster.cpp | 32 | ||||
-rw-r--r-- | src/gui/painting/qpaintengineex.cpp | 12 | ||||
-rw-r--r-- | src/gui/painting/qpaintengineex_p.h | 2 | ||||
-rw-r--r-- | src/gui/painting/qstroker.cpp | 5 | ||||
-rw-r--r-- | src/plugins/gfxdrivers/directfb/qdirectfbmouse.cpp | 14 | ||||
-rw-r--r-- | src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp | 6 | ||||
-rw-r--r-- | src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp | 296 | ||||
-rw-r--r-- | src/plugins/gfxdrivers/directfb/qdirectfbscreen.h | 14 | ||||
-rw-r--r-- | src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp | 275 | ||||
-rw-r--r-- | src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.h | 10 |
10 files changed, 339 insertions, 327 deletions
diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index e9ff752..dfd3e16 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -1101,6 +1101,9 @@ void QRasterPaintEnginePrivate::systemStateChanged() #ifdef QT_DEBUG_DRAW qDebug() << "systemStateChanged" << this << "deviceRect" << deviceRect << clipRect << systemClip; #endif + + exDeviceRect = deviceRect; + Q_Q(QRasterPaintEngine); q->state()->strokeFlags |= QPaintEngine::DirtyClipRegion; q->state()->fillFlags |= QPaintEngine::DirtyClipRegion; @@ -1708,11 +1711,30 @@ void QRasterPaintEngine::stroke(const QVectorPath &path, const QPen &pen) if (!s->penData.blend) return; - if (s->flags.fast_pen && path.shape() <= QVectorPath::NonCurvedShapeHint && s->lastPen.brush().isOpaque()) { - strokePolygonCosmetic((QPointF *) path.points(), path.elementCount(), - path.hasImplicitClose() - ? WindingMode - : PolylineMode); + if (s->flags.fast_pen && path.shape() <= QVectorPath::NonCurvedShapeHint + && s->lastPen.brush().isOpaque()) { + int count = path.elementCount(); + QPointF *points = (QPointF *) path.points(); + const QPainterPath::ElementType *types = path.elements(); + if (types) { + int first = 0; + int last; + while (first < count) { + while (first < count && types[first] != QPainterPath::MoveToElement) ++first; + last = first + 1; + while (last < count && types[last] == QPainterPath::LineToElement) ++last; + strokePolygonCosmetic(points + first, last - first, + path.hasImplicitClose() && last == count // only close last one.. + ? WindingMode + : PolylineMode); + first = last; + } + } else { + strokePolygonCosmetic(points, count, + path.hasImplicitClose() + ? WindingMode + : PolylineMode); + } } else if (s->flags.non_complex_pen && path.shape() == QVectorPath::LinesHint) { qreal width = s->lastPen.isCosmetic() diff --git a/src/gui/painting/qpaintengineex.cpp b/src/gui/painting/qpaintengineex.cpp index a4db284..797a5ab 100644 --- a/src/gui/painting/qpaintengineex.cpp +++ b/src/gui/painting/qpaintengineex.cpp @@ -364,12 +364,12 @@ void QPaintEngineEx::stroke(const QVectorPath &path, const QPen &pen) d->activeStroker = 0; } else { // ### re-enable... -// if (pen.isCosmetic()) { -// d->dashStroker->setClipRect(d->deviceRect); -// } else { -// QRectF clipRect = s->matrix.inverted().mapRect(QRectF(d->deviceRect)); -// d->dashStroker->setClipRect(clipRect); -// } + if (pen.isCosmetic()) { + d->dasher.setClipRect(d->exDeviceRect); + } else { + QRectF clipRect = state()->matrix.inverted().mapRect(QRectF(d->exDeviceRect)); + d->dasher.setClipRect(clipRect); + } d->dasher.setDashPattern(pen.dashPattern()); d->dasher.setDashOffset(pen.dashOffset()); d->activeStroker = &d->dasher; diff --git a/src/gui/painting/qpaintengineex_p.h b/src/gui/painting/qpaintengineex_p.h index d4e4862..7705cc1 100644 --- a/src/gui/painting/qpaintengineex_p.h +++ b/src/gui/painting/qpaintengineex_p.h @@ -225,6 +225,8 @@ public: StrokeHandler *strokeHandler; QStrokerOps *activeStroker; QPen strokerPen; + + QRect exDeviceRect; }; inline uint QVectorPath::polygonFlags(QPaintEngine::PolygonDrawMode mode) { diff --git a/src/gui/painting/qstroker.cpp b/src/gui/painting/qstroker.cpp index 0649589..b24bf86 100644 --- a/src/gui/painting/qstroker.cpp +++ b/src/gui/painting/qstroker.cpp @@ -1012,10 +1012,13 @@ void QDashStroker::processCurrentSubpath() int dashCount = qMin(m_dashPattern.size(), 32); qfixed dashes[32]; + qreal longestLength = 0; qreal sumLength = 0; for (int i=0; i<dashCount; ++i) { dashes[i] = qMax(m_dashPattern.at(i), qreal(0)) * m_stroker->strokeWidth(); sumLength += dashes[i]; + if (dashes[i] > longestLength) + longestLength = dashes[i]; } if (qFuzzyIsNull(sumLength)) @@ -1053,7 +1056,7 @@ void QDashStroker::processCurrentSubpath() qfixed2d line_to_pos; // Pad to avoid clipping the borders of thick pens. - qfixed padding = qMax(m_stroker->strokeWidth(), m_stroker->miterLimit()); + qfixed padding = qt_real_to_fixed(qMax(m_stroker->strokeWidth(), m_stroker->miterLimit()) * longestLength); qfixed2d clip_tl = { qt_real_to_fixed(m_clip_rect.left()) - padding, qt_real_to_fixed(m_clip_rect.top()) - padding }; qfixed2d clip_br = { qt_real_to_fixed(m_clip_rect.right()) + padding , diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbmouse.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbmouse.cpp index 142993d..4365a5d 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbmouse.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbmouse.cpp @@ -203,7 +203,6 @@ void QDirectFBMouseHandlerPrivate::readMouseData() int wheel = 0; if (input.type == DIET_AXISMOTION) { -#ifdef QT_NO_DIRECTFB_LAYER if (input.flags & DIEF_AXISABS) { switch (input.axis) { case DIAI_X: x = input.axisabs; break; @@ -223,19 +222,6 @@ void QDirectFBMouseHandlerPrivate::readMouseData() "unknown axis (releative) %d", input.axis); } } -#else - if (input.axis == DIAI_X || input.axis == DIAI_Y) { - DFBResult result = layer->GetCursorPosition(layer, &x, &y); - if (result != DFB_OK) { - DirectFBError("QDirectFBMouseHandler::readMouseData", - result); - } - } else if (input.axis == DIAI_Z) { - Q_ASSERT(input.flags & DIEF_AXISREL); - wheel = input.axisrel; - wheel *= -120; - } -#endif } Qt::MouseButtons buttons = Qt::NoButton; diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp index 94f1aeb..b264ac0 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp @@ -466,7 +466,7 @@ void QDirectFBPaintEngine::drawImage(const QRectF &r, const QImage &image, d->blit(r, imgSurface, sr); if (release) { #if (Q_DIRECTFB_VERSION >= 0x010000) - imgSurface->ReleaseSource(imgSurface); + d->surface->ReleaseSource(d->surface); #endif imgSurface->Release(imgSurface); } @@ -608,6 +608,8 @@ void QDirectFBPaintEngine::drawTextItem(const QPointF &p, void QDirectFBPaintEngine::fill(const QVectorPath &path, const QBrush &brush) { + if (brush.style() == Qt::NoBrush) + return; RASTERFALLBACK(FILL_PATH, path, brush, VOID_ARG()); Q_D(QDirectFBPaintEngine); d->lock(); @@ -618,6 +620,8 @@ void QDirectFBPaintEngine::fill(const QVectorPath &path, const QBrush &brush) void QDirectFBPaintEngine::fillRect(const QRectF &rect, const QBrush &brush) { Q_D(QDirectFBPaintEngine); + if (brush.style() == Qt::NoBrush) + return; d->updateClip(); if (!d->unsupportedCompositionMode && !(d->transformationType & (QDirectFBPaintEnginePrivate::RectsUnsupported)) diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp index 0928643..4b76ef6 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<IDirectFBSurface*> allocatedSurfaces; @@ -82,6 +81,7 @@ public: #endif QDirectFBScreen::DirectFBFlags directFBFlags; QImage::Format alphaPixmapFormat; + QColor backgroundColor; }; QDirectFBScreenPrivate::QDirectFBScreenPrivate(QDirectFBScreen *screen) @@ -141,6 +141,7 @@ IDirectFBSurface *QDirectFBScreen::createDFBSurface(const QImage &img, SurfaceCr { if (img.isNull()) // assert? return 0; + if (QDirectFBScreen::getSurfacePixelFormat(img.format()) == DSPF_UNKNOWN) { QImage image = img.convertToFormat(img.hasAlphaChannel() ? d_ptr->alphaPixmapFormat @@ -321,10 +322,10 @@ IDirectFBSurface *QDirectFBScreen::copyToDFBSurface(const QImage &img, DFBResult result = dfbSurface->Blit(dfbSurface, imgSurface, 0, 0, 0); if (result != DFB_OK) DirectFBError("QDirectFBScreen::copyToDFBSurface()", result); + imgSurface->Release(imgSurface); #if (Q_DIRECTFB_VERSION >= 0x010000) dfbSurface->ReleaseSource(dfbSurface); #endif - imgSurface->Release(imgSurface); #else // QT_NO_DIRECTFB_PREALLOCATED Q_ASSERT(image.format() == pixmapFormat); int bpl; @@ -1047,6 +1048,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 +1096,7 @@ bool QDirectFBScreen::initDevice() #endif #ifndef QT_NO_QWS_CURSOR -#ifdef QT_NO_DIRECTFB_LAYER +#if defined QT_NO_DIRECTFB_WM || defined QT_NO_DIRECTFB_LAYER QScreenCursor::initSoftwareCursor(); #else qt_screencursor = new QDirectFBScreenCursor; @@ -1145,203 +1154,134 @@ QWSWindowSurface *QDirectFBScreen::createSurface(const QString &key) const return QScreen::createSurface(key); } -void QDirectFBScreen::compose(const QRegion ®ion) -{ - const QList<QWSWindow*> 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<QDirectFBWindowSurface*>(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<QDirectFBWindowSurface*>(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<QWSWindow*> 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<QDirectFBWindowSurface*>(s) : 0; + if (dfbWindowSurface) { + IDirectFBSurface *surface = dfbWindowSurface->directFBSurface(); + const int n = insideWindow.numRects(); + if (n == 1 || d_ptr->directFBFlags & BoundingRectFlip) { + 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<QRect> rects = insideWindow.rects(); + QVarLengthArray<DFBRectangle, 16> dfbRectangles(n); + QVarLengthArray<DFBPoint, 16> dfbPoints(n); + + for (int i=0; i<n; ++i) { + const QRect source = (rects.at(i).intersected(windowGeometry)).translated(-windowGeometry.topLeft()); + DFBRectangle &rect = dfbRectangles[i]; + rect.x = source.x(); + rect.y = source.y(); + rect.w = source.width(); + rect.h = source.height(); + dfbPoints[i].x = (windowGeometry.x() + source.x()); + dfbPoints[i].y = (windowGeometry.y() + source.y()); + } + d_ptr->dfbSurface->BatchBlit(d_ptr->dfbSurface, surface, dfbRectangles.constData(), + dfbPoints.constData(), n); + } + } + } } - 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<QRect> rs = region.translated(-offset()).rects(); - const int size = rs.size(); - const QPoint tl = topLeft - offset(); - - QVarLengthArray<DFBRectangle> rects(size); - QVarLengthArray<DFBPoint> 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; + d_ptr->dfbSurface->SetColor(d_ptr->dfbSurface, + color.red(), color.green(), color.blue(), + color.alpha()); + const int n = region.numRects(); + if (n > 1) { + const QRect r = region.boundingRect(); + d_ptr->dfbSurface->FillRectangle(d_ptr->dfbSurface, r.x(), r.y(), r.width(), r.height()); } 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) { + QVarLengthArray<DFBRectangle, 32> rectArray(n); + for (int i=0; i<n; ++i) { const QRect &r = rects.at(i); - d_ptr->dfbSurface->FillRectangle(d_ptr->dfbSurface, - r.x(), r.y(), r.width(), r.height()); + rectArray[i].x = r.x(); + rectArray[i].y = r.y(); + rectArray[i].w = r.width(); + rectArray[i].h = r.height(); } + d_ptr->dfbSurface->FillRectangles(d_ptr->dfbSurface, rectArray.constData(), n); } } +void QDirectFBScreen::erase(const QRegion ®ion) +{ + solidFill(d_ptr->backgroundColor, region); +} + QImage::Format QDirectFBScreen::alphaPixmapFormat() const { return d_ptr->alphaPixmapFormat; @@ -1377,3 +1317,31 @@ uchar *QDirectFBScreen::lockSurface(IDirectFBSurface *surface, uint flags, int * return reinterpret_cast<uchar*>(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<QRect> rects = region.rects(); + const DFBSurfaceFlipFlags nonWaitFlags = flipFlags & ~DSFLIP_WAIT; + for (int i=0; i<rects.size(); ++i) { + const QRect &r = rects.at(i); + 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, 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 69b09e9..63c608e 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 <QDebug> #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); using QScreen::depth; static int depth(DFBSurfacePixelFormat format); @@ -155,14 +156,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; }; diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp index 7dcf398..a1009ac 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp @@ -44,10 +44,10 @@ #include "qdirectfbpaintengine.h" #include <qwidget.h> +#include <qwindowsystem_qws.h> #include <qpaintdevice.h> #include <qvarlengtharray.h> - //#define QT_DIRECTFB_DEBUG_SURFACES 1 QDirectFBWindowSurface::QDirectFBWindowSurface(DFBSurfaceFlipFlags flip, QDirectFBScreen *scr) @@ -59,6 +59,11 @@ QDirectFBWindowSurface::QDirectFBWindowSurface(DFBSurfaceFlipFlags flip, QDirect , flipFlags(flip) , boundingRectFlip(scr->directFBFlags() & QDirectFBScreen::BoundingRectFlip) { +#ifdef QT_NO_DIRECTFB_WM + mode = Offscreen; +#else + mode = Window; +#endif setSurfaceFlags(Opaque | Buffered); #ifdef QT_DIRECTFB_TIMING frames = 0; @@ -75,11 +80,17 @@ QDirectFBWindowSurface::QDirectFBWindowSurface(DFBSurfaceFlipFlags flip, QDirect , flipFlags(flip) , boundingRectFlip(scr->directFBFlags() & QDirectFBScreen::BoundingRectFlip) { - onscreen = widget->testAttribute(Qt::WA_PaintOnScreen); - if (onscreen) + if (widget && widget->testAttribute(Qt::WA_PaintOnScreen)) { setSurfaceFlags(Opaque | RegionReserved); - else + mode = Primary; + } else { +#ifdef QT_NO_DIRECTFB_WM + mode = Offscreen; +#else + mode = Window; +#endif setSurfaceFlags(Opaque | Buffered); + } #ifdef QT_DIRECTFB_TIMING frames = 0; timer.start(); @@ -99,7 +110,7 @@ bool QDirectFBWindowSurface::isValid() const void QDirectFBWindowSurface::createWindow() { #ifdef QT_NO_DIRECTFB_LAYER -#warning QT_NO_DIRECTFB_LAYER requires QT_NO_DIRECTFB_WM +#error QT_NO_DIRECTFB_LAYER requires QT_NO_DIRECTFB_WM #else IDirectFBDisplayLayer *layer = screen->dfbDisplayLayer(); if (!layer) @@ -129,8 +140,40 @@ void QDirectFBWindowSurface::createWindow() } #endif // QT_NO_DIRECTFB_WM -void QDirectFBWindowSurface::setGeometry(const QRect &rect, const QRegion &mask) +#ifndef QT_NO_DIRECTFB_WM +static DFBResult setGeometry(IDirectFBWindow *dfbWindow, const QRect &old, const QRect &rect) { + DFBResult result = DFB_OK; + const bool isMove = old.isEmpty() || rect.topLeft() != old.topLeft(); + const bool isResize = rect.size() != old.size(); + +#if (Q_DIRECTFB_VERSION >= 0x010000) + if (isResize && isMove) { + result = dfbWindow->SetBounds(dfbWindow, rect.x(), rect.y(), + rect.width(), rect.height()); + } else if (isResize) { + result = dfbWindow->Resize(dfbWindow, + rect.width(), rect.height()); + } else if (isMove) { + result = dfbWindow->MoveTo(dfbWindow, rect.x(), rect.y()); + } +#else + if (isResize) { + result = dfbWindow->Resize(dfbWindow, + rect.width(), rect.height()); + } + if (isMove) { + result = dfbWindow->MoveTo(dfbWindow, rect.x(), rect.y()); + } +#endif + return result; +} +#endif + +void QDirectFBWindowSurface::setGeometry(const QRect &rect) +{ + IDirectFBSurface *primarySurface = screen->dfbSurface(); + Q_ASSERT(primarySurface); if (rect.isNull()) { #ifndef QT_NO_DIRECTFB_WM if (dfbWindow) { @@ -138,22 +181,21 @@ void QDirectFBWindowSurface::setGeometry(const QRect &rect, const QRegion &mask) dfbWindow = 0; } #endif - if (dfbSurface && dfbSurface != screen->dfbSurface()) { - dfbSurface->Release(dfbSurface); + if (dfbSurface) { + if (dfbSurface != primarySurface) { + dfbSurface->Release(dfbSurface); + } dfbSurface = 0; } } else if (rect != geometry()) { + const QRect oldRect = geometry(); DFBResult result = DFB_OK; - // If we're in a resize, the surface shouldn't be locked Q_ASSERT((lockedImage == 0) || (rect.size() == geometry().size())); - - if (onscreen) { - IDirectFBSurface *primarySurface = screen->dfbSurface(); - Q_ASSERT(primarySurface); + switch (mode) { + case Primary: if (dfbSurface && dfbSurface != primarySurface) dfbSurface->Release(dfbSurface); - if (rect == screen->region().boundingRect()) { dfbSurface = primarySurface; } else { @@ -161,58 +203,32 @@ void QDirectFBWindowSurface::setGeometry(const QRect &rect, const QRegion &mask) rect.width(), rect.height() }; result = primarySurface->GetSubSurface(primarySurface, &r, &dfbSurface); } - } else { - const bool isResize = rect.size() != geometry().size(); -#ifdef QT_NO_DIRECTFB_WM - if (isResize) { + break; + case Window: +#ifndef QT_NO_DIRECTFB_WM + if (!dfbWindow) + createWindow(); + ::setGeometry(dfbWindow, oldRect, rect); + // ### do I need to release and get the surface again here? +#endif + break; + case Offscreen: { + if (!dfbSurface || oldRect.size() != rect.size()) { if (dfbSurface) dfbSurface->Release(dfbSurface); - - IDirectFB *dfb = screen->dfb(); - if (!dfb) { - qFatal("QDirectFBWindowSurface::setGeometry(): " - "Unable to get DirectFB handle!"); - } - dfbSurface = screen->createDFBSurface(rect.size(), screen->pixelFormat(), QDirectFBScreen::DontTrackSurface); - } else { - Q_ASSERT(dfbSurface); - } -#else - const QRect oldRect = geometry(); - const bool isMove = oldRect.isEmpty() || - rect.topLeft() != oldRect.topLeft(); - - if (!dfbWindow) - createWindow(); - -#if (Q_DIRECTFB_VERSION >= 0x010000) - if (isResize && isMove) { - result = dfbWindow->SetBounds(dfbWindow, rect.x(), rect.y(), - rect.width(), rect.height()); - } else if (isResize) { - result = dfbWindow->Resize(dfbWindow, - rect.width(), rect.height()); - } else if (isMove) { - result = dfbWindow->MoveTo(dfbWindow, rect.x(), rect.y()); - } -#else - if (isResize) { - result = dfbWindow->Resize(dfbWindow, - rect.width(), rect.height()); - } - if (isMove) { - result = dfbWindow->MoveTo(dfbWindow, rect.x(), rect.y()); } -#endif -#endif + const QRegion region = QRegion(oldRect.isEmpty() ? screen->region() : QRegion(oldRect)).subtracted(rect); + screen->erase(region); + screen->flipSurface(primarySurface, flipFlags, region, QPoint()); + break; } } if (result != DFB_OK) DirectFBErrorFatal("QDirectFBWindowSurface::setGeometry()", result); } - QWSWindowSurface::setGeometry(rect, mask); + QWSWindowSurface::setGeometry(rect); } QByteArray QDirectFBWindowSurface::permanentState() const @@ -254,7 +270,6 @@ static inline void scrollSurface(IDirectFBSurface *surface, const QRect &r, int surface->Blit(surface, surface, &rect, r.x() + dx, r.y() + dy); } - bool QDirectFBWindowSurface::scroll(const QRegion ®ion, int dx, int dy) { if (!dfbSurface || !(flipFlags & DSFLIP_BLIT) || region.isEmpty()) @@ -272,35 +287,13 @@ bool QDirectFBWindowSurface::scroll(const QRegion ®ion, int dx, int dy) return true; } -bool QDirectFBWindowSurface::move(const QPoint &offset) -{ - QWSWindowSurface::move(offset); - -#ifdef QT_NO_DIRECTFB_WM - return true; // buffered -#else - if (!dfbWindow) - return false; - - DFBResult status = dfbWindow->Move(dfbWindow, offset.x(), offset.y()); - return (status == DFB_OK); -#endif -} - -QRegion QDirectFBWindowSurface::move(const QPoint &offset, const QRegion &newClip) +bool QDirectFBWindowSurface::move(const QPoint &moveBy) { -#ifdef QT_NO_DIRECTFB_WM - return QWSWindowSurface::move(offset, newClip); -#else - Q_UNUSED(offset); - Q_UNUSED(newClip); - - // DirectFB handles the entire move, so there's no need to blit. - return QRegion(); -#endif + setGeometry(geometry().translated(moveBy)); + return true; } -QPaintEngine* QDirectFBWindowSurface::paintEngine() const +QPaintEngine *QDirectFBWindowSurface::paintEngine() const { if (!engine) { QDirectFBWindowSurface *that = const_cast<QDirectFBWindowSurface*>(this); @@ -333,57 +326,93 @@ inline bool isWidgetOpaque(const QWidget *w) return false; } -void QDirectFBWindowSurface::flush(QWidget *widget, const QRegion ®ion, + +void QDirectFBWindowSurface::flush(QWidget *, const QRegion ®ion, const QPoint &offset) { - Q_UNUSED(widget); -#ifdef QT_NO_DIRECTFB_WM - Q_UNUSED(region); - Q_UNUSED(offset); -#endif - - QWidget *win = window(); - // hw: make sure opacity information is updated before compositing - const bool opaque = isWidgetOpaque(win); - if (opaque != isOpaque()) { - SurfaceFlags flags = Buffered; - if (opaque) - flags |= Opaque; - setSurfaceFlags(flags); - } + if (QWidget *win = window()) { + + const bool opaque = isWidgetOpaque(win); + if (opaque != isOpaque()) { + SurfaceFlags flags = surfaceFlags(); + if (opaque) { + flags |= Opaque; + } else { + flags &= ~Opaque; + } + setSurfaceFlags(flags); + } #ifndef QT_NO_DIRECTFB_WM - const quint8 winOpacity = quint8(win->windowOpacity() * 255); - quint8 opacity; + const quint8 winOpacity = quint8(win->windowOpacity() * 255); + quint8 opacity; - if (dfbWindow) { - dfbWindow->GetOpacity(dfbWindow, &opacity); - if (winOpacity != opacity) - dfbWindow->SetOpacity(dfbWindow, winOpacity); - } + if (dfbWindow) { + dfbWindow->GetOpacity(dfbWindow, &opacity); + if (winOpacity != opacity) + dfbWindow->SetOpacity(dfbWindow, winOpacity); + } #endif - if (!(flipFlags & DSFLIP_BLIT)) { - dfbSurface->Flip(dfbSurface, 0, flipFlags); - } else { - if (!boundingRectFlip && region.numRects() > 1) { + } + + const QRect windowGeometry = QDirectFBWindowSurface::geometry(); + IDirectFBSurface *primarySurface = screen->dfbSurface(); + if (mode == Offscreen) { + primarySurface->SetBlittingFlags(primarySurface, DSBLIT_NOFX); + const QRect windowRect(0, 0, windowGeometry.width(), windowGeometry.height()); + const int n = region.numRects(); + if (n == 1 || boundingRectFlip ) { + const QRect regionBoundingRect = region.boundingRect().translated(offset); + const QRect source = windowRect & regionBoundingRect; + const DFBRectangle rect = { + source.x(), source.y(), source.width(), source.height() + }; + primarySurface->Blit(primarySurface, dfbSurface, &rect, + windowGeometry.x() + source.x(), + windowGeometry.y() + source.y()); + } else { const QVector<QRect> rects = region.rects(); - const DFBSurfaceFlipFlags nonWaitFlags = flipFlags & ~DSFLIP_WAIT; - for (int i=0; i<rects.size(); ++i) { - const QRect &r = rects.at(i); - const DFBRegion dfbReg = { r.x() + offset.x(), r.y() + offset.y(), - r.x() + r.width() + offset.x(), - r.y() + r.height() + offset.y() }; - dfbSurface->Flip(dfbSurface, &dfbReg, i + 1 < rects.size() ? nonWaitFlags : flipFlags); + QVarLengthArray<DFBRectangle, 16> dfbRectangles(n); + QVarLengthArray<DFBPoint, 16> dfbPoints(n); + + for (int i=0; i<n; ++i) { + const QRect &r = rects.at(i).translated(offset); + const QRect source = windowRect & r; + DFBRectangle &rect = dfbRectangles[i]; + rect.x = source.x(); + rect.y = source.y(); + rect.w = source.width(); + rect.h = source.height(); + dfbPoints[i].x = (windowGeometry.x() + source.x()); + dfbPoints[i].y = (windowGeometry.y() + source.y()); } - } 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() }; - dfbSurface->Flip(dfbSurface, &dfbReg, flipFlags); + primarySurface->BatchBlit(primarySurface, dfbSurface, dfbRectangles.constData(), + dfbPoints.constData(), n); } } + + if (QScreenCursor *cursor = QScreenCursor::instance()) { + const QRect cursorRectangle = cursor->boundingRect(); + if (cursor->isVisible() && !cursor->isAccelerated() + && region.intersects(cursorRectangle.translated(-(offset + windowGeometry.topLeft())))) { + const QImage image = cursor->image(); + + IDirectFBSurface *surface = screen->createDFBSurface(image, QDirectFBScreen::DontTrackSurface); + primarySurface->SetBlittingFlags(primarySurface, DSBLIT_BLEND_ALPHACHANNEL); + primarySurface->Blit(primarySurface, surface, 0, cursorRectangle.x(), cursorRectangle.y()); + surface->Release(surface); +#if (Q_DIRECTFB_VERSION >= 0x010000) + primarySurface->ReleaseSource(primarySurface); +#endif + } + } + if (mode == Offscreen) { + screen->flipSurface(primarySurface, flipFlags, region, offset + windowGeometry.topLeft()); + } else { + screen->flipSurface(dfbSurface, flipFlags, region, offset); + } + #ifdef QT_DIRECTFB_TIMING enum { Secs = 3 }; ++frames; diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.h b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.h index 7885b73..c46d93b 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.h +++ b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.h @@ -67,7 +67,7 @@ public: bool isValid() const; - void setGeometry(const QRect &rect, const QRegion &mask); + void setGeometry(const QRect &rect); QString key() const { return QLatin1String("directfb"); } QByteArray permanentState() const; @@ -76,7 +76,6 @@ public: bool scroll(const QRegion &area, int dx, int dy); bool move(const QPoint &offset); - QRegion move(const QPoint &offset, const QRegion &newClip); QImage image() const { return QImage(); } QPaintDevice *paintDevice() { return this; } @@ -88,7 +87,6 @@ public: void endPaint(const QRegion &); QImage *buffer(const QWidget *widget); - private: #ifndef QT_NO_DIRECTFB_WM void createWindow(); @@ -96,7 +94,11 @@ private: #endif QDirectFBPaintEngine *engine; - bool onscreen; + enum Mode { + Primary, + Offscreen, + Window + } mode; QList<QImage*> bufferImages; DFBSurfaceFlipFlags flipFlags; |