From 00f3f5c0a65e053c4075b92487fc77cfc33f2d5d Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Thu, 7 Aug 2014 12:19:32 +0200 Subject: Fix msaa in QOpenGLWidget Take the correct number of samples from the widget's context, not the tlw's context. The original implementation did the blit only after paintGL(). This is not sufficient for applications that override paintEvent() and do QPainter calls in there (e.g. the 2dpainting example). Therefore the approach is changed to perform the resolving of the samples in a function that is invoked by QWidgetPrivate every time a paint event is sent. Change-Id: Iae0b2c30f6070ec75201339a848854e4582a9c0c Reviewed-by: Gunnar Sletta --- src/widgets/kernel/qopenglwidget.cpp | 33 +++++++++++++++++++++++++++------ src/widgets/kernel/qwidget.cpp | 5 +++++ src/widgets/kernel/qwidget_p.h | 2 ++ 3 files changed, 34 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/widgets/kernel/qopenglwidget.cpp b/src/widgets/kernel/qopenglwidget.cpp index 1d86d2e8d9..68e3082c14 100644 --- a/src/widgets/kernel/qopenglwidget.cpp +++ b/src/widgets/kernel/qopenglwidget.cpp @@ -228,6 +228,18 @@ QT_BEGIN_NAMESPACE regarding stacking orders for example. QOpenGLWidget avoids this by not creating a separate native window. + \section1 Multisampling + + To enable multisampling, set the number of requested samples on the + QSurfaceFormat that is passed to setFormat(). On systems that do not support + it the request may get ignored. + + Multisampling support requires support for multisampled renderbuffers and + framebuffer blits. On OpenGL ES 2.0 implementations it is likely that these + will not be present. This means that multisampling will not be available. With + modern OpenGL versions and OpenGL ES 3.0 and up this is usually not a problem + anymore. + \section1 Threading Performing offscreen rendering on worker threads, for example to generate @@ -435,6 +447,7 @@ public: void beginCompose() Q_DECL_OVERRIDE; void endCompose() Q_DECL_OVERRIDE; void resizeViewportFramebuffer() Q_DECL_OVERRIDE; + void resolveSamples() Q_DECL_OVERRIDE; QOpenGLContext *context; QOpenGLFramebufferObject *fbo; @@ -491,9 +504,11 @@ void QOpenGLWidgetPrivate::recreateFbo() context->makeCurrent(surface); delete fbo; + fbo = 0; delete resolvedFbo; + resolvedFbo = 0; - int samples = get(q->window())->shareContext()->format().samples(); + int samples = context->format().samples(); QOpenGLExtensions *extfuncs = static_cast(context->functions()); if (!extfuncs->hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample)) samples = 0; @@ -570,6 +585,16 @@ void QOpenGLWidgetPrivate::initialize() q->initializeGL(); } +void QOpenGLWidgetPrivate::resolveSamples() +{ + Q_Q(QOpenGLWidget); + if (resolvedFbo) { + q->makeCurrent(); + QRect rect(QPoint(0, 0), fbo->size()); + QOpenGLFramebufferObject::blitFramebuffer(resolvedFbo, rect, fbo, rect); + } +} + void QOpenGLWidgetPrivate::invokeUserPaint() { Q_Q(QOpenGLWidget); @@ -577,11 +602,6 @@ void QOpenGLWidgetPrivate::invokeUserPaint() f->glViewport(0, 0, q->width() * q->devicePixelRatio(), q->height() * q->devicePixelRatio()); q->paintGL(); - - if (resolvedFbo) { - QRect rect(QPoint(0, 0), fbo->size()); - QOpenGLFramebufferObject::blitFramebuffer(resolvedFbo, rect, fbo, rect); - } } void QOpenGLWidgetPrivate::render() @@ -605,6 +625,7 @@ QImage QOpenGLWidgetPrivate::grabFramebuffer() return QImage(); render(); + resolveSamples(); q->makeCurrent(); QImage res = qt_gl_read_framebuffer(q->size() * q->devicePixelRatio(), false, false); diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 95964bfb9d..57169edb9d 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -5595,6 +5595,11 @@ void QWidgetPrivate::sendPaintEvent(const QRegion &toBePainted) Q_Q(QWidget); QPaintEvent e(toBePainted); QCoreApplication::sendSpontaneousEvent(q, &e); + +#ifndef QT_NO_OPENGL + if (renderToTexture) + resolveSamples(); +#endif // QT_NO_OPENGL } void QWidgetPrivate::render(QPaintDevice *target, const QPoint &targetOffset, diff --git a/src/widgets/kernel/qwidget_p.h b/src/widgets/kernel/qwidget_p.h index 011d456a39..1a34ee504c 100644 --- a/src/widgets/kernel/qwidget_p.h +++ b/src/widgets/kernel/qwidget_p.h @@ -653,6 +653,8 @@ public: // filtered away from the widget. This is fine for QGLWidget but bad for QOpenGLWidget // since the fbo must be resized. We need an alternative way to notify. virtual void resizeViewportFramebuffer() { } + // Called after each paint event. + virtual void resolveSamples() { } #endif // Variables. -- cgit v1.2.3