src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp
changeset 19 fcece45ef507
parent 18 2f34d5167611
--- a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp	Fri Apr 16 15:50:13 2010 +0300
+++ b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp	Mon May 03 13:17:34 2010 +0300
@@ -61,6 +61,7 @@
 #endif
     , flipFlags(flip)
     , boundingRectFlip(scr->directFBFlags() & QDirectFBScreen::BoundingRectFlip)
+    , flushPending(false)
 {
 #ifdef QT_NO_DIRECTFB_WM
     mode = Offscreen;
@@ -80,6 +81,7 @@
 #endif
     , flipFlags(flip)
     , boundingRectFlip(scr->directFBFlags() & QDirectFBScreen::BoundingRectFlip)
+    , flushPending(false)
 {
     SurfaceFlags flags = 0;
     if (!widget || widget->window()->windowOpacity() == 0xff)
@@ -92,10 +94,6 @@
         mode = Offscreen;
         flags = Buffered;
     }
-#else
-    noSystemBackground = widget && widget->testAttribute(Qt::WA_NoSystemBackground);
-    if (noSystemBackground)
-        flags &= ~Opaque;
 #endif
     setSurfaceFlags(flags);
 #ifdef QT_DIRECTFB_TIMING
@@ -134,33 +132,35 @@
     if (!layer)
         qFatal("QDirectFBWindowSurface: Unable to get primary display layer!");
 
+    updateIsOpaque();
+
     DFBWindowDescription description;
     memset(&description, 0, sizeof(DFBWindowDescription));
 
+    description.flags = DWDESC_CAPS|DWDESC_HEIGHT|DWDESC_WIDTH|DWDESC_POSX|DWDESC_POSY|DWDESC_SURFACE_CAPS|DWDESC_PIXELFORMAT;
     description.caps = DWCAPS_NODECORATION;
-    description.flags = DWDESC_CAPS|DWDESC_SURFACE_CAPS|DWDESC_PIXELFORMAT|DWDESC_HEIGHT|DWDESC_WIDTH|DWDESC_POSX|DWDESC_POSY;
-#if (Q_DIRECTFB_VERSION >= 0x010200)
-    description.flags |= DWDESC_OPTIONS;
-#endif
+    description.surface_caps = DSCAPS_NONE;
+    imageFormat = screen->pixelFormat();
 
-    if (noSystemBackground) {
+    if (!(surfaceFlags() & Opaque)) {
+        imageFormat = screen->alphaPixmapFormat();
         description.caps |= DWCAPS_ALPHACHANNEL;
 #if (Q_DIRECTFB_VERSION >= 0x010200)
+        description.flags |= DWDESC_OPTIONS;
         description.options |= DWOP_ALPHACHANNEL;
 #endif
     }
-
+    description.pixelformat = QDirectFBScreen::getSurfacePixelFormat(imageFormat);
     description.posx = rect.x();
     description.posy = rect.y();
     description.width = rect.width();
     description.height = rect.height();
-    description.surface_caps = DSCAPS_NONE;
+
+    if (QDirectFBScreen::isPremultiplied(imageFormat))
+        description.surface_caps = DSCAPS_PREMULTIPLIED;
+
     if (screen->directFBFlags() & QDirectFBScreen::VideoOnly)
         description.surface_caps |= DSCAPS_VIDEOONLY;
-    const QImage::Format format = (noSystemBackground ? screen->alphaPixmapFormat() : screen->pixelFormat());
-    description.pixelformat = QDirectFBScreen::getSurfacePixelFormat(format);
-    if (QDirectFBScreen::isPremultiplied(format))
-        description.surface_caps = DSCAPS_PREMULTIPLIED;
 
     DFBResult result = layer->CreateWindow(layer, &description, &dfbWindow);
 
@@ -182,7 +182,6 @@
 
     Q_ASSERT(!dfbSurface);
     dfbWindow->GetSurface(dfbWindow, &dfbSurface);
-    updateFormat();
 }
 
 static DFBResult setWindowGeometry(IDirectFBWindow *dfbWindow, const QRect &old, const QRect &rect)
@@ -267,15 +266,17 @@
             }
         } else { // mode == Offscreen
             if (!dfbSurface) {
-                dfbSurface = screen->createDFBSurface(rect.size(), screen->pixelFormat(), QDirectFBScreen::DontTrackSurface);
+                dfbSurface = screen->createDFBSurface(rect.size(), surfaceFlags() & Opaque ? screen->pixelFormat() : screen->alphaPixmapFormat(),
+                                                      QDirectFBScreen::DontTrackSurface);
             }
         }
         if (result != DFB_OK)
             DirectFBErrorFatal("QDirectFBWindowSurface::setGeometry()", result);
 #endif
     }
-    if (oldSurface != dfbSurface)
-        updateFormat();
+    if (oldSurface != dfbSurface) {
+        imageFormat = dfbSurface ? QDirectFBScreen::getImageFormat(dfbSurface) : QImage::Format_Invalid;
+    }
 
     if (oldRect.size() != rect.size()) {
         QWSWindowSurface::setGeometry(rect);
@@ -296,32 +297,23 @@
     if (state.size() == sizeof(this)) {
         sibling = *reinterpret_cast<QDirectFBWindowSurface *const*>(state.constData());
         Q_ASSERT(sibling);
-        sibling->setSurfaceFlags(surfaceFlags());
+        setSurfaceFlags(sibling->surfaceFlags());
     }
 }
 
