From 9548d05769e817915fe476094b3e3cda178563ab Mon Sep 17 00:00:00 2001 From: Kim Motoyoshi Kalland Date: Fri, 26 Nov 2010 15:53:57 +0100 Subject: Implemented multisampled shader effect items. --- src/effects/shadereffectitem.cpp | 49 ++++++++++++++++++++++++++++++++-------- src/effects/shadereffectitem.h | 2 ++ tests/effects.qml | 30 ++++++++++++++++++++---- 3 files changed, 67 insertions(+), 14 deletions(-) diff --git a/src/effects/shadereffectitem.cpp b/src/effects/shadereffectitem.cpp index 8c179d8..4670a14 100644 --- a/src/effects/shadereffectitem.cpp +++ b/src/effects/shadereffectitem.cpp @@ -183,6 +183,7 @@ ShaderEffectSource::ShaderEffectSource(QObject *parent) , m_size(0, 0) , m_static(false) , m_fbo(0) + , m_multisampledFbo(0) , m_renderer(0) , m_refs(0) , m_dirtyTexture(true) @@ -195,6 +196,7 @@ ShaderEffectSource::~ShaderEffectSource() if (m_refs && m_sourceItem) QxItemPrivate::get(m_sourceItem)->derefFromEffectItem(); delete m_fbo; + delete m_multisampledFbo; delete m_renderer; } @@ -402,17 +404,38 @@ void ShaderEffectSource::update() Q_ASSERT(m_renderer); const QGLContext *ctx = QGLContext::currentContext(); - if (m_renderer->openGLFeatures() == 0) + if (m_renderer->openGLFeatures() == 0) { m_renderer->initializeGLFunctions(ctx); + QList extensions = QByteArray((const char *)glGetString(GL_EXTENSIONS)).split(' '); + m_multisamplingSupported = extensions.contains("GL_EXT_framebuffer_multisample") + && extensions.contains("GL_EXT_framebuffer_blit"); + } if (!m_fbo) { - // TODO: Implement support for multisampling. - QGLFramebufferObjectFormat format; - format.setAttachment(QGLFramebufferObject::CombinedDepthStencil); - format.setMipmap(m_mipmap != None); - m_fbo = new QGLFramebufferObject(m_size, format); + if (ctx->format().sampleBuffers() && m_multisamplingSupported) { + // If mipmapping was just enabled, m_fbo might be 0 while m_multisampledFbo != 0. + if (!m_multisampledFbo) { + QGLFramebufferObjectFormat format; + format.setAttachment(QGLFramebufferObject::CombinedDepthStencil); + format.setSamples(ctx->format().samples()); + m_multisampledFbo = new QGLFramebufferObject(m_size, format); + } + { + QGLFramebufferObjectFormat format; + format.setAttachment(QGLFramebufferObject::NoAttachment); + format.setMipmap(m_mipmap != None); + m_fbo = new QGLFramebufferObject(m_size, format); + } + } else { + QGLFramebufferObjectFormat format; + format.setAttachment(QGLFramebufferObject::CombinedDepthStencil); + format.setMipmap(m_mipmap != None); + m_fbo = new QGLFramebufferObject(m_size, format); + } } + Q_ASSERT(m_size == m_fbo->size()); + Q_ASSERT(m_multisampledFbo == 0 || m_size == m_multisampledFbo->size()); QRectF r(0, 0, m_sourceItem->width(), m_sourceItem->height()); r.adjust(-m_margins.width(), -m_margins.height(), m_margins.width(), m_margins.height()); @@ -420,7 +443,13 @@ void ShaderEffectSource::update() m_renderer->setProjectMatrixToRect(r); m_renderer->setClearColor(Qt::transparent); - m_renderer->renderScene(BindableFbo(const_cast(QGLContext::currentContext()), m_fbo)); + if (m_multisampledFbo) { + m_renderer->renderScene(BindableFbo(const_cast(QGLContext::currentContext()), m_multisampledFbo)); + QRect r(0, 0, m_size.width(), m_size.height()); + QGLFramebufferObject::blitFramebuffer(m_fbo, r, m_multisampledFbo, r); + } else { + m_renderer->renderScene(BindableFbo(const_cast(QGLContext::currentContext()), m_fbo)); + } if (m_mipmap != None) { QGLFramebufferObject::bindDefault(); glBindTexture(GL_TEXTURE_2D, m_fbo->texture()); @@ -458,7 +487,8 @@ void ShaderEffectSource::updateSizeAndTexture() size.setHeight(1); if (m_fbo && m_fbo->size() != size) { delete m_fbo; - m_fbo = 0; + delete m_multisampledFbo; + m_fbo = m_multisampledFbo = 0; } if (m_size.width() != size.width()) { m_size.setWidth(size.width()); @@ -472,7 +502,8 @@ void ShaderEffectSource::updateSizeAndTexture() } else { if (m_fbo) { delete m_fbo; - m_fbo = 0; + delete m_multisampledFbo; + m_fbo = m_multisampledFbo = 0; } if (!m_sourceImage.isEmpty()) { m_texture = QGLTexture2DPtr(new QGLTexture2D); diff --git a/src/effects/shadereffectitem.h b/src/effects/shadereffectitem.h index 689ef64..6a5f836 100644 --- a/src/effects/shadereffectitem.h +++ b/src/effects/shadereffectitem.h @@ -164,10 +164,12 @@ private: QGLTexture2DPtr m_texture; QGLFramebufferObject *m_fbo; + QGLFramebufferObject *m_multisampledFbo; Renderer *m_renderer; int m_refs; uint m_dirtyTexture : 1; // Causes update no matter what. uint m_dirtySceneGraph : 1; // Causes update if not static. + uint m_multisamplingSupported : 1; }; class ShaderEffectNode : public GeometryNode diff --git a/tests/effects.qml b/tests/effects.qml index 3f7786c..a7d9ab2 100644 --- a/tests/effects.qml +++ b/tests/effects.qml @@ -159,7 +159,6 @@ Rectangle { color: "red" font.pixelSize: 12 text: effectSource2.static ? "Static" : "Dynamic" - horizontalAlignment: Text.AlignHCenter } } @@ -243,7 +242,6 @@ Rectangle { color: "red" font.pixelSize: 12 text: effectSource3.static ? "Static" : "Dynamic" - horizontalAlignment: Text.AlignHCenter } } @@ -379,7 +377,6 @@ Rectangle { color: "red" font.pixelSize: 12 text: effectSource5.static ? "Static" : "Dynamic" - horizontalAlignment: Text.AlignHCenter } } @@ -570,6 +567,25 @@ Rectangle { visible: !parent.active } } + + Text { + anchors.left: effect1.left + anchors.top: effect1.top + anchors.margins: 3 + color: "red" + font.pixelSize: 12 + text: effectSource2.mipmap ? "Mipmap on" : "Mipmap off" + opacity: 0 + + SequentialAnimation on opacity { + id: mipmapStateAnim + running: false + PropertyAction { value: 1 } + PauseAnimation { duration: 1000 } + NumberAnimation { to: 0; duration: 1000 } + } + } + ShaderEffectItem { id: effect2 @@ -800,6 +816,7 @@ Rectangle { onClicked: { parent.value = Math.min(1.25 * parent.value, parent.max) } } MouseArea { + id: mipmapButton anchors.left: parent.left anchors.top: parent.top height: parent.height / 2 @@ -823,10 +840,13 @@ Rectangle { width: parent.width height: 4 rotation: -45 - visible: !controls.mipmap + visible: controls.mipmap } } - onClicked: { parent.mipmap = !parent.mipmap } + onClicked: { + parent.mipmap = !parent.mipmap + mipmapStateAnim.restart() + } } } } -- cgit v1.2.3