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:
parent
9ba3145f79
commit
00f3f5c0a6
@ -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);
|
||||||
|
|
||||||
|
@ -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,
|
||||||
|
@ -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.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user