-static inline void scrollSurface(IDirectFBSurface *surface, const QRect &r, int dx, int dy)
-{
-    const DFBRectangle rect = { r.x(), r.y(), r.width(), r.height() };
-    surface->Blit(surface, surface, &rect, r.x() + dx, r.y() + dy);
-    const DFBRegion region = { rect.x + dx, rect.y + dy, r.right() + dx, r.bottom() + dy };
-    surface->Flip(surface, &region, DSFLIP_BLIT);
-}
-
 bool QDirectFBWindowSurface::scroll(const QRegion &region, int dx, int dy)
 {
-    if (!dfbSurface || !(flipFlags & DSFLIP_BLIT) || region.isEmpty())
+    if (!dfbSurface || !(flipFlags & DSFLIP_BLIT) || region.rectCount() != 1)
         return false;
-    dfbSurface->SetBlittingFlags(dfbSurface, DSBLIT_NOFX);
-    if (region.rectCount() == 1) {
-        scrollSurface(dfbSurface, region.boundingRect(), dx, dy);
+    if (flushPending) {
+        dfbSurface->Flip(dfbSurface, 0, DSFLIP_BLIT);
     } else {
-        const QVector<QRect> rects = region.rects();
-        const int n = rects.size();
-        for (int i=0; i<n; ++i) {
-            scrollSurface(dfbSurface, rects.at(i), dx, dy);
-        }
+        flushPending = true;
     }
+    dfbSurface->SetBlittingFlags(dfbSurface, DSBLIT_NOFX);
+    const QRect r = region.boundingRect();
+    const DFBRectangle rect = { r.x(), r.y(), r.width(), r.height() };
+    dfbSurface->Blit(dfbSurface, dfbSurface, &rect, r.x() + dx, r.y() + dy);
     return true;
 }
 
@@ -359,8 +351,6 @@
     const quint8 windowOpacity = quint8(win->windowOpacity() * 0xff);
     const QRect windowGeometry = geometry();
 #ifdef QT_DIRECTFB_WM
-    const bool wasNoSystemBackground = noSystemBackground;
-    noSystemBackground = win->testAttribute(Qt::WA_NoSystemBackground);
     quint8 currentOpacity;
     Q_ASSERT(dfbWindow);
     dfbWindow->GetOpacity(dfbWindow, &currentOpacity);
@@ -368,18 +358,9 @@
         dfbWindow->SetOpacity(dfbWindow, windowOpacity);
     }
 
-    setOpaque(noSystemBackground || windowOpacity != 0xff);
-    if (wasNoSystemBackground != noSystemBackground) {
-        releaseSurface();
-        dfbWindow->Release(dfbWindow);
-        dfbWindow = 0;
-        createWindow(windowGeometry);
-        win->update();
-        return;
-    }
     screen->flipSurface(dfbSurface, flipFlags, region, offset);
 #else
-    setOpaque(windowOpacity != 0xff);
+    setOpaque(windowOpacity == 0xff);
     if (mode == Offscreen) {
         screen->exposeRegion(region.translated(offset + geometry().topLeft()), 0);
     } else {
@@ -396,6 +377,7 @@
         timer.restart();
     }
 #endif
+    flushPending = false;
 }
 
 void QDirectFBWindowSurface::beginPaint(const QRegion &)
@@ -403,6 +385,7 @@
     if (!engine) {
         engine = new QDirectFBPaintEngine(this);
     }
+    flushPending = true;
 }
 
 void QDirectFBWindowSurface::endPaint(const QRegion &)
@@ -442,11 +425,6 @@
     return dfbSurface;
 }
 
-void QDirectFBWindowSurface::updateFormat()
-{
-    imageFormat = dfbSurface ? QDirectFBScreen::getImageFormat(dfbSurface) : QImage::Format_Invalid;
-}
-
 void QDirectFBWindowSurface::releaseSurface()
 {
     if (dfbSurface) {
@@ -465,9 +443,37 @@
     }
 }
 
+void QDirectFBWindowSurface::updateIsOpaque()
+{
+    const QWidget *win = window();
+    Q_ASSERT(win);
+    if (win->testAttribute(Qt::WA_OpaquePaintEvent) || win->testAttribute(Qt::WA_PaintOnScreen)) {
+        setOpaque(true);
+        return;
+    }
+
+    if (qFuzzyCompare(static_cast<float>(win->windowOpacity()), 1.0f)) {
+        const QPalette &pal = win->palette();
+
+        if (win->autoFillBackground()) {
+            const QBrush &autoFillBrush = pal.brush(win->backgroundRole());
+            if (autoFillBrush.style() != Qt::NoBrush && autoFillBrush.isOpaque()) {
+                setOpaque(true);
+                return;
+            }
+        }
+
+        if (win->isWindow() && !win->testAttribute(Qt::WA_NoSystemBackground)) {
+            const QBrush &windowBrush = win->palette().brush(QPalette::Window);
+            if (windowBrush.style() != Qt::NoBrush && windowBrush.isOpaque()) {
+                setOpaque(true);
+                return;
+            }
+        }
+    }
+    setOpaque(false);
+}
 
 QT_END_NAMESPACE
 
 #endif // QT_NO_QWS_DIRECTFB
-
-