summaryrefslogtreecommitdiffstats
path: root/src/widgets/kernel/qwidgetbackingstore.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/widgets/kernel/qwidgetbackingstore.cpp')
-rw-r--r--src/widgets/kernel/qwidgetbackingstore.cpp87
1 files changed, 77 insertions, 10 deletions
diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp
index d373400623..c8d5440999 100644
--- a/src/widgets/kernel/qwidgetbackingstore.cpp
+++ b/src/widgets/kernel/qwidgetbackingstore.cpp
@@ -57,6 +57,8 @@
#include <private/qpaintengine_raster_p.h>
#include <private/qgraphicseffect_p.h>
+#include <qpa/qplatformbackingstore.h>
+
#if defined(Q_OS_WIN) && !defined(QT_NO_PAINT_DEBUG)
# include <QtCore/qt_windows.h>
# include <qpa/qplatformnativeinterface.h>
@@ -72,10 +74,15 @@ extern QRegion qt_dirtyRegion(QWidget *);
* \a region is the region to be updated in \a widget coordinates.
*/
static inline void qt_flush(QWidget *widget, const QRegion &region, QBackingStore *backingStore,
- QWidget *tlw, const QPoint &tlwOffset)
+ QWidget *tlw, const QPoint &tlwOffset, QPlatformTextureList *widgetTextures = 0,
+ QOpenGLContext *context = 0)
{
+#ifdef QT_NO_OPENGL
+ Q_UNUSED(widgetTextures);
+ Q_UNUSED(context);
+#endif
Q_ASSERT(widget);
- Q_ASSERT(!region.isEmpty());
+ Q_ASSERT(!region.isEmpty() || (context && widgetTextures && widgetTextures->count()));
Q_ASSERT(backingStore);
Q_ASSERT(tlw);
@@ -104,10 +111,16 @@ static inline void qt_flush(QWidget *widget, const QRegion &region, QBackingStor
if (tlw->testAttribute(Qt::WA_DontShowOnScreen) || widget->testAttribute(Qt::WA_DontShowOnScreen))
return;
+ QPoint offset = tlwOffset;
if (widget != tlw)
- backingStore->flush(region, widget->windowHandle(), tlwOffset + widget->mapTo(tlw, QPoint()));
+ offset += widget->mapTo(tlw, QPoint());
+
+#ifndef QT_NO_OPENGL
+ if (widgetTextures)
+ backingStore->handle()->composeAndFlush(widget->windowHandle(), region, offset, widgetTextures, context);
else
- backingStore->flush(region, widget->windowHandle(), tlwOffset);
+#endif
+ backingStore->flush(region, widget->windowHandle(), offset);
}
#ifndef QT_NO_PAINT_DEBUG
@@ -430,7 +443,7 @@ QRegion QWidgetBackingStore::staticContents(QWidget *parent, const QRect &within
return region;
}
-static inline void sendUpdateRequest(QWidget *widget, bool updateImmediately)
+void QWidgetBackingStore::sendUpdateRequest(QWidget *widget, bool updateImmediately)
{
if (!widget)
return;
@@ -439,6 +452,7 @@ static inline void sendUpdateRequest(QWidget *widget, bool updateImmediately)
QEvent event(QEvent::UpdateRequest);
QApplication::sendEvent(widget, &event);
} else {
+ updateRequestSent = true;
QApplication::postEvent(widget, new QEvent(QEvent::UpdateRequest), Qt::LowEventPriority);
}
}
@@ -488,6 +502,7 @@ void QWidgetBackingStore::markDirty(const QRegion &rgn, QWidget *widget, bool up
return;
}
+ //### FIXME fullUpdatePending seems to be always false????
if (fullUpdatePending) {
if (updateImmediately)
sendUpdateRequest(tlw, updateImmediately);
@@ -495,6 +510,13 @@ void QWidgetBackingStore::markDirty(const QRegion &rgn, QWidget *widget, bool up
}
const QPoint offset = widget->mapTo(tlw, QPoint());
+
+ if (QWidgetPrivate::get(widget)->renderToTexture) {
+ if (!updateRequestSent || updateImmediately)
+ sendUpdateRequest(tlw, updateImmediately);
+ return;
+ }
+
const QRect widgetRect = widget->d_func()->effectiveRectFor(widget->rect());
if (qt_region_strictContains(dirty, widgetRect.translated(offset))) {
if (updateImmediately)
@@ -503,7 +525,7 @@ void QWidgetBackingStore::markDirty(const QRegion &rgn, QWidget *widget, bool up
}
if (invalidateBuffer) {
- const bool eventAlreadyPosted = !dirty.isEmpty();
+ const bool eventAlreadyPosted = !dirty.isEmpty() || updateRequestSent;
#ifndef QT_NO_GRAPHICSEFFECT
if (widget->d_func()->graphicsEffect)
dirty += widget->d_func()->effectiveRectFor(rgn.boundingRect()).translated(offset);
@@ -583,6 +605,13 @@ void QWidgetBackingStore::markDirty(const QRect &rect, QWidget *widget, bool upd
return;
}
+ if (QWidgetPrivate::get(widget)->renderToTexture) {
+ if (!updateRequestSent || updateImmediately)
+ sendUpdateRequest(tlw, updateImmediately);
+ return;
+ }
+
+
const QRect widgetRect = widget->d_func()->effectiveRectFor(rect);
const QRect translatedRect(widgetRect.translated(widget->mapTo(tlw, QPoint())));
if (qt_region_strictContains(dirty, translatedRect)) {
@@ -703,7 +732,11 @@ void QWidgetBackingStore::updateLists(QWidget *cur)
}
QWidgetBackingStore::QWidgetBackingStore(QWidget *topLevel)
- : tlw(topLevel), dirtyOnScreenWidgets(0), fullUpdatePending(0)
+ : tlw(topLevel),
+ dirtyOnScreenWidgets(0),
+ widgetTextures(0),
+ fullUpdatePending(0),
+ updateRequestSent(0)
{
store = tlw->backingStore();
Q_ASSERT(store);
@@ -902,7 +935,7 @@ void QWidgetBackingStore::sync(QWidget *exposedWidget, const QRegion &exposedReg
// Nothing to repaint.
if (!isDirty()) {
- qt_flush(exposedWidget, exposedRegion, store, tlw, tlwOffset);
+ qt_flush(exposedWidget, exposedRegion, store, tlw, tlwOffset, widgetTextures, tlw->d_func()->shareContext());
return;
}
@@ -914,11 +947,27 @@ void QWidgetBackingStore::sync(QWidget *exposedWidget, const QRegion &exposedReg
doSync();
}
+#ifndef QT_NO_OPENGL
+static void findTextureWidgetsRecursively(QWidget *tlw, QWidget *widget, QPlatformTextureList *widgetTextures)
+{
+ QWidgetPrivate *wd = QWidgetPrivate::get(widget);
+ if (wd->renderToTexture)
+ widgetTextures->appendTexture(wd->textureId(), QRect(widget->mapTo(tlw, QPoint()), widget->size()));
+
+ for (int i = 0; i < wd->children.size(); ++i) {
+ QWidget *w = qobject_cast<QWidget *>(wd->children.at(i));
+ if (w && !w->isWindow() && !w->isHidden() && QWidgetPrivate::get(w)->textureChildSeen)
+ findTextureWidgetsRecursively(tlw, w, widgetTextures);
+ }
+}
+#endif
+
/*!
Synchronizes the backing store, i.e. dirty areas are repainted and flushed.
*/
void QWidgetBackingStore::sync()
{
+ updateRequestSent = false;
QTLWExtra *tlwExtra = tlw->d_func()->maybeTopData();
if (discardSyncRequest(tlw, tlwExtra)) {
// If the top-level is minimized, it's not visible on the screen so we can delay the
@@ -1024,7 +1073,15 @@ void QWidgetBackingStore::doSync()
}
dirtyWidgets.clear();
+#ifndef QT_NO_OPENGL
+ delete widgetTextures;
+ widgetTextures = 0;
+ if (tlw->d_func()->textureChildSeen) {
+ widgetTextures = new QPlatformTextureList; // TODO: implement support for locking
+ findTextureWidgetsRecursively(tlw, tlw, widgetTextures);
+ }
fullUpdatePending = false;
+#endif
if (toClean.isEmpty()) {
// Nothing to repaint. However, we might have newly exposed areas on the
@@ -1038,6 +1095,7 @@ void QWidgetBackingStore::doSync()
if (tlw->d_func()->extra->proxyWidget) {
updateStaticContentsSize();
dirty = QRegion();
+ updateRequestSent = false;
const QVector<QRect> rects(toClean.rects());
for (int i = 0; i < rects.size(); ++i)
tlw->d_func()->extra->proxyWidget->update(rects.at(i));
@@ -1051,6 +1109,7 @@ void QWidgetBackingStore::doSync()
for (int i = 0; i < opaqueNonOverlappedWidgets.size(); ++i)
resetWidget(opaqueNonOverlappedWidgets[i]);
dirty = QRegion();
+ updateRequestSent = false;
return;
}
@@ -1059,6 +1118,7 @@ void QWidgetBackingStore::doSync()
updateStaticContentsSize();
const QRegion dirtyCopy(dirty);
dirty = QRegion();
+ updateRequestSent = false;
// Paint opaque non overlapped widgets.
for (int i = 0; i < opaqueNonOverlappedWidgets.size(); ++i) {
@@ -1099,12 +1159,19 @@ void QWidgetBackingStore::flush(QWidget *widget)
{
if (!dirtyOnScreen.isEmpty()) {
QWidget *target = widget ? widget : tlw;
- qt_flush(target, dirtyOnScreen, store, tlw, tlwOffset);
+ qt_flush(target, dirtyOnScreen, store, tlw, tlwOffset, widgetTextures, tlw->d_func()->shareContext());
dirtyOnScreen = QRegion();
}
- if (!dirtyOnScreenWidgets || dirtyOnScreenWidgets->isEmpty())
+ if (!dirtyOnScreenWidgets || dirtyOnScreenWidgets->isEmpty()) {
+#ifndef QT_NO_OPENGL
+ if (widgetTextures && widgetTextures->count()) {
+ QWidget *target = widget ? widget : tlw;
+ qt_flush(target, QRegion(), store, tlw, tlwOffset, widgetTextures, tlw->d_func()->shareContext());
+ }
+#endif
return;
+ }
for (int i = 0; i < dirtyOnScreenWidgets->size(); ++i) {
QWidget *w = dirtyOnScreenWidgets->at(i);