summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorYoann Lopes <yoann.lopes@nokia.com>2010-12-08 15:14:52 +0100
committerYoann Lopes <yoann.lopes@nokia.com>2010-12-08 15:14:52 +0100
commitf87a860553c4cdb70fe33154bee6ce96fb407d85 (patch)
tree6144894d7407072c9d4e2a3063d1f9f2f6c9d233
parent35000ce69a75e0442758f6b2c124705d54258600 (diff)
Implemented 'smooth' property for QxPaintItem.
When smooth is set to true, a multisample framebuffer object is used (if the extension is available).
-rw-r--r--examples/paintitem/myfile.qml1
-rw-r--r--src/graphicsitems/nodes/qxpainternode.cpp68
-rw-r--r--src/graphicsitems/nodes/qxpainternode.h7
-rw-r--r--src/graphicsitems/qxpaintitem.cpp1
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<QByteArray> 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();
}