From 210bb5a06811057a8ce2747bd187817a06968042 Mon Sep 17 00:00:00 2001 From: Sarah Smith Date: Thu, 20 Oct 2011 10:01:39 +1000 Subject: [PATCH] Provide a way to cheaply flip your painted FBO After recent changes the painted images are upside down from previous and there is no way to get at the texture coordinates to flip them back without reimplementing QSGPainterNode and QSGPaintedItem. This change adds only an enum and has minimal impact, while providing useful functionality that also fixes this problem. Change-Id: I6884da884d9303f6e08a984d4560cc7f7728d918 Reviewed-by: Sarah Jane Smith --- src/declarative/items/qquickpainteditem.cpp | 15 +++++++++++---- src/declarative/items/qquickpainteditem.h | 3 ++- src/declarative/scenegraph/util/qsgpainternode.cpp | 10 +++++++--- 3 files changed, 20 insertions(+), 8 deletions(-) diff --git a/src/declarative/items/qquickpainteditem.cpp b/src/declarative/items/qquickpainteditem.cpp index 5e5eb79..ac67f6a 100644 --- a/src/declarative/items/qquickpainteditem.cpp +++ b/src/declarative/items/qquickpainteditem.cpp @@ -92,6 +92,12 @@ QT_BEGIN_NAMESPACE quality is not as good as if using an image. This render target allows faster rendering in some cases, but you should avoid using it if the item is resized often. + \value InvertedYFramebufferObject Exactly as for FramebufferObject above, except once + the painting is done, prior to rendering the painted image is flipped about the + x-axis so that the top-most pixels are now at the bottom. Since this is done with the + OpenGL texture coordinates it is a much faster way to achieve this effect than using a + painter transform. + \sa setRenderTarget() */ @@ -437,10 +443,11 @@ void QQuickPaintedItem::setFillColor(const QColor &c) \brief The item's render target. This property defines which render target the QPainter renders into, it can be either - QQuickPaintedItem::Image or QQuickPaintedItem::FramebufferObject. Both have certains benefits, - typically performance versus quality. Using a framebuffer object avoids a costly upload - of the image contents to the texture in graphics memory, while using an image enables - high quality anti-aliasing. + QSGPaintedItem::Image, QSGPaintedItem::FramebufferObject or QSGPaintedItem::InvertedYFramebufferObject. + + Each has certain benefits, typically performance versus quality. Using a framebuffer + object avoids a costly upload of the image contents to the texture in graphics memory, + while using an image enables high quality anti-aliasing. \warning Resizing a framebuffer object is a costly operation, avoid using the QQuickPaintedItem::FramebufferObject render target if the item gets resized often. diff --git a/src/declarative/items/qquickpainteditem.h b/src/declarative/items/qquickpainteditem.h index 5f461fd..1ddfa25 100644 --- a/src/declarative/items/qquickpainteditem.h +++ b/src/declarative/items/qquickpainteditem.h @@ -65,7 +65,8 @@ public: enum RenderTarget { Image, - FramebufferObject + FramebufferObject, + InvertedYFramebufferObject }; enum PerformanceHint { diff --git a/src/declarative/scenegraph/util/qsgpainternode.cpp b/src/declarative/scenegraph/util/qsgpainternode.cpp index 3f07f20..1f44750 100644 --- a/src/declarative/scenegraph/util/qsgpainternode.cpp +++ b/src/declarative/scenegraph/util/qsgpainternode.cpp @@ -238,8 +238,11 @@ void QSGPainterNode::updateGeometry() source = QRectF(0, 0, 1, 1); else source = QRectF(0, 0, qreal(m_size.width()) / m_fboSize.width(), qreal(m_size.height()) / m_fboSize.height()); + QRectF dest(0, 0, m_size.width(), m_size.height()); + if (m_actualRenderTarget == QQuickPaintedItem::InvertedYFramebufferObject) + dest = QRectF(QPointF(0, m_size.height()), QPointF(m_size.width(), 0)); QSGGeometry::updateTexturedRectGeometry(&m_geometry, - QRectF(0, 0, m_size.width(), m_size.height()), + dest, source); markDirty(DirtyGeometry); } @@ -262,7 +265,7 @@ void QSGPainterNode::updateRenderTarget() if (!m_multisamplingSupported && m_smoothPainting) m_actualRenderTarget = QQuickPaintedItem::Image; else - m_actualRenderTarget = QQuickPaintedItem::FramebufferObject; + m_actualRenderTarget = m_preferredRenderTarget; } if (oldTarget != m_actualRenderTarget) { m_image = QImage(); @@ -271,7 +274,8 @@ void QSGPainterNode::updateRenderTarget() m_fbo = m_multisampledFbo = 0; } - if (m_actualRenderTarget == QQuickPaintedItem::FramebufferObject) { + if (m_actualRenderTarget == QQuickPaintedItem::FramebufferObject || + m_actualRenderTarget == QQuickPaintedItem::InvertedYFramebufferObject) { const QOpenGLContext *ctx = m_context->glContext(); if (m_fbo && !m_dirtyGeometry && (!ctx->format().samples() || !m_multisamplingSupported)) return; -- 2.7.4