From 533f71abae2ecf05a217e63e9695647eb9e9a3ca Mon Sep 17 00:00:00 2001 From: Anders Bakken Date: Wed, 30 Sep 2009 11:00:39 -0700 Subject: Fix a window opacity bug with DirectFB Initialize IDirectFBWindows with the correct capabilities/options when supporting top level transparency. Also, properly deal with runtime changes of top level transparency. Reviewed-by: Noam Rosenthal --- .../gfxdrivers/directfb/qdirectfbwindowsurface.cpp | 110 +++++++++++---------- .../gfxdrivers/directfb/qdirectfbwindowsurface.h | 2 + 2 files changed, 60 insertions(+), 52 deletions(-) diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp index 51afcc7..f33e820 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp @@ -81,18 +81,23 @@ QDirectFBWindowSurface::QDirectFBWindowSurface(DFBSurfaceFlipFlags flip, QDirect , flipFlags(flip) , boundingRectFlip(scr->directFBFlags() & QDirectFBScreen::BoundingRectFlip) { + SurfaceFlags flags = 0; + if (!widget || widget->window()->windowOpacity() == 0xff) + flags |= Opaque; #ifdef QT_NO_DIRECTFB_WM if (widget && widget->testAttribute(Qt::WA_PaintOnScreen)) { - setSurfaceFlags(Opaque | RegionReserved); + flags = RegionReserved; mode = Primary; } else { mode = Offscreen; - setSurfaceFlags(Opaque | Buffered); + flags = Buffered; } #else - setSurfaceFlags(Opaque | Buffered); + noSystemBackground = widget && widget->testAttribute(Qt::WA_NoSystemBackground); + if (noSystemBackground) + flags &= ~Opaque; #endif - + setSurfaceFlags(flags); #ifdef QT_DIRECTFB_TIMING frames = 0; timer.start(); @@ -135,6 +140,16 @@ void QDirectFBWindowSurface::createWindow(const QRect &rect) description.caps = DWCAPS_NODECORATION|DWCAPS_DOUBLEBUFFER; 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 + + if (noSystemBackground) { + description.caps |= DWCAPS_ALPHACHANNEL; +#if (Q_DIRECTFB_VERSION >= 0x010200) + description.options |= DWOP_ALPHACHANNEL; +#endif + } description.posx = rect.x(); description.posy = rect.y(); @@ -143,7 +158,7 @@ void QDirectFBWindowSurface::createWindow(const QRect &rect) description.surface_caps = DSCAPS_NONE; if (screen->directFBFlags() & QDirectFBScreen::VideoOnly) description.surface_caps |= DSCAPS_VIDEOONLY; - const QImage::Format format = screen->pixelFormat(); + const QImage::Format format = (noSystemBackground ? screen->alphaPixmapFormat() : screen->pixelFormat()); description.pixelformat = QDirectFBScreen::getSurfacePixelFormat(format); if (QDirectFBScreen::isPremultiplied(format)) description.surface_caps = DSCAPS_PREMULTIPLIED; @@ -153,9 +168,7 @@ void QDirectFBWindowSurface::createWindow(const QRect &rect) if (result != DFB_OK) DirectFBErrorFatal("QDirectFBWindowSurface::createWindow", result); - if (dfbSurface) - dfbSurface->Release(dfbSurface); - + Q_ASSERT(!dfbSurface); dfbWindow->GetSurface(dfbWindow, &dfbSurface); updateFormat(); } @@ -297,29 +310,20 @@ bool QDirectFBWindowSurface::move(const QPoint &moveBy) return true; } -// hw: XXX: copied from QWidgetPrivate::isOpaque() -inline bool isWidgetOpaque(const QWidget *w) +void QDirectFBWindowSurface::setOpaque(bool opaque) { - if (w->testAttribute(Qt::WA_OpaquePaintEvent) - || w->testAttribute(Qt::WA_PaintOnScreen)) - return true; - - const QPalette &pal = w->palette(); - - if (w->autoFillBackground()) { - const QBrush &autoFillBrush = pal.brush(w->backgroundRole()); - if (autoFillBrush.style() != Qt::NoBrush && autoFillBrush.isOpaque()) - return true; + SurfaceFlags flags = surfaceFlags(); + if (opaque != (flags & Opaque)) { + if (opaque) { + flags |= Opaque; + } else { + flags &= ~Opaque; + } + setSurfaceFlags(flags); } +} - if (!w->testAttribute(Qt::WA_NoSystemBackground)) { - const QBrush &windowBrush = w->palette().brush(QPalette::Window); - if (windowBrush.style() != Qt::NoBrush && windowBrush.isOpaque()) - return true; - } - return false; -} void QDirectFBWindowSurface::flush(QWidget *widget, const QRegion ®ion, const QPoint &offset) { @@ -331,37 +335,39 @@ void QDirectFBWindowSurface::flush(QWidget *widget, const QRegion ®ion, if (extra && extra->proxyWidget) return; - // hw: make sure opacity information is updated before compositing - const bool opaque = isWidgetOpaque(win); - if (opaque != isOpaque()) { - SurfaceFlags flags = surfaceFlags(); - if (opaque) { - flags |= Opaque; - } else { - flags &= ~Opaque; - } - setSurfaceFlags(flags); + 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, ¤tOpacity); + if (currentOpacity != windowOpacity) { + dfbWindow->SetOpacity(dfbWindow, windowOpacity); } -#ifndef QT_NO_DIRECTFB_WM - const quint8 winOpacity = quint8(win->windowOpacity() * 255); - quint8 opacity; - - if (dfbWindow) { - dfbWindow->GetOpacity(dfbWindow, &opacity); - if (winOpacity != opacity) - dfbWindow->SetOpacity(dfbWindow, winOpacity); + setOpaque(noSystemBackground || windowOpacity != 0xff); + if (wasNoSystemBackground != noSystemBackground) { + releaseSurface(); + dfbWindow->Release(dfbWindow); + dfbWindow = 0; + createWindow(windowGeometry); + win->update(); + return; } -#endif - - const QRect windowGeometry = QDirectFBWindowSurface::geometry(); -#ifdef QT_NO_DIRECTFB_WM + screen->flipSurface(dfbSurface, flipFlags, region, offset); + if (noSystemBackground) { + dfbSurface->Clear(dfbSurface, 0, 0, 0, 0); + } +#else + setOpaque(windowOpacity != 0xff); if (mode == Offscreen) { screen->exposeRegion(region.translated(offset + geometry().topLeft()), 0); - - } else -#endif + } else { screen->flipSurface(dfbSurface, flipFlags, region, offset); + } +#endif #ifdef QT_DIRECTFB_TIMING enum { Secs = 3 }; diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.h b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.h index 0dd3a3b..2f78179 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.h +++ b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.h @@ -97,6 +97,7 @@ public: IDirectFBWindow *directFBWindow() const; #endif private: + void setOpaque(bool opaque); void updateFormat(); void releaseSurface(); QDirectFBWindowSurface *sibling; @@ -112,6 +113,7 @@ private: #endif DFBSurfaceFlipFlags flipFlags; + bool noSystemBackground; bool boundingRectFlip; #ifdef QT_DIRECTFB_TIMING int frames; -- cgit v0.12