From a18130b26501b93c7d799f79ca21e448b7e697eb Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Wed, 8 Dec 2010 16:09:28 +0100 Subject: Creates QxPaintItem's node on componentComplete. Also, QxPainterNode now uses update flags. --- src/graphicsitems/nodes/qxpainternode.cpp | 119 +++++++++++++++++------------- src/graphicsitems/nodes/qxpainternode.h | 17 ++++- src/graphicsitems/qxpaintitem.cpp | 40 ++++++---- src/graphicsitems/qxpaintitem_p.h | 3 +- 4 files changed, 111 insertions(+), 68 deletions(-) diff --git a/src/graphicsitems/nodes/qxpainternode.cpp b/src/graphicsitems/nodes/qxpainternode.cpp index 2b3edf7..9190587 100644 --- a/src/graphicsitems/nodes/qxpainternode.cpp +++ b/src/graphicsitems/nodes/qxpainternode.cpp @@ -51,6 +51,7 @@ QxPainterNode::QxPainterNode(QxPaintItem *item) , m_multisampledFbo(0) , m_size(1, 1) , m_opacity(1.0) + , m_opaquePainting(false) , m_linear_filtering(false) , m_smoothPainting(false) , m_extensionsChecked(false) @@ -58,6 +59,7 @@ QxPainterNode::QxPainterNode(QxPaintItem *item) { setFlag(Node::UsePreprocess); setMaterial(&m_material); + updateGeometryDescription(Utilities::getTexturedRectGeometryDescription(), GL_UNSIGNED_SHORT); } QxPainterNode::~QxPainterNode() @@ -71,35 +73,7 @@ void QxPainterNode::preprocess() if (!m_item || !m_item->isDirty()) return; - if (!m_fbo) { - 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(); - } + Q_ASSERT(m_fbo != 0); QPainter fbo_painter; if (m_multisampledFbo) @@ -123,41 +97,82 @@ void QxPainterNode::preprocess() m_item->setDirty(false); } +void QxPainterNode::update(uint updateFlags) +{ + if (updateFlags & UpdateGeometry) + updateGeometry(); + if (updateFlags & (UpdateFBO | UpdateGeometry)) + updateFBO(); + if (updateFlags & (UpdateTexture | UpdateFBO)) + updateTexture(); +} + void QxPainterNode::updateTexture() { QSGTexture *texture = new QSGTexture; texture->setTextureId(m_fbo->texture()); texture->setTextureSize(m_fbo->size()); - texture->setAlphaChannel(m_item->opaquePainting()); + texture->setAlphaChannel(m_opaquePainting); texture->setOwnsTexture(false); texture->setStatus(QSGTexture::Ready); m_texture = QSGTextureRef(texture); - m_material.setTexture(m_texture, m_item->opaquePainting()); + m_material.setTexture(m_texture, m_opaquePainting); m_material.setLinearFiltering(m_linear_filtering); - m_materialO.setTexture(m_texture, m_item->opaquePainting()); + m_materialO.setTexture(m_texture, m_opaquePainting); m_materialO.setLinearFiltering(m_linear_filtering); m_materialO.setOpacity(m_opacity); setMaterial(m_opacity == 1 ? &m_material : &m_materialO); } -void QxPainterNode::setSize(const QSize &size) +void QxPainterNode::updateGeometry() { - if (size == m_size) - return; - - m_size = size; + Utilities::setupRectGeometry(geometry(), QRectF(0, 0, m_size.width(), m_size.height()), QSize(1, 1), QRectF(0,1,1,-1)); + markDirty(DirtyGeometry); +} +void QxPainterNode::updateFBO() +{ delete m_fbo; delete m_multisampledFbo; - m_fbo = 0; - m_multisampledFbo = 0; + m_fbo = m_multisampledFbo = 0; + + 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 (geometry()->isNull()) - updateGeometryDescription(Utilities::getTexturedRectGeometryDescription(), GL_UNSIGNED_SHORT); - Utilities::setupRectGeometry(geometry(), QRectF(0, 0, size.width(), size.height()), QSize(1, 1), QRectF(0,1,1,-1)); + 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); + } +} - markDirty(DirtyGeometry); +void QxPainterNode::setSize(const QSize &size) +{ + if (size == m_size) + return; + + m_size = size; + setBoundingRect(QRectF(0, 0, size.width(), size.height())); + setUpdateFlag(UpdateGeometry); } void QxPainterNode::setOpacity(qreal opacity) @@ -171,6 +186,15 @@ void QxPainterNode::setOpacity(qreal opacity) setMaterial(opacity == 1 ? &m_material : &m_materialO); } +void QxPainterNode::setOpaquePainting(bool opaque) +{ + if (opaque == m_opaquePainting) + return; + + m_opaquePainting = opaque; + setUpdateFlag(UpdateTexture); +} + void QxPainterNode::setLinearFiltering(bool linearFiltering) { if (linearFiltering == m_linear_filtering) @@ -189,12 +213,5 @@ void QxPainterNode::setSmoothPainting(bool s) return; m_smoothPainting = s; - - if (m_multisamplingSupported) { - delete m_fbo; - delete m_multisampledFbo; - m_fbo = 0; - m_multisampledFbo = 0; - markDirty(DirtyMaterial); - } + setUpdateFlag(UpdateFBO); } diff --git a/src/graphicsitems/nodes/qxpainternode.h b/src/graphicsitems/nodes/qxpainternode.h index 7d6212c..bf7b71d 100644 --- a/src/graphicsitems/nodes/qxpainternode.h +++ b/src/graphicsitems/nodes/qxpainternode.h @@ -64,15 +64,29 @@ public: void setOpacity(qreal opacity) ; qreal opacity() const { return m_opacity; } + void setOpaquePainting(bool opaque); + bool opaquePainting() const { return m_opaquePainting; } + void setLinearFiltering(bool linearFiltering); bool linearFiltering() const { return m_linear_filtering; } void setSmoothPainting(bool s); bool smoothPainting() const { return m_smoothPainting; } - void updateTexture(); + virtual void update(uint updateFlags); private: + enum UpdateFlag + { + UpdateTexture = 0x01, + UpdateGeometry = 0x02, + UpdateFBO = 0x03 + }; + + void updateTexture(); + void updateGeometry(); + void updateFBO(); + QxPaintItem *m_item; QGLFramebufferObject *m_fbo; @@ -83,6 +97,7 @@ private: QSize m_size; qreal m_opacity; + bool m_opaquePainting; bool m_linear_filtering; bool m_smoothPainting; bool m_extensionsChecked; diff --git a/src/graphicsitems/qxpaintitem.cpp b/src/graphicsitems/qxpaintitem.cpp index fa6e7d6..3c74455 100644 --- a/src/graphicsitems/qxpaintitem.cpp +++ b/src/graphicsitems/qxpaintitem.cpp @@ -56,19 +56,23 @@ QxPaintItemPrivate::QxPaintItemPrivate() : QxItemPrivate() + , m_node(0) , m_opaque_painting(false) , m_dirty(false) { } +QxPaintItemPrivate::~QxPaintItemPrivate() +{ + delete m_node; +} + /*! Constructs a QxPaintItem with \a parent. */ QxPaintItem::QxPaintItem(QxItem *parent) : QxItem(*(new QxPaintItemPrivate), parent) { - Q_D(QxPaintItem); - d->m_node.setPaintItem(this); } /*! @@ -77,8 +81,6 @@ QxPaintItem::QxPaintItem(QxItem *parent) QxPaintItem::QxPaintItem(QxPaintItemPrivate &dd, QxItem *parent) : QxItem(dd, parent) { - Q_D(QxPaintItem); - d->m_node.setPaintItem(this); } /*! @@ -95,7 +97,8 @@ void QxPaintItem::update() { Q_D(QxPaintItem); d->m_dirty = true; - d->m_node.markDirty(Node::DirtyMaterial); + if (d->m_node) + d->m_node->markDirty(Node::DirtyMaterial); } /*! @@ -105,8 +108,14 @@ void QxPaintItem::componentComplete() { Q_D(QxPaintItem); QxItem::componentComplete(); - d->m_node.setSize(size().toSize()); - setPaintNode(&d->m_node); + Q_ASSERT(d->m_node == 0); + d->m_node = new QxPainterNode(this); + d->m_node->setSize(size().toSize()); + d->m_node->setOpacity(renderOpacity()); + d->m_node->setSmoothPainting(smooth()); + d->m_node->setLinearFiltering(smooth()); + d->m_node->setOpaquePainting(d->m_opaque_painting); + setPaintNode(d->m_node); update(); } @@ -116,8 +125,8 @@ void QxPaintItem::componentComplete() void QxPaintItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry) { Q_D(QxPaintItem); - if (newGeometry.size() != oldGeometry.size()) { - d->m_node.setSize(newGeometry.size().toSize()); + if (d->m_node && newGeometry.size() != oldGeometry.size()) { + d->m_node->setSize(newGeometry.size().toSize()); update(); } QxItem::geometryChanged(newGeometry, oldGeometry); @@ -129,8 +138,8 @@ void QxPaintItem::geometryChanged(const QRectF &newGeometry, const QRectF &oldGe void QxPaintItem::renderOpacityChanged(qreal newOpacity, qreal oldOpacity) { Q_D(QxPaintItem); - if (newOpacity != oldOpacity) - d->m_node.setOpacity(newOpacity); + if (d->m_node && newOpacity != oldOpacity) + d->m_node->setOpacity(newOpacity); QxItem::renderOpacityChanged(newOpacity, oldOpacity); } @@ -140,9 +149,9 @@ void QxPaintItem::renderOpacityChanged(qreal newOpacity, qreal oldOpacity) void QxPaintItem::smoothChange(bool newSmooth, bool oldSmooth) { Q_D(QxPaintItem); - if (newSmooth != oldSmooth) { - d->m_node.setSmoothPainting(newSmooth); - d->m_node.setLinearFiltering(newSmooth); + if (d->m_node && newSmooth != oldSmooth) { + d->m_node->setSmoothPainting(newSmooth); + d->m_node->setLinearFiltering(newSmooth); update(); } QxItem::smoothChange(newSmooth, oldSmooth); @@ -163,7 +172,8 @@ void QxPaintItem::setOpaquePainting(bool opaque) if (opaque == d->m_opaque_painting) return; d->m_opaque_painting = opaque; - d->m_node.updateTexture(); + if (d->m_node) + d->m_node->setOpaquePainting(d->m_opaque_painting); } /*! diff --git a/src/graphicsitems/qxpaintitem_p.h b/src/graphicsitems/qxpaintitem_p.h index c40e1cd..37efcc8 100644 --- a/src/graphicsitems/qxpaintitem_p.h +++ b/src/graphicsitems/qxpaintitem_p.h @@ -52,8 +52,9 @@ class QxPaintItemPrivate : public QxItemPrivate public: QxPaintItemPrivate(); + ~QxPaintItemPrivate(); - QxPainterNode m_node; + QxPainterNode *m_node; bool m_opaque_painting; bool m_dirty; -- cgit v1.2.3