diff options
Diffstat (limited to 'src/declarative/opengl/gltexture.cpp')
-rw-r--r-- | src/declarative/opengl/gltexture.cpp | 321 |
1 files changed, 321 insertions, 0 deletions
diff --git a/src/declarative/opengl/gltexture.cpp b/src/declarative/opengl/gltexture.cpp new file mode 100644 index 0000000..73deece --- /dev/null +++ b/src/declarative/opengl/gltexture.cpp @@ -0,0 +1,321 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** Contact: Qt Software Information (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $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 either Technology Preview License Agreement or the +** Beta Release License Agreement. +** +** 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.0, included in the file LGPL_EXCEPTION.txt in this +** package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at qt-sales@nokia.com. +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "gltexture.h" +#include <QImage> + + +QT_BEGIN_NAMESPACE +/*! + \class GLTexture + \brief The GLTexture class simplifies the use of OpenGL textures. +*/ + +// Copied from QGLWidget::convertToGLFormat +static QImage QGLWidget_convertToGLFormat(const QImage& img) +{ + QImage res = img.convertToFormat(QImage::Format_ARGB32); + res = res.mirrored(); + + if (QSysInfo::ByteOrder == QSysInfo::BigEndian) { + // Qt has ARGB; OpenGL wants RGBA + for (int i=0; i < res.height(); i++) { + uint *p = (uint*)res.scanLine(i); + uint *end = p + res.width(); + while (p < end) { + *p = (*p << 8) | ((*p >> 24) & 0xFF); + p++; + } + } + } + else { + // Qt has ARGB; OpenGL wants ABGR (i.e. RGBA backwards) + res = res.rgbSwapped(); + } + return res; +} +class GLTexturePrivate +{ +public: + GLTexturePrivate(GLTexture *_q) + : q(_q), texture(0), width(0), height(0), + horizWrap(GLTexture::Repeat), vertWrap(GLTexture::Repeat), + minFilter(GLTexture::Linear), magFilter(GLTexture::Linear) + { + } + + GLTexture *q; + GLuint texture; + int width; + int height; + GLTexture::WrapMode horizWrap; + GLTexture::WrapMode vertWrap; + GLTexture::FilterMode minFilter; + GLTexture::FilterMode magFilter; + + void genTexture(); +}; + +void GLTexturePrivate::genTexture() +{ + if(texture) + return; + + glGenTextures(1, &texture); + glBindTexture(GL_TEXTURE_2D, texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, minFilter); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, magFilter); + q->setHorizontalWrap(horizWrap); + q->setVerticalWrap(vertWrap); +} + +GLTexture::GLTexture() +: d(new GLTexturePrivate(this)) +{ +} + +GLTexture::GLTexture(const QString &file) +: d(new GLTexturePrivate(this)) +{ + QImage img(file); + if(!img.isNull()) + setImage(img); +} + +GLTexture::GLTexture(const QImage &img) +: d(new GLTexturePrivate(this)) +{ + setImage(img); +} + +GLTexture::~GLTexture() +{ + if(d->texture) + glDeleteTextures(1, &d->texture); + delete d; + d = 0; +} + +bool GLTexture::isNull() const +{ + return d->texture == 0; +} + +void GLTexture::clear() +{ + if(d->texture) { + glDeleteTextures(1, &d->texture); + d->texture = 0; + d->width = 0; + d->height = 0; + } +} + +static inline int npot(int size) +{ + size--; + size |= size >> 1; + size |= size >> 2; + size |= size >> 4; + size |= size >> 8; + size |= size >> 16; + size++; + return size; +} + +/*! + Set the texture to \a img. If the texture has already been created (either + by explicitly setting the size, or by previously setting an image), it will + be destroyed and a new texture created with \a img's contents and size. + */ +void GLTexture::setImage(const QImage &img) +{ + if(img.isNull()) + return; + + d->genTexture(); + + //QImage dataImage = img.scaled(npot(img.width()), npot(img.height()), Qt::IgnoreAspectRatio, Qt::SmoothTransformation); + QImage dataImage = QGLWidget_convertToGLFormat(img); + + glBindTexture(GL_TEXTURE_2D, d->texture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, dataImage.width(), + dataImage.height(), 0, + (dataImage.format() == QImage::Format_ARGB32)?GL_RGBA:GL_RGB, + GL_UNSIGNED_BYTE, dataImage.bits()); + d->width = dataImage.width(); + d->height = dataImage.height(); + +#if 0 + glGenerateMipmap(GL_TEXTURE_2D); + int e = glGetError(); + if(d->magFilter == Linear) + setMagFilter(MipmapLinear); + if(d->minFilter == Linear) + setMinFilter((GLTexture::FilterMode)GL_LINEAR_MIPMAP_LINEAR); +#endif +} + +void GLTexture::copyImage(const QImage &img, const QPoint &point, + const QRect &srcRect) +{ + qFatal("Not implemented"); + Q_UNUSED(img); + Q_UNUSED(point); + Q_UNUSED(srcRect); +} + +QSize GLTexture::size() const +{ + return QSize(d->width, d->height); +} + +int GLTexture::width() const +{ + return d->width; +} + +int GLTexture::height() const +{ + return d->height; +} + +/*! + Sets the \a size of the texture. This will destroy the current contents of + the texture. If an image has been assigned, it will need to be reassigned + using either setImage() or copyImage(). + + If size is invalid (width or height is less than or equal to 0) the texture + will be destroyed. This is equivalent to calling clear(). +*/ +void GLTexture::setSize(const QSize &size) +{ + if(size.width() <= 0 || size.height() <= 0) { + clear(); + return; + } + + d->genTexture(); + glBindTexture(GL_TEXTURE_2D, d->texture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); + d->width = size.width(); + d->height = size.height(); +} + +GLTexture::WrapMode GLTexture::horizontalWrap() const +{ + return d->horizWrap; +} + +GLTexture::WrapMode GLTexture::verticalWrap() const +{ + return d->vertWrap; +} + +void GLTexture::setHorizontalWrap(WrapMode mode) +{ + d->horizWrap = mode; + if(d->texture) { + GLint last; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last); + if(GLuint(last) != d->texture) + glBindTexture(GL_TEXTURE_2D, d->texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, mode); + if(GLuint(last) != d->texture) + glBindTexture(GL_TEXTURE_2D, last); + } +} + +/*! + Set the veritcal wrap mode to \a mode. + */ +void GLTexture::setVerticalWrap(WrapMode mode) +{ + d->vertWrap = mode; + if(d->texture) { + GLint last; + glGetIntegerv(GL_TEXTURE_BINDING_2D, &last); + if(GLuint(last) != d->texture) + glBindTexture(GL_TEXTURE_2D, d->texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, mode); + if(GLuint(last) != d->texture) + glBindTexture(GL_TEXTURE_2D, last); + } +} + +GLTexture::FilterMode GLTexture::minFilter() const +{ + return d->minFilter; +} + +GLTexture::FilterMode GLTexture::magFilter() const +{ + return d->magFilter; +} + +void GLTexture::setMinFilter(FilterMode f) +{ + if(d->minFilter == f) + return; + d->minFilter = f; + if(d->texture) { + glBindTexture(GL_TEXTURE_2D, d->texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, d->minFilter); + } +} + +void GLTexture::setMagFilter(FilterMode f) +{ + if(d->magFilter == f) + return; + d->magFilter = f; + if(d->texture) { + glBindTexture(GL_TEXTURE_2D, d->texture); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, d->magFilter); + } +} + +GLuint GLTexture::texture() const +{ + return d->texture; +} + +QT_END_NAMESPACE |