summaryrefslogtreecommitdiffstats
path: root/src/plugins/gfxdrivers/directfb
diff options
context:
space:
mode:
authorAnders Bakken <anders.bakken@nokia.com>2009-09-03 03:55:07 (GMT)
committerAnders Bakken <anders.bakken@nokia.com>2009-09-04 00:54:38 (GMT)
commit470ced8337f1ccd448e92fbde48a8e3b1ce39143 (patch)
treef251e1759b2511a283123555bd181bf533538540 /src/plugins/gfxdrivers/directfb
parent9753f87080e1d0f850854bc63f10aca1f3652cce (diff)
downloadQt-470ced8337f1ccd448e92fbde48a8e3b1ce39143.zip
Qt-470ced8337f1ccd448e92fbde48a8e3b1ce39143.tar.gz
Qt-470ced8337f1ccd448e92fbde48a8e3b1ce39143.tar.bz2
Make exposeRegion work better in DFB_NO_WM mode
Previously we didn't properly compose windows so QT_NO_DIRECTFB_WM mode would generally only work for single windows (with no popups). This also simplifies the code a lot. Previously we would among other things paint the mouse cursor twice in this mode.
Diffstat (limited to 'src/plugins/gfxdrivers/directfb')
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp173
-rw-r--r--src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp68
2 files changed, 123 insertions, 118 deletions
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp
index 520bb1a..211e8a5 100644
--- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp
+++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp
@@ -1391,79 +1391,132 @@ QWSWindowSurface *QDirectFBScreen::createSurface(const QString &key) const
return QScreen::createSurface(key);
}
-// 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.
-void QDirectFBScreen::exposeRegion(QRegion r, int changing)
+#if defined QT_NO_DIRECTFB_WM
+struct PaintCommand {
+ PaintCommand() : dfbSurface(0), windowOpacity(255), blittingFlags(DSBLIT_NOFX) {}
+ IDirectFBSurface *dfbSurface;
+ QImage image;
+ QPoint windowPosition;
+ QRegion source;
+ quint8 windowOpacity;
+ DFBSurfaceBlittingFlags blittingFlags;
+};
+
+static inline void initParameters(DFBRectangle &source, const QRect &sourceGlobal, const QPoint &pos)
+{
+ source.x = sourceGlobal.x() - pos.x();
+ source.y = sourceGlobal.y() - pos.y();
+ source.w = sourceGlobal.width();
+ source.h = sourceGlobal.height();
+}
+#endif
+
+void QDirectFBScreen::exposeRegion(QRegion r, int)
{
+ Q_UNUSED(r);
#if defined QT_NO_DIRECTFB_WM
- const QList<QWSWindow*> windows = QWSServer::instance()->clientWindows();
- if (changing < 0 || changing >= windows.size()) {
- return;
- }
- QWSWindow *win = windows.at(changing);
- QWSWindowSurface *s = win->windowSurface();
r &= region();
if (r.isEmpty()) {
return;
}
+ r = r.boundingRect();
- const QRect brect = r.boundingRect();
+ IDirectFBSurface *primary = d_ptr->primarySurface;
+ const QList<QWSWindow*> windows = QWSServer::instance()->clientWindows();
+ QVarLengthArray<PaintCommand, 4> commands(windows.size());
+ QRegion region = r;
+ int idx = 0;
+ for (int i=0; i<windows.size(); ++i) {
+ QWSWindowSurface *surface = windows.at(i)->windowSurface();
+ if (!surface)
+ continue;
+
+ const QRect windowGeometry = surface->geometry();
+ const QRegion intersection = region & windowGeometry;
+ if (intersection.isEmpty()) {
+ continue;
+ }
- if (!s) {
- solidFill(d_ptr->backgroundColor, r);
- } else {
- const QRect windowGeometry = s->geometry();
- const QRegion outsideWindow = r.subtracted(windowGeometry);
- if (!outsideWindow.isEmpty()) {
- solidFill(d_ptr->backgroundColor, outsideWindow);
+ PaintCommand &cmd = commands[idx];
+
+ if (surface->key() == QLatin1String("directfb")) {
+ const QDirectFBWindowSurface *ws = static_cast<QDirectFBWindowSurface*>(surface);
+ cmd.dfbSurface = ws->directFBSurface();
+
+ if (!cmd.dfbSurface) {
+ continue;
+ }
+ } else {
+ cmd.image = surface->image();
+ if (cmd.image.isNull()) {
+ continue;
+ }
}
- 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();
- Q_ASSERT(surface);
- 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->primarySurface->Blit(d_ptr->primarySurface, 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->primarySurface->BatchBlit(d_ptr->primarySurface, surface, dfbRectangles.constData(),
- dfbPoints.constData(), n);
- }
+ ++idx;
+
+ cmd.windowPosition = windowGeometry.topLeft();
+ cmd.source = intersection;
+ if (windows.at(i)->isOpaque()) {
+ region -= intersection;
+ if (region.isEmpty())
+ break;
+ } else {
+ cmd.windowOpacity = windows.at(i)->opacity();
+ cmd.blittingFlags = cmd.windowOpacity == 255
+ ? DSBLIT_BLEND_ALPHACHANNEL
+ : (DSBLIT_BLEND_ALPHACHANNEL|DSBLIT_BLEND_COLORALPHA);
+ }
+ }
+ if (!region.isEmpty()) {
+ solidFill(d_ptr->backgroundColor, region);
+ }
+
+ while (idx > 0) {
+ const PaintCommand &cmd = commands[--idx];
+ Q_ASSERT(cmd.dfbSurface || !cmd.image.isNull());
+ IDirectFBSurface *surface;
+ if (cmd.dfbSurface) {
+ surface = cmd.dfbSurface;
+ } else {
+ Q_ASSERT(!cmd.image.isNull());
+ DFBResult result;
+ surface = createDFBSurface(cmd.image, cmd.image.format(), DontTrackSurface, &result);
+ Q_ASSERT((result != DFB_OK) == !surface);
+ if (result != DFB_OK) {
+ DirectFBError("QDirectFBScreen::exposeRegion: Can't create surface from image", result);
+ continue;
+ }
+ }
+
+ primary->SetBlittingFlags(primary, cmd.blittingFlags);
+ if (cmd.blittingFlags & DSBLIT_BLEND_COLORALPHA) {
+ primary->SetColor(primary, 0xff, 0xff, 0xff, cmd.windowOpacity);
+ }
+ const QRegion &region = cmd.source;
+ const int rectCount = region.numRects();
+ DFBRectangle source;
+ if (rectCount == 1) {
+ ::initParameters(source, region.boundingRect(), cmd.windowPosition);
+ primary->Blit(primary, surface, &source, cmd.windowPosition.x() + source.x, cmd.windowPosition.y() + source.y);
+ } else {
+ const QVector<QRect> rects = region.rects();
+ for (int i=0; i<rectCount; ++i) {
+ ::initParameters(source, rects.at(i), cmd.windowPosition);
+ primary->Blit(primary, surface, &source, cmd.windowPosition.x() + source.x, cmd.windowPosition.y() + source.y);
}
}
+ if (surface != cmd.dfbSurface) {
+ surface->Release(surface);
+ }
}
-#ifdef QT_NO_DIRECTFB_CURSOR
+ primary->SetColor(primary, 0xff, 0xff, 0xff, 0xff);
+
+#if defined QT_NO_DIRECTFB_CURSOR and !defined QT_NO_QWS_CURSOR
if (QScreenCursor *cursor = QScreenCursor::instance()) {
const QRect cursorRectangle = cursor->boundingRect();
- if (cursor->isVisible() && !cursor->isAccelerated() && cursorRectangle.intersects(brect)) {
+ if (cursor->isVisible() && !cursor->isAccelerated() && r.intersects(cursorRectangle)) {
const QImage image = cursor->image();
if (image.cacheKey() != d_ptr->cursorImageKey) {
if (d_ptr->cursorSurface) {
@@ -1479,10 +1532,8 @@ void QDirectFBScreen::exposeRegion(QRegion r, int changing)
}
}
#endif
- flipSurface(d_ptr->primarySurface, d_ptr->flipFlags, r, QPoint());
-#else
- Q_UNUSED(r);
- Q_UNUSED(changing);
+ flipSurface(primary, d_ptr->flipFlags, r, QPoint());
+ primary->SetBlittingFlags(primary, DSBLIT_NOFX);
#endif
}
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp
index 58f7098..61cfec51 100644
--- a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp
+++ b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp
@@ -238,9 +238,6 @@ void QDirectFBWindowSurface::setGeometry(const QRect &rect)
if (!dfbSurface) {
dfbSurface = screen->createDFBSurface(rect.size(), screen->pixelFormat(), QDirectFBScreen::DontTrackSurface);
}
- const QRegion region = QRegion(oldRect.isEmpty() ? screen->region() : QRegion(oldRect)).subtracted(rect);
- screen->erase(region);
- screen->flipSurface(primarySurface, flipFlags, region, QPoint());
}
if (result != DFB_OK)
DirectFBErrorFatal("QDirectFBWindowSurface::setGeometry()", result);
@@ -250,6 +247,10 @@ void QDirectFBWindowSurface::setGeometry(const QRect &rect)
updateFormat();
QWSWindowSurface::setGeometry(rect);
+#ifdef QT_NO_DIRECTFB_WM
+ if (oldRect.isEmpty())
+ screen->exposeRegion(screen->region(), 0);
+#endif
}
QByteArray QDirectFBWindowSurface::permanentState() const
@@ -350,63 +351,16 @@ void QDirectFBWindowSurface::flush(QWidget *, const QRegion &region,
const QRect windowGeometry = QDirectFBWindowSurface::geometry();
#ifdef QT_NO_DIRECTFB_WM
- IDirectFBSurface *primarySurface = screen->primarySurface();
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();
- 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());
- }
- primarySurface->BatchBlit(primarySurface, dfbSurface, dfbRectangles.constData(),
- dfbPoints.constData(), n);
- }
- }
-
-#ifdef QT_NO_DIRECTFB_CURSOR
- 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, image.format(), 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
- }
+ QRegion r = region;
+ r.translate(offset + windowGeometry.topLeft());
+ screen->exposeRegion(r, 0);
+ } else {
+ screen->flipSurface(dfbSurface, flipFlags, region, offset);
}
-#endif
- if (mode == Offscreen) {
- screen->flipSurface(primarySurface, flipFlags, region, offset + windowGeometry.topLeft());
- } else
-#endif
+#else
screen->flipSurface(dfbSurface, flipFlags, region, offset);
+#endif
#ifdef QT_DIRECTFB_TIMING
enum { Secs = 3 };