From f87a860553c4cdb70fe33154bee6ce96fb407d85 Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Wed, 8 Dec 2010 15:14:52 +0100 Subject: Implemented 'smooth' property for QxPaintItem. When smooth is set to true, a multisample framebuffer object is used (if the extension is available). --- examples/paintitem/myfile.qml | 1 + src/graphicsitems/nodes/qxpainternode.cpp | 68 +++++++++++++++++++++++++++---- src/graphicsitems/nodes/qxpainternode.h | 7 ++++ src/graphicsitems/qxpaintitem.cpp | 1 + 4 files changed, 70 insertions(+), 7 deletions(-) diff --git a/examples/paintitem/myfile.qml b/examples/paintitem/myfile.qml index b1b1446..a8bfa45 100644 --- a/examples/paintitem/myfile.qml +++ b/examples/paintitem/myfile.qml @@ -12,5 +12,6 @@ Rectangle { MyPaintItem { anchors.fill: parent anchors.margins: 10 + smooth: true } } diff --git a/src/graphicsitems/nodes/qxpainternode.cpp b/src/graphicsitems/nodes/qxpainternode.cpp index 74d2c3a..2b3edf7 100644 --- a/src/graphicsitems/nodes/qxpainternode.cpp +++ b/src/graphicsitems/nodes/qxpainternode.cpp @@ -48,8 +48,13 @@ QxPainterNode::QxPainterNode(QxPaintItem *item) : GeometryNode() , m_item(item) , m_fbo(0) + , m_multisampledFbo(0) , m_size(1, 1) , m_opacity(1.0) + , m_linear_filtering(false) + , m_smoothPainting(false) + , m_extensionsChecked(false) + , m_multisamplingSupported(false) { setFlag(Node::UsePreprocess); setMaterial(&m_material); @@ -58,6 +63,7 @@ QxPainterNode::QxPainterNode(QxPaintItem *item) QxPainterNode::~QxPainterNode() { delete m_fbo; + delete m_multisampledFbo; } void QxPainterNode::preprocess() @@ -66,17 +72,42 @@ void QxPainterNode::preprocess() return; if (!m_fbo) { - m_fbo = new QGLFramebufferObject(m_size, QGLFramebufferObject::CombinedDepthStencil); - if (!m_fbo->isValid()) { - delete m_fbo; - m_fbo = 0; - return; + const QGLContext *ctx = QGLContext::currentContext(); + if (!m_extensionsChecked) { + QList extensions = QByteArray((const char *)glGetString(GL_EXTENSIONS)).split(' '); + m_multisamplingSupported = extensions.contains("GL_EXT_framebuffer_multisample") + && extensions.contains("GL_EXT_framebuffer_blit"); + m_extensionsChecked = true; + } + + if (m_smoothPainting && 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); + m_fbo = new QGLFramebufferObject(m_size, format); + } + } else { + QGLFramebufferObjectFormat format; + format.setAttachment(QGLFramebufferObject::CombinedDepthStencil); + m_fbo = new QGLFramebufferObject(m_size, format); } updateTexture(); } - QPainter fbo_painter(m_fbo); - if (m_item->smooth()) + QPainter fbo_painter; + if (m_multisampledFbo) + fbo_painter.begin(m_multisampledFbo); + else + fbo_painter.begin(m_fbo); + + if (m_smoothPainting) fbo_painter.setRenderHints(QPainter::HighQualityAntialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform); fbo_painter.setCompositionMode(QPainter::CompositionMode_Source); fbo_painter.fillRect(QRectF(QPointF(0, 0), m_fbo->size()), Qt::transparent); @@ -84,6 +115,11 @@ void QxPainterNode::preprocess() m_item->paint(&fbo_painter); fbo_painter.end(); + if (m_multisampledFbo) { + QRect r(0, 0, m_size.width(), m_size.height()); + QGLFramebufferObject::blitFramebuffer(m_fbo, r, m_multisampledFbo, r); + } + m_item->setDirty(false); } @@ -113,7 +149,9 @@ void QxPainterNode::setSize(const QSize &size) m_size = size; delete m_fbo; + delete m_multisampledFbo; m_fbo = 0; + m_multisampledFbo = 0; if (geometry()->isNull()) updateGeometryDescription(Utilities::getTexturedRectGeometryDescription(), GL_UNSIGNED_SHORT); @@ -144,3 +182,19 @@ void QxPainterNode::setLinearFiltering(bool linearFiltering) m_materialO.setLinearFiltering(linearFiltering); setMaterial(m_opacity == 1 ? &m_material : &m_materialO); } + +void QxPainterNode::setSmoothPainting(bool s) +{ + if (s == m_smoothPainting) + return; + + m_smoothPainting = s; + + if (m_multisamplingSupported) { + delete m_fbo; + delete m_multisampledFbo; + m_fbo = 0; + m_multisampledFbo = 0; + markDirty(DirtyMaterial); + } +} diff --git a/src/graphicsitems/nodes/qxpainternode.h b/src/graphicsitems/nodes/qxpainternode.h index 32d4f97..7d6212c 100644 --- a/src/graphicsitems/nodes/qxpainternode.h +++ b/src/graphicsitems/nodes/qxpainternode.h @@ -67,12 +67,16 @@ public: void setLinearFiltering(bool linearFiltering); bool linearFiltering() const { return m_linear_filtering; } + void setSmoothPainting(bool s); + bool smoothPainting() const { return m_smoothPainting; } + void updateTexture(); private: QxPaintItem *m_item; QGLFramebufferObject *m_fbo; + QGLFramebufferObject *m_multisampledFbo; TextureMaterial m_material; TextureMaterialWithOpacity m_materialO; QSGTextureRef m_texture; @@ -80,6 +84,9 @@ private: QSize m_size; qreal m_opacity; bool m_linear_filtering; + bool m_smoothPainting; + bool m_extensionsChecked; + bool m_multisamplingSupported; }; #endif // QXPAINTERNODE_H diff --git a/src/graphicsitems/qxpaintitem.cpp b/src/graphicsitems/qxpaintitem.cpp index c42699e..fa6e7d6 100644 --- a/src/graphicsitems/qxpaintitem.cpp +++ b/src/graphicsitems/qxpaintitem.cpp @@ -141,6 +141,7 @@ void QxPaintItem::smoothChange(bool newSmooth, bool oldSmooth) { Q_D(QxPaintItem); if (newSmooth != oldSmooth) { + d->m_node.setSmoothPainting(newSmooth); d->m_node.setLinearFiltering(newSmooth); update(); } -- cgit v1.2.3