summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/gui/painting/qpaintengine_raster.cpp32
-rw-r--r--src/gui/painting/qpaintengineex.cpp12
-rw-r--r--src/gui/painting/qpaintengineex_p.h2
-rw-r--r--src/gui/painting/qstroker.cpp5
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbmouse.cpp14
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbpaintengine.cpp6
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp296
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbscreen.h14
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp275
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.h10
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 &region)
-{
- 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 &reg)
-{
- 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 &region)
-{
- 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 &region)
{
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 &region)
+{
+ 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 &region, 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 &region);
void scroll(const QRegion &region, const QPoint &offset);
void solidFill(const QColor &color, const QRegion &region);
@@ -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 &region, const QPoint &offset);
void releaseDFBSurface(IDirectFBSurface *surface);
+ void erase(const QRegion &region);
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 &region);
-
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 &region, int dx, int dy)
{
if (!dfbSurface || !(flipFlags & DSFLIP_BLIT) || region.isEmpty())
@@ -272,35 +287,13 @@ bool QDirectFBWindowSurface::scroll(const QRegion &region, 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 &region,
+
+void QDirectFBWindowSurface::flush(QWidget *, const QRegion &region,
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;