diff options
author | Michael Brasser <michael.brasser@nokia.com> | 2009-09-04 04:42:14 (GMT) |
---|---|---|
committer | Michael Brasser <michael.brasser@nokia.com> | 2009-09-04 04:42:14 (GMT) |
commit | b28719ab2549918398c35bfa8ea90d0ddbad6a52 (patch) | |
tree | 467e831981a5934929480c5285dda829f5d1c8f5 | |
parent | 0e8e79623faf7228119af75965f5726a01d1141d (diff) | |
parent | 470ced8337f1ccd448e92fbde48a8e3b1ce39143 (diff) | |
download | Qt-b28719ab2549918398c35bfa8ea90d0ddbad6a52.zip Qt-b28719ab2549918398c35bfa8ea90d0ddbad6a52.tar.gz Qt-b28719ab2549918398c35bfa8ea90d0ddbad6a52.tar.bz2 |
Merge branch '4.6' of git@scm.dev.nokia.troll.no:qt/qt into 4.6
-rw-r--r-- | src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp | 196 | ||||
-rw-r--r-- | src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp | 125 |
2 files changed, 170 insertions, 151 deletions
diff --git a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp index 5651506..211e8a5 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbscreen.cpp @@ -95,6 +95,9 @@ public: IDirectFBImageProvider *imageProvider; #endif QColor backgroundColor; + IDirectFBSurface *cursorSurface; + qint64 cursorImageKey; + QDirectFBScreen *q; }; @@ -117,6 +120,8 @@ QDirectFBScreenPrivate::QDirectFBScreenPrivate(QDirectFBScreen *qptr) #if defined QT_DIRECTFB_IMAGEPROVIDER && defined QT_DIRECTFB_IMAGEPROVIDER_KEEPALIVE , imageProvider(0) #endif + , cursorSurface(0) + , cursorImageKey(0) , q(qptr) { #ifndef QT_NO_QWS_SIGNALHANDLER @@ -1386,94 +1391,149 @@ 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 ®ion = 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(); - IDirectFBSurface *surface = createDFBSurface(image, image.format(), QDirectFBScreen::DontTrackSurface); - d_ptr->primarySurface->SetBlittingFlags(d_ptr->primarySurface, DSBLIT_BLEND_ALPHACHANNEL); - d_ptr->primarySurface->Blit(d_ptr->primarySurface, surface, 0, cursorRectangle.x(), cursorRectangle.y()); - surface->Release(surface); -#if (Q_DIRECTFB_VERSION >= 0x010000) - d_ptr->primarySurface->ReleaseSource(d_ptr->primarySurface); -#endif + if (image.cacheKey() != d_ptr->cursorImageKey) { + if (d_ptr->cursorSurface) { + releaseDFBSurface(d_ptr->cursorSurface); + } + d_ptr->cursorSurface = createDFBSurface(image, image.format(), QDirectFBScreen::TrackSurface); + d_ptr->cursorImageKey = image.cacheKey(); + } + + Q_ASSERT(d_ptr->cursorSurface); + primary->SetBlittingFlags(primary, DSBLIT_BLEND_ALPHACHANNEL); + primary->Blit(primary, d_ptr->cursorSurface, 0, cursorRectangle.x(), cursorRectangle.y()); } } #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 9e0691d..61cfec51 100644 --- a/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp +++ b/src/plugins/gfxdrivers/directfb/qdirectfbwindowsurface.cpp @@ -184,11 +184,23 @@ static DFBResult setWindowGeometry(IDirectFBWindow *dfbWindow, const QRect &old, void QDirectFBWindowSurface::setGeometry(const QRect &rect) { + const QRect oldRect = geometry(); + if (oldRect == rect) + return; + IDirectFBSurface *oldSurface = dfbSurface; -#ifdef QT_NO_DIRECTFB_WM - IDirectFBSurface *primarySurface = screen->primarySurface(); - Q_ASSERT(primarySurface); + const bool sizeChanged = oldRect.size() != rect.size(); + if (sizeChanged) { + delete engine; + engine = 0; + unlockSurface(); +#ifdef QT_DIRECTFB_SUBSURFACE + releaseSubSurface(); #endif + releaseSurface(); + Q_ASSERT(!dfbSurface); + } + if (rect.isNull()) { #ifndef QT_NO_DIRECTFB_WM if (dfbWindow) { @@ -196,27 +208,25 @@ void QDirectFBWindowSurface::setGeometry(const QRect &rect) dfbWindow = 0; } #endif - if (dfbSurface) { -#ifdef QT_NO_DIRECTFB_WM - if (dfbSurface != primarySurface) + Q_ASSERT(!dfbSurface); +#ifdef QT_DIRECTFB_SUBSURFACE + Q_ASSERT(!subSurface); #endif - 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 + } else { #ifdef QT_DIRECTFB_WM if (!dfbWindow) { createWindow(rect); } else { setWindowGeometry(dfbWindow, oldRect, rect); + Q_ASSERT(!sizeChanged || !dfbSurface); + if (sizeChanged) + dfbWindow->GetSurface(dfbWindow, &dfbSurface); } #else + IDirectFBSurface *primarySurface = screen->primarySurface(); + DFBResult result = DFB_OK; if (mode == Primary) { - if (dfbSurface && dfbSurface != primarySurface) - dfbSurface->Release(dfbSurface); + Q_ASSERT(primarySurface); if (rect == screen->region().boundingRect()) { dfbSurface = primarySurface; } else { @@ -224,28 +234,23 @@ void QDirectFBWindowSurface::setGeometry(const QRect &rect) rect.width(), rect.height() }; result = primarySurface->GetSubSurface(primarySurface, &r, &dfbSurface); } - } else { - if (!dfbSurface || oldRect.size() != rect.size()) { - if (dfbSurface) - dfbSurface->Release(dfbSurface); + } else { // mode == Offscreen + 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()); - } -#endif - if (size() != geometry().size()) { - delete engine; - engine = 0; } - if (result != DFB_OK) DirectFBErrorFatal("QDirectFBWindowSurface::setGeometry()", result); +#endif } if (oldSurface != dfbSurface) updateFormat(); + QWSWindowSurface::setGeometry(rect); +#ifdef QT_NO_DIRECTFB_WM + if (oldRect.isEmpty()) + screen->exposeRegion(screen->region(), 0); +#endif } QByteArray QDirectFBWindowSurface::permanentState() const @@ -346,63 +351,16 @@ void QDirectFBWindowSurface::flush(QWidget *, const QRegion ®ion, 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 }; @@ -417,8 +375,9 @@ void QDirectFBWindowSurface::flush(QWidget *, const QRegion ®ion, void QDirectFBWindowSurface::beginPaint(const QRegion &) { - if (!engine) + if (!engine) { engine = new QDirectFBPaintEngine(this); + } } void QDirectFBWindowSurface::endPaint(const QRegion &) |