summaryrefslogtreecommitdiffstats
path: root/src/widgets/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'src/widgets/kernel')
-rw-r--r--src/widgets/kernel/kernel.pri5
-rw-r--r--src/widgets/kernel/qopenglwidget.cpp183
-rw-r--r--src/widgets/kernel/qopenglwidget_p.h135
-rw-r--r--src/widgets/kernel/qwidget.cpp45
-rw-r--r--src/widgets/kernel/qwidget_p.h28
-rw-r--r--src/widgets/kernel/qwidget_qpa.cpp5
-rw-r--r--src/widgets/kernel/qwidgetbackingstore.cpp87
-rw-r--r--src/widgets/kernel/qwidgetbackingstore_p.h6
-rw-r--r--src/widgets/kernel/qwidgetwindow.cpp6
9 files changed, 486 insertions, 14 deletions
diff --git a/src/widgets/kernel/kernel.pri b/src/widgets/kernel/kernel.pri
index 444b9b687f..857fe4ac91 100644
--- a/src/widgets/kernel/kernel.pri
+++ b/src/widgets/kernel/kernel.pri
@@ -79,3 +79,8 @@ wince*: {
SOURCES += \
kernel/qwidgetsfunctions_wince.cpp
}
+
+contains(QT_CONFIG, opengl) {
+ HEADERS += kernel/qopenglwidget_p.h
+ SOURCES += kernel/qopenglwidget.cpp
+}
diff --git a/src/widgets/kernel/qopenglwidget.cpp b/src/widgets/kernel/qopenglwidget.cpp
new file mode 100644
index 0000000000..a5f81a9df8
--- /dev/null
+++ b/src/widgets/kernel/qopenglwidget.cpp
@@ -0,0 +1,183 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtWidgets module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qopenglwidget_p.h"
+#include <QOpenGLContext>
+#include <QtWidgets/private/qwidget_p.h>
+
+#include <QOpenGLFramebufferObject>
+#include <QWindow>
+#include <qpa/qplatformwindow.h>
+#include <QDebug>
+#include <QtGui/QGuiApplication>
+#include <QtGui/QScreen>
+
+QT_BEGIN_NAMESPACE
+
+class QOpenGLWidgetPrivate : public QWidgetPrivate
+{
+ Q_DECLARE_PUBLIC(QOpenGLWidget)
+public:
+ QOpenGLWidgetPrivate()
+ : fbo(0), uninitialized(true)
+ {
+ setRenderToTexture();
+ }
+ GLuint textureId() const { return fbo ? fbo->texture() : 0; }
+
+ const QSurface *surface() const { return q_func()->window()->windowHandle(); }
+ QSurface *surface() { return q_func()->window()->windowHandle(); }
+ void initialize();
+
+ QOpenGLContext context;
+ QOpenGLFramebufferObject *fbo;
+ bool uninitialized;
+
+ int w,h;
+};
+
+void QOpenGLWidgetPrivate::initialize()
+{
+ Q_Q(QOpenGLWidget);
+ if (!uninitialized)
+ return;
+ context.setShareContext(get(q->window())->shareContext());
+ context.setFormat(surface()->format());
+ context.create();
+ context.makeCurrent(surface());
+ q->initializeGL();
+ uninitialized = false;
+}
+
+QOpenGLWidget::QOpenGLWidget(QWidget *parent, Qt::WindowFlags f)
+ : QWidget(*(new QOpenGLWidgetPrivate), parent, f)
+{
+}
+
+QOpenGLWidget::~QOpenGLWidget()
+{
+}
+
+bool QOpenGLWidget::isValid() const
+{
+ Q_D(const QOpenGLWidget);
+ return d->context.isValid();
+}
+
+void QOpenGLWidget::makeCurrent()
+{
+ Q_D(QOpenGLWidget);
+ d->context.makeCurrent(d->surface());
+ d->fbo->bind();
+}
+
+void QOpenGLWidget::doneCurrent()
+{
+ Q_D(QOpenGLWidget);
+ d->context.doneCurrent();
+}
+
+QSurfaceFormat QOpenGLWidget::format() const
+{
+ Q_D(const QOpenGLWidget);
+ return d->surface()->format();
+}
+
+GLuint QOpenGLWidget::defaultFramebufferObject() const
+{
+ Q_D(const QOpenGLWidget);
+ return d->fbo ? d->fbo->handle() : 0;
+}
+
+void QOpenGLWidget::initializeGL()
+{
+
+}
+
+void QOpenGLWidget::resizeGL(int w, int h)
+{
+ Q_UNUSED(w);
+ Q_UNUSED(h);
+}
+
+void QOpenGLWidget::paintGL()
+{
+}
+
+void QOpenGLWidget::updateGL()
+{
+ makeCurrent();
+ paintGL();
+ glFlush();
+ doneCurrent();
+ update();
+}
+
+
+void QOpenGLWidget::resizeEvent(QResizeEvent *)
+{
+ Q_D(QOpenGLWidget);
+ d->w = width();
+ d->h = height();
+ d->initialize();
+
+ d->context.makeCurrent(d->surface());
+ delete d->fbo; // recreate when resized
+ d->fbo = new QOpenGLFramebufferObject(size());
+ d->fbo->bind();
+ glBindTexture(GL_TEXTURE_2D, d->fbo->texture());
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
+ glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
+
+ resizeGL(width(), height());
+ paintGL();
+ glFlush();
+}
+
+void QOpenGLWidget::paintEvent(QPaintEvent *)
+{
+ qWarning("QOpenGLWidget does not support paintEvent() yet.");
+ return;
+}
+
+QT_END_NAMESPACE
diff --git a/src/widgets/kernel/qopenglwidget_p.h b/src/widgets/kernel/qopenglwidget_p.h
new file mode 100644
index 0000000000..1c7f0bfeec
--- /dev/null
+++ b/src/widgets/kernel/qopenglwidget_p.h
@@ -0,0 +1,135 @@
+/****************************************************************************
+**
+** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/legal
+**
+** This file is part of the QtWidgets module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and Digia. For licensing terms and
+** conditions see http://qt.digia.com/licensing. For further information
+** use the contact form at http://qt.digia.com/contact-us.
+**
+** GNU Lesser General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU Lesser
+** General Public License version 2.1 as published by the Free Software
+** Foundation and appearing in the file LICENSE.LGPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU Lesser General Public License version 2.1 requirements
+** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Digia gives you certain additional
+** rights. These rights are described in the Digia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3.0 as published by the Free Software
+** Foundation and appearing in the file LICENSE.GPL included in the
+** packaging of this file. Please review the following information to
+** ensure the GNU General Public License version 3.0 requirements will be
+** met: http://www.gnu.org/copyleft/gpl.html.
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It may change from version to version
+// without notice, or even be removed.
+//
+// We mean it.
+//
+#ifndef QOPENGLWIDGET_H
+#define QOPENGLWIDGET_H
+
+#include <QWidget>
+#include <QSurfaceFormat>
+
+#include <QtGui/qopengl.h>
+
+QT_BEGIN_NAMESPACE
+
+class QOpenGLWidgetPrivate;
+
+class Q_WIDGETS_EXPORT QOpenGLWidget : public QWidget
+{
+ Q_OBJECT
+ Q_DECLARE_PRIVATE(QOpenGLWidget)
+
+public:
+ explicit QOpenGLWidget(QWidget* parent=0,
+ Qt::WindowFlags f=0);
+
+// This API is not finalized yet. The commented-out functions below are
+// QGLWidget functions that have not been implemented for QOpenGLWidget.
+// Some of them may not end up in the final version (which is planned for a
+// future release of Qt).
+
+// explicit QOpenGLWidget(const QSurfaceFormat& format, QWidget* parent=0,
+// Qt::WindowFlags f=0);
+ ~QOpenGLWidget();
+
+// void qglClearColor(const QColor& c) const;
+
+ bool isValid() const;
+// bool isSharing() const;
+
+ void makeCurrent();
+ void doneCurrent();
+
+// void swapBuffers();
+
+ QSurfaceFormat format() const;
+ GLuint defaultFramebufferObject() const;
+
+// QPixmap renderPixmap(int w = 0, int h = 0, bool useContext = false);
+ QImage grabFrameBuffer(bool withAlpha = false);
+
+// static QImage convertToGLFormat(const QImage& img);
+
+// QPaintEngine *paintEngine() const;
+
+// void drawTexture(const QRectF &target, GLuint textureId, GLenum textureTarget = GL_TEXTURE_2D);
+// void drawTexture(const QPointF &point, GLuint textureId, GLenum textureTarget = GL_TEXTURE_2D);
+
+public Q_SLOTS:
+ void updateGL();
+
+protected:
+// bool event(QEvent *);
+ virtual void initializeGL();
+ virtual void resizeGL(int w, int h);
+ virtual void paintGL();
+
+// void setAutoBufferSwap(bool on);
+// bool autoBufferSwap() const;
+
+ void paintEvent(QPaintEvent*);
+ void resizeEvent(QResizeEvent*);
+
+// virtual void glInit();
+// virtual void glDraw();
+
+// QOpenGLWidget(QOpenGLWidgetPrivate &dd,
+// const QGLFormat &format = QGLFormat(),
+// QWidget *parent = 0,
+// const QOpenGLWidget* shareWidget = 0,
+// Qt::WindowFlags f = 0);
+private:
+ Q_DISABLE_COPY(QOpenGLWidget)
+
+
+};
+
+QT_END_NAMESPACE
+
+#endif // QOPENGLWIDGET_H
diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp
index 034e2c9e97..46aa93fe48 100644
--- a/src/widgets/kernel/qwidget.cpp
+++ b/src/widgets/kernel/qwidget.cpp
@@ -78,6 +78,7 @@
#include "private/qstyle_p.h"
#include "qfileinfo.h"
#include <QtGui/qinputmethod.h>
+#include <QtGui/qopenglcontext.h>
#include <private/qgraphicseffect_p.h>
#include <qbackingstore.h>
@@ -270,6 +271,8 @@ QWidgetPrivate::QWidgetPrivate(int version)
, isMoved(0)
, usesDoubleBufferedGLContext(0)
, mustHaveWindowHandle(0)
+ , renderToTexture(0)
+ , textureChildSeen(0)
#ifndef QT_NO_IM
, inheritsInputMethodHints(0)
#endif
@@ -1558,6 +1561,7 @@ void QWidgetPrivate::createTLExtra()
x->inRepaint = false;
x->embedded = 0;
x->window = 0;
+ x->shareContext = 0;
x->screenIndex = 0;
#ifdef Q_WS_MAC
x->wasMaximized = false;
@@ -5133,9 +5137,17 @@ void QWidgetPrivate::drawWidget(QPaintDevice *pdev, const QRegion &rgn, const QP
<< "geometry ==" << QRect(q->mapTo(q->window(), QPoint(0, 0)), q->size());
#endif
- //actually send the paint event
- QPaintEvent e(toBePainted);
- QCoreApplication::sendSpontaneousEvent(q, &e);
+ if (renderToTexture) {
+ // This widget renders into a texture which is composed later. We just need to
+ // punch a hole in the backingstore, so the texture will be visible.
+ QPainter p(q);
+ p.setCompositionMode(QPainter::CompositionMode_Source);
+ p.fillRect(q->rect(), Qt::transparent);
+ } else {
+ //actually send the paint event
+ QPaintEvent e(toBePainted);
+ QCoreApplication::sendSpontaneousEvent(q, &e);
+ }
// Native widgets need to be marked dirty on screen so painting will be done in correct context
if (backingStore && !onScreen && !asRoot && (q->internalWinId() || !q->nativeParentWidget()->isWindow()))
@@ -9637,6 +9649,13 @@ void QWidget::setParent(QWidget *parent, Qt::WindowFlags f)
if (desktopWidget)
parent = 0;
+#ifndef QT_NO_OPENGL
+ if (d->textureChildSeen && parent) {
+ // set the textureChildSeen flag up the whole parent chain
+ QWidgetPrivate::get(parent)->setTextureChildSeen();
+ }
+#endif
+
if (QWidgetBackingStore *oldBs = oldtlw->d_func()->maybeBackingStore()) {
if (newParent)
oldBs->removeDirtyWidget(this);
@@ -11108,7 +11127,25 @@ void QWidgetPrivate::adjustQuitOnCloseAttribute()
}
}
-
+QOpenGLContext *QWidgetPrivate::shareContext() const
+{
+#ifdef QT_NO_OPENGL
+ return 0;
+#else
+ if (!extra || !extra->topextra || !extra->topextra->window) {
+ qWarning() << "Asking for share context for widget that does not have a window handle";
+ return 0;
+ }
+ QWidgetPrivate *that = const_cast<QWidgetPrivate *>(this);
+ if (!extra->topextra->shareContext) {
+ QOpenGLContext *ctx = new QOpenGLContext();
+ ctx->setFormat(extra->topextra->window->format());
+ ctx->create();
+ that->extra->topextra->shareContext = ctx;
+ }
+ return that->extra->topextra->shareContext;
+#endif // QT_NO_OPENGL
+}
Q_WIDGETS_EXPORT QWidgetData *qt_qwidget_data(QWidget *widget)
{
diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h
index 45606685cb..bdfc57f7c3 100644
--- a/src/widgets/kernel/qwidget_p.h
+++ b/src/widgets/kernel/qwidget_p.h
@@ -60,6 +60,7 @@
#include "QtCore/qset.h"
#include "QtGui/qregion.h"
#include "QtGui/qinputmethod.h"
+#include "QtGui/qopengl.h"
#include "QtWidgets/qsizepolicy.h"
#include "QtWidgets/qstyle.h"
#include "QtWidgets/qapplication.h"
@@ -80,6 +81,7 @@ class QPixmap;
class QWidgetBackingStore;
class QGraphicsProxyWidget;
class QWidgetItemV2;
+class QOpenGLContext;
class QStyle;
@@ -216,6 +218,7 @@ struct QTLWExtra {
bool wasMaximized;
#endif
QWidgetWindow *window;
+ QOpenGLContext *shareContext;
quint32 screenIndex; // index in qplatformscreenlist
};
@@ -324,6 +327,8 @@ public:
explicit QWidgetPrivate(int version = QObjectPrivateVersion);
~QWidgetPrivate();
+ static QWidgetPrivate *get(QWidget *w) { return w->d_func(); }
+
QWExtra *extraData() const;
QTLWExtra *topData() const;
QTLWExtra *maybeTopData() const;
@@ -618,6 +623,27 @@ public:
inline QRect mapFromWS(const QRect &r) const
{ QRect rr(r); rr.translate(data.wrect.topLeft()); return rr; }
+ QOpenGLContext *shareContext() const;
+
+#ifndef QT_NO_OPENGL
+ virtual GLuint textureId() const { return 0; }
+
+ void setRenderToTexture() { renderToTexture = true; textureChildSeen = true; }
+ void setTextureChildSeen()
+ {
+ Q_Q(QWidget);
+ if (textureChildSeen)
+ return;
+ textureChildSeen = 1;
+
+ if (!q->isWindow()) {
+ QWidget *parent = q->parentWidget();
+ if (parent)
+ get(parent)->setTextureChildSeen();
+ }
+ }
+#endif
+
// Variables.
// Regular pointers (keep them together to avoid gaps on 64 bit architectures).
QWExtra *extra;
@@ -698,6 +724,8 @@ public:
uint isMoved : 1;
uint usesDoubleBufferedGLContext : 1;
uint mustHaveWindowHandle : 1;
+ uint renderToTexture : 1;
+ uint textureChildSeen : 1;
#ifndef QT_NO_IM
uint inheritsInputMethodHints : 1;
#endif
diff --git a/src/widgets/kernel/qwidget_qpa.cpp b/src/widgets/kernel/qwidget_qpa.cpp
index 0a4bc990e6..c2260b6e7d 100644
--- a/src/widgets/kernel/qwidget_qpa.cpp
+++ b/src/widgets/kernel/qwidget_qpa.cpp
@@ -49,6 +49,7 @@
#include "QtWidgets/qdesktopwidget.h"
#include <qpa/qplatformwindow.h>
#include "QtGui/qsurfaceformat.h"
+#include <QtGui/qopenglcontext.h>
#include <qpa/qplatformopenglcontext.h>
#include <qpa/qplatformintegration.h>
#include "QtGui/private/qwindow_p.h"
@@ -953,6 +954,10 @@ void QWidgetPrivate::deleteTLSysExtra()
delete extra->topextra->backingStore;
extra->topextra->backingStore = 0;
+#ifndef QT_NO_OPENGL
+ delete extra->topextra->shareContext;
+ extra->topextra->shareContext = 0;
+#endif
}
}
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);
diff --git a/src/widgets/kernel/qwidgetbackingstore_p.h b/src/widgets/kernel/qwidgetbackingstore_p.h
index 3d12524c98..c6f6541e1f 100644
--- a/src/widgets/kernel/qwidgetbackingstore_p.h
+++ b/src/widgets/kernel/qwidgetbackingstore_p.h
@@ -60,6 +60,8 @@
QT_BEGIN_NAMESPACE
+class QPlatformTextureList;
+
struct BeginPaintInfo {
inline BeginPaintInfo() : wasFlushed(0), nothingToPaint(0), backingStoreRecreated(0) {}
uint wasFlushed : 1;
@@ -102,11 +104,15 @@ private:
QVector<QWidget *> dirtyWidgets;
QVector<QWidget *> *dirtyOnScreenWidgets;
QList<QWidget *> staticWidgets;
+ QPlatformTextureList *widgetTextures;
QBackingStore *store;
uint fullUpdatePending : 1;
+ uint updateRequestSent : 1;
QPoint tlwOffset;
+ void sendUpdateRequest(QWidget *widget, bool updateImmediately);
+
static bool flushPaint(QWidget *widget, const QRegion &rgn);
static void unflushPaint(QWidget *widget, const QRegion &rgn);
diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp
index 672c4156cd..0e40dd866f 100644
--- a/src/widgets/kernel/qwidgetwindow.cpp
+++ b/src/widgets/kernel/qwidgetwindow.cpp
@@ -92,6 +92,12 @@ QWidgetWindow::QWidgetWindow(QWidget *widget)
, m_widget(widget)
{
updateObjectName();
+ // Enable QOpenGLWidget/QQuickWidget children if the platform plugin supports it,
+ // and the application developer has not explicitly disabled it.
+ if (QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::RasterGLSurface)
+ && !QApplication::testAttribute(Qt::AA_ForceRasterWidgets)) {
+ setSurfaceType(QSurface::RasterGLSurface);
+ }
connect(m_widget, &QObject::objectNameChanged, this, &QWidgetWindow::updateObjectName);
}