From 05260ab5903d4ce42fba14c92b17d91759426da8 Mon Sep 17 00:00:00 2001 From: Gunnar Sletta Date: Thu, 2 Dec 2010 19:38:08 +0100 Subject: A few fixes to the Image element / TextureNode - actually propegate the texture to the texture node - use a proper source rect. subsources are still broken, will get to that later --- .../default/default_texturenode.cpp | 239 +++++++++++++++++++++ src/adaptationlayers/default/default_texturenode.h | 77 +++++++ src/graphicsitems/qximage.cpp | 1 + 3 files changed, 317 insertions(+) create mode 100644 src/adaptationlayers/default/default_texturenode.cpp create mode 100644 src/adaptationlayers/default/default_texturenode.h diff --git a/src/adaptationlayers/default/default_texturenode.cpp b/src/adaptationlayers/default/default_texturenode.cpp new file mode 100644 index 0000000..f42beec --- /dev/null +++ b/src/adaptationlayers/default/default_texturenode.cpp @@ -0,0 +1,239 @@ +/**************************************************************************** +** +** 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 "adaptationinterfaces.h" + +#include "default_texturenode.h" +#include "adaptationlayer.h" + +#include +#include + +DefaultTextureNode::DefaultTextureNode() + : m_texture(0) +{ + m_material.setLinearFiltering(m_linear_filtering); + m_materialO.setLinearFiltering(m_linear_filtering); + m_materialO.setOpacity(m_opacity); + setMaterial(&m_material); + + updateGeometryDescription(Utilities::getTexturedRectGeometryDescription(), GL_UNSIGNED_SHORT); + +#ifdef QML_RUNTIME_TESTING + description = "pixmap"; +#endif +} + +void DefaultTextureNode::setRect(const QRectF &rect) +{ + if (m_rect == rect) + return; + m_rect = rect; + setBoundingRect(rect); + setUpdateFlag(UpdateGeometry); +} + +void DefaultTextureNode::setSourceRect(const QRectF &rect) +{ + if (m_source_rect == rect) + return; + m_source_rect = rect; + setUpdateFlag(UpdateGeometry); +} + +void DefaultTextureNode::setOpacity(qreal opacity) +{ + if (m_opacity == opacity) + return; + m_materialO.setOpacity(opacity); + m_opacity = opacity; + setMaterial(opacity == 1 ? &m_material : &m_materialO); // Indicate that the material state has changed. +} + +void DefaultTextureNode::setTexture(TextureReference *texture) +{ + if (texture == m_texture) + return; + + m_texture = texture; + setUpdateFlag(UpdateTexture); +} + +void DefaultTextureNode::setClampToEdge(bool clampToEdge) +{ + if (m_clamp_to_edge == clampToEdge) + return; + m_clamp_to_edge = clampToEdge; + setUpdateFlag(UpdateTexture); +} + +void DefaultTextureNode::setLinearFiltering(bool linearFiltering) +{ + if (m_linear_filtering == linearFiltering) + return; + m_material.setLinearFiltering(linearFiltering); + m_materialO.setLinearFiltering(linearFiltering); + m_linear_filtering = linearFiltering; + setMaterial(m_opacity == 1 ? &m_material : &m_materialO); // Indicate that the material state has changed. +} + +void DefaultTextureNode::update(uint updateFlags) +{ + if (updateFlags & UpdateTexture) + updateTexture(); + // A texture update causes the source rectangle to change, so update geometry too. + if (updateFlags & (UpdateTexture | UpdateGeometry)) + updateGeometry(); +} + +void DefaultTextureNode::updateGeometry() +{ + if (!m_texture) + return; + + Geometry *g = geometry(); + + QRectF normalizedSource(0, 0, 1, 1); + // ### gunnar: Make the source rect be set in normalized coords in QxImage already.. +// if (!m_source_rect.isEmpty()) { +// normalizedSource = QRectF(tRect.x() + m_source_rect.x() * tRect.width(), +// tRect.y() + m_source_rect.y() * tRect.height(), +// m_source_rect.width() * tRect.width(), +// m_source_rect.height() * tRect.height()); +// } + + QVarLengthArray xSrc, xDst; + xSrc.append(normalizedSource.left()); + xDst.append(m_rect.left()); + // ### gunnar: needs porting +// if (!m_texture.isNull() && !m_texture->hasOwnTexture()) { +// for (int i = qFloor(normalizedSource.left()) + 1; i <= qCeil(normalizedSource.right()) - 1; ++i) { +// xSrc.append(i); +// xDst.append(m_rect.left() + m_rect.width() * (i - normalizedSource.left()) / normalizedSource.width()); +// } +// } + xSrc.append(normalizedSource.right()); + xDst.append(m_rect.right()); + + QVarLengthArray ySrc, yDst; + ySrc.append(normalizedSource.top()); + yDst.append(m_rect.top()); + // ### gunnar: needs porting +// if (!m_texture.isNull() && !m_texture->hasOwnTexture()) { +// for (int i = qFloor(normalizedSource.top()) + 1; i <= qCeil(normalizedSource.bottom()) - 1; ++i) { +// ySrc.append(i); +// yDst.append(m_rect.top() + m_rect.height() * (i - normalizedSource.top()) / normalizedSource.height()); +// } +// } + ySrc.append(normalizedSource.bottom()); + yDst.append(m_rect.bottom()); + + if (xSrc.size() == 2 && ySrc.size() == 2) { + g->setDrawingMode(QGL::TriangleStrip); + g->setVertexCount(4); + if (!m_clamp_to_edge) { + g->setIndexCount(4); + for (int i=0; i<4; ++i) + g->ushortIndexData()[i] = i; + } + } else { + g->setDrawingMode(QGL::Triangles); + int cellCount = (xSrc.size() - 1) * (ySrc.size() - 1); + int vertexCount = cellCount * 4; // Four vertices per grid cell. + if (vertexCount > 0x10000) + qWarning("QxPixmapNode::updateGeometry: Number of vertices exceeds 65536."); + g->setVertexCount(vertexCount); + + if (!m_clamp_to_edge) { + int indexCount = cellCount * 6; // Six indices per grid cell. + g->setIndexCount(indexCount); + + for (int i = 0; i < cellCount; ++i) { + g->ushortIndexData()[6 * i + 0] = i * 4 + 0; + g->ushortIndexData()[6 * i + 1] = i * 4 + 1; + g->ushortIndexData()[6 * i + 2] = i * 4 + 3; + g->ushortIndexData()[6 * i + 3] = i * 4 + 3; + g->ushortIndexData()[6 * i + 4] = i * 4 + 2; + g->ushortIndexData()[6 * i + 5] = i * 4 + 0; + } + } + } + + struct V { + float x, y, tx, ty; + }; + + V *v = (V *) g->vertexData(); + + qreal xSrcOffset = qFloor(normalizedSource.left()); + qreal ySrcOffset = qFloor(normalizedSource.top()); + QRectF texSrcRect = m_texture->subRect(); + + for (int j = 0; j < ySrc.size() - 1; ++j) { + for (int i = 0; i < xSrc.size() - 1; ++i) { + v[0].x = v[1].x = xDst.at(i); + v[2].x = v[3].x = xDst.at(i + 1); + v[0].y = v[2].y = yDst.at(j); + v[1].y = v[3].y = yDst.at(j + 1); + + QRectF src(texSrcRect.x() + (xSrc.at(i) - i - xSrcOffset) * texSrcRect.width(), + texSrcRect.y() + (ySrc.at(j) - j - ySrcOffset) * texSrcRect.height(), + (xSrc.at(i + 1) - xSrc.at(i)) * texSrcRect.width(), + (ySrc.at(j + 1) - ySrc.at(j)) * texSrcRect.height()); + + v[0].tx = v[1].tx = src.left(); + v[2].tx = v[3].tx = src.right(); + v[0].ty = v[2].ty = src.top(); + v[1].ty = v[3].ty = src.bottom(); + v += 4; + } + } + + markDirty(DirtyGeometry); +} + +void DefaultTextureNode::updateTexture() +{ + bool opaque = !m_texture->hasAlphaChannel(); + m_material.setTexture(m_texture, opaque); + m_materialO.setTexture(m_texture, opaque); + setMaterial(m_opacity == 1 ? &m_material : &m_materialO); // Indicate that the material state has changed. +} diff --git a/src/adaptationlayers/default/default_texturenode.h b/src/adaptationlayers/default/default_texturenode.h new file mode 100644 index 0000000..b43b279 --- /dev/null +++ b/src/adaptationlayers/default/default_texturenode.h @@ -0,0 +1,77 @@ +/**************************************************************************** +** +** 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$ +** +****************************************************************************/ + + +#ifndef DEFAULT_PIXMAPNODE_H +#define DEFAULT_PIXMAPNODE_H + +#include "adaptationinterfaces.h" + +#include "texturematerial.h" +#include "utilities.h" + +class DefaultTextureNode : public TextureNodeInterface +{ +public: + DefaultTextureNode (); + virtual void setRect(const QRectF &rect); + virtual void setSourceRect(const QRectF &rect); + virtual void setOpacity(qreal opacity); + virtual void setTexture(TextureReference *texture); + virtual void setClampToEdge(bool clampToEdge); + virtual void setLinearFiltering(bool linearFiltering); + virtual void update(uint updateFlags); +private: + enum UpdateFlag + { + UpdateTexture = 0x01, + UpdateGeometry = 0x02 + }; + + void updateGeometry(); + void updateTexture(); + + TextureReference *m_texture; + TextureMaterial m_material; + TextureMaterialWithOpacity m_materialO; +}; + +#endif diff --git a/src/graphicsitems/qximage.cpp b/src/graphicsitems/qximage.cpp index 9366bf0..075da68 100644 --- a/src/graphicsitems/qximage.cpp +++ b/src/graphicsitems/qximage.cpp @@ -202,6 +202,7 @@ void QxImagePrivate::update() TextureManager::SynchronousUploadHint); } + node->setTexture(texture); node->setRect(targetRect); node->setSourceRect(sourceRect); node->setOpacity(renderOpacity); -- cgit v1.2.3