summaryrefslogtreecommitdiffstats
path: root/src/declarative/opengl/gltexture.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/declarative/opengl/gltexture.cpp')
-rw-r--r--src/declarative/opengl/gltexture.cpp321
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