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 <gunnar.sletta@jollamobile.com>
This commit is contained in:
Laszlo Agocs 2014-08-07 12:19:32 +02:00
parent 9ba3145f79
commit 00f3f5c0a6
3 changed files with 34 additions and 6 deletions

View File

@ -228,6 +228,18 @@ QT_BEGIN_NAMESPACE
regarding stacking orders for example. QOpenGLWidget avoids this by not regarding stacking orders for example. QOpenGLWidget avoids this by not
creating a separate native window. 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 \section1 Threading
Performing offscreen rendering on worker threads, for example to generate Performing offscreen rendering on worker threads, for example to generate
@ -435,6 +447,7 @@ public:
void beginCompose() Q_DECL_OVERRIDE; void beginCompose() Q_DECL_OVERRIDE;
void endCompose() Q_DECL_OVERRIDE; void endCompose() Q_DECL_OVERRIDE;
void resizeViewportFramebuffer() Q_DECL_OVERRIDE; void resizeViewportFramebuffer() Q_DECL_OVERRIDE;
void resolveSamples() Q_DECL_OVERRIDE;
QOpenGLContext *context; QOpenGLContext *context;
QOpenGLFramebufferObject *fbo; QOpenGLFramebufferObject *fbo;
@ -491,9 +504,11 @@ void QOpenGLWidgetPrivate::recreateFbo()
context->makeCurrent(surface); context->makeCurrent(surface);
delete fbo; delete fbo;
fbo = 0;
delete resolvedFbo; delete resolvedFbo;
resolvedFbo = 0;
int samples = get(q->window())->shareContext()->format().samples(); int samples = context->format().samples();
QOpenGLExtensions *extfuncs = static_cast<QOpenGLExtensions *>(context->functions()); QOpenGLExtensions *extfuncs = static_cast<QOpenGLExtensions *>(context->functions());
if (!extfuncs->hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample)) if (!extfuncs->hasOpenGLExtension(QOpenGLExtensions::FramebufferMultisample))
samples = 0; samples = 0;
@ -570,6 +585,16 @@ void QOpenGLWidgetPrivate::initialize()
q->initializeGL(); 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() void QOpenGLWidgetPrivate::invokeUserPaint()
{ {
Q_Q(QOpenGLWidget); Q_Q(QOpenGLWidget);
@ -577,11 +602,6 @@ void QOpenGLWidgetPrivate::invokeUserPaint()
f->glViewport(0, 0, q->width() * q->devicePixelRatio(), q->height() * q->devicePixelRatio()); f->glViewport(0, 0, q->width() * q->devicePixelRatio(), q->height() * q->devicePixelRatio());
q->paintGL(); q->paintGL();
if (resolvedFbo) {
QRect rect(QPoint(0, 0), fbo->size());
QOpenGLFramebufferObject::blitFramebuffer(resolvedFbo, rect, fbo, rect);
}
} }
void QOpenGLWidgetPrivate::render() void QOpenGLWidgetPrivate::render()
@ -605,6 +625,7 @@ QImage QOpenGLWidgetPrivate::grabFramebuffer()
return QImage(); return QImage();
render(); render();
resolveSamples();
q->makeCurrent(); q->makeCurrent();
QImage res = qt_gl_read_framebuffer(q->size() * q->devicePixelRatio(), false, false); QImage res = qt_gl_read_framebuffer(q->size() * q->devicePixelRatio(), false, false);

View File

@ -5595,6 +5595,11 @@ void QWidgetPrivate::sendPaintEvent(const QRegion &toBePainted)
Q_Q(QWidget); Q_Q(QWidget);
QPaintEvent e(toBePainted); QPaintEvent e(toBePainted);
QCoreApplication::sendSpontaneousEvent(q, &e); QCoreApplication::sendSpontaneousEvent(q, &e);
#ifndef QT_NO_OPENGL
if (renderToTexture)
resolveSamples();
#endif // QT_NO_OPENGL
} }
void QWidgetPrivate::render(QPaintDevice *target, const QPoint &targetOffset, void QWidgetPrivate::render(QPaintDevice *target, const QPoint &targetOffset,

View File

@ -653,6 +653,8 @@ public:
// filtered away from the widget. This is fine for QGLWidget but bad for QOpenGLWidget // 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. // since the fbo must be resized. We need an alternative way to notify.
virtual void resizeViewportFramebuffer() { } virtual void resizeViewportFramebuffer() { }
// Called after each paint event.
virtual void resolveSamples() { }
#endif #endif
// Variables. // Variables.