/**************************************************************************** ** ** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** This file is part of the Qt scene graph research project. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** ** ** ** ** ** ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qxpainternode.h" #include "qxpaintitem.h" #include 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); } QxPainterNode::~QxPainterNode() { delete m_fbo; delete m_multisampledFbo; } 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(); } 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); fbo_painter.setCompositionMode(QPainter::CompositionMode_SourceOver); 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); } void QxPainterNode::updateTexture() { QSGTexture *texture = new QSGTexture; texture->setTextureId(m_fbo->texture()); texture->setTextureSize(m_fbo->size()); texture->setAlphaChannel(m_item->opaquePainting()); texture->setOwnsTexture(false); texture->setStatus(QSGTexture::Ready); m_texture = QSGTextureRef(texture); m_material.setTexture(m_texture, m_item->opaquePainting()); m_material.setLinearFiltering(m_linear_filtering); m_materialO.setTexture(m_texture, m_item->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) { if (size == m_size) return; m_size = size; delete m_fbo; delete m_multisampledFbo; m_fbo = 0; m_multisampledFbo = 0; 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)); markDirty(DirtyGeometry); } void QxPainterNode::setOpacity(qreal opacity) { if (opacity == m_opacity) return; m_opacity = opacity; m_materialO.setOpacity(opacity); setMaterial(opacity == 1 ? &m_material : &m_materialO); } void QxPainterNode::setLinearFiltering(bool linearFiltering) { if (linearFiltering == m_linear_filtering) return; m_linear_filtering = linearFiltering; m_material.setLinearFiltering(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); } }