summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/corelib/global/qglobal.cpp7
-rw-r--r--src/corelib/global/qglobal.h2
-rw-r--r--src/gui/gui.pro1
-rw-r--r--src/gui/math3d/math3d.pri20
-rw-r--r--src/gui/math3d/qfixedpt.cpp681
-rw-r--r--src/gui/math3d/qfixedpt.h521
-rw-r--r--src/gui/math3d/qgenericmatrix.cpp221
-rw-r--r--src/gui/math3d/qgenericmatrix.h341
-rw-r--r--src/gui/math3d/qmath3dglobal.h72
-rw-r--r--src/gui/math3d/qmath3dutil.cpp164
-rw-r--r--src/gui/math3d/qmath3dutil_p.h66
-rw-r--r--src/gui/math3d/qmatrix4x4.cpp1649
-rw-r--r--src/gui/math3d/qmatrix4x4.h954
-rw-r--r--src/gui/math3d/qquaternion.cpp513
-rw-r--r--src/gui/math3d/qquaternion.h313
-rw-r--r--src/gui/math3d/qvector2d.cpp386
-rw-r--r--src/gui/math3d/qvector2d.h237
-rw-r--r--src/gui/math3d/qvector3d.cpp535
-rw-r--r--src/gui/math3d/qvector3d.h266
-rw-r--r--src/gui/math3d/qvector4d.cpp491
-rw-r--r--src/gui/math3d/qvector4d.h270
-rw-r--r--src/opengl/gl2paintengineex/qglshader_p.h2
-rw-r--r--src/opengl/opengl.pro6
-rw-r--r--src/opengl/qglextensions.cpp174
-rw-r--r--src/opengl/qglextensions_p.h134
-rw-r--r--src/opengl/qglpixmapfilter.cpp172
-rw-r--r--src/opengl/qglpixmapfilter_p.h29
-rw-r--r--src/opengl/qglshaderprogram.cpp2828
-rw-r--r--src/opengl/qglshaderprogram.h285
29 files changed, 11130 insertions, 210 deletions
diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp
index b9c2bee..2767f6f 100644
--- a/src/corelib/global/qglobal.cpp
+++ b/src/corelib/global/qglobal.cpp
@@ -2939,7 +2939,12 @@ bool QInternal::callFunction(InternalFunction func, void **args)
\relates <QtGlobal>
\since 4.4
\threadsafe
- \overload
+
+ Compares the floating point value \a p1 and \a p2 and
+ returns \c true if they are considered equal, otherwise \c false.
+
+ The two numbers are compared in a relative way, where the
+ exactness is stronger the smaller the numbers are.
*/
/*!
diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h
index 210f713..6f886c2 100644
--- a/src/corelib/global/qglobal.h
+++ b/src/corelib/global/qglobal.h
@@ -1833,7 +1833,7 @@ enum { /* TYPEINFO flags */
#define Q_DECLARE_TYPEINFO(TYPE, FLAGS) \
template <> \
-class QTypeInfo<TYPE> \
+class QTypeInfo<TYPE > \
{ \
public: \
enum { \
diff --git a/src/gui/gui.pro b/src/gui/gui.pro
index f224e67..1aa6558 100644
--- a/src/gui/gui.pro
+++ b/src/gui/gui.pro
@@ -31,6 +31,7 @@ include(itemviews/itemviews.pri)
include(inputmethod/inputmethod.pri)
include(graphicsview/graphicsview.pri)
include(util/util.pri)
+include(math3d/math3d.pri)
embedded: QT += network
diff --git a/src/gui/math3d/math3d.pri b/src/gui/math3d/math3d.pri
new file mode 100644
index 0000000..581adbd
--- /dev/null
+++ b/src/gui/math3d/math3d.pri
@@ -0,0 +1,20 @@
+HEADERS += \
+ math3d/qfixedpt.h \
+ math3d/qgenericmatrix.h \
+ math3d/qmath3dglobal.h \
+ math3d/qmath3dutil_p.h \
+ math3d/qmatrix4x4.h \
+ math3d/qquaternion.h \
+ math3d/qvector2d.h \
+ math3d/qvector3d.h \
+ math3d/qvector4d.h
+
+SOURCES += \
+ math3d/qfixedpt.cpp \
+ math3d/qgenericmatrix.cpp \
+ math3d/qmath3dutil.cpp \
+ math3d/qmatrix4x4.cpp \
+ math3d/qquaternion.cpp \
+ math3d/qvector2d.cpp \
+ math3d/qvector3d.cpp \
+ math3d/qvector4d.cpp
diff --git a/src/gui/math3d/qfixedpt.cpp b/src/gui/math3d/qfixedpt.cpp
new file mode 100644
index 0000000..e7e61b6
--- /dev/null
+++ b/src/gui/math3d/qfixedpt.cpp
@@ -0,0 +1,681 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qfixedpt.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \internal
+ Returns the fixed-point square root of \a value.
+*/
+qint64 qt_math3d_fixed_sqrt(qint64 value)
+{
+ qint64 result = 0;
+ qint64 bit = ((qint64)1) << 62;
+ while (bit > value)
+ bit >>= 2;
+ while (bit != 0) {
+ if (value >= (result + bit)) {
+ value -= result + bit;
+ result += (bit << 1);
+ }
+ result >>= 1;
+ bit >>= 2;
+ }
+ return result;
+}
+
+/*!
+ \class QFixedPt
+ \brief The QFixedPt class represents fixed-point numbers within a 32-bit integer with a configurable precision.
+
+ The template parameter is the number of bits of precision after
+ the decimal point. For example, QFixedPt<5> indicates that there
+ are 27 bits before the decimal point, and 5 bits of precision after
+ the decimal point.
+*/
+
+/*!
+ \fn QFixedPt::QFixedPt()
+
+ Constructs a default fixed-point number. The initial value
+ is undefined.
+*/
+
+/*!
+ \fn QFixedPt::QFixedPt(int value)
+
+ Constructs a fixed-point number from the integer \a value.
+*/
+
+/*!
+ \fn QFixedPt::QFixedPt(qreal value)
+
+ Constructs a fixed-point number from the floating-point \a value.
+*/
+
+/*!
+ \fn QFixedPt<PrecBits>& QFixedPt::operator=(int value)
+
+ Assigns the integer \a value to this fixed-point variable.
+*/
+
+/*!
+ \fn QFixedPt<PrecBits>& QFixedPt::operator=(qreal value)
+
+ Assigns the floating-point \a value to this fixed-point variable.
+*/
+
+/*!
+ \fn int QFixedPt::bits() const
+
+ Returns the raw bits that represent the fixed-point value of this object.
+
+ \sa setBits()
+*/
+
+/*!
+ \fn void QFixedPt::setBits(int value)
+
+ Sets the raw bits that represent the fixed-point value of
+ this object to \a value.
+
+ \sa bits()
+*/
+
+#if !defined(QT_NO_MEMBER_TEMPLATES) || defined(Q_QDOC)
+
+/*!
+ \fn QFixedPt<Prec> QFixedPt::toPrecision() const
+
+ Returns this fixed-point number, converted to the new fixed-point
+ precision Prec.
+
+ \sa qFixedPtToPrecision()
+*/
+
+#endif
+
+/*!
+ \fn QFixedPt<Prec> qFixedPtToPrecision(const QFixedPt<PrecBits>& value)
+
+ Returns the fixed-point number \a value, converted to the new fixed-point
+ precision Prec.
+
+ \sa QFixedPt::toPrecision()
+*/
+
+/*!
+ \fn QFixedPt<PrecBits>& QFixedPt::operator+=(const QFixedPt<PrecBits>& value)
+
+ Adds \a value to this fixed-point number.
+*/
+
+/*!
+ \fn QFixedPt<PrecBits>& QFixedPt::operator+=(int value)
+
+ Adds an integer \a value to this fixed-point number.
+*/
+
+/*!
+ \fn QFixedPt<PrecBits>& QFixedPt::operator+=(qreal value)
+
+ Adds a floating-point \a value to this fixed-point number.
+*/
+
+/*!
+ \fn QFixedPt<PrecBits>& QFixedPt::operator-=(const QFixedPt<PrecBits>& value)
+
+ Subtracts \a value from this fixed-point number.
+*/
+
+/*!
+ \fn QFixedPt<PrecBits>& QFixedPt::operator-=(int value)
+
+ Subtracts an integer \a value from this fixed-point number.
+*/
+
+/*!
+ \fn QFixedPt<PrecBits>& QFixedPt::operator-=(qreal value)
+
+ Subtracts a floating-point \a value from this fixed-point number.
+*/
+
+/*!
+ \fn QFixedPt<PrecBits>& QFixedPt::operator*=(const QFixedPt<PrecBits>& value)
+
+ Multiplies this fixed-point number by \a value.
+*/
+
+/*!
+ \fn QFixedPt<PrecBits>& QFixedPt::operator*=(int value)
+
+ Multiplies this fixed-point number by an integer \a value.
+*/
+
+/*!
+ \fn QFixedPt<PrecBits>& QFixedPt::operator*=(qreal value)
+
+ Multiplies this fixed-point number by a floating-point \a value.
+*/
+
+/*!
+ \fn QFixedPt<PrecBits>& QFixedPt::operator/=(const QFixedPt<PrecBits>& value)
+
+ Divides this fixed-point number by \a value. Division by zero
+ will result in zero.
+*/
+
+/*!
+ \fn QFixedPt<PrecBits>& QFixedPt::operator/=(int value)
+
+ Divides this fixed-point number by an integer \a value. Division
+ by zero will result in zero.
+*/
+
+/*!
+ \fn QFixedPt<PrecBits>& QFixedPt::operator/=(qreal value)
+
+ Divides this fixed-point number by a floating-point \a value. Division
+ by zero will result in zero.
+*/
+
+/*!
+ \fn QFixedPt<PrecBits>& QFixedPt::operator<<=(int value)
+
+ Shifts this fixed-point number left by \a value bits.
+*/
+
+/*!
+ \fn QFixedPt<PrecBits>& QFixedPt::operator>>=(int value)
+
+ Shifts this fixed-point number right by \a value bits.
+*/
+
+/*!
+ \fn QFixedPt<PrecBits> QFixedPt::operator<<(int value) const
+
+ Returns the result of shifting this fixed-point number
+ left by \a value bits.
+*/
+
+/*!
+ \fn QFixedPt<PrecBits> QFixedPt::operator>>(int value) const
+
+ Returns the result of shifting this fixed-point number
+ right by \a value bits.
+*/
+
+/*!
+ \fn bool QFixedPt::operator==(const QFixedPt<PrecBits>& value) const
+
+ Returns true if this fixed-point number is equal to \a value;
+ false otherwise.
+*/
+
+/*!
+ \fn bool operator==(const QFixedPt<PrecBits>& v1, int v2)
+ \relates QFixedPt
+
+ Returns true if \a v1 is equal to \a v2; false otherwise.
+*/
+
+/*!
+ \fn bool operator==(int v1, const QFixedPt<PrecBits>& v2)
+ \relates QFixedPt
+
+ Returns true if \a v1 is equal to \a v2; false otherwise.
+*/
+
+/*!
+ \fn bool operator==(const QFixedPt<PrecBits>& v1, qreal v2)
+ \relates QFixedPt
+
+ Returns true if \a v1 is equal to \a v2; false otherwise.
+*/
+
+/*!
+ \fn bool operator==(qreal v1, const QFixedPt<PrecBits>& v2)
+ \relates QFixedPt
+
+ Returns true if \a v1 is equal to \a v2; false otherwise.
+*/
+
+/*!
+ \fn bool QFixedPt::operator!=(const QFixedPt<PrecBits>& value) const
+
+ Returns true if this fixed-point number is not equal to \a value;
+ false otherwise.
+*/
+
+/*!
+ \fn bool operator!=(const QFixedPt<PrecBits>& v1, int v2)
+ \relates QFixedPt
+
+ Returns true if \a v1 is not equal to \a v2; false otherwise.
+*/
+
+/*!
+ \fn bool operator!=(int v1, const QFixedPt<PrecBits>& v2)
+ \relates QFixedPt
+
+ Returns true if \a v1 is not equal to \a v2; false otherwise.
+*/
+
+/*!
+ \fn bool operator!=(const QFixedPt<PrecBits>& v1, qreal v2)
+ \relates QFixedPt
+
+ Returns true if \a v1 is not equal to \a v2; false otherwise.
+*/
+
+/*!
+ \fn bool operator!=(qreal v1, const QFixedPt<PrecBits>& v2)
+ \relates QFixedPt
+
+ Returns true if \a v1 is not equal to \a v2; false otherwise.
+*/
+
+/*!
+ \fn bool QFixedPt::operator<=(const QFixedPt<PrecBits>& value) const
+
+ Returns true if this fixed-point number is less than or equal to
+ \a value; false otherwise.
+*/
+
+/*!
+ \fn bool operator<=(const QFixedPt<PrecBits>& v1, int v2)
+ \relates QFixedPt
+
+ Returns true if \a v1 is less than or equal to \a v2; false otherwise.
+*/
+
+/*!
+ \fn bool operator<=(int v1, const QFixedPt<PrecBits>& v2)
+ \relates QFixedPt
+
+ Returns true if \a v1 is less than or equal to \a v2; false otherwise.
+*/
+
+/*!
+ \fn bool operator<=(const QFixedPt<PrecBits>& v1, qreal v2)
+ \relates QFixedPt
+
+ Returns true if \a v1 is less than or equal to \a v2; false otherwise.
+*/
+
+/*!
+ \fn bool operator<=(qreal v1, const QFixedPt<PrecBits>& v2)
+ \relates QFixedPt
+
+ Returns true if \a v1 is less than or equal to \a v2; false otherwise.
+*/
+
+/*!
+ \fn bool QFixedPt::operator<(const QFixedPt<PrecBits>& value) const
+
+ Returns true if this fixed-point number is less than \a value;
+ false otherwise.
+*/
+
+/*!
+ \fn bool operator<(const QFixedPt<PrecBits>& v1, int v2)
+ \relates QFixedPt
+
+ Returns true if \a v1 is less than \a v2; false otherwise.
+*/
+
+/*!
+ \fn bool operator<(int v1, const QFixedPt<PrecBits>& v2)
+ \relates QFixedPt
+
+ Returns true if \a v1 is less than \a v2; false otherwise.
+*/
+
+/*!
+ \fn bool operator<(const QFixedPt<PrecBits>& v1, qreal v2)
+ \relates QFixedPt
+
+ Returns true if \a v1 is less than \a v2; false otherwise.
+*/
+
+/*!
+ \fn bool operator<(qreal v1, const QFixedPt<PrecBits>& v2)
+ \relates QFixedPt
+
+ Returns true if \a v1 is less than \a v2; false otherwise.
+*/
+
+/*!
+ \fn bool QFixedPt::operator>=(const QFixedPt<PrecBits>& value) const
+
+ Returns true if this fixed-point number is greater than or equal to
+ \a value; false otherwise.
+*/
+
+/*!
+ \fn bool operator>=(const QFixedPt<PrecBits>& v1, int v2)
+ \relates QFixedPt
+
+ Returns true if \a v1 is greater than or equal to \a v2; false otherwise.
+*/
+
+/*!
+ \fn bool operator>=(int v1, const QFixedPt<PrecBits>& v2)
+ \relates QFixedPt
+
+ Returns true if \a v1 is greater than or equal to \a v2; false otherwise.
+*/
+
+/*!
+ \fn bool operator>=(const QFixedPt<PrecBits>& v1, qreal v2)
+ \relates QFixedPt
+
+ Returns true if \a v1 is greater than or equal to \a v2; false otherwise.
+*/
+
+/*!
+ \fn bool operator>=(qreal v1, const QFixedPt<PrecBits>& v2)
+ \relates QFixedPt
+
+ Returns true if \a v1 is greater than or equal to \a v2; false otherwise.
+*/
+
+/*!
+ \fn bool QFixedPt::operator>(const QFixedPt<PrecBits>& value) const
+
+ Returns true if this fixed-point number is greater than \a value;
+ false otherwise.
+*/
+
+/*!
+ \fn bool operator>(const QFixedPt<PrecBits>& v1, int v2)
+ \relates QFixedPt
+
+ Returns true if \a v1 is greater than \a v2; false otherwise.
+*/
+
+/*!
+ \fn bool operator>(int v1, const QFixedPt<PrecBits>& v2)
+ \relates QFixedPt
+
+ Returns true if \a v1 is greater than \a v2; false otherwise.
+*/
+
+/*!
+ \fn bool operator>(const QFixedPt<PrecBits>& v1, qreal v2)
+ \relates QFixedPt
+
+ Returns true if \a v1 is greater than \a v2; false otherwise.
+*/
+
+/*!
+ \fn bool operator>(qreal v1, const QFixedPt<PrecBits>& v2)
+ \relates QFixedPt
+
+ Returns true if \a v1 is greater than \a v2; false otherwise.
+*/
+
+/*!
+ \fn QFixedPt<PrecBits> QFixedPt::operator+(const QFixedPt<PrecBits>& value) const
+
+ Returns the result of adding this fixed-point number and \a value.
+*/
+
+/*!
+ \fn QFixedPt<PrecBits> QFixedPt::operator+(int value) const
+
+ Returns the result of adding this fixed-point number and \a value.
+*/
+
+/*!
+ \fn QFixedPt<PrecBits> QFixedPt::operator+(qreal value) const
+
+ Returns the result of adding this fixed-point number and \a value.
+*/
+
+/*!
+ \fn QFixedPt<PrecBits> operator+(int v1, const QFixedPt<PrecBits>& v2)
+ \relates QFixedPt
+
+ Returns the result of adding \a v1 and \a v2.
+*/
+
+/*!
+ \fn QFixedPt<PrecBits> operator+(qreal v1, const QFixedPt<PrecBits>& v2)
+ \relates QFixedPt
+
+ Returns the result of adding \a v1 and \a v2.
+*/
+
+/*!
+ \fn QFixedPt<PrecBits> QFixedPt::operator-(const QFixedPt<PrecBits>& value) const
+
+ Returns the result of subtracting \a value from this fixed-point number.
+*/
+
+/*!
+ \fn QFixedPt<PrecBits> QFixedPt::operator-(int value) const
+
+ Returns the result of subtracting \a value from this fixed-point number.
+*/
+
+/*!
+ \fn QFixedPt<PrecBits> QFixedPt::operator-(qreal value) const
+
+ Returns the result of subtracting \a value from this fixed-point number.
+*/
+
+/*!
+ \fn QFixedPt<PrecBits> operator-(int v1, const QFixedPt<PrecBits>& v2)
+ \relates QFixedPt
+
+ Returns the result of subtracting \a v2 from \a v1.
+*/
+
+/*!
+ \fn QFixedPt<PrecBits> operator-(qreal v1, const QFixedPt<PrecBits>& v2)
+ \relates QFixedPt
+
+ Returns the result of subtracting \a v2 from \a v1.
+*/
+
+/*!
+ \fn QFixedPt<PrecBits> QFixedPt::operator*(const QFixedPt<PrecBits>& value) const
+
+ Returns the result of multiplying this fixed-point number by \a value.
+*/
+
+/*!
+ \fn QFixedPt<PrecBits> QFixedPt::operator*(int value) const
+
+ Returns the result of multiplying this fixed-point number by \a value.
+*/
+
+/*!
+ \fn QFixedPt<PrecBits> QFixedPt::operator*(qreal value) const
+
+ Returns the result of multiplying this fixed-point number by \a value.
+*/
+
+/*!
+ \fn QFixedPt<PrecBits> operator*(int v1, const QFixedPt<PrecBits>& v2)
+ \relates QFixedPt
+
+ Returns the result of multiplying \a v1 by \a v2.
+*/
+
+/*!
+ \fn QFixedPt<PrecBits> operator*(qreal v1, const QFixedPt<PrecBits>& v2)
+ \relates QFixedPt
+
+ Returns the result of multiplying \a v1 by \a v2.
+*/
+
+/*!
+ \fn QFixedPt<PrecBits> QFixedPt::operator/(const QFixedPt<PrecBits>& value) const
+
+ Returns the result of dividing this fixed-point number by \a value.
+ Division by zero will result in zero.
+*/
+
+/*!
+ \fn QFixedPt<PrecBits> QFixedPt::operator/(int value) const
+
+ Returns the result of dividing this fixed-point number by \a value.
+ Division by zero will result in zero.
+*/
+
+/*!
+ \fn QFixedPt<PrecBits> QFixedPt::operator/(qreal value) const
+
+ Returns the result of dividing this fixed-point number by \a value.
+ Division by zero will result in zero.
+*/
+
+/*!
+ \fn QFixedPt<PrecBits> operator/(int v1, const QFixedPt<PrecBits>& v2)
+ \relates QFixedPt
+
+ Returns the result of dividing \a v1 by \a v2. Division by zero will
+ result in zero.
+*/
+
+/*!
+ \fn QFixedPt<PrecBits> operator/(qreal v1, const QFixedPt<PrecBits>& v2)
+ \relates QFixedPt
+
+ Returns the result of dividing \a v1 by \a v2. Division by zero will
+ result in zero.
+*/
+
+/*!
+ \fn QFixedPt<PrecBits> QFixedPt::operator-() const
+
+ Returns the negation of this fixed-point number.
+*/
+
+/*!
+ \fn QFixedPt<PrecBits> QFixedPt::sqrt() const
+
+ Returns the square root of this fixed-point number.
+
+ \sa sqrtF()
+*/
+
+/*!
+ \fn qreal QFixedPt::sqrtF() const
+
+ Return the square root of this fixed-point number as a
+ floating-point value.
+
+ \sa sqrt()
+*/
+
+/*!
+ \fn QFixedPt<PrecBits> QFixedPt::round() const
+
+ Returns this fixed-point number, rounded to the nearest integer.
+
+ \sa floor(), ceil(), truncate()
+*/
+
+/*!
+ \fn QFixedPt<PrecBits> QFixedPt::floor() const;
+
+ Returns the largest integer that is less than or equal to
+ this fixed-point number.
+
+ \sa round(), ceil(), truncate()
+*/
+
+/*!
+ \fn QFixedPt<PrecBits> QFixedPt::ceil() const
+
+ Returns the smallest integer that is greater than or equal to
+ this fixed-point number.
+
+ \sa round(), floor(), truncate()
+*/
+
+/*!
+ \fn int QFixedPt::truncate() const
+
+ Returns this fixed-point number with the bits after the
+ decimal point truncated.
+
+ \sa round(), floor(), ceil()
+*/
+
+/*!
+ \fn int QFixedPt::toInt() const
+
+ Returns this fixed-point number, rounded to the nearest integer.
+
+ \sa toReal()
+*/
+
+/*!
+ \fn qreal QFixedPt::toReal() const
+
+ Returns this fixed-point number as a floating-point value.
+
+ \sa toInt()
+*/
+
+/*!
+ \fn int qCeil(const QFixedPt<PrecBits>& value)
+ \relates QFixedPt
+
+ Returns the smallest integer that is greater than or equal to
+ \a value.
+
+ \sa qFloor(), qRound(), QFixedPt::ceil()
+*/
+
+/*!
+ \fn int qFloor(const QFixedPt<PrecBits>& value)
+ \relates QFixedPt
+
+ Returns the largest integer that is less than or equal to
+ \a value.
+
+ \sa qCeil(), qRound(), QFixedPt::floor()
+*/
+
+/*!
+ \fn int qRound(const QFixedPt<PrecBits>& value)
+ \relates QFixedPt
+
+ Returns \a value, rounded to the nearest integer.
+
+ \sa qCeil(), qFloor(), QFixedPt::round()
+*/
+
+/*!
+ \fn bool qFuzzyCompare(const QFixedPt<PrecBits>& v1, const QFixedPt<PrecBits>& v2, int compareBits)
+ \relates QFixedPt
+
+ Returns true if \a v1 is almost equal to \a v2; false otherwise.
+ The \a compareBits parameter specifies the number of bits of precision
+ that should be considered relevant when performing the comparison.
+ By default, \a compareBits is PrecBits / 4.
+*/
+
+/*!
+ \fn bool qIsNull(const QFixedPt<PrecBits>& v)
+ \relates QFixedPt
+
+ Returns true if \a v is zero; false otherwise.
+*/
+
+QT_END_NAMESPACE
diff --git a/src/gui/math3d/qfixedpt.h b/src/gui/math3d/qfixedpt.h
new file mode 100644
index 0000000..ecbcad4
--- /dev/null
+++ b/src/gui/math3d/qfixedpt.h
@@ -0,0 +1,521 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFIXEDPT_H
+#define QFIXEDPT_H
+
+#include <QtCore/qglobal.h>
+#include <QtCore/qdebug.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+Q_GUI_EXPORT qint64 qt_math3d_fixed_sqrt(qint64 value);
+
+// Should be called QFixed or QFixedPoint, but both of those
+// are already in use in src/gui/painting/qfixed_p.h.
+template <int PrecBits>
+class QFixedPt
+{
+public:
+ inline QFixedPt() {} // Deliberately not initialized - don't change this.
+ inline QFixedPt(int value) : val(value << PrecBits) {}
+ inline QFixedPt(qreal value) : val(int(value * (1 << PrecBits))) {}
+
+ inline QFixedPt<PrecBits>& operator=(int value)
+ { val = value << PrecBits; return *this; }
+ inline QFixedPt<PrecBits>& operator=(qreal value)
+ { val = int(value * (1 << PrecBits)); return *this; }
+
+ inline int bits() const { return val; }
+ inline void setBits(int value) { val = value; }
+
+#if !defined(QT_NO_MEMBER_TEMPLATES) || defined(Q_QDOC)
+ template <int Prec>
+ inline QFixedPt<Prec> toPrecision() const
+ {
+ QFixedPt<Prec> result;
+ if (Prec < PrecBits)
+ result.setBits(shiftRight(val, (PrecBits - Prec)));
+ else
+ result.setBits(shiftLeft(val, (Prec - PrecBits)));
+ return result;
+ }
+#endif
+
+ inline QFixedPt<PrecBits>& operator+=(const QFixedPt<PrecBits>& value)
+ { val += value.val; return *this; }
+ inline QFixedPt<PrecBits>& operator+=(int value)
+ { val += (value << PrecBits); return *this; }
+ inline QFixedPt<PrecBits>& operator+=(qreal value)
+ { val += int(value * (1 << PrecBits)); return *this; }
+
+ inline QFixedPt<PrecBits>& operator-=(const QFixedPt<PrecBits>& value)
+ { val -= value.val; return *this; }
+ inline QFixedPt<PrecBits>& operator-=(int value)
+ { val -= (value << PrecBits); return *this; }
+ inline QFixedPt<PrecBits>& operator-=(qreal value)
+ { val -= int(value * (1 << PrecBits)); return *this; }
+
+ inline QFixedPt<PrecBits>& operator*=(const QFixedPt<PrecBits>& value)
+ { val = mul(val, value.val); return *this; }
+ inline QFixedPt<PrecBits>& operator*=(int value)
+ { val = mul(val, (value << PrecBits)); return *this; }
+ inline QFixedPt<PrecBits>& operator*=(qreal value)
+ { val = mul(val, int(value * (1 << PrecBits))); return *this; }
+
+ inline QFixedPt<PrecBits>& operator/=(const QFixedPt<PrecBits>& value)
+ { val = div(val, value.val); return *this; }
+ inline QFixedPt<PrecBits>& operator/=(int value)
+ { val = div(val, (value << PrecBits)); return *this; }
+ inline QFixedPt<PrecBits>& operator/=(qreal value)
+ { val = div(val, int(value * (1 << PrecBits))); return *this; }
+
+ inline QFixedPt<PrecBits>& operator<<=(int value)
+ { val <<= value; return *this; }
+ inline QFixedPt<PrecBits>& operator>>=(int value)
+ { val >>= value; return *this; }
+
+ inline QFixedPt<PrecBits> operator<<(int value) const
+ { QFixedPt<PrecBits> result; result.val = val << value; return result; }
+ inline QFixedPt<PrecBits> operator>>(int value) const
+ { QFixedPt<PrecBits> result; result.val = val >> value; return result; }
+
+ inline bool operator==(const QFixedPt<PrecBits>& value) const
+ { return val == value.val; }
+ inline bool operator!=(const QFixedPt<PrecBits>& value) const
+ { return val != value.val; }
+ inline bool operator<=(const QFixedPt<PrecBits>& value) const
+ { return val <= value.val; }
+ inline bool operator<(const QFixedPt<PrecBits>& value) const
+ { return val < value.val; }
+ inline bool operator>=(const QFixedPt<PrecBits>& value) const
+ { return val >= value.val; }
+ inline bool operator>(const QFixedPt<PrecBits>& value) const
+ { return val > value.val; }
+
+ inline QFixedPt<PrecBits> operator+(const QFixedPt<PrecBits>& value) const
+ { QFixedPt<PrecBits> result;
+ result.val = val + value.val; return result; }
+ inline QFixedPt<PrecBits> operator+(int value) const
+ { QFixedPt<PrecBits> result;
+ result.val = val + (value << PrecBits); return result; }
+ inline QFixedPt<PrecBits> operator+(qreal value) const
+ { QFixedPt<PrecBits> result;
+ result.val = val + int(value * (1 << PrecBits)); return result; }
+
+ inline QFixedPt<PrecBits> operator-(const QFixedPt<PrecBits>& value) const
+ { QFixedPt<PrecBits> result;
+ result.val = val - value.val; return result; }
+ inline QFixedPt<PrecBits> operator-(int value) const
+ { QFixedPt<PrecBits> result;
+ result.val = val - (value << PrecBits); return result; }
+ inline QFixedPt<PrecBits> operator-(qreal value) const
+ { QFixedPt<PrecBits> result;
+ result.val = val - int(value * (1 << PrecBits)); return result; }
+
+ inline QFixedPt<PrecBits> operator*(const QFixedPt<PrecBits>& value) const
+ { QFixedPt<PrecBits> result;
+ result.val = mul(val, value.val); return result; }
+ inline QFixedPt<PrecBits> operator*(int value) const
+ { QFixedPt<PrecBits> result;
+ result.val = mul(val, (value << PrecBits)); return result; }
+ inline QFixedPt<PrecBits> operator*(qreal value) const
+ { QFixedPt<PrecBits> result;
+ result.val = mul(val, int(value * (1 << PrecBits))); return result; }
+
+ inline QFixedPt<PrecBits> operator/(const QFixedPt<PrecBits>& value) const
+ { QFixedPt<PrecBits> result;
+ result.val = div(val, value.val); return result; }
+ inline QFixedPt<PrecBits> operator/(int value) const
+ { QFixedPt<PrecBits> result;
+ result.val = div(val, (value << PrecBits)); return result; }
+ inline QFixedPt<PrecBits> operator/(qreal value) const
+ { QFixedPt<PrecBits> result;
+ result.val = div(val, int(value * (1 << PrecBits))); return result; }
+
+ inline QFixedPt<PrecBits> operator-() const
+ { QFixedPt<PrecBits> result; result.val = -val; return result; }
+
+ inline QFixedPt<PrecBits> sqrt() const;
+ inline qreal sqrtF() const;
+ inline QFixedPt<PrecBits> round() const;
+ inline QFixedPt<PrecBits> floor() const;
+ inline QFixedPt<PrecBits> ceil() const;
+ inline int truncate() const { return val >> PrecBits; }
+
+ inline int toInt() const { return (val + (1 << (PrecBits - 1))) >> PrecBits; }
+ inline qreal toReal() const { return qreal(val) / qreal(1 << PrecBits); }
+
+#if !defined(Q_NO_TEMPLATE_FRIENDS)
+ template <int Prec>
+ friend QFixedPt<Prec> operator/(int v1, const QFixedPt<Prec>& v2);
+ template <int Prec>
+ friend QFixedPt<Prec> operator/(qreal v1, const QFixedPt<Prec>& v2);
+
+private:
+#endif
+ int val;
+
+ inline static int mul(int v1, int v2)
+ {
+ return int((qint64(v1) * qint64(v2)) >> PrecBits);
+ }
+
+ inline static int div(int v1, int v2)
+ {
+ if (v2)
+ return int((qint64(v1) << PrecBits) / qint64(v2));
+ else
+ return 0;
+ }
+
+ // These are used by toPrecision() to avoid a silly gcc compiler warning
+ // related to negative shift values that will never actually be used.
+ inline static int shiftRight(int val, int shift)
+ {
+ return val >> shift;
+ }
+ inline static int shiftLeft(int val, int shift)
+ {
+ return val << shift;
+ }
+
+#if !defined(Q_NO_TEMPLATE_FRIENDS)
+ template <int Prec, int Prec2>
+ friend QFixedPt<Prec> qFixedPtToPrecision(const QFixedPt<Prec2>& value);
+#endif
+};
+
+template <int PrecBits>
+inline bool operator==(const QFixedPt<PrecBits>& v1, int v2)
+{
+ return v1.bits() == (v2 << PrecBits);
+}
+
+template <int PrecBits>
+inline bool operator==(int v1, const QFixedPt<PrecBits>& v2)
+{
+ return (v1 << PrecBits) == v2.bits();
+}
+
+template <int PrecBits>
+inline bool operator==(const QFixedPt<PrecBits>& v1, qreal v2)
+{
+ return v1.bits() == int(v2 * (1 << PrecBits));
+}
+
+template <int PrecBits>
+inline bool operator==(qreal v1, const QFixedPt<PrecBits>& v2)
+{
+ return int(v1 * (1 << PrecBits)) == v2.bits();
+}
+
+template <int PrecBits>
+inline bool operator!=(const QFixedPt<PrecBits>& v1, int v2)
+{
+ return v1.bits() != (v2 << PrecBits);
+}
+
+template <int PrecBits>
+inline bool operator!=(int v1, const QFixedPt<PrecBits>& v2)
+{
+ return (v1 << PrecBits) != v2.bits();
+}
+
+template <int PrecBits>
+inline bool operator!=(const QFixedPt<PrecBits>& v1, qreal v2)
+{
+ return v1.bits() != int(v2 * (1 << PrecBits));
+}
+
+template <int PrecBits>
+inline bool operator!=(qreal v1, const QFixedPt<PrecBits>& v2)
+{
+ return int(v1 * (1 << PrecBits)) != v2.bits();
+}
+
+template <int PrecBits>
+inline bool operator<=(const QFixedPt<PrecBits>& v1, int v2)
+{
+ return v1.bits() <= (v2 << PrecBits);
+}
+
+template <int PrecBits>
+inline bool operator<=(int v1, const QFixedPt<PrecBits>& v2)
+{
+ return (v1 << PrecBits) <= v2.bits();
+}
+
+template <int PrecBits>
+inline bool operator<=(const QFixedPt<PrecBits>& v1, qreal v2)
+{
+ return v1.bits() <= int(v2 * (1 << PrecBits));
+}
+
+template <int PrecBits>
+inline bool operator<=(qreal v1, const QFixedPt<PrecBits>& v2)
+{
+ return int(v1 * (1 << PrecBits)) <= v2.bits();
+}
+
+template <int PrecBits>
+inline bool operator<(const QFixedPt<PrecBits>& v1, int v2)
+{
+ return v1.bits() < (v2 << PrecBits);
+}
+
+template <int PrecBits>
+inline bool operator<(int v1, const QFixedPt<PrecBits>& v2)
+{
+ return (v1 << PrecBits) < v2.bits();
+}
+
+template <int PrecBits>
+inline bool operator<(const QFixedPt<PrecBits>& v1, qreal v2)
+{
+ return v1.bits() < int(v2 * (1 << PrecBits));
+}
+
+template <int PrecBits>
+inline bool operator<(qreal v1, const QFixedPt<PrecBits>& v2)
+{
+ return int(v1 * (1 << PrecBits)) < v2.bits();
+}
+
+template <int PrecBits>
+inline bool operator>=(const QFixedPt<PrecBits>& v1, int v2)
+{
+ return v1.bits() >= (v2 << PrecBits);
+}
+
+template <int PrecBits>
+inline bool operator>=(int v1, const QFixedPt<PrecBits>& v2)
+{
+ return (v1 << PrecBits) >= v2.bits();
+}
+
+template <int PrecBits>
+inline bool operator>=(const QFixedPt<PrecBits>& v1, qreal v2)
+{
+ return v1.bits() >= int(v2 * (1 << PrecBits));
+}
+
+template <int PrecBits>
+inline bool operator>=(qreal v1, const QFixedPt<PrecBits>& v2)
+{
+ return int(v1 * (1 << PrecBits)) >= v2.bits();
+}
+
+template <int PrecBits>
+inline bool operator>(const QFixedPt<PrecBits>& v1, int v2)
+{
+ return v1.bits() > (v2 << PrecBits);
+}
+
+template <int PrecBits>
+inline bool operator>(int v1, const QFixedPt<PrecBits>& v2)
+{
+ return (v1 << PrecBits) > v2.bits();
+}
+
+template <int PrecBits>
+inline bool operator>(const QFixedPt<PrecBits>& v1, qreal v2)
+{
+ return v1.bits() > int(v2 * (1 << PrecBits));
+}
+
+template <int PrecBits>
+inline bool operator>(qreal v1, const QFixedPt<PrecBits>& v2)
+{
+ return int(v1 * (1 << PrecBits)) > v2.bits();
+}
+
+template <int PrecBits>
+inline QFixedPt<PrecBits> operator+(int v1, const QFixedPt<PrecBits>& v2)
+{
+ return v2 + v1;
+}
+
+template <int PrecBits>
+inline QFixedPt<PrecBits> operator+(qreal v1, const QFixedPt<PrecBits>& v2)
+{
+ return v2 + v1;
+}
+
+template <int PrecBits>
+inline QFixedPt<PrecBits> operator-(int v1, const QFixedPt<PrecBits>& v2)
+{
+ return -(v2 - v1);
+}
+
+template <int PrecBits>
+inline QFixedPt<PrecBits> operator-(qreal v1, const QFixedPt<PrecBits>& v2)
+{
+ return -(v2 - v1);
+}
+
+template <int PrecBits>
+inline QFixedPt<PrecBits> operator*(int v1, const QFixedPt<PrecBits>& v2)
+{
+ return v2 * v1;
+}
+
+template <int PrecBits>
+inline QFixedPt<PrecBits> operator*(qreal v1, const QFixedPt<PrecBits>& v2)
+{
+ return v2 * v1;
+}
+
+template <int PrecBits>
+inline QFixedPt<PrecBits> operator/(int v1, const QFixedPt<PrecBits>& v2)
+{
+ QFixedPt<PrecBits> result;
+ result.val = QFixedPt<PrecBits>::div(v1 << PrecBits, v2.val);
+ return result;
+}
+
+template <int PrecBits>
+inline QFixedPt<PrecBits> operator/(qreal v1, const QFixedPt<PrecBits>& v2)
+{
+ QFixedPt<PrecBits> result;
+ result.val = QFixedPt<PrecBits>::div(int(v1 * (1 << PrecBits)), v2.val);
+ return result;
+}
+
+template <int PrecBits>
+inline QFixedPt<PrecBits> QFixedPt<PrecBits>::sqrt() const
+{
+ QFixedPt<PrecBits> result;
+ result.val = int(qt_math3d_fixed_sqrt
+ (qint64(val) << (PrecBits * 2)) >> (PrecBits / 2));
+ return result;
+}
+
+template <int PrecBits>
+inline qreal QFixedPt<PrecBits>::sqrtF() const
+{
+ return qt_math3d_fixed_sqrt
+ (qint64(val) << (PrecBits * 2)) / (qreal)(1 << (PrecBits + (PrecBits / 2)));
+}
+
+template <int PrecBits>
+inline QFixedPt<PrecBits> QFixedPt<PrecBits>::round() const
+{
+ QFixedPt<PrecBits> result;
+ result.val = (val + (1 << (PrecBits - 1))) & ~((1 << PrecBits) - 1);
+ return result;
+}
+
+template <int PrecBits>
+inline QFixedPt<PrecBits> QFixedPt<PrecBits>::floor() const
+{
+ QFixedPt<PrecBits> result;
+ result.val = val & ~((1 << PrecBits) - 1);
+ return result;
+}
+
+template <int PrecBits>
+inline QFixedPt<PrecBits> QFixedPt<PrecBits>::ceil() const
+{
+ QFixedPt<PrecBits> result;
+ result.val = (val + (1 << PrecBits) - 1) & ~((1 << PrecBits) - 1);
+ return result;
+}
+
+template <int PrecBits>
+inline int qCeil(const QFixedPt<PrecBits>& value)
+{
+ return value.ceil().bits() >> PrecBits;
+}
+
+template <int PrecBits>
+inline int qFloor(const QFixedPt<PrecBits>& value)
+{
+ return value.floor().bits() >> PrecBits;
+}
+
+template <int PrecBits>
+inline int qRound(const QFixedPt<PrecBits>& value)
+{
+ return value.round().bits() >> PrecBits;
+}
+
+template <int PrecBits>
+inline bool qFuzzyCompare(const QFixedPt<PrecBits>& v1, const QFixedPt<PrecBits>& v2, int compareBits = (PrecBits / 4))
+{
+ return ((v1.bits() ^ v2.bits()) & ~((1 << compareBits) - 1)) == 0;
+}
+
+template <int PrecBits>
+inline bool qIsNull(const QFixedPt<PrecBits>& v)
+{
+ return v.bits() == 0;
+}
+
+template <int Prec, int PrecBits>
+QFixedPt<Prec> qFixedPtToPrecision(const QFixedPt<PrecBits>& value)
+{
+ QFixedPt<Prec> result;
+ if (Prec < PrecBits)
+ result.setBits(QFixedPt<PrecBits>::shiftRight(value.bits(), (PrecBits - Prec)));
+ else
+ result.setBits(QFixedPt<PrecBits>::shiftLeft(value.bits(), (Prec - PrecBits)));
+ return result;
+}
+
+template <int PrecBits>
+inline QDebug &operator<<(QDebug &dbg, const QFixedPt<PrecBits> &f)
+{
+ return dbg << f.toReal();
+}
+
+Q_DECLARE_TYPEINFO(QFixedPt<0>, Q_PRIMITIVE_TYPE);
+Q_DECLARE_TYPEINFO(QFixedPt<1>, Q_PRIMITIVE_TYPE);
+Q_DECLARE_TYPEINFO(QFixedPt<2>, Q_PRIMITIVE_TYPE);
+Q_DECLARE_TYPEINFO(QFixedPt<3>, Q_PRIMITIVE_TYPE);
+Q_DECLARE_TYPEINFO(QFixedPt<4>, Q_PRIMITIVE_TYPE);
+Q_DECLARE_TYPEINFO(QFixedPt<5>, Q_PRIMITIVE_TYPE);
+Q_DECLARE_TYPEINFO(QFixedPt<6>, Q_PRIMITIVE_TYPE);
+Q_DECLARE_TYPEINFO(QFixedPt<7>, Q_PRIMITIVE_TYPE);
+Q_DECLARE_TYPEINFO(QFixedPt<8>, Q_PRIMITIVE_TYPE);
+Q_DECLARE_TYPEINFO(QFixedPt<9>, Q_PRIMITIVE_TYPE);
+Q_DECLARE_TYPEINFO(QFixedPt<10>, Q_PRIMITIVE_TYPE);
+Q_DECLARE_TYPEINFO(QFixedPt<11>, Q_PRIMITIVE_TYPE);
+Q_DECLARE_TYPEINFO(QFixedPt<12>, Q_PRIMITIVE_TYPE);
+Q_DECLARE_TYPEINFO(QFixedPt<13>, Q_PRIMITIVE_TYPE);
+Q_DECLARE_TYPEINFO(QFixedPt<14>, Q_PRIMITIVE_TYPE);
+Q_DECLARE_TYPEINFO(QFixedPt<15>, Q_PRIMITIVE_TYPE);
+Q_DECLARE_TYPEINFO(QFixedPt<16>, Q_PRIMITIVE_TYPE);
+Q_DECLARE_TYPEINFO(QFixedPt<17>, Q_PRIMITIVE_TYPE);
+Q_DECLARE_TYPEINFO(QFixedPt<18>, Q_PRIMITIVE_TYPE);
+Q_DECLARE_TYPEINFO(QFixedPt<19>, Q_PRIMITIVE_TYPE);
+Q_DECLARE_TYPEINFO(QFixedPt<20>, Q_PRIMITIVE_TYPE);
+Q_DECLARE_TYPEINFO(QFixedPt<21>, Q_PRIMITIVE_TYPE);
+Q_DECLARE_TYPEINFO(QFixedPt<22>, Q_PRIMITIVE_TYPE);
+Q_DECLARE_TYPEINFO(QFixedPt<23>, Q_PRIMITIVE_TYPE);
+Q_DECLARE_TYPEINFO(QFixedPt<24>, Q_PRIMITIVE_TYPE);
+Q_DECLARE_TYPEINFO(QFixedPt<25>, Q_PRIMITIVE_TYPE);
+Q_DECLARE_TYPEINFO(QFixedPt<26>, Q_PRIMITIVE_TYPE);
+Q_DECLARE_TYPEINFO(QFixedPt<27>, Q_PRIMITIVE_TYPE);
+Q_DECLARE_TYPEINFO(QFixedPt<28>, Q_PRIMITIVE_TYPE);
+Q_DECLARE_TYPEINFO(QFixedPt<29>, Q_PRIMITIVE_TYPE);
+Q_DECLARE_TYPEINFO(QFixedPt<30>, Q_PRIMITIVE_TYPE);
+Q_DECLARE_TYPEINFO(QFixedPt<31>, Q_PRIMITIVE_TYPE);
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/gui/math3d/qgenericmatrix.cpp b/src/gui/math3d/qgenericmatrix.cpp
new file mode 100644
index 0000000..cb48909
--- /dev/null
+++ b/src/gui/math3d/qgenericmatrix.cpp
@@ -0,0 +1,221 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qgenericmatrix.h"
+
+QT_BEGIN_NAMESPACE
+
+/*!
+ \class QGenericMatrix
+ \brief The QGenericMatrix class is a template class that represents a NxM transformation matrix with N columns and M rows.
+ \since 4.6
+
+ The QGenericMatrix template has four parameters:
+
+ \table
+ \row \i N \i Number of columns.
+ \row \i M \i Number of rows.
+ \row \i T \i Element type that is visible to users of the class.
+ \row \i InnerT \i Element type that is used inside the class.
+ \endtable
+
+ Normally T and InnerT are the same type; e.g. float or double.
+ But they can be different if the user wants to store elements
+ internally in a fixed-point format for the underlying hardware.
+
+ \sa QMatrix4x4, QFixedPt
+*/
+
+/*!
+ \fn QGenericMatrix::QGenericMatrix()
+
+ Constructs a NxM identity matrix.
+*/
+
+/*!
+ \fn QGenericMatrix::QGenericMatrix(const QGenericMatrix<N, M, T, InnerT>& other)
+
+ Constructs a copy of \a other.
+*/
+
+/*!
+ \fn QGenericMatrix::QGenericMatrix(const T *values)
+
+ Constructs a matrix from the given N * M floating-point \a values.
+ The contents of the array \a values is assumed to be in
+ row-major order.
+
+ \sa toValueArray()
+*/
+
+/*!
+ \fn T QGenericMatrix::operator()(int row, int column) const
+
+ Returns the element at position (\a row, \a column) in this matrix.
+*/
+
+/*!
+ \fn InnerT& QGenericMatrix::operator()(int row, int column)
+
+ Returns a reference to the element at position (\a row, \a column)
+ in this matrix so that the element can be assigned to.
+*/
+
+/*!
+ \fn bool QGenericMatrix::isIdentity() const
+
+ Returns true if this matrix is the identity; false otherwise.
+
+ \sa setIdentity()
+*/
+
+/*!
+ \fn void QGenericMatrix::setIdentity()
+
+ Sets this matrix to the identity.
+
+ \sa isIdentity()
+*/
+
+/*!
+ \fn void QGenericMatrix::fill(qreal value)
+
+ Fills all elements of this matrix with \a value.
+*/
+
+/*!
+ \fn QGenericMatrix<M, N> QGenericMatrix::transposed() const
+
+ Returns this matrix, transposed about its diagonal.
+*/
+
+/*!
+ \fn QGenericMatrix<N, M, T, InnerT>& QGenericMatrix::operator+=(const QGenericMatrix<N, M, T, InnerT>& other)
+
+ Adds the contents of \a other to this matrix.
+*/
+
+/*!
+ \fn QGenericMatrix<N, M, T, InnerT>& QGenericMatrix::operator-=(const QGenericMatrix<N, M, T, InnerT>& other)
+
+ Subtracts the contents of \a other from this matrix.
+*/
+
+/*!
+ \fn QGenericMatrix<N, M, T, InnerT>& QGenericMatrix::operator*=(T factor)
+
+ Multiplies all elements of this matrix by \a factor.
+*/
+
+/*!
+ \fn QGenericMatrix<N, M, T, InnerT>& QGenericMatrix::operator/=(T divisor)
+
+ Divides all elements of this matrix by \a divisor.
+*/
+
+/*!
+ \fn bool QGenericMatrix::operator==(const QGenericMatrix<N, M, T, InnerT>& other) const
+
+ Returns true if this matrix is identical to \a other; false otherwise.
+*/
+
+/*!
+ \fn bool QGenericMatrix::operator!=(const QGenericMatrix<N, M, T, InnerT>& other) const
+
+ Returns true if this matrix is not identical to \a other; false otherwise.
+*/
+
+/*!
+ \fn QGenericMatrix<N, M, T, InnerT> operator+(const QGenericMatrix<N, M, T, InnerT>& m1, const QGenericMatrix<N, M, T, InnerT>& m2)
+ \relates QGenericMatrix
+
+ Returns the sum of \a m1 and \a m2.
+*/
+
+/*!
+ \fn QGenericMatrix<N, M, T, InnerT> operator-(const QGenericMatrix<N, M, T, InnerT>& m1, const QGenericMatrix<N, M, T, InnerT>& m2)
+ \relates QGenericMatrix
+
+ Returns the difference of \a m1 and \a m2.
+*/
+
+/*!
+ \fn QGenericMatrix<M1, M2, T, InnerT> operator*(const QGenericMatrix<N, M2, T, InnerT>& m1, const QGenericMatrix<M1, N, T, InnerT>& m2)
+ \relates QGenericMatrix
+
+ Returns the product of the NxM2 matrix \a m1 and the M1xN matrix \a m2
+ to produce a M1xM2 matrix result.
+*/
+
+/*!
+ \fn QGenericMatrix<N, M, T, InnerT> operator-(const QGenericMatrix<N, M, T, InnerT>& matrix)
+ \overload
+ \relates QGenericMatrix
+
+ Returns the negation of \a matrix.
+*/
+
+/*!
+ \fn QGenericMatrix<N, M, T, InnerT> operator*(T factor, const QGenericMatrix<N, M, T, InnerT>& matrix)
+ \relates QGenericMatrix
+
+ Returns the result of multiplying all elements of \a matrix by \a factor.
+*/
+
+/*!
+ \fn QGenericMatrix<N, M, T, InnerT> operator*(const QGenericMatrix<N, M, T, InnerT>& matrix, T factor)
+ \relates QGenericMatrix
+
+ Returns the result of multiplying all elements of \a matrix by \a factor.
+*/
+
+/*!
+ \fn QGenericMatrix<N, M, T, InnerT> operator/(const QGenericMatrix<N, M, T, InnerT>& matrix, T divisor)
+ \relates QGenericMatrix
+
+ Returns the result of dividing all elements of \a matrix by \a divisor.
+*/
+
+/*!
+ \fn void QGenericMatrix::toValueArray(T *values)
+
+ Retrieves the N * M items in this matrix and writes them to \a values
+ in row-major order.
+*/
+
+/*!
+ \fn InnerT *QGenericMatrix::data()
+
+ Returns a pointer to the raw data of this matrix. This is indended
+ for use with raw GL functions.
+
+ \sa constData()
+*/
+
+/*!
+ \fn const InnerT *QGenericMatrix::data() const
+
+ Returns a constant pointer to the raw data of this matrix.
+ This is indended for use with raw GL functions.
+
+ \sa constData()
+*/
+
+/*!
+ \fn const InnerT *QGenericMatrix::constData() const
+
+ Returns a constant pointer to the raw data of this matrix.
+ This is indended for use with raw GL functions.
+
+ \sa data()
+*/
+
+QT_END_NAMESPACE
diff --git a/src/gui/math3d/qgenericmatrix.h b/src/gui/math3d/qgenericmatrix.h
new file mode 100644
index 0000000..26a0e48
--- /dev/null
+++ b/src/gui/math3d/qgenericmatrix.h
@@ -0,0 +1,341 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QGENERICMATRIX_H
+#define QGENERICMATRIX_H
+
+#include <QtGui/qmath3dglobal.h>
+#include <QtCore/qmetatype.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+template <int N, int M, typename T, typename InnerT = T>
+class QGenericMatrix
+{
+public:
+ QGenericMatrix();
+ QGenericMatrix(const QGenericMatrix<N, M, T, InnerT>& other);
+ explicit QGenericMatrix(const T *values);
+
+ T operator()(int row, int column) const;
+ InnerT& operator()(int row, int column);
+
+ bool isIdentity() const;
+ void setIdentity();
+
+ void fill(qreal value);
+
+ QGenericMatrix<M, N, T, InnerT> transposed() const;
+
+ QGenericMatrix<N, M, T, InnerT>& operator+=(const QGenericMatrix<N, M, T, InnerT>& other);
+ QGenericMatrix<N, M, T, InnerT>& operator-=(const QGenericMatrix<N, M, T, InnerT>& other);
+ QGenericMatrix<N, M, T, InnerT>& operator*=(T factor);
+ QGenericMatrix<N, M, T, InnerT>& operator/=(T divisor);
+ bool operator==(const QGenericMatrix<N, M, T, InnerT>& other) const;
+ bool operator!=(const QGenericMatrix<N, M, T, InnerT>& other) const;
+
+ void toValueArray(T *values);
+
+ InnerT *data() { return m[0]; }
+ const InnerT *data() const { return m[0]; }
+ const InnerT *constData() const { return m[0]; }
+
+#if !defined(Q_NO_TEMPLATE_FRIENDS)
+ template<int NN, int MM, typename TT, typename ITT>
+ friend QGenericMatrix<NN, MM, TT, ITT> operator+(const QGenericMatrix<NN, MM, TT, ITT>& m1, const QGenericMatrix<NN, MM, TT, ITT>& m2);
+ template<int NN, int MM, typename TT, typename ITT>
+ friend QGenericMatrix<NN, MM, TT, ITT> operator-(const QGenericMatrix<NN, MM, TT, ITT>& m1, const QGenericMatrix<NN, MM, TT, ITT>& m2);
+ template<int NN, int M1, int M2, typename TT, typename ITT>
+ friend QGenericMatrix<M1, M2, TT, ITT> operator*(const QGenericMatrix<NN, M2, TT, ITT>& m1, const QGenericMatrix<M1, NN, TT, ITT>& m2);
+ template<int NN, int MM, typename TT, typename ITT>
+ friend QGenericMatrix<NN, MM, TT, ITT> operator-(const QGenericMatrix<NN, MM, TT, ITT>& matrix);
+ template<int NN, int MM, typename TT, typename ITT>
+ friend QGenericMatrix<NN, MM, TT, ITT> operator*(TT factor, const QGenericMatrix<NN, MM, TT, ITT>& matrix);
+ template<int NN, int MM, typename TT, typename ITT>
+ friend QGenericMatrix<NN, MM, TT, ITT> operator*(const QGenericMatrix<NN, MM, TT, ITT>& matrix, TT factor);
+ template<int NN, int MM, typename TT, typename ITT>
+ friend QGenericMatrix<NN, MM, TT, ITT> operator/(const QGenericMatrix<NN, MM, TT, ITT>& matrix, TT divisor);
+
+private:
+#endif
+ InnerT m[N][M]; // Column-major order to match OpenGL.
+
+ QGenericMatrix(int) {} // Construct without initializing identity matrix.
+
+#if !defined(Q_NO_TEMPLATE_FRIENDS)
+ template <int NN, int MM, typename TT, typename ITT>
+ friend class QGenericMatrix;
+#endif
+};
+
+template <int N, int M, typename T, typename InnerT>
+Q_INLINE_TEMPLATE QGenericMatrix<N, M, T, InnerT>::QGenericMatrix()
+{
+ setIdentity();
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_INLINE_TEMPLATE QGenericMatrix<N, M, T, InnerT>::QGenericMatrix(const QGenericMatrix<N, M, T, InnerT>& other)
+{
+ qMemCopy(m, other.m, sizeof(m));
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE QGenericMatrix<N, M, T, InnerT>::QGenericMatrix(const T *values)
+{
+ for (int col = 0; col < N; ++col)
+ for (int row = 0; row < M; ++row)
+ m[col][row] = values[row * N + col];
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_INLINE_TEMPLATE T QGenericMatrix<N, M, T, InnerT>::operator()(int row, int column) const
+{
+ Q_ASSERT(row >= 0 && row < M && column >= 0 && column < N);
+ return qt_math3d_convert<T, InnerT>(m[column][row]);
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_INLINE_TEMPLATE InnerT& QGenericMatrix<N, M, T, InnerT>::operator()(int row, int column)
+{
+ Q_ASSERT(row >= 0 && row < M && column >= 0 && column < N);
+ return m[column][row];
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE bool QGenericMatrix<N, M, T, InnerT>::isIdentity() const
+{
+ for (int col = 0; col < N; ++col) {
+ for (int row = 0; row < M; ++row) {
+ if (row == col) {
+ if (m[col][row] != 1.0f)
+ return false;
+ } else {
+ if (m[col][row] != 0.0f)
+ return false;
+ }
+ }
+ }
+ return true;
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE void QGenericMatrix<N, M, T, InnerT>::setIdentity()
+{
+ for (int col = 0; col < N; ++col) {
+ for (int row = 0; row < M; ++row) {
+ if (row == col)
+ m[col][row] = 1.0f;
+ else
+ m[col][row] = 0.0f;
+ }
+ }
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE void QGenericMatrix<N, M, T, InnerT>::fill(qreal value)
+{
+ for (int col = 0; col < N; ++col)
+ for (int row = 0; row < M; ++row)
+ m[col][row] = value;
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE QGenericMatrix<M, N, T, InnerT> QGenericMatrix<N, M, T, InnerT>::transposed() const
+{
+ QGenericMatrix<M, N, T, InnerT> result(1);
+ for (int row = 0; row < M; ++row)
+ for (int col = 0; col < N; ++col)
+ result.m[row][col] = m[col][row];
+ return result;
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE QGenericMatrix<N, M, T, InnerT>& QGenericMatrix<N, M, T, InnerT>::operator+=(const QGenericMatrix<N, M, T, InnerT>& other)
+{
+ for (int index = 0; index < N * M; ++index)
+ m[0][index] += other.m[0][index];
+ return *this;
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE QGenericMatrix<N, M, T, InnerT>& QGenericMatrix<N, M, T, InnerT>::operator-=(const QGenericMatrix<N, M, T, InnerT>& other)
+{
+ for (int index = 0; index < N * M; ++index)
+ m[0][index] -= other.m[0][index];
+ return *this;
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE QGenericMatrix<N, M, T, InnerT>& QGenericMatrix<N, M, T, InnerT>::operator*=(T factor)
+{
+ InnerT f(factor);
+ for (int index = 0; index < N * M; ++index)
+ m[0][index] *= f;
+ return *this;
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE bool QGenericMatrix<N, M, T, InnerT>::operator==(const QGenericMatrix<N, M, T, InnerT>& other) const
+{
+ for (int index = 0; index < N * M; ++index) {
+ if (m[0][index] != other.m[0][index])
+ return false;
+ }
+ return true;
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE bool QGenericMatrix<N, M, T, InnerT>::operator!=(const QGenericMatrix<N, M, T, InnerT>& other) const
+{
+ for (int index = 0; index < N * M; ++index) {
+ if (m[0][index] != other.m[0][index])
+ return true;
+ }
+ return false;
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE QGenericMatrix<N, M, T, InnerT>& QGenericMatrix<N, M, T, InnerT>::operator/=(T divisor)
+{
+ InnerT d(divisor);
+ for (int index = 0; index < N * M; ++index)
+ m[0][index] /= d;
+ return *this;
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE QGenericMatrix<N, M, T, InnerT> operator+(const QGenericMatrix<N, M, T, InnerT>& m1, const QGenericMatrix<N, M, T, InnerT>& m2)
+{
+ QGenericMatrix<N, M, T, InnerT> result(1);
+ for (int index = 0; index < N * M; ++index)
+ result.m[0][index] = m1.m[0][index] + m2.m[0][index];
+ return result;
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE QGenericMatrix<N, M, T, InnerT> operator-(const QGenericMatrix<N, M, T, InnerT>& m1, const QGenericMatrix<N, M, T, InnerT>& m2)
+{
+ QGenericMatrix<N, M, T, InnerT> result(1);
+ for (int index = 0; index < N * M; ++index)
+ result.m[0][index] = m1.m[0][index] - m2.m[0][index];
+ return result;
+}
+
+template <int N, int M1, int M2, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE QGenericMatrix<M1, M2, T, InnerT> operator*(const QGenericMatrix<N, M2, T, InnerT>& m1, const QGenericMatrix<M1, N, T, InnerT>& m2)
+{
+ QGenericMatrix<M1, M2, T, InnerT> result(1);
+ for (int row = 0; row < M2; ++row) {
+ for (int col = 0; col < M1; ++col) {
+ InnerT sum(0.0f);
+ for (int j = 0; j < N; ++j)
+ sum += m1.m[j][row] * m2.m[col][j];
+ result.m[col][row] = sum;
+ }
+ }
+ return result;
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE QGenericMatrix<N, M, T, InnerT> operator-(const QGenericMatrix<N, M, T, InnerT>& matrix)
+{
+ QGenericMatrix<N, M, T, InnerT> result(1);
+ for (int index = 0; index < N * M; ++index)
+ result.m[0][index] = -matrix.m[0][index];
+ return result;
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE QGenericMatrix<N, M, T, InnerT> operator*(T factor, const QGenericMatrix<N, M, T, InnerT>& matrix)
+{
+ InnerT f(factor);
+ QGenericMatrix<N, M, T, InnerT> result(1);
+ for (int index = 0; index < N * M; ++index)
+ result.m[0][index] = matrix.m[0][index] * f;
+ return result;
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE QGenericMatrix<N, M, T, InnerT> operator*(const QGenericMatrix<N, M, T, InnerT>& matrix, T factor)
+{
+ InnerT f(factor);
+ QGenericMatrix<N, M, T, InnerT> result(1);
+ for (int index = 0; index < N * M; ++index)
+ result.m[0][index] = matrix.m[0][index] * f;
+ return result;
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE QGenericMatrix<N, M, T, InnerT> operator/(const QGenericMatrix<N, M, T, InnerT>& matrix, T divisor)
+{
+ InnerT d(divisor);
+ QGenericMatrix<N, M, T, InnerT> result(1);
+ for (int index = 0; index < N * M; ++index)
+ result.m[0][index] = matrix.m[0][index] / d;
+ return result;
+}
+
+template <int N, int M, typename T, typename InnerT>
+Q_OUTOFLINE_TEMPLATE void QGenericMatrix<N, M, T, InnerT>::toValueArray(T *values)
+{
+ for (int col = 0; col < N; ++col)
+ for (int row = 0; row < M; ++row)
+ values[row * N + col] = qt_math3d_convert<T, InnerT>(m[col][row]);
+}
+
+// Define aliases for the useful variants of QGenericMatrix.
+typedef QGenericMatrix<2, 2, qreal, qrealinner> QMatrix2x2;
+typedef QGenericMatrix<2, 3, qreal, qrealinner> QMatrix2x3;
+typedef QGenericMatrix<2, 4, qreal, qrealinner> QMatrix2x4;
+typedef QGenericMatrix<3, 2, qreal, qrealinner> QMatrix3x2;
+typedef QGenericMatrix<3, 3, qreal, qrealinner> QMatrix3x3;
+typedef QGenericMatrix<3, 4, qreal, qrealinner> QMatrix3x4;
+typedef QGenericMatrix<4, 2, qreal, qrealinner> QMatrix4x2;
+typedef QGenericMatrix<4, 3, qreal, qrealinner> QMatrix4x3;
+
+#ifndef QT_NO_DEBUG_STREAM
+
+template <int N, int M, typename T, typename InnerT>
+QDebug operator<<(QDebug dbg, const QGenericMatrix<N, M, T, InnerT> &m)
+{
+ dbg.nospace() << "QGenericMatrix<" << N << ", " << M
+ << ", " << QTypeInfo<T>::name() << ", " << QTypeInfo<InnerT>::name()
+ << ">(" << endl << qSetFieldWidth(10);
+ for (int row = 0; row < M; ++row) {
+ for (int col = 0; col < N; ++col)
+ dbg << m(row, col);
+ dbg << endl;
+ }
+ dbg << qSetFieldWidth(0) << ')';
+ return dbg.space();
+}
+
+#endif
+
+QT_END_NAMESPACE
+
+Q_DECLARE_METATYPE(QMatrix2x2)
+Q_DECLARE_METATYPE(QMatrix2x3)
+Q_DECLARE_METATYPE(QMatrix2x4)
+Q_DECLARE_METATYPE(QMatrix3x2)
+Q_DECLARE_METATYPE(QMatrix3x3)
+Q_DECLARE_METATYPE(QMatrix3x4)
+Q_DECLARE_METATYPE(QMatrix4x2)
+Q_DECLARE_METATYPE(QMatrix4x3)
+
+QT_END_HEADER
+
+#endif
diff --git a/src/gui/math3d/qmath3dglobal.h b/src/gui/math3d/qmath3dglobal.h
new file mode 100644
index 0000000..ee5e734
--- /dev/null
+++ b/src/gui/math3d/qmath3dglobal.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMATH3DGLOBAL_H
+#define QMATH3DGLOBAL_H
+
+#include <QtCore/qglobal.h>
+#include <QtGui/qfixedpt.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+// Detect the presence of a fixed-point OpenGL implementation.
+#if defined(QT_OPENGL_ES_1_CL) || defined(QT_NO_GL_FLOAT)
+#ifndef QT_GL_FIXED_PREFERRED
+#define QT_GL_FIXED_PREFERRED 1
+#endif
+#endif
+
+// QT_GL_FIXED_PREFERRED indicates that fixed-point should be
+// preferred over floating-point for operations requiring high performance.
+//
+// qreal is the floating-point type that should be used in
+// user-visible functions. qrealinner is used internally where
+// values may be stored as either floating-point or fixed-point.
+// qrealinner will typically be the same size as GLfloat or GLfixed.
+#if defined(QT_GL_FIXED_PREFERRED)
+typedef QFixedPt<16> qrealinner;
+#else
+typedef float qrealinner;
+#endif
+
+// Explicit conversion operator, primarily for converting from
+// fixed point back to floating-point. This is safer than
+// declaring conversion operators in the QFixedPt class.
+template <typename T1, typename T2>
+T1 qt_math3d_convert(T2 v)
+{
+ return T1(v);
+}
+template <>
+inline float qt_math3d_convert< float, QFixedPt<16> >(QFixedPt<16> v)
+{
+ return float(v.toReal());
+}
+template <>
+inline double qt_math3d_convert< double, QFixedPt<16> >(QFixedPt<16> v)
+{
+ return double(v.toReal());
+}
+template <>
+inline int qt_math3d_convert< int, QFixedPt<16> >(QFixedPt<16> v)
+{
+ return v.toInt();
+}
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif
diff --git a/src/gui/math3d/qmath3dutil.cpp b/src/gui/math3d/qmath3dutil.cpp
new file mode 100644
index 0000000..91d4b15
--- /dev/null
+++ b/src/gui/math3d/qmath3dutil.cpp
@@ -0,0 +1,164 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qmath3dutil_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifdef QT_GL_FIXED_PREFERRED
+
+// The table that follows was automatically generated by the following code:
+//
+//#include <math.h>
+//#include <stdio.h>
+//
+//int main()
+//{
+// double angle;
+// int count = 0;
+// for (angle = 0.0; angle < 360.0; angle += 1.0) {
+// if ((count % 4) == 0)
+// printf(" ");
+// printf(" qf2vt(%f)", sin(angle * M_PI / 180.0));
+// ++count;
+// if (count != 360)
+// printf(",");
+// if ((count % 4) == 0)
+// printf("\n");
+// }
+// return 0;
+//}
+
+#define qf2vt(x) (int((x) * 65536.0))
+
+static int const sinTable[360] = {
+ qf2vt(0.000000), qf2vt(0.017452), qf2vt(0.034899), qf2vt(0.052336),
+ qf2vt(0.069756), qf2vt(0.087156), qf2vt(0.104528), qf2vt(0.121869),
+ qf2vt(0.139173), qf2vt(0.156434), qf2vt(0.173648), qf2vt(0.190809),
+ qf2vt(0.207912), qf2vt(0.224951), qf2vt(0.241922), qf2vt(0.258819),
+ qf2vt(0.275637), qf2vt(0.292372), qf2vt(0.309017), qf2vt(0.325568),
+ qf2vt(0.342020), qf2vt(0.358368), qf2vt(0.374607), qf2vt(0.390731),
+ qf2vt(0.406737), qf2vt(0.422618), qf2vt(0.438371), qf2vt(0.453990),
+ qf2vt(0.469472), qf2vt(0.484810), qf2vt(0.500000), qf2vt(0.515038),
+ qf2vt(0.529919), qf2vt(0.544639), qf2vt(0.559193), qf2vt(0.573576),
+ qf2vt(0.587785), qf2vt(0.601815), qf2vt(0.615661), qf2vt(0.629320),
+ qf2vt(0.642788), qf2vt(0.656059), qf2vt(0.669131), qf2vt(0.681998),
+ qf2vt(0.694658), qf2vt(0.707107), qf2vt(0.719340), qf2vt(0.731354),
+ qf2vt(0.743145), qf2vt(0.754710), qf2vt(0.766044), qf2vt(0.777146),
+ qf2vt(0.788011), qf2vt(0.798636), qf2vt(0.809017), qf2vt(0.819152),
+ qf2vt(0.829038), qf2vt(0.838671), qf2vt(0.848048), qf2vt(0.857167),
+ qf2vt(0.866025), qf2vt(0.874620), qf2vt(0.882948), qf2vt(0.891007),
+ qf2vt(0.898794), qf2vt(0.906308), qf2vt(0.913545), qf2vt(0.920505),
+ qf2vt(0.927184), qf2vt(0.933580), qf2vt(0.939693), qf2vt(0.945519),
+ qf2vt(0.951057), qf2vt(0.956305), qf2vt(0.961262), qf2vt(0.965926),
+ qf2vt(0.970296), qf2vt(0.974370), qf2vt(0.978148), qf2vt(0.981627),
+ qf2vt(0.984808), qf2vt(0.987688), qf2vt(0.990268), qf2vt(0.992546),
+ qf2vt(0.994522), qf2vt(0.996195), qf2vt(0.997564), qf2vt(0.998630),
+ qf2vt(0.999391), qf2vt(0.999848), qf2vt(1.000000), qf2vt(0.999848),
+ qf2vt(0.999391), qf2vt(0.998630), qf2vt(0.997564), qf2vt(0.996195),
+ qf2vt(0.994522), qf2vt(0.992546), qf2vt(0.990268), qf2vt(0.987688),
+ qf2vt(0.984808), qf2vt(0.981627), qf2vt(0.978148), qf2vt(0.974370),
+ qf2vt(0.970296), qf2vt(0.965926), qf2vt(0.961262), qf2vt(0.956305),
+ qf2vt(0.951057), qf2vt(0.945519), qf2vt(0.939693), qf2vt(0.933580),
+ qf2vt(0.927184), qf2vt(0.920505), qf2vt(0.913545), qf2vt(0.906308),
+ qf2vt(0.898794), qf2vt(0.891007), qf2vt(0.882948), qf2vt(0.874620),
+ qf2vt(0.866025), qf2vt(0.857167), qf2vt(0.848048), qf2vt(0.838671),
+ qf2vt(0.829038), qf2vt(0.819152), qf2vt(0.809017), qf2vt(0.798636),
+ qf2vt(0.788011), qf2vt(0.777146), qf2vt(0.766044), qf2vt(0.754710),
+ qf2vt(0.743145), qf2vt(0.731354), qf2vt(0.719340), qf2vt(0.707107),
+ qf2vt(0.694658), qf2vt(0.681998), qf2vt(0.669131), qf2vt(0.656059),
+ qf2vt(0.642788), qf2vt(0.629320), qf2vt(0.615661), qf2vt(0.601815),
+ qf2vt(0.587785), qf2vt(0.573576), qf2vt(0.559193), qf2vt(0.544639),
+ qf2vt(0.529919), qf2vt(0.515038), qf2vt(0.500000), qf2vt(0.484810),
+ qf2vt(0.469472), qf2vt(0.453990), qf2vt(0.438371), qf2vt(0.422618),
+ qf2vt(0.406737), qf2vt(0.390731), qf2vt(0.374607), qf2vt(0.358368),
+ qf2vt(0.342020), qf2vt(0.325568), qf2vt(0.309017), qf2vt(0.292372),
+ qf2vt(0.275637), qf2vt(0.258819), qf2vt(0.241922), qf2vt(0.224951),
+ qf2vt(0.207912), qf2vt(0.190809), qf2vt(0.173648), qf2vt(0.156434),
+ qf2vt(0.139173), qf2vt(0.121869), qf2vt(0.104528), qf2vt(0.087156),
+ qf2vt(0.069756), qf2vt(0.052336), qf2vt(0.034899), qf2vt(0.017452),
+ qf2vt(0.000000), qf2vt(-0.017452), qf2vt(-0.034899), qf2vt(-0.052336),
+ qf2vt(-0.069756), qf2vt(-0.087156), qf2vt(-0.104528), qf2vt(-0.121869),
+ qf2vt(-0.139173), qf2vt(-0.156434), qf2vt(-0.173648), qf2vt(-0.190809),
+ qf2vt(-0.207912), qf2vt(-0.224951), qf2vt(-0.241922), qf2vt(-0.258819),
+ qf2vt(-0.275637), qf2vt(-0.292372), qf2vt(-0.309017), qf2vt(-0.325568),
+ qf2vt(-0.342020), qf2vt(-0.358368), qf2vt(-0.374607), qf2vt(-0.390731),
+ qf2vt(-0.406737), qf2vt(-0.422618), qf2vt(-0.438371), qf2vt(-0.453990),
+ qf2vt(-0.469472), qf2vt(-0.484810), qf2vt(-0.500000), qf2vt(-0.515038),
+ qf2vt(-0.529919), qf2vt(-0.544639), qf2vt(-0.559193), qf2vt(-0.573576),
+ qf2vt(-0.587785), qf2vt(-0.601815), qf2vt(-0.615661), qf2vt(-0.629320),
+ qf2vt(-0.642788), qf2vt(-0.656059), qf2vt(-0.669131), qf2vt(-0.681998),
+ qf2vt(-0.694658), qf2vt(-0.707107), qf2vt(-0.719340), qf2vt(-0.731354),
+ qf2vt(-0.743145), qf2vt(-0.754710), qf2vt(-0.766044), qf2vt(-0.777146),
+ qf2vt(-0.788011), qf2vt(-0.798636), qf2vt(-0.809017), qf2vt(-0.819152),
+ qf2vt(-0.829038), qf2vt(-0.838671), qf2vt(-0.848048), qf2vt(-0.857167),
+ qf2vt(-0.866025), qf2vt(-0.874620), qf2vt(-0.882948), qf2vt(-0.891007),
+ qf2vt(-0.898794), qf2vt(-0.906308), qf2vt(-0.913545), qf2vt(-0.920505),
+ qf2vt(-0.927184), qf2vt(-0.933580), qf2vt(-0.939693), qf2vt(-0.945519),
+ qf2vt(-0.951057), qf2vt(-0.956305), qf2vt(-0.961262), qf2vt(-0.965926),
+ qf2vt(-0.970296), qf2vt(-0.974370), qf2vt(-0.978148), qf2vt(-0.981627),
+ qf2vt(-0.984808), qf2vt(-0.987688), qf2vt(-0.990268), qf2vt(-0.992546),
+ qf2vt(-0.994522), qf2vt(-0.996195), qf2vt(-0.997564), qf2vt(-0.998630),
+ qf2vt(-0.999391), qf2vt(-0.999848), qf2vt(-1.000000), qf2vt(-0.999848),
+ qf2vt(-0.999391), qf2vt(-0.998630), qf2vt(-0.997564), qf2vt(-0.996195),
+ qf2vt(-0.994522), qf2vt(-0.992546), qf2vt(-0.990268), qf2vt(-0.987688),
+ qf2vt(-0.984808), qf2vt(-0.981627), qf2vt(-0.978148), qf2vt(-0.974370),
+ qf2vt(-0.970296), qf2vt(-0.965926), qf2vt(-0.961262), qf2vt(-0.956305),
+ qf2vt(-0.951057), qf2vt(-0.945519), qf2vt(-0.939693), qf2vt(-0.933580),
+ qf2vt(-0.927184), qf2vt(-0.920505), qf2vt(-0.913545), qf2vt(-0.906308),
+ qf2vt(-0.898794), qf2vt(-0.891007), qf2vt(-0.882948), qf2vt(-0.874620),
+ qf2vt(-0.866025), qf2vt(-0.857167), qf2vt(-0.848048), qf2vt(-0.838671),
+ qf2vt(-0.829038), qf2vt(-0.819152), qf2vt(-0.809017), qf2vt(-0.798636),
+ qf2vt(-0.788011), qf2vt(-0.777146), qf2vt(-0.766044), qf2vt(-0.754710),
+ qf2vt(-0.743145), qf2vt(-0.731354), qf2vt(-0.719340), qf2vt(-0.707107),
+ qf2vt(-0.694658), qf2vt(-0.681998), qf2vt(-0.669131), qf2vt(-0.656059),
+ qf2vt(-0.642788), qf2vt(-0.629320), qf2vt(-0.615661), qf2vt(-0.601815),
+ qf2vt(-0.587785), qf2vt(-0.573576), qf2vt(-0.559193), qf2vt(-0.544639),
+ qf2vt(-0.529919), qf2vt(-0.515038), qf2vt(-0.500000), qf2vt(-0.484810),
+ qf2vt(-0.469472), qf2vt(-0.453990), qf2vt(-0.438371), qf2vt(-0.422618),
+ qf2vt(-0.406737), qf2vt(-0.390731), qf2vt(-0.374607), qf2vt(-0.358368),
+ qf2vt(-0.342020), qf2vt(-0.325568), qf2vt(-0.309017), qf2vt(-0.292372),
+ qf2vt(-0.275637), qf2vt(-0.258819), qf2vt(-0.241922), qf2vt(-0.224951),
+ qf2vt(-0.207912), qf2vt(-0.190809), qf2vt(-0.173648), qf2vt(-0.156434),
+ qf2vt(-0.139173), qf2vt(-0.121869), qf2vt(-0.104528), qf2vt(-0.087156),
+ qf2vt(-0.069756), qf2vt(-0.052336), qf2vt(-0.034899), qf2vt(-0.017452)
+};
+
+void qt_math3d_sincos(qreal angle, qrealinner *s, qrealinner *c)
+{
+ if (angle == qFloor(angle)) {
+ // The angle is an integer number of degrees, so look up the results.
+ int a = (int)angle;
+ if (a >= 0)
+ a = (a % 360);
+ else
+ a = 360 - (-a % 360);
+ s->setBits(sinTable[a]);
+ c->setBits(sinTable[(a + 90) % 360]);
+ } else {
+ qreal a = angle * M_PI / 180.0f;
+ *s = qSin(a);
+ *c = qCos(a);
+ }
+}
+
+#else
+
+void qt_math3d_sincos(qreal angle, qrealinner *s, qrealinner *c)
+{
+ qreal a = angle * M_PI / 180.0f;
+ *s = qSin(a);
+ *c = qCos(a);
+}
+
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/gui/math3d/qmath3dutil_p.h b/src/gui/math3d/qmath3dutil_p.h
new file mode 100644
index 0000000..1cb0bb9
--- /dev/null
+++ b/src/gui/math3d/qmath3dutil_p.h
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMATH3DUTIL_P_H
+#define QMATH3DUTIL_P_H
+
+#include <QtGui/qmath3dglobal.h>
+#include <QtCore/qmath.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifdef QT_GL_FIXED_PREFERRED
+#define qvtsqrt(x) ((x).sqrtF())
+#else
+#define qvtsqrt(x) qSqrt((x))
+#endif
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+
+void qt_math3d_sincos(qreal degrees, qrealinner *s, qrealinner *c);
+
+#ifdef QT_GL_FIXED_PREFERRED
+
+inline qrealinner qf2vt_round(qreal x)
+{
+ QFixedPt<16> result;
+ if (x >= 0.0f)
+ result.setBits(int(x * 65536.0f + 0.5f));
+ else
+ result.setBits(int(x * 65536.0f - 0.5f));
+ return result;
+}
+
+// Helper macros for computing dot products without losing precision.
+// In fixed-point mode, a 64-bit intermediate result is used.
+#define qvtmul64(x,y) ((qint64((x).bits())) * (qint64((y).bits())))
+#define qvtsqrt64(x) \
+ (qt_math3d_fixed_sqrt((x) << 16) / (qreal)(1 << 24))
+#define qvtdot64(x) ((x) / (qreal)(((qint64)1) << 32))
+
+#else
+
+inline qrealinner qf2vt_round(qreal x)
+{
+ return x;
+}
+
+#define qvtmul64(x,y) ((x) * (y))
+#define qvtsqrt64(x) (qvtsqrt((x)))
+#define qvtdot64(x) ((x))
+
+#endif
+
+QT_END_NAMESPACE
+
+#endif
diff --git a/src/gui/math3d/qmatrix4x4.cpp b/src/gui/math3d/qmatrix4x4.cpp
new file mode 100644
index 0000000..9941ca8
--- /dev/null
+++ b/src/gui/math3d/qmatrix4x4.cpp
@@ -0,0 +1,1649 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qmatrix4x4.h"
+#include "qmath3dutil_p.h"
+#include <QtCore/qmath.h>
+#include <QtGui/qmatrix.h>
+#include <QtGui/qtransform.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_MATRIX4X4
+
+/*!
+ \class QMatrix4x4
+ \brief The QMatrix4x4 class represents a 4x4 transformation matrix in 3D space.
+ \since 4.6
+
+ The matrix elements are stored internally using the most efficient
+ numeric representation for the underlying hardware: floating-point
+ or fixed-point.
+
+ \sa QVector3D, QGenericMatrix
+*/
+
+/*!
+ \fn QMatrix4x4::QMatrix4x4()
+
+ Constructs an identity matrix.
+*/
+
+/*!
+ Constructs a matrix from the given 16 floating-point \a values.
+ The contents of the array \a values is assumed to be in
+ row-major order.
+
+ If the matrix has a special type (identity, translate, scale, etc),
+ the programmer should follow this constructor with a call to
+ inferSpecialType() if they wish QMatrix4x4 to optimize further
+ calls to translate(), scale(), etc.
+
+ \sa toValueArray(), inferSpecialType()
+*/
+QMatrix4x4::QMatrix4x4(const qreal *values)
+{
+ for (int row = 0; row < 4; ++row)
+ for (int col = 0; col < 4; ++col)
+ m[col][row] = values[row * 4 + col];
+ flagBits = General;
+}
+
+/*!
+ \fn QMatrix4x4::QMatrix4x4(qreal m11, qreal m12, qreal m13, qreal m14, qreal m21, qreal m22, qreal m23, qreal m24, qreal m31, qreal m32, qreal m33, qreal m34, qreal m41, qreal m42, qreal m43, qreal m44)
+
+ Constructs a matrix from the 16 elements \a m11, \a m12, \a m13, \a m14,
+ \a m21, \a m22, \a m23, \a m24, \a m31, \a m32, \a m33, \a m34,
+ \a m41, \a m42, \a m43, and \a m44. The elements are specified in
+ row-major order.
+
+ If the matrix has a special type (identity, translate, scale, etc),
+ the programmer should follow this constructor with a call to
+ inferSpecialType() if they wish QMatrix4x4 to optimize further
+ calls to translate(), scale(), etc.
+
+ \sa inferSpecialType()
+*/
+
+#if !defined(QT_NO_MEMBER_TEMPLATES) || defined(Q_QDOC)
+
+/*!
+ \fn QMatrix4x4::QMatrix4x4(const QGenericMatrix<N, M, qreal, qrealinner>& matrix)
+
+ Constructs a 4x4 matrix from the left-most 4 columns and top-most
+ 4 rows of \a matrix. If \a matrix has less than 4 columns or rows,
+ the remaining elements are filled with elements from the identity
+ matrix.
+
+ \sa toGenericMatrix(), qGenericMatrixToMatrix4x4()
+*/
+
+/*!
+ \fn QGenericMatrix<N, M, qreal, qrealinner> QMatrix4x4::toGenericMatrix() const
+
+ Constructs a NxM generic matrix from the left-most N columns and
+ top-most M rows of this 4x4 matrix. If N or M is greater than 4,
+ then the remaining elements are filled with elements from the
+ identity matrix.
+
+ \sa qGenericMatrixFromMatrix4x4()
+*/
+
+#endif
+
+/*!
+ \fn QMatrix4x4 qGenericMatrixToMatrix4x4(const QGenericMatrix<N, M, qreal, qrealinner>& matrix)
+ \relates QMatrix4x4
+
+ Returns a 4x4 matrix constructed from the left-most 4 columns and
+ top-most 4 rows of \a matrix. If \a matrix has less than 4 columns
+ or rows, the remaining elements are filled with elements from the
+ identity matrix.
+
+ \sa qGenericMatrixFromMatrix4x4()
+*/
+
+/*!
+ \fn QGenericMatrix<N, M, qreal, qrealinner> qGenericMatrixFromMatrix4x4(const QMatrix4x4& matrix)
+ \relates QMatrix4x4
+
+ Returns a NxM generic matrix constructed from the left-most N columns
+ and top-most M rows of \a matrix. If N or M is greater than 4,
+ then the remaining elements are filled with elements from the
+ identity matrix.
+
+ \sa qGenericMatrixToMatrix4x4(), QMatrix4x4::toGenericMatrix()
+*/
+
+/*!
+ \internal
+*/
+QMatrix4x4::QMatrix4x4(const qrealinner *values, int cols, int rows)
+{
+ for (int col = 0; col < 4; ++col) {
+ for (int row = 0; row < 4; ++row) {
+ if (col < cols && row < rows)
+ m[col][row] = values[col * rows + row];
+ else if (col == row)
+ m[col][row] = 1.0f;
+ else
+ m[col][row] = 0.0f;
+ }
+ }
+ flagBits = General;
+}
+
+/*!
+ Constructs a 4x4 matrix from a conventional Qt 2D affine
+ transformation \a matrix.
+
+ If \a matrix has a special type (identity, translate, scale, etc),
+ the programmer should follow this constructor with a call to
+ inferSpecialType() if they wish QMatrix4x4 to optimize further
+ calls to translate(), scale(), etc.
+
+ \sa toAffine(), inferSpecialType()
+*/
+QMatrix4x4::QMatrix4x4(const QMatrix& matrix)
+{
+ m[0][0] = matrix.m11();
+ m[0][1] = matrix.m12();
+ m[0][2] = 0.0f;
+ m[0][3] = 0.0f;
+ m[1][0] = matrix.m21();
+ m[1][1] = matrix.m22();
+ m[1][2] = 0.0f;
+ m[1][3] = 0.0f;
+ m[2][0] = 0.0f;
+ m[2][1] = 0.0f;
+ m[2][2] = 1.0f;
+ m[2][3] = 0.0f;
+ m[3][0] = matrix.dx();
+ m[3][1] = matrix.dy();
+ m[3][2] = 0.0f;
+ m[3][3] = 1.0f;
+ flagBits = General;
+}
+
+/*!
+ Constructs a 4x4 matrix from the conventional Qt 2D
+ transformation matrix \a transform.
+
+ If \a transform has a special type (identity, translate, scale, etc),
+ the programmer should follow this constructor with a call to
+ inferSpecialType() if they wish QMatrix4x4 to optimize further
+ calls to translate(), scale(), etc.
+
+ \sa toTransform(), inferSpecialType()
+*/
+QMatrix4x4::QMatrix4x4(const QTransform& transform)
+{
+ m[0][0] = transform.m11();
+ m[0][1] = transform.m12();
+ m[0][2] = 0.0f;
+ m[0][3] = transform.m13();
+ m[1][0] = transform.m21();
+ m[1][1] = transform.m22();
+ m[1][2] = 0.0f;
+ m[1][3] = transform.m23();
+ m[2][0] = 0.0f;
+ m[2][1] = 0.0f;
+ m[2][2] = 1.0f;
+ m[2][3] = 0.0f;
+ m[3][0] = transform.dx();
+ m[3][1] = transform.dy();
+ m[3][2] = 0.0f;
+ m[3][3] = transform.m33();
+ flagBits = General;
+}
+
+/*!
+ \fn qreal QMatrix4x4::operator()(int row, int column) const
+
+ Returns the element at position (\a row, \a column) in this matrix.
+
+ \sa column(), row()
+*/
+
+/*!
+ \fn qrealinner& QMatrix4x4::operator()(int row, int column)
+
+ Returns a reference to the element at position (\a row, \a column)
+ in this matrix so that the element can be assigned to.
+
+ \sa inferSpecialType(), setColumn(), setRow()
+*/
+
+/*!
+ \fn QVector4D QMatrix4x4::column(int index) const
+
+ Returns the elements of column \a index as a 4D vector.
+
+ \sa setColumn(), row()
+*/
+
+/*!
+ \fn void QMatrix4x4::setColumn(int index, const QVector4D& value)
+
+ Sets the elements of column \a index to the components of \a value.
+
+ \sa column(), setRow()
+*/
+
+/*!
+ \fn QVector4D QMatrix4x4::row(int index) const
+
+ Returns the elements of row \a index as a 4D vector.
+
+ \sa setRow(), column()
+*/
+
+/*!
+ \fn void QMatrix4x4::setRow(int index, const QVector4D& value)
+
+ Sets the elements of row \a index to the components of \a value.
+
+ \sa row(), setColumn()
+*/
+
+/*!
+ \fn bool QMatrix4x4::isIdentity() const
+
+ Returns true if this matrix is the identity; false otherwise.
+
+ \sa setIdentity()
+*/
+
+/*!
+ \fn void QMatrix4x4::setIdentity()
+
+ Sets this matrix to the identity.
+
+ \sa isIdentity()
+*/
+
+/*!
+ \fn void QMatrix4x4::fill(qreal value)
+
+ Fills all elements of this matrx with \a value.
+*/
+
+// The 4x4 matrix inverse algorithm is based on that described at:
+// http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q24
+// Some optimization has been done to avoid making copies of 3x3
+// sub-matrices, to do calculations in fixed-point where required,
+// and to unroll the loops.
+
+// Calculate the determinant of a 3x3 sub-matrix.
+// | A B C |
+// M = | D E F | det(M) = A * (EI - HF) - B * (DI - GF) + C * (DH - GE)
+// | G H I |
+static inline qrealinner matrixDet3
+ (const qrealinner m[4][4], int col0, int col1, int col2,
+ int row0, int row1, int row2)
+{
+ return m[col0][row0] *
+ (m[col1][row1] * m[col2][row2] -
+ m[col1][row2] * m[col2][row1]) -
+ m[col1][row0] *
+ (m[col0][row1] * m[col2][row2] -
+ m[col0][row2] * m[col2][row1]) +
+ m[col2][row0] *
+ (m[col0][row1] * m[col1][row2] -
+ m[col0][row2] * m[col1][row1]);
+}
+
+// Calculate the determinant of a 4x4 matrix.
+static inline qrealinner matrixDet4(const qrealinner m[4][4])
+{
+ qrealinner det;
+ det = m[0][0] * matrixDet3(m, 1, 2, 3, 1, 2, 3);
+ det -= m[1][0] * matrixDet3(m, 0, 2, 3, 1, 2, 3);
+ det += m[2][0] * matrixDet3(m, 0, 1, 3, 1, 2, 3);
+ det -= m[3][0] * matrixDet3(m, 0, 1, 2, 1, 2, 3);
+ return det;
+}
+
+/*!
+ Returns the determinant of this matrix.
+*/
+qreal QMatrix4x4::determinant() const
+{
+ return qt_math3d_convert<qreal, qrealinner>(matrixDet4(m));
+}
+
+/*!
+ Returns the inverse of this matrix. Returns the identity if
+ this matrix cannot be inverted; i.e. determinant() is zero.
+ If \a invertible is not null, then true will be written to
+ that location if the matrix can be inverted; false otherwise.
+
+ If the matrix is recognized as the identity or an orthonormal
+ matrix, then this function will quickly invert the matrix
+ using optimized routines.
+
+ \sa determinant(), normalMatrix()
+*/
+QMatrix4x4 QMatrix4x4::inverted(bool *invertible) const
+{
+ // Handle some of the easy cases first.
+ if (flagBits == Identity) {
+ if (invertible)
+ *invertible = true;
+ return QMatrix4x4();
+ } else if (flagBits == Translation) {
+ QMatrix4x4 inv;
+ inv.m[3][0] = -m[3][0];
+ inv.m[3][1] = -m[3][1];
+ inv.m[3][2] = -m[3][2];
+ inv.flagBits = Translation;
+ if (invertible)
+ *invertible = true;
+ return inv;
+ } else if (flagBits == Rotation || flagBits == (Rotation | Translation)) {
+ if (invertible)
+ *invertible = true;
+ return orthonormalInverse();
+ }
+
+ QMatrix4x4 inv(1); // The "1" says to not load the identity.
+
+ qrealinner det = matrixDet4(m);
+ if (det == 0.0f) {
+ if (invertible)
+ *invertible = false;
+ return QMatrix4x4();
+ }
+ det = qrealinner(1.0f) / det;
+
+ inv.m[0][0] = matrixDet3(m, 1, 2, 3, 1, 2, 3) * det;
+ inv.m[0][1] = -matrixDet3(m, 0, 2, 3, 1, 2, 3) * det;
+ inv.m[0][2] = matrixDet3(m, 0, 1, 3, 1, 2, 3) * det;
+ inv.m[0][3] = -matrixDet3(m, 0, 1, 2, 1, 2, 3) * det;
+ inv.m[1][0] = -matrixDet3(m, 1, 2, 3, 0, 2, 3) * det;
+ inv.m[1][1] = matrixDet3(m, 0, 2, 3, 0, 2, 3) * det;
+ inv.m[1][2] = -matrixDet3(m, 0, 1, 3, 0, 2, 3) * det;
+ inv.m[1][3] = matrixDet3(m, 0, 1, 2, 0, 2, 3) * det;
+ inv.m[2][0] = matrixDet3(m, 1, 2, 3, 0, 1, 3) * det;
+ inv.m[2][1] = -matrixDet3(m, 0, 2, 3, 0, 1, 3) * det;
+ inv.m[2][2] = matrixDet3(m, 0, 1, 3, 0, 1, 3) * det;
+ inv.m[2][3] = -matrixDet3(m, 0, 1, 2, 0, 1, 3) * det;
+ inv.m[3][0] = -matrixDet3(m, 1, 2, 3, 0, 1, 2) * det;
+ inv.m[3][1] = matrixDet3(m, 0, 2, 3, 0, 1, 2) * det;
+ inv.m[3][2] = -matrixDet3(m, 0, 1, 3, 0, 1, 2) * det;
+ inv.m[3][3] = matrixDet3(m, 0, 1, 2, 0, 1, 2) * det;
+
+ if (invertible)
+ *invertible = true;
+ return inv;
+}
+
+/*!
+ Returns the normal matrix corresponding to this 4x4 transformation.
+ The normal matrix is the transpose of the inverse of the top-left
+ 3x3 part of this 4x4 matrix. If the 3x3 sub-matrix is not invertible,
+ this function returns the identity.
+
+ \sa inverted()
+*/
+QMatrix3x3 QMatrix4x4::normalMatrix() const
+{
+ QMatrix3x3 inv;
+
+ // Handle the simple cases first.
+ if (flagBits == Identity || flagBits == Translation) {
+ return inv;
+ } else if (flagBits == Scale || flagBits == (Translation | Scale)) {
+ if (m[0][0] == 0.0f || m[1][1] == 0.0f || m[2][2] == 0.0f)
+ return inv;
+ inv.data()[0] = qrealinner(1.0f) / m[0][0];
+ inv.data()[4] = qrealinner(1.0f) / m[1][1];
+ inv.data()[8] = qrealinner(1.0f) / m[2][2];
+ return inv;
+ }
+
+ qrealinner det = matrixDet3(m, 0, 1, 2, 0, 1, 2);
+ if (det == 0.0f)
+ return inv;
+ det = qrealinner(1.0f) / det;
+
+ qrealinner *invm = inv.data();
+
+ // Invert and transpose in a single step.
+ invm[0 + 0 * 3] = (m[1][1] * m[2][2] - m[2][1] * m[1][2]) * det;
+ invm[1 + 0 * 3] = -(m[1][0] * m[2][2] - m[1][2] * m[2][0]) * det;
+ invm[2 + 0 * 3] = (m[1][0] * m[2][1] - m[1][1] * m[2][0]) * det;
+ invm[0 + 1 * 3] = -(m[0][1] * m[2][2] - m[2][1] * m[0][2]) * det;
+ invm[1 + 1 * 3] = (m[0][0] * m[2][2] - m[0][2] * m[2][0]) * det;
+ invm[2 + 1 * 3] = -(m[0][0] * m[2][1] - m[0][1] * m[2][0]) * det;
+ invm[0 + 2 * 3] = (m[0][1] * m[1][2] - m[0][2] * m[1][1]) * det;
+ invm[1 + 2 * 3] = -(m[0][0] * m[1][2] - m[0][2] * m[1][0]) * det;
+ invm[2 + 2 * 3] = (m[0][0] * m[1][1] - m[1][0] * m[0][1]) * det;
+
+ return inv;
+}
+
+/*!
+ Returns this matrix, transposed about its diagonal.
+*/
+QMatrix4x4 QMatrix4x4::transposed() const
+{
+ QMatrix4x4 result(1); // The "1" says to not load the identity.
+ for (int row = 0; row < 4; ++row) {
+ for (int col = 0; col < 4; ++col) {
+ result.m[col][row] = m[row][col];
+ }
+ }
+ return result;
+}
+
+/*!
+ \fn QMatrix4x4& QMatrix4x4::operator+=(const QMatrix4x4& other)
+
+ Adds the contents of \a other to this matrix.
+*/
+
+/*!
+ \fn QMatrix4x4& QMatrix4x4::operator-=(const QMatrix4x4& other)
+
+ Subtracts the contents of \a other from this matrix.
+*/
+
+/*!
+ \fn QMatrix4x4& QMatrix4x4::operator*=(const QMatrix4x4& other)
+
+ Multiplies the contents of \a other by this matrix.
+*/
+
+/*!
+ \fn QMatrix4x4& QMatrix4x4::operator*=(qreal factor)
+ \overload
+
+ Multiplies all elements of this matrix by \a factor.
+*/
+
+/*!
+ \overload
+
+ Divides all elements of this matrix by \a divisor.
+*/
+QMatrix4x4& QMatrix4x4::operator/=(qreal divisor)
+{
+ qrealinner d(divisor);
+ m[0][0] /= d;
+ m[0][1] /= d;
+ m[0][2] /= d;
+ m[0][3] /= d;
+ m[1][0] /= d;
+ m[1][1] /= d;
+ m[1][2] /= d;
+ m[1][3] /= d;
+ m[2][0] /= d;
+ m[2][1] /= d;
+ m[2][2] /= d;
+ m[2][3] /= d;
+ m[3][0] /= d;
+ m[3][1] /= d;
+ m[3][2] /= d;
+ m[3][3] /= d;
+ flagBits = General;
+ return *this;
+}
+
+/*!
+ \fn bool QMatrix4x4::operator==(const QMatrix4x4& other) const
+
+ Returns true if this matrix is identical to \a other; false otherwise.
+ This operator uses an exact floating-point comparison.
+*/
+
+/*!
+ \fn bool QMatrix4x4::operator!=(const QMatrix4x4& other) const
+
+ Returns true if this matrix is not identical to \a other; false otherwise.
+ This operator uses an exact floating-point comparison.
+*/
+
+/*!
+ \fn QMatrix4x4 operator+(const QMatrix4x4& m1, const QMatrix4x4& m2)
+ \relates QMatrix4x4
+
+ Returns the sum of \a m1 and \a m2.
+*/
+
+/*!
+ \fn QMatrix4x4 operator-(const QMatrix4x4& m1, const QMatrix4x4& m2)
+ \relates QMatrix4x4
+
+ Returns the difference of \a m1 and \a m2.
+*/
+
+/*!
+ \fn QMatrix4x4 operator*(const QMatrix4x4& m1, const QMatrix4x4& m2)
+ \relates QMatrix4x4
+
+ Returns the product of \a m1 and \a m2.
+*/
+
+#ifndef QT_NO_VECTOR3D
+
+/*!
+ \fn QVector3D operator*(const QVector3D& vector, const QMatrix4x4& matrix)
+ \relates QMatrix4x4
+
+ Returns the result of transforming \a vector according to \a matrix,
+ with the matrix applied post-vector.
+*/
+
+/*!
+ \fn QVector3D operator*(const QMatrix4x4& matrix, const QVector3D& vector)
+ \relates QMatrix4x4
+
+ Returns the result of transforming \a vector according to \a matrix,
+ with the matrix applied pre-vector.
+*/
+
+#endif
+
+#ifndef QT_NO_VECTOR4D
+
+/*!
+ \fn QVector4D operator*(const QVector4D& vector, const QMatrix4x4& matrix)
+ \relates QMatrix4x4
+
+ Returns the result of transforming \a vector according to \a matrix,
+ with the matrix applied post-vector.
+*/
+
+/*!
+ \fn QVector4D operator*(const QMatrix4x4& matrix, const QVector4D& vector)
+ \relates QMatrix4x4
+
+ Returns the result of transforming \a vector according to \a matrix,
+ with the matrix applied pre-vector.
+*/
+
+#endif
+
+/*!
+ \fn QPoint operator*(const QPoint& point, const QMatrix4x4& matrix)
+ \relates QMatrix4x4
+
+ Returns the result of transforming \a point according to \a matrix,
+ with the matrix applied post-point.
+*/
+
+/*!
+ \fn QPointF operator*(const QPointF& point, const QMatrix4x4& matrix)
+ \relates QMatrix4x4
+
+ Returns the result of transforming \a point according to \a matrix,
+ with the matrix applied post-point.
+*/
+
+/*!
+ \fn QPoint operator*(const QMatrix4x4& matrix, const QPoint& point)
+ \relates QMatrix4x4
+
+ Returns the result of transforming \a point according to \a matrix,
+ with the matrix applied pre-point.
+*/
+
+/*!
+ \fn QPointF operator*(const QMatrix4x4& matrix, const QPointF& point)
+ \relates QMatrix4x4
+
+ Returns the result of transforming \a point according to \a matrix,
+ with the matrix applied pre-point.
+*/
+
+/*!
+ \fn QMatrix4x4 operator-(const QMatrix4x4& matrix)
+ \overload
+ \relates QMatrix4x4
+
+ Returns the negation of \a matrix.
+*/
+
+/*!
+ \fn QMatrix4x4 operator*(qreal factor, const QMatrix4x4& matrix)
+ \relates QMatrix4x4
+
+ Returns the result of multiplying all elements of \a matrix by \a factor.
+*/
+
+/*!
+ \fn QMatrix4x4 operator*(const QMatrix4x4& matrix, qreal factor)
+ \relates QMatrix4x4
+
+ Returns the result of multiplying all elements of \a matrix by \a factor.
+*/
+
+/*!
+ \relates QMatrix4x4
+
+ Returns the result of dividing all elements of \a matrix by \a divisor.
+*/
+QMatrix4x4 operator/(const QMatrix4x4& matrix, qreal divisor)
+{
+ QMatrix4x4 m(1); // The "1" says to not load the identity.
+ qrealinner d(divisor);
+ m.m[0][0] = matrix.m[0][0] / d;
+ m.m[0][1] = matrix.m[0][1] / d;
+ m.m[0][2] = matrix.m[0][2] / d;
+ m.m[0][3] = matrix.m[0][3] / d;
+ m.m[1][0] = matrix.m[1][0] / d;
+ m.m[1][1] = matrix.m[1][1] / d;
+ m.m[1][2] = matrix.m[1][2] / d;
+ m.m[1][3] = matrix.m[1][3] / d;
+ m.m[2][0] = matrix.m[2][0] / d;
+ m.m[2][1] = matrix.m[2][1] / d;
+ m.m[2][2] = matrix.m[2][2] / d;
+ m.m[2][3] = matrix.m[2][3] / d;
+ m.m[3][0] = matrix.m[3][0] / d;
+ m.m[3][1] = matrix.m[3][1] / d;
+ m.m[3][2] = matrix.m[3][2] / d;
+ m.m[3][3] = matrix.m[3][3] / d;
+ return m;
+}
+
+/*!
+ \fn bool qFuzzyCompare(const QMatrix4x4& m1, const QMatrix4x4& m2)
+ \relates QMatrix4x4
+
+ Returns true if \a m1 and \a m2 are equal, allowing for a small
+ fuzziness factor for floating-point comparisons; false otherwise.
+*/
+
+#ifndef QT_NO_VECTOR3D
+
+/*!
+ Multiplies this matrix by another that scales coordinates by
+ the components of \a vector. Returns this matrix.
+
+ \sa translate(), rotate()
+*/
+QMatrix4x4& QMatrix4x4::scale(const QVector3D& vector)
+{
+ qrealinner vx = vector.xp;
+ qrealinner vy = vector.yp;
+ qrealinner vz = vector.zp;
+ if (flagBits == Identity) {
+ m[0][0] = vx;
+ m[1][1] = vy;
+ m[2][2] = vz;
+ flagBits = Scale;
+ } else if (flagBits == Scale || flagBits == (Scale | Translation)) {
+ m[0][0] *= vx;
+ m[1][1] *= vy;
+ m[2][2] *= vz;
+ } else if (flagBits == Translation) {
+ m[0][0] = vx;
+ m[1][1] = vy;
+ m[2][2] = vz;
+ flagBits |= Scale;
+ } else {
+ m[0][0] *= vx;
+ m[0][1] *= vx;
+ m[0][2] *= vx;
+ m[0][3] *= vx;
+ m[1][0] *= vy;
+ m[1][1] *= vy;
+ m[1][2] *= vy;
+ m[1][3] *= vy;
+ m[2][0] *= vz;
+ m[2][1] *= vz;
+ m[2][2] *= vz;
+ m[2][3] *= vz;
+ flagBits = General;
+ }
+ return *this;
+}
+#endif
+
+/*!
+ \overload
+
+ Multiplies this matrix by another that scales coordinates by the
+ components \a x, \a y, and \a z. Returns this matrix.
+
+ \sa translate(), rotate()
+*/
+QMatrix4x4& QMatrix4x4::scale(qreal x, qreal y, qreal z)
+{
+ qrealinner vx(x);
+ qrealinner vy(y);
+ qrealinner vz(z);
+ if (flagBits == Identity) {
+ m[0][0] = vx;
+ m[1][1] = vy;
+ m[2][2] = vz;
+ flagBits = Scale;
+ } else if (flagBits == Scale || flagBits == (Scale | Translation)) {
+ m[0][0] *= vx;
+ m[1][1] *= vy;
+ m[2][2] *= vz;
+ } else if (flagBits == Translation) {
+ m[0][0] = vx;
+ m[1][1] = vy;
+ m[2][2] = vz;
+ flagBits |= Scale;
+ } else {
+ m[0][0] *= vx;
+ m[0][1] *= vx;
+ m[0][2] *= vx;
+ m[0][3] *= vx;
+ m[1][0] *= vy;
+ m[1][1] *= vy;
+ m[1][2] *= vy;
+ m[1][3] *= vy;
+ m[2][0] *= vz;
+ m[2][1] *= vz;
+ m[2][2] *= vz;
+ m[2][3] *= vz;
+ flagBits = General;
+ }
+ return *this;
+}
+
+/*!
+ \overload
+
+ Multiplies this matrix by another that scales coordinates by the
+ given \a factor. Returns this matrix.
+
+ \sa translate(), rotate()
+*/
+QMatrix4x4& QMatrix4x4::scale(qreal factor)
+{
+ qrealinner f(factor);
+ if (flagBits == Identity) {
+ m[0][0] = f;
+ m[1][1] = f;
+ m[2][2] = f;
+ flagBits = Scale;
+ } else if (flagBits == Scale || flagBits == (Scale | Translation)) {
+ m[0][0] *= f;
+ m[1][1] *= f;
+ m[2][2] *= f;
+ } else if (flagBits == Translation) {
+ m[0][0] = f;
+ m[1][1] = f;
+ m[2][2] = f;
+ flagBits |= Scale;
+ } else {
+ m[0][0] *= f;
+ m[0][1] *= f;
+ m[0][2] *= f;
+ m[0][3] *= f;
+ m[1][0] *= f;
+ m[1][1] *= f;
+ m[1][2] *= f;
+ m[1][3] *= f;
+ m[2][0] *= f;
+ m[2][1] *= f;
+ m[2][2] *= f;
+ m[2][3] *= f;
+ flagBits = General;
+ }
+ return *this;
+}
+
+#ifndef QT_NO_VECTOR3D
+/*!
+ Multiplies this matrix by another that translates coordinates by
+ the components of \a vector. Returns this matrix.
+
+ \sa scale(), rotate()
+*/
+QMatrix4x4& QMatrix4x4::translate(const QVector3D& vector)
+{
+ qrealinner vx = vector.xp;
+ qrealinner vy = vector.yp;
+ qrealinner vz = vector.zp;
+ if (flagBits == Identity) {
+ m[3][0] = vx;
+ m[3][1] = vy;
+ m[3][2] = vz;
+ flagBits = Translation;
+ } else if (flagBits == Translation) {
+ m[3][0] += vx;
+ m[3][1] += vy;
+ m[3][2] += vz;
+ } else if (flagBits == Scale) {
+ m[3][0] = m[0][0] * vx;
+ m[3][1] = m[1][1] * vy;
+ m[3][2] = m[2][2] * vz;
+ flagBits |= Translation;
+ } else if (flagBits == (Scale | Translation)) {
+ m[3][0] += m[0][0] * vx;
+ m[3][1] += m[1][1] * vy;
+ m[3][2] += m[2][2] * vz;
+ } else {
+ m[3][0] += m[0][0] * vx + m[1][0] * vy + m[2][0] * vz;
+ m[3][1] += m[0][1] * vx + m[1][1] * vy + m[2][1] * vz;
+ m[3][2] += m[0][2] * vx + m[1][2] * vy + m[2][2] * vz;
+ m[3][3] += m[0][3] * vx + m[1][3] * vy + m[2][3] * vz;
+ if (flagBits == Rotation)
+ flagBits |= Translation;
+ else if (flagBits != (Rotation | Translation))
+ flagBits = General;
+ }
+ return *this;
+}
+
+#endif
+
+/*!
+ \overload
+
+ Multiplies this matrix by another that translates coordinates
+ by the components \a x, \a y, and \a z. Returns this matrix.
+
+ \sa scale(), rotate()
+*/
+QMatrix4x4& QMatrix4x4::translate(qreal x, qreal y, qreal z)
+{
+ qrealinner vx(x);
+ qrealinner vy(y);
+ qrealinner vz(z);
+ if (flagBits == Identity) {
+ m[3][0] = vx;
+ m[3][1] = vy;
+ m[3][2] = vz;
+ flagBits = Translation;
+ } else if (flagBits == Translation) {
+ m[3][0] += vx;
+ m[3][1] += vy;
+ m[3][2] += vz;
+ } else if (flagBits == Scale) {
+ m[3][0] = m[0][0] * vx;
+ m[3][1] = m[1][1] * vy;
+ m[3][2] = m[2][2] * vz;
+ flagBits |= Translation;
+ } else if (flagBits == (Scale | Translation)) {
+ m[3][0] += m[0][0] * vx;
+ m[3][1] += m[1][1] * vy;
+ m[3][2] += m[2][2] * vz;
+ } else {
+ m[3][0] += m[0][0] * vx + m[1][0] * vy + m[2][0] * vz;
+ m[3][1] += m[0][1] * vx + m[1][1] * vy + m[2][1] * vz;
+ m[3][2] += m[0][2] * vx + m[1][2] * vy + m[2][2] * vz;
+ m[3][3] += m[0][3] * vx + m[1][3] * vy + m[2][3] * vz;
+ if (flagBits == Rotation)
+ flagBits |= Translation;
+ else if (flagBits != (Rotation | Translation))
+ flagBits = General;
+ }
+ return *this;
+}
+
+#ifndef QT_NO_VECTOR3D
+
+/*!
+ Multiples this matrix by another that rotates coordinates through
+ \a angle degrees about \a vector. Returns this matrix.
+
+ \sa scale(), translate()
+*/
+QMatrix4x4& QMatrix4x4::rotate(qreal angle, const QVector3D& vector)
+{
+ return rotate(angle, vector.x(), vector.y(), vector.z());
+}
+
+#endif
+
+/*!
+ \overload
+
+ Multiplies this matrix by another that rotates coordinates through
+ \a angle degrees about the vector (\a x, \a y, \a z). Returns this matrix.
+
+ \sa scale(), translate()
+*/
+QMatrix4x4& QMatrix4x4::rotate(qreal angle, qreal x, qreal y, qreal z)
+{
+ QMatrix4x4 m(1); // The "1" says to not load the identity.
+ qrealinner c, s, ic;
+ qt_math3d_sincos(angle, &s, &c);
+ bool quick = false;
+ if (x == 0.0f) {
+ if (y == 0.0f) {
+ if (z != 0.0f) {
+ // Rotate around the Z axis.
+ m.setIdentity();
+ m.m[0][0] = c;
+ m.m[1][1] = c;
+ if (z < 0.0f) {
+ m.m[1][0] = s;
+ m.m[0][1] = -s;
+ } else {
+ m.m[1][0] = -s;
+ m.m[0][1] = s;
+ }
+ m.flagBits = General;
+ quick = true;
+ }
+ } else if (z == 0.0f) {
+ // Rotate around the Y axis.
+ m.setIdentity();
+ m.m[0][0] = c;
+ m.m[2][2] = c;
+ if (y < 0.0f) {
+ m.m[2][0] = -s;
+ m.m[0][2] = s;
+ } else {
+ m.m[2][0] = s;
+ m.m[0][2] = -s;
+ }
+ m.flagBits = General;
+ quick = true;
+ }
+ } else if (y == 0.0f && z == 0.0f) {
+ // Rotate around the X axis.
+ m.setIdentity();
+ m.m[1][1] = c;
+ m.m[2][2] = c;
+ if (x < 0.0f) {
+ m.m[2][1] = s;
+ m.m[1][2] = -s;
+ } else {
+ m.m[2][1] = -s;
+ m.m[1][2] = s;
+ }
+ m.flagBits = General;
+ quick = true;
+ }
+ if (!quick) {
+ qrealinner vx(x);
+ qrealinner vy(y);
+ qrealinner vz(z);
+ qrealinner len(qvtsqrt(vx * vx + vy * vy + vz * vz));
+ if (len != 0) {
+ vx /= len;
+ vy /= len;
+ vz /= len;
+ }
+ ic = 1.0f - c;
+ m.m[0][0] = vx * vx * ic + c;
+ m.m[1][0] = vx * vy * ic - vz * s;
+ m.m[2][0] = vx * vz * ic + vy * s;
+ m.m[3][0] = 0.0f;
+ m.m[0][1] = vy * vx * ic + vz * s;
+ m.m[1][1] = vy * vy * ic + c;
+ m.m[2][1] = vy * vz * ic - vx * s;
+ m.m[3][1] = 0.0f;
+ m.m[0][2] = vx * vz * ic - vy * s;
+ m.m[1][2] = vy * vz * ic + vx * s;
+ m.m[2][2] = vz * vz * ic + c;
+ m.m[3][2] = 0.0f;
+ m.m[0][3] = 0.0f;
+ m.m[1][3] = 0.0f;
+ m.m[2][3] = 0.0f;
+ m.m[3][3] = 1.0f;
+ }
+ int flags = flagBits;
+ *this *= m;
+ if (flags != Identity)
+ flagBits = flags | Rotation;
+ else
+ flagBits = Rotation;
+ return *this;
+}
+
+#ifndef QT_NO_VECTOR4D
+
+/*!
+ Multiples this matrix by another that rotates coordinates according
+ to a specified \a quaternion. The \a quaternion is assumed to have
+ been normalized. Returns this matrix.
+
+ \sa scale(), translate(), QQuaternion
+*/
+QMatrix4x4& QMatrix4x4::rotate(const QQuaternion& quaternion)
+{
+ // Algorithm from:
+ // http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q54
+ QMatrix4x4 m(1);
+ qrealinner xx = quaternion.xp * quaternion.xp;
+ qrealinner xy = quaternion.xp * quaternion.yp;
+ qrealinner xz = quaternion.xp * quaternion.zp;
+ qrealinner xw = quaternion.xp * quaternion.wp;
+ qrealinner yy = quaternion.yp * quaternion.yp;
+ qrealinner yz = quaternion.yp * quaternion.zp;
+ qrealinner yw = quaternion.yp * quaternion.wp;
+ qrealinner zz = quaternion.zp * quaternion.zp;
+ qrealinner zw = quaternion.zp * quaternion.wp;
+ m.m[0][0] = 1.0f - 2 * (yy + zz);
+ m.m[1][0] = 2 * (xy - zw);
+ m.m[2][0] = 2 * (xz + yw);
+ m.m[3][0] = 0.0f;
+ m.m[0][1] = 2 * (xy + zw);
+ m.m[1][1] = 1.0f - 2 * (xx + zz);
+ m.m[2][1] = 2 * (yz - xw);
+ m.m[3][1] = 0.0f;
+ m.m[0][2] = 2 * (xz - yw);
+ m.m[1][2] = 2 * (yz + xw);
+ m.m[2][2] = 1.0f - 2 * (xx + yy);
+ m.m[3][2] = 0.0f;
+ m.m[0][3] = 0.0f;
+ m.m[1][3] = 0.0f;
+ m.m[2][3] = 0.0f;
+ m.m[3][3] = 1.0f;
+ int flags = flagBits;
+ *this *= m;
+ if (flags != Identity)
+ flagBits = flags | Rotation;
+ else
+ flagBits = Rotation;
+ return *this;
+}
+
+#endif
+
+/*!
+ \overload
+
+ Multiplies this matrix by another that applies an orthographic
+ projection for a window with boundaries specified by \a rect.
+ The near and far clipping planes will be -1 and 1 respectively.
+ Returns this matrix.
+
+ \sa frustum(), perspective()
+*/
+QMatrix4x4& QMatrix4x4::ortho(const QRect& rect)
+{
+ // Note: rect.right() and rect.bottom() subtract 1 in QRect,
+ // which gives the location of a pixel within the rectangle,
+ // instead of the extent of the rectangle. We want the extent.
+ // QRectF expresses the extent properly.
+ return ortho(rect.x(), rect.x() + rect.width(), rect.y() + rect.height(), rect.y(), -1.0f, 1.0f);
+}
+
+/*!
+ \overload
+
+ Multiplies this matrix by another that applies an orthographic
+ projection for a window with boundaries specified by \a rect.
+ The near and far clipping planes will be -1 and 1 respectively.
+ Returns this matrix.
+
+ \sa frustum(), perspective()
+*/
+QMatrix4x4& QMatrix4x4::ortho(const QRectF& rect)
+{
+ return ortho(rect.left(), rect.right(), rect.bottom(), rect.top(), -1.0f, 1.0f);
+}
+
+/*!
+ Multiplies this matrix by another that applies an orthographic
+ projection for a window with lower-left corner (\a left, \a bottom),
+ upper-right corner (\a right, \a top), and the specified \a nearPlane
+ and \a farPlane clipping planes. Returns this matrix.
+
+ \sa frustum(), perspective()
+*/
+QMatrix4x4& QMatrix4x4::ortho(qreal left, qreal right, qreal bottom, qreal top, qreal nearPlane, qreal farPlane)
+{
+ // Bail out if the projection volume is zero-sized.
+ if (left == right || bottom == top || nearPlane == farPlane)
+ return *this;
+
+ // Construct the projection.
+ qreal width = right - left;
+ qreal invheight = top - bottom;
+ qreal clip = farPlane - nearPlane;
+#ifndef QT_NO_VECTOR3D
+ if (clip == 2.0f && (nearPlane + farPlane) == 0.0f) {
+ // We can express this projection as a translate and scale
+ // which will be more efficient to modify with further
+ // transformations than producing a "General" matrix.
+ translate(QVector3D
+ (qf2vt_round(-(left + right) / width),
+ qf2vt_round(-(top + bottom) / invheight),
+ 0.0f, 1));
+ scale(QVector3D
+ (qf2vt_round(2.0f / width),
+ qf2vt_round(2.0f / invheight),
+ -1.0f, 1));
+ return *this;
+ }
+#endif
+ QMatrix4x4 m(1);
+ m.m[0][0] = qf2vt_round(2.0f / width);
+ m.m[1][0] = qf2vt_round(0.0f);
+ m.m[2][0] = qf2vt_round(0.0f);
+ m.m[3][0] = qf2vt_round(-(left + right) / width);
+ m.m[0][1] = qf2vt_round(0.0f);
+ m.m[1][1] = qf2vt_round(2.0f / invheight);
+ m.m[2][1] = qf2vt_round(0.0f);
+ m.m[3][1] = qf2vt_round(-(top + bottom) / invheight);
+ m.m[0][2] = qf2vt_round(0.0f);
+ m.m[1][2] = qf2vt_round(0.0f);
+ m.m[2][2] = qf2vt_round(-2.0f / clip);
+ m.m[3][2] = qf2vt_round(-(nearPlane + farPlane) / clip);
+ m.m[0][3] = qf2vt_round(0.0f);
+ m.m[1][3] = qf2vt_round(0.0f);
+ m.m[2][3] = qf2vt_round(0.0f);
+ m.m[3][3] = qf2vt_round(1.0f);
+
+ // Apply the projection.
+ *this *= m;
+ return *this;
+}
+
+/*!
+ Multiplies this matrix by another that applies a perspective
+ frustum projection for a window with lower-left corner (\a left, \a bottom),
+ upper-right corner (\a right, \a top), and the specified \a nearPlane
+ and \a farPlane clipping planes. Returns this matrix.
+
+ \sa ortho(), perspective()
+*/
+QMatrix4x4& QMatrix4x4::frustum(qreal left, qreal right, qreal bottom, qreal top, qreal nearPlane, qreal farPlane)
+{
+ // Bail out if the projection volume is zero-sized.
+ if (left == right || bottom == top || nearPlane == farPlane)
+ return *this;
+
+ // Construct the projection.
+ QMatrix4x4 m(1);
+ qreal width = right - left;
+ qreal invheight = top - bottom;
+ qreal clip = farPlane - nearPlane;
+ m.m[0][0] = qf2vt_round(2.0f * nearPlane / width);
+ m.m[1][0] = qf2vt_round(0.0f);
+ m.m[2][0] = qf2vt_round((left + right) / width);
+ m.m[3][0] = qf2vt_round(0.0f);
+ m.m[0][1] = qf2vt_round(0.0f);
+ m.m[1][1] = qf2vt_round(2.0f * nearPlane / invheight);
+ m.m[2][1] = qf2vt_round((top + bottom) / invheight);
+ m.m[3][1] = qf2vt_round(0.0f);
+ m.m[0][2] = qf2vt_round(0.0f);
+ m.m[1][2] = qf2vt_round(0.0f);
+ m.m[2][2] = qf2vt_round(-(nearPlane + farPlane) / clip);
+ m.m[3][2] = qf2vt_round(-(2.0f * nearPlane * farPlane) / clip);
+ m.m[0][3] = qf2vt_round(0.0f);
+ m.m[1][3] = qf2vt_round(0.0f);
+ m.m[2][3] = qf2vt_round(-1.0f);
+ m.m[3][3] = qf2vt_round(0.0f);
+
+ // Apply the projection.
+ *this *= m;
+ return *this;
+}
+
+/*!
+ Multiplies this matrix by another that applies a perspective
+ projection. The field of view will be \a angle degrees within
+ a window with a given \a aspect ratio. The projection will
+ have the specified \a nearPlane and \a farPlane clipping planes.
+ Returns this matrix.
+
+ \sa ortho(), frustum()
+*/
+QMatrix4x4& QMatrix4x4::perspective(qreal angle, qreal aspect, qreal nearPlane, qreal farPlane)
+{
+ // Bail out if the projection volume is zero-sized.
+ if (nearPlane == farPlane || aspect == 0.0f)
+ return *this;
+
+ // Construct the projection.
+ QMatrix4x4 m(1);
+ qreal radians = (angle / 2.0f) * M_PI / 180.0f;
+ qreal sine = qSin(radians);
+ if (sine == 0.0f)
+ return *this;
+ qreal cotan = qCos(radians) / sine;
+ qreal clip = farPlane - nearPlane;
+ m.m[0][0] = qf2vt_round(cotan / aspect);
+ m.m[1][0] = qf2vt_round(0.0f);
+ m.m[2][0] = qf2vt_round(0.0f);
+ m.m[3][0] = qf2vt_round(0.0f);
+ m.m[0][1] = qf2vt_round(0.0f);
+ m.m[1][1] = qf2vt_round(cotan);
+ m.m[2][1] = qf2vt_round(0.0f);
+ m.m[3][1] = qf2vt_round(0.0f);
+ m.m[0][2] = qf2vt_round(0.0f);
+ m.m[1][2] = qf2vt_round(0.0f);
+ m.m[2][2] = qf2vt_round(-(nearPlane + farPlane) / clip);
+ m.m[3][2] = qf2vt_round(-(2.0f * nearPlane * farPlane) / clip);
+ m.m[0][3] = qf2vt_round(0.0f);
+ m.m[1][3] = qf2vt_round(0.0f);
+ m.m[2][3] = qf2vt_round(-1.0f);
+ m.m[3][3] = qf2vt_round(0.0f);
+
+ // Apply the projection.
+ *this *= m;
+ return *this;
+}
+
+#ifndef QT_NO_VECTOR3D
+
+/*!
+ Multiplies this matrix by another that applies an \a eye position
+ transformation. The \a center value indicates the center of the
+ view that the \a eye is looking at. The \a up value indicates
+ which direction should be considered up with respect to the \a eye.
+ Returns this matrix.
+*/
+QMatrix4x4& QMatrix4x4::lookAt(const QVector3D& eye, const QVector3D& center, const QVector3D& up)
+{
+ QVector3D forward = (center - eye).normalized();
+ QVector3D side = QVector3D::crossProduct(forward, up).normalized();
+ QVector3D upVector = QVector3D::crossProduct(side, forward);
+
+ QMatrix4x4 m(1);
+
+ m.m[0][0] = side.xp;
+ m.m[1][0] = side.yp;
+ m.m[2][0] = side.zp;
+ m.m[3][0] = 0.0f;
+ m.m[0][1] = upVector.xp;
+ m.m[1][1] = upVector.yp;
+ m.m[2][1] = upVector.zp;
+ m.m[3][1] = 0.0f;
+ m.m[0][2] = -forward.xp;
+ m.m[1][2] = -forward.yp;
+ m.m[2][2] = -forward.zp;
+ m.m[3][2] = 0.0f;
+ m.m[0][3] = 0.0f;
+ m.m[1][3] = 0.0f;
+ m.m[2][3] = 0.0f;
+ m.m[3][3] = 1.0f;
+
+ *this *= m;
+ return translate(-eye);
+}
+
+#endif
+
+/*!
+ Flips between right-handed and left-handed coordinate systems
+ by multiplying the y and z co-ordinates by -1. This is normally
+ used to create a left-handed orthographic view without scaling
+ the viewport as ortho() does. Returns this matrix.
+
+ \sa ortho()
+*/
+QMatrix4x4& QMatrix4x4::flipCoordinates()
+{
+ if (flagBits == Scale || flagBits == (Scale | Translation)) {
+ m[1][1] = -m[1][1];
+ m[2][2] = -m[2][2];
+ } else if (flagBits == Translation) {
+ m[1][1] = -m[1][1];
+ m[2][2] = -m[2][2];
+ flagBits |= Scale;
+ } else if (flagBits == Identity) {
+ m[1][1] = -1.0f;
+ m[2][2] = -1.0f;
+ flagBits = Scale;
+ } else {
+ m[1][0] = -m[1][0];
+ m[1][1] = -m[1][1];
+ m[1][2] = -m[1][2];
+ m[1][3] = -m[1][3];
+ m[2][0] = -m[2][0];
+ m[2][1] = -m[2][1];
+ m[2][2] = -m[2][2];
+ m[2][3] = -m[2][3];
+ flagBits = General;
+ }
+ return *this;
+}
+
+/*!
+ Retrieves the 16 items in this matrix and writes them to \a values
+ in row-major order.
+*/
+void QMatrix4x4::toValueArray(qreal *values) const
+{
+ for (int row = 0; row < 4; ++row)
+ for (int col = 0; col < 4; ++col)
+ values[row * 4 + col] = qt_math3d_convert<qreal, qrealinner>(m[col][row]);
+}
+
+/*!
+ Returns the conventional Qt 2D affine transformation matrix that
+ corresponds to this matrix. It is assumed that this matrix
+ only contains 2D affine transformation elements.
+
+ \sa toTransform()
+*/
+QMatrix QMatrix4x4::toAffine() const
+{
+ return QMatrix(qt_math3d_convert<qreal, qrealinner>(m[0][0]),
+ qt_math3d_convert<qreal, qrealinner>(m[0][1]),
+ qt_math3d_convert<qreal, qrealinner>(m[1][0]),
+ qt_math3d_convert<qreal, qrealinner>(m[1][1]),
+ qt_math3d_convert<qreal, qrealinner>(m[3][0]),
+ qt_math3d_convert<qreal, qrealinner>(m[3][1]));
+}
+
+/*!
+ Returns the conventional Qt 2D transformation matrix that
+ corresponds to this matrix. It is assumed that this matrix
+ only contains 2D transformation elements.
+
+ \sa toAffine()
+*/
+QTransform QMatrix4x4::toTransform() const
+{
+ return QTransform(qt_math3d_convert<qreal, qrealinner>(m[0][0]),
+ qt_math3d_convert<qreal, qrealinner>(m[0][1]),
+ qt_math3d_convert<qreal, qrealinner>(m[0][3]),
+ qt_math3d_convert<qreal, qrealinner>(m[1][0]),
+ qt_math3d_convert<qreal, qrealinner>(m[1][1]),
+ qt_math3d_convert<qreal, qrealinner>(m[1][3]),
+ qt_math3d_convert<qreal, qrealinner>(m[3][0]),
+ qt_math3d_convert<qreal, qrealinner>(m[3][1]),
+ qt_math3d_convert<qreal, qrealinner>(m[3][3]));
+}
+
+/*!
+ \fn QPoint QMatrix4x4::map(const QPoint& point) const
+
+ Maps \a point by multiplying this matrix by \a point.
+
+ \sa mapRect()
+*/
+
+/*!
+ \fn QPointF QMatrix4x4::map(const QPointF& point) const
+
+ Maps \a point by multiplying this matrix by \a point.
+
+ \sa mapRect()
+*/
+
+#ifndef QT_NO_VECTOR3D
+
+/*!
+ \fn QVector3D QMatrix4x4::map(const QVector3D& point) const
+
+ Maps \a point by multiplying this matrix by \a point.
+
+ \sa mapRect()
+*/
+
+#endif
+
+#ifndef QT_NO_VECTOR4D
+
+/*!
+ \fn QVector4D QMatrix4x4::map(const QVector4D& point) const;
+
+ Maps \a point by multiplying this matrix by \a point.
+
+ \sa mapRect()
+*/
+
+#endif
+
+/*!
+ \fn QRect QMatrix4x4::mapRect(const QRect& rect) const
+
+ Maps \a rect by multiplying this matrix by the corners
+ of \a rect and then forming a new rectangle from the results.
+ The returned rectangle will be an ordinary 2D rectangle
+ with sides parallel to the horizontal and vertical axes.
+
+ \sa map()
+*/
+
+/*!
+ \fn QRectF QMatrix4x4::mapRect(const QRectF& rect) const
+
+ Maps \a rect by multiplying this matrix by the corners
+ of \a rect and then forming a new rectangle from the results.
+ The returned rectangle will be an ordinary 2D rectangle
+ with sides parallel to the horizontal and vertical axes.
+
+ \sa map()
+*/
+
+/*!
+ \fn qrealinner *QMatrix4x4::data()
+
+ Returns a pointer to the raw data of this matrix. This is indended
+ for use with raw GL functions.
+
+ \sa constData(), inferSpecialType()
+*/
+
+/*!
+ \fn const qrealinner *QMatrix4x4::data() const
+
+ Returns a constant pointer to the raw data of this matrix.
+ This is indended for use with raw GL functions.
+
+ \sa constData()
+*/
+
+/*!
+ \fn const qrealinner *QMatrix4x4::constData() const
+
+ Returns a constant pointer to the raw data of this matrix.
+ This is indended for use with raw GL functions.
+
+ \sa data()
+*/
+
+// Helper routine for inverting orthonormal matrices that consist
+// of just rotations and translations.
+QMatrix4x4 QMatrix4x4::orthonormalInverse() const
+{
+ QMatrix4x4 result(1); // The '1' says not to load identity
+
+ result.m[0][0] = m[0][0];
+ result.m[1][0] = m[0][1];
+ result.m[2][0] = m[0][2];
+
+ result.m[0][1] = m[1][0];
+ result.m[1][1] = m[1][1];
+ result.m[2][1] = m[1][2];
+
+ result.m[0][2] = m[2][0];
+ result.m[1][2] = m[2][1];
+ result.m[2][2] = m[2][2];
+
+ result.m[0][3] = 0.0f;
+ result.m[1][3] = 0.0f;
+ result.m[2][3] = 0.0f;
+
+ result.m[3][0] = -(result.m[0][0] * m[3][0] + result.m[1][0] * m[3][1] + result.m[2][0] * m[3][2]);
+ result.m[3][1] = -(result.m[0][1] * m[3][0] + result.m[1][1] * m[3][1] + result.m[2][1] * m[3][2]);
+ result.m[3][2] = -(result.m[0][2] * m[3][0] + result.m[1][2] * m[3][1] + result.m[2][2] * m[3][2]);
+ result.m[3][3] = 1.0f;
+
+ return result;
+}
+
+#ifndef QT_NO_VECTOR3D
+/*!
+ Decomposes the current rotation matrix into an \a axis of rotation plus
+ an \a angle. The result can be used to construct an equivalent rotation
+ matrix using glRotate(). It is assumed that the homogenous coordinate
+ is 1.0. The returned vector is guaranteed to be normalized.
+
+ \code
+ qreal angle;
+ QVector3D axis;
+
+ matrix.extractAxisAngle(angle, axis);
+ glRotate(angle, axis[0], axis[1], axis[2]);
+ \endcode
+
+ \sa rotate()
+*/
+void QMatrix4x4::extractAxisRotation(qreal &angle, QVector3D &axis) const
+{
+ // Orientation is dependent on the upper 3x3 matrix; subtract the
+ // homogeneous scaling element from the trace of the 4x4 matrix
+ qrealinner tr = m[0][0] + m[1][1] + m[2][2];
+ qreal cosa = qt_math3d_convert<qreal, qrealinner>(0.5f * (tr - 1.0f));
+ angle = acos(cosa) * 180.0f / M_PI;
+
+ // Any axis will work if r is zero (means no rotation)
+ if (qFuzzyCompare(angle, (qreal)0.0f)) {
+ axis.setX(1.0f);
+ axis.setY(0.0f);
+ axis.setZ(0.0f);
+ return;
+ }
+
+ if (angle < 180.0f) {
+ axis.xp = m[1][2] - m[2][1];
+ axis.yp = m[2][0] - m[0][2];
+ axis.zp = m[0][1] - m[1][0];
+ axis.normalize();
+ return;
+ }
+
+ // rads == PI
+ qrealinner tmp;
+
+ // r00 is maximum
+ if ((m[0][0] >= m[2][2]) && (m[0][0] >= m[1][1])) {
+ axis.xp = 0.5f * qvtsqrt(m[0][0] - m[1][1] - m[2][2] + 1.0f);
+ tmp = 0.5f / axis.x();
+ axis.yp = m[1][0] * tmp;
+ axis.zp = m[2][0] * tmp;
+ }
+
+ // r11 is maximum
+ if ((m[1][1] >= m[2][2]) && (m[1][1] >= m[0][0])) {
+ axis.yp = 0.5f * qvtsqrt(m[1][1] - m[0][0] - m[2][2] + 1.0f);
+ tmp = 0.5f / axis.y();
+ axis.xp = tmp * m[1][0];
+ axis.zp = tmp * m[2][1];
+ }
+
+ // r22 is maximum
+ if ((m[2][2] >= m[1][1]) && (m[2][2] >= m[0][0])) {
+ axis.zp = 0.5f * qvtsqrt(m[2][2] - m[0][0] - m[1][1] + 1.0f);
+ tmp = 0.5f / axis.z();
+ axis.xp = m[2][0]*tmp;
+ axis.yp = m[2][1]*tmp;
+ }
+}
+
+/*!
+ If this is an orthonormal transformation matrix (e.g. only rotations and
+ translations have been applied to the matrix, no scaling, or shearing)
+ then the world translational component can be obtained by calling this function.
+
+ This is most useful for camera matrices, where the negation of this vector
+ is effectively the camera world coordinates.
+*/
+QVector3D QMatrix4x4::extractTranslation() const
+{
+ return QVector3D
+ (m[0][0] * m[3][0] + m[0][1] * m[3][1] + m[0][2] * m[3][2],
+ m[1][0] * m[3][0] + m[1][1] * m[3][1] + m[1][2] * m[3][2],
+ m[2][0] * m[3][0] + m[2][1] * m[3][1] + m[2][2] * m[3][2], 1);
+}
+#endif
+
+/*!
+ Infers the special type of this matrix from its current elements.
+
+ Some operations such as translate(), scale(), and rotate() can be
+ performed more efficiently if the matrix being modified is already
+ known to be the identity, a previous translate(), a previous
+ scale(), etc.
+
+ Normally the QMatrix4x4 class keeps track of this special type internally
+ as operations are performed. However, if the matrix is modified
+ directly with operator()() or data(), then QMatrix4x4 will lose track of
+ the special type and will revert to the safest but least efficient
+ operations thereafter.
+
+ By calling inferSpecialType() after directly modifying the matrix,
+ the programmer can force QMatrix4x4 to recover the special type if
+ the elements appear to conform to one of the known optimized types.
+
+ \sa operator()(), data(), translate()
+*/
+void QMatrix4x4::inferSpecialType()
+{
+ // If the last element is not 1, then it can never be special.
+ if (m[3][3] != 1.0f) {
+ flagBits = General;
+ return;
+ }
+
+ // If the upper three elements m12, m13, and m21 are not all zero,
+ // or the lower elements below the diagonal are not all zero, then
+ // the matrix can never be special.
+ if (m[1][0] != 0.0f || m[2][0] != 0.0f || m[2][1] != 0.0f) {
+ flagBits = General;
+ return;
+ }
+ if (m[0][1] != 0.0f || m[0][2] != 0.0f || m[0][3] != 0.0f ||
+ m[1][2] != 0.0f || m[1][3] != 0.0f || m[2][3] != 0.0f) {
+ flagBits = General;
+ return;
+ }
+
+ // Determine what we have in the remaining regions of the matrix.
+ bool identityAlongDiagonal
+ = (m[0][0] == 1.0f && m[1][1] == 1.0f && m[2][2] == 1.0f);
+ bool translationPresent
+ = (m[3][0] != 0.0f || m[3][1] != 0.0f || m[3][2] != 0.0f);
+
+ // Now determine the special matrix type.
+ if (translationPresent && identityAlongDiagonal)
+ flagBits = Translation;
+ else if (translationPresent)
+ flagBits = (Translation | Scale);
+ else if (identityAlongDiagonal)
+ flagBits = Identity;
+ else
+ flagBits = Scale;
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+
+QDebug operator<<(QDebug dbg, const QMatrix4x4 &m)
+{
+ // Create a string that represents the matrix type.
+ QByteArray bits;
+ if ((m.flagBits & QMatrix4x4::Identity) != 0)
+ bits += "Identity,";
+ if ((m.flagBits & QMatrix4x4::General) != 0)
+ bits += "General,";
+ if ((m.flagBits & QMatrix4x4::Translation) != 0)
+ bits += "Translation,";
+ if ((m.flagBits & QMatrix4x4::Scale) != 0)
+ bits += "Scale,";
+ if ((m.flagBits & QMatrix4x4::Rotation) != 0)
+ bits += "Rotation,";
+ if (bits.size() > 0)
+ bits = bits.left(bits.size() - 1);
+
+ // Output in row-major order because it is more human-readable.
+ dbg.nospace() << "QMatrix4x4(type:" << bits.constData() << endl
+ << qSetFieldWidth(10)
+ << m(0, 0) << m(0, 1) << m(0, 2) << m(0, 3) << endl
+ << m(1, 0) << m(1, 1) << m(1, 2) << m(1, 3) << endl
+ << m(2, 0) << m(2, 1) << m(2, 2) << m(2, 3) << endl
+ << m(3, 0) << m(3, 1) << m(3, 2) << m(3, 3) << endl
+ << qSetFieldWidth(0) << ')';
+ return dbg.space();
+}
+
+#endif
+
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/gui/math3d/qmatrix4x4.h b/src/gui/math3d/qmatrix4x4.h
new file mode 100644
index 0000000..8ef73bf
--- /dev/null
+++ b/src/gui/math3d/qmatrix4x4.h
@@ -0,0 +1,954 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QMATRIX4X4_H
+#define QMATRIX4X4_H
+
+#include <QtGui/qvector3d.h>
+#include <QtGui/qvector4d.h>
+#include <QtGui/qquaternion.h>
+#include <QtGui/qgenericmatrix.h>
+#include <QtCore/qrect.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_MATRIX4X4
+
+class QMatrix;
+class QTransform;
+
+class Q_GUI_EXPORT QMatrix4x4
+{
+public:
+ inline QMatrix4x4() { setIdentity(); }
+ explicit QMatrix4x4(const qreal *values);
+ inline QMatrix4x4(qreal m11, qreal m12, qreal m13, qreal m14,
+ qreal m21, qreal m22, qreal m23, qreal m24,
+ qreal m31, qreal m32, qreal m33, qreal m34,
+ qreal m41, qreal m42, qreal m43, qreal m44);
+#if !defined(QT_NO_MEMBER_TEMPLATES) || defined(Q_QDOC)
+ template <int N, int M>
+ explicit QMatrix4x4(const QGenericMatrix<N, M, qreal, qrealinner>& matrix);
+#endif
+ QMatrix4x4(const qrealinner *values, int cols, int rows);
+ QMatrix4x4(const QTransform& transform);
+ QMatrix4x4(const QMatrix& matrix);
+
+ inline qreal operator()(int row, int column) const;
+ inline qrealinner& operator()(int row, int column);
+
+ inline QVector4D column(int index) const;
+ inline void setColumn(int index, const QVector4D& value);
+
+ inline QVector4D row(int index) const;
+ inline void setRow(int index, const QVector4D& value);
+
+ inline bool isIdentity() const;
+ inline void setIdentity();
+
+ inline void fill(qreal value);
+
+ qreal determinant() const;
+ QMatrix4x4 inverted(bool *invertible = 0) const;
+ QMatrix4x4 transposed() const;
+ QMatrix3x3 normalMatrix() const;
+
+ inline QMatrix4x4& operator+=(const QMatrix4x4& other);
+ inline QMatrix4x4& operator-=(const QMatrix4x4& other);
+ inline QMatrix4x4& operator*=(const QMatrix4x4& other);
+ inline QMatrix4x4& operator*=(qreal factor);
+ QMatrix4x4& operator/=(qreal divisor);
+ inline bool operator==(const QMatrix4x4& other) const;
+ inline bool operator!=(const QMatrix4x4& other) const;
+
+ friend QMatrix4x4 operator+(const QMatrix4x4& m1, const QMatrix4x4& m2);
+ friend QMatrix4x4 operator-(const QMatrix4x4& m1, const QMatrix4x4& m2);
+ friend QMatrix4x4 operator*(const QMatrix4x4& m1, const QMatrix4x4& m2);
+#ifndef QT_NO_VECTOR3D
+ friend QVector3D operator*(const QMatrix4x4& matrix, const QVector3D& vector);
+ friend QVector3D operator*(const QVector3D& vector, const QMatrix4x4& matrix);
+#endif
+#ifndef QT_NO_VECTOR4D
+ friend QVector4D operator*(const QVector4D& vector, const QMatrix4x4& matrix);
+ friend QVector4D operator*(const QMatrix4x4& matrix, const QVector4D& vector);
+#endif
+ friend QPoint operator*(const QPoint& point, const QMatrix4x4& matrix);
+ friend QPointF operator*(const QPointF& point, const QMatrix4x4& matrix);
+ friend QMatrix4x4 operator-(const QMatrix4x4& matrix);
+ friend QPoint operator*(const QMatrix4x4& matrix, const QPoint& point);
+ friend QPointF operator*(const QMatrix4x4& matrix, const QPointF& point);
+ friend QMatrix4x4 operator*(qreal factor, const QMatrix4x4& matrix);
+ friend QMatrix4x4 operator*(const QMatrix4x4& matrix, qreal factor);
+ friend Q_GUI_EXPORT QMatrix4x4 operator/(const QMatrix4x4& matrix, qreal divisor);
+
+ friend inline bool qFuzzyCompare(const QMatrix4x4& m1, const QMatrix4x4& m2);
+
+#ifndef QT_NO_VECTOR3D
+ QMatrix4x4& scale(const QVector3D& vector);
+ QMatrix4x4& translate(const QVector3D& vector);
+ QMatrix4x4& rotate(qreal angle, const QVector3D& vector);
+#endif
+ QMatrix4x4& scale(qreal x, qreal y, qreal z = 1.0f);
+ QMatrix4x4& scale(qreal factor);
+ QMatrix4x4& translate(qreal x, qreal y, qreal z = 0.0f);
+ QMatrix4x4& rotate(qreal angle, qreal x, qreal y, qreal z = 0.0f);
+#ifndef QT_NO_QUATERNION
+ QMatrix4x4& rotate(const QQuaternion& quaternion);
+#endif
+
+#ifndef QT_NO_VECTOR3D
+ void extractAxisRotation(qreal &angle, QVector3D &axis) const;
+ QVector3D extractTranslation() const;
+#endif
+
+ QMatrix4x4& ortho(const QRect& rect);
+ QMatrix4x4& ortho(const QRectF& rect);
+ QMatrix4x4& ortho(qreal left, qreal right, qreal bottom, qreal top, qreal nearPlane, qreal farPlane);
+ QMatrix4x4& frustum(qreal left, qreal right, qreal bottom, qreal top, qreal nearPlane, qreal farPlane);
+ QMatrix4x4& perspective(qreal angle, qreal aspect, qreal nearPlane, qreal farPlane);
+#ifndef QT_NO_VECTOR3D
+ QMatrix4x4& lookAt(const QVector3D& eye, const QVector3D& center, const QVector3D& up);
+#endif
+ QMatrix4x4& flipCoordinates();
+
+ void toValueArray(qreal *values) const;
+
+ QMatrix toAffine() const;
+ QTransform toTransform() const;
+
+ QPoint map(const QPoint& point) const;
+ QPointF map(const QPointF& point) const;
+#ifndef QT_NO_VECTOR3D
+ QVector3D map(const QVector3D& point) const;
+#endif
+#ifndef QT_NO_VECTOR4D
+ QVector4D map(const QVector4D& point) const;
+#endif
+ QRect mapRect(const QRect& rect) const;
+ QRectF mapRect(const QRectF& rect) const;
+
+#if !defined(QT_NO_MEMBER_TEMPLATES) || defined(Q_QDOC)
+ template <int N, int M>
+ QGenericMatrix<N, M, qreal, qrealinner> toGenericMatrix() const;
+#endif
+
+ inline qrealinner *data();
+ inline const qrealinner *data() const { return m[0]; }
+ inline const qrealinner *constData() const { return m[0]; }
+
+ void inferSpecialType();
+
+#ifndef QT_NO_DEBUG_STREAM
+ friend Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QMatrix4x4 &m);
+#endif
+
+private:
+ qrealinner m[4][4]; // Column-major order to match OpenGL.
+ int flagBits; // Flag bits from the enum below.
+
+ enum {
+ Identity = 0x0001, // Identity matrix
+ General = 0x0002, // General matrix, unknown contents
+ Translation = 0x0004, // Contains a simple translation
+ Scale = 0x0008, // Contains a simple scale
+ Rotation = 0x0010 // Contains a simple rotation
+ };
+
+ // Construct without initializing identity matrix.
+ QMatrix4x4(int) { flagBits = General; }
+
+ QMatrix4x4 orthonormalInverse() const;
+};
+
+inline QMatrix4x4::QMatrix4x4
+ (qreal m11, qreal m12, qreal m13, qreal m14,
+ qreal m21, qreal m22, qreal m23, qreal m24,
+ qreal m31, qreal m32, qreal m33, qreal m34,
+ qreal m41, qreal m42, qreal m43, qreal m44)
+{
+ m[0][0] = m11; m[0][1] = m21; m[0][2] = m31; m[0][3] = m41;
+ m[1][0] = m12; m[1][1] = m22; m[1][2] = m32; m[1][3] = m42;
+ m[2][0] = m13; m[2][1] = m23; m[2][2] = m33; m[2][3] = m43;
+ m[3][0] = m14; m[3][1] = m24; m[3][2] = m34; m[3][3] = m44;
+ flagBits = General;
+}
+
+#if !defined(QT_NO_MEMBER_TEMPLATES)
+
+template <int N, int M>
+Q_INLINE_TEMPLATE QMatrix4x4::QMatrix4x4
+ (const QGenericMatrix<N, M, qreal, qrealinner>& matrix)
+{
+ const qrealinner *values = matrix.constData();
+ for (int col = 0; col < 4; ++col) {
+ for (int row = 0; row < 4; ++row) {
+ if (col < N && row < M)
+ m[col][row] = values[col * M + row];
+ else if (col == row)
+ m[col][row] = 1.0f;
+ else
+ m[col][row] = 0.0f;
+ }
+ }
+ flagBits = General;
+}
+
+template <int N, int M>
+QGenericMatrix<N, M, qreal, qrealinner> QMatrix4x4::toGenericMatrix() const
+{
+ QGenericMatrix<N, M, qreal, qrealinner> result;
+ qrealinner *values = result.data();
+ for (int col = 0; col < N; ++col) {
+ for (int row = 0; row < M; ++row) {
+ if (col < 4 && row < 4)
+ values[col * M + row] = m[col][row];
+ else if (col == row)
+ values[col * M + row] = 1.0f;
+ else
+ values[col * M + row] = 0.0f;
+ }
+ }
+ return result;
+}
+
+#endif
+
+inline qreal QMatrix4x4::operator()(int row, int column) const
+{
+ Q_ASSERT(row >= 0 && row < 4 && column >= 0 && column < 4);
+ return qt_math3d_convert<qreal, qrealinner>(m[column][row]);
+}
+
+inline qrealinner& QMatrix4x4::operator()(int row, int column)
+{
+ Q_ASSERT(row >= 0 && row < 4 && column >= 0 && column < 4);
+ flagBits = General;
+ return m[column][row];
+}
+
+inline QVector4D QMatrix4x4::column(int index) const
+{
+ Q_ASSERT(index >= 0 && index < 4);
+ return QVector4D(m[index][0], m[index][1], m[index][2], m[index][3], 1);
+}
+
+inline void QMatrix4x4::setColumn(int index, const QVector4D& value)
+{
+ Q_ASSERT(index >= 0 && index < 4);
+ m[index][0] = value.xp;
+ m[index][1] = value.yp;
+ m[index][2] = value.zp;
+ m[index][3] = value.wp;
+ flagBits = General;
+}
+
+inline QVector4D QMatrix4x4::row(int index) const
+{
+ Q_ASSERT(index >= 0 && index < 4);
+ return QVector4D(m[0][index], m[1][index], m[2][index], m[3][index], 1);
+}
+
+inline void QMatrix4x4::setRow(int index, const QVector4D& value)
+{
+ Q_ASSERT(index >= 0 && index < 4);
+ m[0][index] = value.xp;
+ m[1][index] = value.yp;
+ m[2][index] = value.zp;
+ m[3][index] = value.wp;
+ flagBits = General;
+}
+
+Q_GUI_EXPORT QMatrix4x4 operator/(const QMatrix4x4& matrix, qreal divisor);
+
+inline bool QMatrix4x4::isIdentity() const
+{
+ if (flagBits == Identity)
+ return true;
+ if (m[0][0] != 1.0f || m[0][1] != 0.0f || m[0][2] != 0.0f)
+ return false;
+ if (m[0][3] != 0.0f || m[1][0] != 0.0f || m[1][1] != 1.0f)
+ return false;
+ if (m[1][2] != 0.0f || m[1][3] != 0.0f || m[2][0] != 0.0f)
+ return false;
+ if (m[2][1] != 0.0f || m[2][2] != 1.0f || m[2][3] != 0.0f)
+ return false;
+ if (m[3][0] != 0.0f || m[3][1] != 0.0f || m[3][2] != 0.0f)
+ return false;
+ return (m[3][3] == 1.0f);
+}
+
+inline void QMatrix4x4::setIdentity()
+{
+ m[0][0] = 1.0f;
+ m[0][1] = 0.0f;
+ m[0][2] = 0.0f;
+ m[0][3] = 0.0f;
+ m[1][0] = 0.0f;
+ m[1][1] = 1.0f;
+ m[1][2] = 0.0f;
+ m[1][3] = 0.0f;
+ m[2][0] = 0.0f;
+ m[2][1] = 0.0f;
+ m[2][2] = 1.0f;
+ m[2][3] = 0.0f;
+ m[3][0] = 0.0f;
+ m[3][1] = 0.0f;
+ m[3][2] = 0.0f;
+ m[3][3] = 1.0f;
+ flagBits = Identity;
+}
+
+inline void QMatrix4x4::fill(qreal value)
+{
+ m[0][0] = value;
+ m[0][1] = value;
+ m[0][2] = value;
+ m[0][3] = value;
+ m[1][0] = value;
+ m[1][1] = value;
+ m[1][2] = value;
+ m[1][3] = value;
+ m[2][0] = value;
+ m[2][1] = value;
+ m[2][2] = value;
+ m[2][3] = value;
+ m[3][0] = value;
+ m[3][1] = value;
+ m[3][2] = value;
+ m[3][3] = value;
+ flagBits = General;
+}
+
+inline QMatrix4x4& QMatrix4x4::operator+=(const QMatrix4x4& other)
+{
+ m[0][0] += other.m[0][0];
+ m[0][1] += other.m[0][1];
+ m[0][2] += other.m[0][2];
+ m[0][3] += other.m[0][3];
+ m[1][0] += other.m[1][0];
+ m[1][1] += other.m[1][1];
+ m[1][2] += other.m[1][2];
+ m[1][3] += other.m[1][3];
+ m[2][0] += other.m[2][0];
+ m[2][1] += other.m[2][1];
+ m[2][2] += other.m[2][2];
+ m[2][3] += other.m[2][3];
+ m[3][0] += other.m[3][0];
+ m[3][1] += other.m[3][1];
+ m[3][2] += other.m[3][2];
+ m[3][3] += other.m[3][3];
+ flagBits = General;
+ return *this;
+}
+
+inline QMatrix4x4& QMatrix4x4::operator-=(const QMatrix4x4& other)
+{
+ m[0][0] -= other.m[0][0];
+ m[0][1] -= other.m[0][1];
+ m[0][2] -= other.m[0][2];
+ m[0][3] -= other.m[0][3];
+ m[1][0] -= other.m[1][0];
+ m[1][1] -= other.m[1][1];
+ m[1][2] -= other.m[1][2];
+ m[1][3] -= other.m[1][3];
+ m[2][0] -= other.m[2][0];
+ m[2][1] -= other.m[2][1];
+ m[2][2] -= other.m[2][2];
+ m[2][3] -= other.m[2][3];
+ m[3][0] -= other.m[3][0];
+ m[3][1] -= other.m[3][1];
+ m[3][2] -= other.m[3][2];
+ m[3][3] -= other.m[3][3];
+ flagBits = General;
+ return *this;
+}
+
+inline QMatrix4x4& QMatrix4x4::operator*=(const QMatrix4x4& other)
+{
+ if (flagBits == Identity) {
+ *this = other;
+ return *this;
+ } else if (other.flagBits == Identity) {
+ return *this;
+ } else {
+ *this = *this * other;
+ return *this;
+ }
+}
+
+inline QMatrix4x4& QMatrix4x4::operator*=(qreal factor)
+{
+ qrealinner f(factor);
+ m[0][0] *= f;
+ m[0][1] *= f;
+ m[0][2] *= f;
+ m[0][3] *= f;
+ m[1][0] *= f;
+ m[1][1] *= f;
+ m[1][2] *= f;
+ m[1][3] *= f;
+ m[2][0] *= f;
+ m[2][1] *= f;
+ m[2][2] *= f;
+ m[2][3] *= f;
+ m[3][0] *= f;
+ m[3][1] *= f;
+ m[3][2] *= f;
+ m[3][3] *= f;
+ flagBits = General;
+ return *this;
+}
+
+inline bool QMatrix4x4::operator==(const QMatrix4x4& other) const
+{
+ return m[0][0] == other.m[0][0] &&
+ m[0][1] == other.m[0][1] &&
+ m[0][2] == other.m[0][2] &&
+ m[0][3] == other.m[0][3] &&
+ m[1][0] == other.m[1][0] &&
+ m[1][1] == other.m[1][1] &&
+ m[1][2] == other.m[1][2] &&
+ m[1][3] == other.m[1][3] &&
+ m[2][0] == other.m[2][0] &&
+ m[2][1] == other.m[2][1] &&
+ m[2][2] == other.m[2][2] &&
+ m[2][3] == other.m[2][3] &&
+ m[3][0] == other.m[3][0] &&
+ m[3][1] == other.m[3][1] &&
+ m[3][2] == other.m[3][2] &&
+ m[3][3] == other.m[3][3];
+}
+
+inline bool QMatrix4x4::operator!=(const QMatrix4x4& other) const
+{
+ return m[0][0] != other.m[0][0] ||
+ m[0][1] != other.m[0][1] ||
+ m[0][2] != other.m[0][2] ||
+ m[0][3] != other.m[0][3] ||
+ m[1][0] != other.m[1][0] ||
+ m[1][1] != other.m[1][1] ||
+ m[1][2] != other.m[1][2] ||
+ m[1][3] != other.m[1][3] ||
+ m[2][0] != other.m[2][0] ||
+ m[2][1] != other.m[2][1] ||
+ m[2][2] != other.m[2][2] ||
+ m[2][3] != other.m[2][3] ||
+ m[3][0] != other.m[3][0] ||
+ m[3][1] != other.m[3][1] ||
+ m[3][2] != other.m[3][2] ||
+ m[3][3] != other.m[3][3];
+}
+
+inline QMatrix4x4 operator+(const QMatrix4x4& m1, const QMatrix4x4& m2)
+{
+ QMatrix4x4 m(1);
+ m.m[0][0] = m1.m[0][0] + m2.m[0][0];
+ m.m[0][1] = m1.m[0][1] + m2.m[0][1];
+ m.m[0][2] = m1.m[0][2] + m2.m[0][2];
+ m.m[0][3] = m1.m[0][3] + m2.m[0][3];
+ m.m[1][0] = m1.m[1][0] + m2.m[1][0];
+ m.m[1][1] = m1.m[1][1] + m2.m[1][1];
+ m.m[1][2] = m1.m[1][2] + m2.m[1][2];
+ m.m[1][3] = m1.m[1][3] + m2.m[1][3];
+ m.m[2][0] = m1.m[2][0] + m2.m[2][0];
+ m.m[2][1] = m1.m[2][1] + m2.m[2][1];
+ m.m[2][2] = m1.m[2][2] + m2.m[2][2];
+ m.m[2][3] = m1.m[2][3] + m2.m[2][3];
+ m.m[3][0] = m1.m[3][0] + m2.m[3][0];
+ m.m[3][1] = m1.m[3][1] + m2.m[3][1];
+ m.m[3][2] = m1.m[3][2] + m2.m[3][2];
+ m.m[3][3] = m1.m[3][3] + m2.m[3][3];
+ return m;
+}
+
+inline QMatrix4x4 operator-(const QMatrix4x4& m1, const QMatrix4x4& m2)
+{
+ QMatrix4x4 m(1);
+ m.m[0][0] = m1.m[0][0] - m2.m[0][0];
+ m.m[0][1] = m1.m[0][1] - m2.m[0][1];
+ m.m[0][2] = m1.m[0][2] - m2.m[0][2];
+ m.m[0][3] = m1.m[0][3] - m2.m[0][3];
+ m.m[1][0] = m1.m[1][0] - m2.m[1][0];
+ m.m[1][1] = m1.m[1][1] - m2.m[1][1];
+ m.m[1][2] = m1.m[1][2] - m2.m[1][2];
+ m.m[1][3] = m1.m[1][3] - m2.m[1][3];
+ m.m[2][0] = m1.m[2][0] - m2.m[2][0];
+ m.m[2][1] = m1.m[2][1] - m2.m[2][1];
+ m.m[2][2] = m1.m[2][2] - m2.m[2][2];
+ m.m[2][3] = m1.m[2][3] - m2.m[2][3];
+ m.m[3][0] = m1.m[3][0] - m2.m[3][0];
+ m.m[3][1] = m1.m[3][1] - m2.m[3][1];
+ m.m[3][2] = m1.m[3][2] - m2.m[3][2];
+ m.m[3][3] = m1.m[3][3] - m2.m[3][3];
+ return m;
+}
+
+inline QMatrix4x4 operator*(const QMatrix4x4& m1, const QMatrix4x4& m2)
+{
+ if (m1.flagBits == QMatrix4x4::Identity)
+ return m2;
+ else if (m2.flagBits == QMatrix4x4::Identity)
+ return m1;
+
+ QMatrix4x4 m(1);
+ m.m[0][0] = m1.m[0][0] * m2.m[0][0] +
+ m1.m[1][0] * m2.m[0][1] +
+ m1.m[2][0] * m2.m[0][2] +
+ m1.m[3][0] * m2.m[0][3];
+ m.m[0][1] = m1.m[0][1] * m2.m[0][0] +
+ m1.m[1][1] * m2.m[0][1] +
+ m1.m[2][1] * m2.m[0][2] +
+ m1.m[3][1] * m2.m[0][3];
+ m.m[0][2] = m1.m[0][2] * m2.m[0][0] +
+ m1.m[1][2] * m2.m[0][1] +
+ m1.m[2][2] * m2.m[0][2] +
+ m1.m[3][2] * m2.m[0][3];
+ m.m[0][3] = m1.m[0][3] * m2.m[0][0] +
+ m1.m[1][3] * m2.m[0][1] +
+ m1.m[2][3] * m2.m[0][2] +
+ m1.m[3][3] * m2.m[0][3];
+ m.m[1][0] = m1.m[0][0] * m2.m[1][0] +
+ m1.m[1][0] * m2.m[1][1] +
+ m1.m[2][0] * m2.m[1][2] +
+ m1.m[3][0] * m2.m[1][3];
+ m.m[1][1] = m1.m[0][1] * m2.m[1][0] +
+ m1.m[1][1] * m2.m[1][1] +
+ m1.m[2][1] * m2.m[1][2] +
+ m1.m[3][1] * m2.m[1][3];
+ m.m[1][2] = m1.m[0][2] * m2.m[1][0] +
+ m1.m[1][2] * m2.m[1][1] +
+ m1.m[2][2] * m2.m[1][2] +
+ m1.m[3][2] * m2.m[1][3];
+ m.m[1][3] = m1.m[0][3] * m2.m[1][0] +
+ m1.m[1][3] * m2.m[1][1] +
+ m1.m[2][3] * m2.m[1][2] +
+ m1.m[3][3] * m2.m[1][3];
+ m.m[2][0] = m1.m[0][0] * m2.m[2][0] +
+ m1.m[1][0] * m2.m[2][1] +
+ m1.m[2][0] * m2.m[2][2] +
+ m1.m[3][0] * m2.m[2][3];
+ m.m[2][1] = m1.m[0][1] * m2.m[2][0] +
+ m1.m[1][1] * m2.m[2][1] +
+ m1.m[2][1] * m2.m[2][2] +
+ m1.m[3][1] * m2.m[2][3];
+ m.m[2][2] = m1.m[0][2] * m2.m[2][0] +
+ m1.m[1][2] * m2.m[2][1] +
+ m1.m[2][2] * m2.m[2][2] +
+ m1.m[3][2] * m2.m[2][3];
+ m.m[2][3] = m1.m[0][3] * m2.m[2][0] +
+ m1.m[1][3] * m2.m[2][1] +
+ m1.m[2][3] * m2.m[2][2] +
+ m1.m[3][3] * m2.m[2][3];
+ m.m[3][0] = m1.m[0][0] * m2.m[3][0] +
+ m1.m[1][0] * m2.m[3][1] +
+ m1.m[2][0] * m2.m[3][2] +
+ m1.m[3][0] * m2.m[3][3];
+ m.m[3][1] = m1.m[0][1] * m2.m[3][0] +
+ m1.m[1][1] * m2.m[3][1] +
+ m1.m[2][1] * m2.m[3][2] +
+ m1.m[3][1] * m2.m[3][3];
+ m.m[3][2] = m1.m[0][2] * m2.m[3][0] +
+ m1.m[1][2] * m2.m[3][1] +
+ m1.m[2][2] * m2.m[3][2] +
+ m1.m[3][2] * m2.m[3][3];
+ m.m[3][3] = m1.m[0][3] * m2.m[3][0] +
+ m1.m[1][3] * m2.m[3][1] +
+ m1.m[2][3] * m2.m[3][2] +
+ m1.m[3][3] * m2.m[3][3];
+ return m;
+}
+
+#ifndef QT_NO_VECTOR3D
+
+inline QVector3D operator*(const QVector3D& vector, const QMatrix4x4& matrix)
+{
+ qrealinner x, y, z, w;
+ x = vector.xp * matrix.m[0][0] +
+ vector.yp * matrix.m[0][1] +
+ vector.zp * matrix.m[0][2] +
+ matrix.m[0][3];
+ y = vector.xp * matrix.m[1][0] +
+ vector.yp * matrix.m[1][1] +
+ vector.zp * matrix.m[1][2] +
+ matrix.m[1][3];
+ z = vector.xp * matrix.m[2][0] +
+ vector.yp * matrix.m[2][1] +
+ vector.zp * matrix.m[2][2] +
+ matrix.m[2][3];
+ w = vector.xp * matrix.m[3][0] +
+ vector.yp * matrix.m[3][1] +
+ vector.zp * matrix.m[3][2] +
+ matrix.m[3][3];
+ if (w == 1.0f)
+ return QVector3D(x, y, z, 1);
+ else
+ return QVector3D(x / w, y / w, z / w, 1);
+}
+
+inline QVector3D operator*(const QMatrix4x4& matrix, const QVector3D& vector)
+{
+ qrealinner x, y, z, w;
+ x = vector.xp * matrix.m[0][0] +
+ vector.yp * matrix.m[1][0] +
+ vector.zp * matrix.m[2][0] +
+ matrix.m[3][0];
+ y = vector.xp * matrix.m[0][1] +
+ vector.yp * matrix.m[1][1] +
+ vector.zp * matrix.m[2][1] +
+ matrix.m[3][1];
+ z = vector.xp * matrix.m[0][2] +
+ vector.yp * matrix.m[1][2] +
+ vector.zp * matrix.m[2][2] +
+ matrix.m[3][2];
+ w = vector.xp * matrix.m[0][3] +
+ vector.yp * matrix.m[1][3] +
+ vector.zp * matrix.m[2][3] +
+ matrix.m[3][3];
+ if (w == 1.0f)
+ return QVector3D(x, y, z, 1);
+ else
+ return QVector3D(x / w, y / w, z / w, 1);
+}
+
+#endif
+
+#ifndef QT_NO_VECTOR4D
+
+inline QVector4D operator*(const QVector4D& vector, const QMatrix4x4& matrix)
+{
+ qrealinner x, y, z, w;
+ x = vector.xp * matrix.m[0][0] +
+ vector.yp * matrix.m[0][1] +
+ vector.zp * matrix.m[0][2] +
+ vector.wp * matrix.m[0][3];
+ y = vector.xp * matrix.m[1][0] +
+ vector.yp * matrix.m[1][1] +
+ vector.zp * matrix.m[1][2] +
+ vector.wp * matrix.m[1][3];
+ z = vector.xp * matrix.m[2][0] +
+ vector.yp * matrix.m[2][1] +
+ vector.zp * matrix.m[2][2] +
+ vector.wp * matrix.m[2][3];
+ w = vector.xp * matrix.m[3][0] +
+ vector.yp * matrix.m[3][1] +
+ vector.zp * matrix.m[3][2] +
+ vector.wp * matrix.m[3][3];
+ return QVector4D(x, y, z, w, 1);
+}
+
+inline QVector4D operator*(const QMatrix4x4& matrix, const QVector4D& vector)
+{
+ qrealinner x, y, z, w;
+ x = vector.xp * matrix.m[0][0] +
+ vector.yp * matrix.m[1][0] +
+ vector.zp * matrix.m[2][0] +
+ vector.wp * matrix.m[3][0];
+ y = vector.xp * matrix.m[0][1] +
+ vector.yp * matrix.m[1][1] +
+ vector.zp * matrix.m[2][1] +
+ vector.wp * matrix.m[3][1];
+ z = vector.xp * matrix.m[0][2] +
+ vector.yp * matrix.m[1][2] +
+ vector.zp * matrix.m[2][2] +
+ vector.wp * matrix.m[3][2];
+ w = vector.xp * matrix.m[0][3] +
+ vector.yp * matrix.m[1][3] +
+ vector.zp * matrix.m[2][3] +
+ vector.wp * matrix.m[3][3];
+ return QVector4D(x, y, z, w, 1);
+}
+
+#endif
+
+inline QPoint operator*(const QPoint& point, const QMatrix4x4& matrix)
+{
+ qrealinner xin, yin;
+ qrealinner x, y, w;
+ xin = point.x();
+ yin = point.y();
+ x = xin * matrix.m[0][0] +
+ yin * matrix.m[0][1] +
+ matrix.m[0][3];
+ y = xin * matrix.m[1][0] +
+ yin * matrix.m[1][1] +
+ matrix.m[1][3];
+ w = xin * matrix.m[3][0] +
+ yin * matrix.m[3][1] +
+ matrix.m[3][3];
+ if (w == 1.0f)
+ return QPoint(qRound(x), qRound(y));
+ else
+ return QPoint(qRound(x / w), qRound(y / w));
+}
+
+inline QPointF operator*(const QPointF& point, const QMatrix4x4& matrix)
+{
+ qrealinner xin, yin;
+ qrealinner x, y, w;
+ xin = point.x();
+ yin = point.y();
+ x = xin * matrix.m[0][0] +
+ yin * matrix.m[0][1] +
+ matrix.m[0][3];
+ y = xin * matrix.m[1][0] +
+ yin * matrix.m[1][1] +
+ matrix.m[1][3];
+ w = xin * matrix.m[3][0] +
+ yin * matrix.m[3][1] +
+ matrix.m[3][3];
+ if (w == 1.0f) {
+ return QPointF(qt_math3d_convert<qreal, qrealinner>(x),
+ qt_math3d_convert<qreal, qrealinner>(y));
+ } else {
+ return QPointF(qt_math3d_convert<qreal, qrealinner>(x / w),
+ qt_math3d_convert<qreal, qrealinner>(y / w));
+ }
+}
+
+inline QPoint operator*(const QMatrix4x4& matrix, const QPoint& point)
+{
+ qrealinner xin, yin;
+ qrealinner x, y, w;
+ xin = point.x();
+ yin = point.y();
+ x = xin * matrix.m[0][0] +
+ yin * matrix.m[1][0] +
+ matrix.m[3][0];
+ y = xin * matrix.m[0][1] +
+ yin * matrix.m[1][1] +
+ matrix.m[3][1];
+ w = xin * matrix.m[0][3] +
+ yin * matrix.m[1][3] +
+ matrix.m[3][3];
+ if (w == 1.0f)
+ return QPoint(qRound(x), qRound(y));
+ else
+ return QPoint(qRound(x / w), qRound(y / w));
+}
+
+inline QPointF operator*(const QMatrix4x4& matrix, const QPointF& point)
+{
+ qrealinner xin, yin;
+ qrealinner x, y, w;
+ xin = point.x();
+ yin = point.y();
+ x = xin * matrix.m[0][0] +
+ yin * matrix.m[1][0] +
+ matrix.m[3][0];
+ y = xin * matrix.m[0][1] +
+ yin * matrix.m[1][1] +
+ matrix.m[3][1];
+ w = xin * matrix.m[0][3] +
+ yin * matrix.m[1][3] +
+ matrix.m[3][3];
+ if (w == 1.0f) {
+ return QPointF(qt_math3d_convert<qreal, qrealinner>(x),
+ qt_math3d_convert<qreal, qrealinner>(y));
+ } else {
+ return QPointF(qt_math3d_convert<qreal, qrealinner>(x / w),
+ qt_math3d_convert<qreal, qrealinner>(y / w));
+ }
+}
+
+inline QMatrix4x4 operator-(const QMatrix4x4& matrix)
+{
+ QMatrix4x4 m(1);
+ m.m[0][0] = -matrix.m[0][0];
+ m.m[0][1] = -matrix.m[0][1];
+ m.m[0][2] = -matrix.m[0][2];
+ m.m[0][3] = -matrix.m[0][3];
+ m.m[1][0] = -matrix.m[1][0];
+ m.m[1][1] = -matrix.m[1][1];
+ m.m[1][2] = -matrix.m[1][2];
+ m.m[1][3] = -matrix.m[1][3];
+ m.m[2][0] = -matrix.m[2][0];
+ m.m[2][1] = -matrix.m[2][1];
+ m.m[2][2] = -matrix.m[2][2];
+ m.m[2][3] = -matrix.m[2][3];
+ m.m[3][0] = -matrix.m[3][0];
+ m.m[3][1] = -matrix.m[3][1];
+ m.m[3][2] = -matrix.m[3][2];
+ m.m[3][3] = -matrix.m[3][3];
+ return m;
+}
+
+inline QMatrix4x4 operator*(qreal factor, const QMatrix4x4& matrix)
+{
+ QMatrix4x4 m(1);
+ qrealinner f(factor);
+ m.m[0][0] = matrix.m[0][0] * f;
+ m.m[0][1] = matrix.m[0][1] * f;
+ m.m[0][2] = matrix.m[0][2] * f;
+ m.m[0][3] = matrix.m[0][3] * f;
+ m.m[1][0] = matrix.m[1][0] * f;
+ m.m[1][1] = matrix.m[1][1] * f;
+ m.m[1][2] = matrix.m[1][2] * f;
+ m.m[1][3] = matrix.m[1][3] * f;
+ m.m[2][0] = matrix.m[2][0] * f;
+ m.m[2][1] = matrix.m[2][1] * f;
+ m.m[2][2] = matrix.m[2][2] * f;
+ m.m[2][3] = matrix.m[2][3] * f;
+ m.m[3][0] = matrix.m[3][0] * f;
+ m.m[3][1] = matrix.m[3][1] * f;
+ m.m[3][2] = matrix.m[3][2] * f;
+ m.m[3][3] = matrix.m[3][3] * f;
+ return m;
+}
+
+inline QMatrix4x4 operator*(const QMatrix4x4& matrix, qreal factor)
+{
+ QMatrix4x4 m(1);
+ qrealinner f(factor);
+ m.m[0][0] = matrix.m[0][0] * f;
+ m.m[0][1] = matrix.m[0][1] * f;
+ m.m[0][2] = matrix.m[0][2] * f;
+ m.m[0][3] = matrix.m[0][3] * f;
+ m.m[1][0] = matrix.m[1][0] * f;
+ m.m[1][1] = matrix.m[1][1] * f;
+ m.m[1][2] = matrix.m[1][2] * f;
+ m.m[1][3] = matrix.m[1][3] * f;
+ m.m[2][0] = matrix.m[2][0] * f;
+ m.m[2][1] = matrix.m[2][1] * f;
+ m.m[2][2] = matrix.m[2][2] * f;
+ m.m[2][3] = matrix.m[2][3] * f;
+ m.m[3][0] = matrix.m[3][0] * f;
+ m.m[3][1] = matrix.m[3][1] * f;
+ m.m[3][2] = matrix.m[3][2] * f;
+ m.m[3][3] = matrix.m[3][3] * f;
+ return m;
+}
+
+inline bool qFuzzyCompare(const QMatrix4x4& m1, const QMatrix4x4& m2)
+{
+ return qFuzzyCompare(m1.m[0][0], m2.m[0][0]) &&
+ qFuzzyCompare(m1.m[0][1], m2.m[0][1]) &&
+ qFuzzyCompare(m1.m[0][2], m2.m[0][2]) &&
+ qFuzzyCompare(m1.m[0][3], m2.m[0][3]) &&
+ qFuzzyCompare(m1.m[1][0], m2.m[1][0]) &&
+ qFuzzyCompare(m1.m[1][1], m2.m[1][1]) &&
+ qFuzzyCompare(m1.m[1][2], m2.m[1][2]) &&
+ qFuzzyCompare(m1.m[1][3], m2.m[1][3]) &&
+ qFuzzyCompare(m1.m[2][0], m2.m[2][0]) &&
+ qFuzzyCompare(m1.m[2][1], m2.m[2][1]) &&
+ qFuzzyCompare(m1.m[2][2], m2.m[2][2]) &&
+ qFuzzyCompare(m1.m[2][3], m2.m[2][3]) &&
+ qFuzzyCompare(m1.m[3][0], m2.m[3][0]) &&
+ qFuzzyCompare(m1.m[3][1], m2.m[3][1]) &&
+ qFuzzyCompare(m1.m[3][2], m2.m[3][2]) &&
+ qFuzzyCompare(m1.m[3][3], m2.m[3][3]);
+}
+
+inline QPoint QMatrix4x4::map(const QPoint& point) const
+{
+ return *this * point;
+}
+
+inline QPointF QMatrix4x4::map(const QPointF& point) const
+{
+ return *this * point;
+}
+
+#ifndef QT_NO_VECTOR3D
+
+inline QVector3D QMatrix4x4::map(const QVector3D& point) const
+{
+ return *this * point;
+}
+
+#endif
+
+#ifndef QT_NO_VECTOR4D
+
+inline QVector4D QMatrix4x4::map(const QVector4D& point) const
+{
+ return *this * point;
+}
+
+#endif
+
+inline QRect QMatrix4x4::mapRect(const QRect& rect) const
+{
+ QPoint tl = map(rect.topLeft()); QPoint tr = map(rect.topRight());
+ QPoint bl = map(rect.bottomLeft()); QPoint br = map(rect.bottomRight());
+
+ int xmin = qMin(qMin(tl.x(), tr.x()), qMin(bl.x(), br.x()));
+ int xmax = qMax(qMax(tl.x(), tr.x()), qMax(bl.x(), br.x()));
+ int ymin = qMin(qMin(tl.y(), tr.y()), qMin(bl.y(), br.y()));
+ int ymax = qMax(qMax(tl.y(), tr.y()), qMax(bl.y(), br.y()));
+
+ return QRect(QPoint(xmin, ymin), QPoint(xmax, ymax));
+}
+
+inline QRectF QMatrix4x4::mapRect(const QRectF& rect) const
+{
+ QPointF tl = map(rect.topLeft()); QPointF tr = map(rect.topRight());
+ QPointF bl = map(rect.bottomLeft()); QPointF br = map(rect.bottomRight());
+
+ qreal xmin = qMin(qMin(tl.x(), tr.x()), qMin(bl.x(), br.x()));
+ qreal xmax = qMax(qMax(tl.x(), tr.x()), qMax(bl.x(), br.x()));
+ qreal ymin = qMin(qMin(tl.y(), tr.y()), qMin(bl.y(), br.y()));
+ qreal ymax = qMax(qMax(tl.y(), tr.y()), qMax(bl.y(), br.y()));
+
+ return QRectF(QPointF(xmin, ymin), QPointF(xmax, ymax));
+}
+
+inline qrealinner *QMatrix4x4::data()
+{
+ // We have to assume that the caller will modify the matrix elements,
+ // so we flip it over to "General" mode.
+ flagBits = General;
+ return m[0];
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QMatrix4x4 &m);
+#endif
+
+template <int N, int M>
+QMatrix4x4 qGenericMatrixToMatrix4x4(const QGenericMatrix<N, M, qreal, qrealinner>& matrix)
+{
+ return QMatrix4x4(matrix.constData(), N, M);
+}
+
+template <int N, int M>
+QGenericMatrix<N, M, qreal, qrealinner> qGenericMatrixFromMatrix4x4(const QMatrix4x4& matrix)
+{
+ QGenericMatrix<N, M, qreal, qrealinner> result;
+ const qrealinner *m = matrix.constData();
+ qrealinner *values = result.data();
+ for (int col = 0; col < N; ++col) {
+ for (int row = 0; row < M; ++row) {
+ if (col < 4 && row < 4)
+ values[col * M + row] = m[col * 4 + row];
+ else if (col == row)
+ values[col * M + row] = 1.0f;
+ else
+ values[col * M + row] = 0.0f;
+ }
+ }
+ return result;
+}
+
+#endif
+
+QT_END_NAMESPACE
+
+#ifndef QT_NO_MATRIX4X4
+Q_DECLARE_METATYPE(QMatrix4x4)
+#endif
+
+QT_END_HEADER
+
+#endif
diff --git a/src/gui/math3d/qquaternion.cpp b/src/gui/math3d/qquaternion.cpp
new file mode 100644
index 0000000..730844f
--- /dev/null
+++ b/src/gui/math3d/qquaternion.cpp
@@ -0,0 +1,513 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qquaternion.h"
+#include "qmath3dutil_p.h"
+#include <QtCore/qmath.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_QUATERNION
+
+/*!
+ \class QQuaternion
+ \brief The QQuaternion class represents a quaternion consisting of a vector and scalar.
+ \since 4.6
+
+ Quaternions are used to represent rotations in 3D space, and
+ consist of a 3D rotation axis specified by the x, y, and z
+ coordinates, and a scalar representing the rotation angle.
+
+ The components of a quaternion are stored internally using the most
+ efficient representation for the GL rendering engine, which will be
+ either floating-point or fixed-point.
+*/
+
+/*!
+ \fn QQuaternion::QQuaternion()
+
+ Constructs an identity quaternion, i.e. with coordinates (1, 0, 0, 0).
+*/
+
+/*!
+ \fn QQuaternion::QQuaternion(qreal scalar, qreal xpos, qreal ypos, qreal zpos)
+
+ Constructs a quaternion with the vector (\a xpos, \a ypos, \a zpos)
+ and \a scalar.
+*/
+
+/*!
+ \fn QQuaternion::QQuaternion(int scalar, int xpos, int ypos, int zpos)
+
+ Constructs a quaternion with the vector (\a xpos, \a ypos, \a zpos)
+ and \a scalar.
+*/
+
+#ifndef QT_NO_VECTOR3D
+
+/*!
+ \fn QQuaternion::QQuaternion(qreal scalar, const QVector3D& vector)
+
+ Constructs a quaternion vector from the specified \a vector and
+ \a scalar.
+
+ \sa vector(), scalar()
+*/
+
+/*!
+ \fn QVector3D QQuaternion::vector() const
+
+ Returns the vector component of this quaternion.
+
+ \sa setVector(), scalar()
+*/
+
+/*!
+ \fn void QQuaternion::setVector(const QVector3D& vector)
+
+ Sets the vector component of this quaternion to \a vector.
+
+ \sa vector(), setScalar()
+*/
+
+#endif
+
+/*!
+ \fn void QQuaternion::setVector(qreal x, qreal y, qreal z)
+
+ Sets the vector component of this quaternion to (\a x, \a y, \a z).
+
+ \sa vector(), setScalar()
+*/
+
+#ifndef QT_NO_VECTOR4D
+
+/*!
+ \fn QQuaternion::QQuaternion(const QVector4D& vector)
+
+ Constructs a quaternion from the components of \a vector.
+*/
+
+/*!
+ \fn QVector4D QQuaternion::toVector4D() const
+
+ Returns this quaternion as a 4D vector.
+*/
+
+#endif
+
+/*!
+ \fn bool QQuaternion::isNull() const
+
+ Returns true if the x, y, z, and scalar components of this
+ quaternion are set to 0.0; otherwise returns false.
+*/
+
+/*!
+ \fn bool QQuaternion::isIdentity() const
+
+ Returns true if the x, y, and z components of this
+ quaternion are set to 0.0, and the scalar component is set
+ to 1.0; otherwise returns false.
+*/
+
+/*!
+ \fn qreal QQuaternion::x() const
+
+ Returns the x coordinate of this quaternion's vector.
+
+ \sa setX(), y(), z(), scalar()
+*/
+
+/*!
+ \fn qreal QQuaternion::y() const
+
+ Returns the y coordinate of this quaternion's vector.
+
+ \sa setY(), x(), z(), scalar()
+*/
+
+/*!
+ \fn qreal QQuaternion::z() const
+
+ Returns the z coordinate of this quaternion's vector.
+
+ \sa setZ(), x(), y(), scalar()
+*/
+
+/*!
+ \fn qreal QQuaternion::scalar() const
+
+ Returns the scalar component of this quaternion.
+
+ \sa setScalar(), x(), y(), z()
+*/
+
+/*!
+ \fn void QQuaternion::setX(qreal x)
+
+ Sets the x coordinate of this quaternion's vector to the given
+ \a x coordinate.
+
+ \sa x(), setY(), setZ(), setScalar()
+*/
+
+/*!
+ \fn void QQuaternion::setY(qreal y)
+
+ Sets the y coordinate of this quaternion's vector to the given
+ \a y coordinate.
+
+ \sa y(), setX(), setZ(), setScalar()
+*/
+
+/*!
+ \fn void QQuaternion::setZ(qreal z)
+
+ Sets the z coordinate of this quaternion's vector to the given
+ \a z coordinate.
+
+ \sa z(), setX(), setY(), setScalar()
+*/
+
+/*!
+ \fn void QQuaternion::setScalar(qreal scalar)
+
+ Sets the scalar component of this quaternion to \a scalar.
+
+ \sa scalar(), setX(), setY(), setZ()
+*/
+
+/*!
+ Returns the length of the quaternion. This is also called the "norm".
+
+ \sa lengthSquared(), normalized()
+*/
+qreal QQuaternion::length() const
+{
+ return qvtsqrt64(qvtmul64(xp, xp) + qvtmul64(yp, yp) +
+ qvtmul64(zp, zp) + qvtmul64(wp, wp));
+}
+
+/*!
+ Returns the squared length of the quaternion.
+
+ \sa length()
+*/
+qreal QQuaternion::lengthSquared() const
+{
+ return qvtdot64(qvtmul64(xp, xp) + qvtmul64(yp, yp) +
+ qvtmul64(zp, zp) + qvtmul64(wp, wp));
+}
+
+/*!
+ Returns the normalized unit form of this quaternion. If this quaternion
+ is not null, the returned quaternion is guaranteed to be 1.0 in length.
+ If this quaternion is null, then a null quaternion is returned.
+
+ \sa length(), normalize()
+*/
+QQuaternion QQuaternion::normalized() const
+{
+ qreal len = length();
+ if (!qIsNull(len))
+ return *this / len;
+ else
+ return QQuaternion(0.0f, 0.0f, 0.0f, 0.0f);
+}
+
+/*!
+ Normalizes the currect quaternion in place. Nothing happens if this
+ is a null quaternion.
+
+ \sa length(), normalized()
+*/
+void QQuaternion::normalize()
+{
+ qreal len = length();
+ if (qIsNull(len))
+ return;
+
+ xp /= len;
+ yp /= len;
+ zp /= len;
+ wp /= len;
+}
+
+
+/*!
+ \fn QQuaternion QQuaternion::conjugate() const
+
+ Returns the conjugate of this quaternion, which is
+ (-x, -y, -z, scalar).
+*/
+
+/*!
+ Rotates \a vector with this quaternion to produce a new vector
+ in 3D space. The following code:
+
+ \code
+ QVector3D result = q.rotateVector(vector);
+ \endcode
+
+ is equivalent to the following:
+
+ \code
+ QVector3D result = (q * QQuaternion(0, vector) * q.conjugate()).vector();
+ \endcode
+*/
+QVector3D QQuaternion::rotateVector(const QVector3D& vector) const
+{
+ return (*this * QQuaternion(0, vector) * conjugate()).vector();
+}
+
+/*!
+ \fn QQuaternion &QQuaternion::operator+=(const QQuaternion &quaternion)
+
+ Adds the given \a quaternion to this quaternion and returns a reference to
+ this quaternion.
+
+ \sa operator-=()
+*/
+
+/*!
+ \fn QQuaternion &QQuaternion::operator-=(const QQuaternion &quaternion)
+
+ Subtracts the given \a quaternion from this quaternion and returns a
+ reference to this quaternion.
+
+ \sa operator+=()
+*/
+
+/*!
+ \fn QQuaternion &QQuaternion::operator*=(qreal factor)
+
+ Multiplies this quaternion's components by the given \a factor, and
+ returns a reference to this quaternion.
+
+ \sa operator/=()
+*/
+
+/*!
+ \fn QQuaternion &QQuaternion::operator*=(const QQuaternion &quaternion)
+
+ Multiplies this quaternion by \a quaternion and returns a reference
+ to this quaternion.
+*/
+
+/*!
+ \fn QQuaternion &QQuaternion::operator/=(qreal divisor)
+
+ Divides this quaternion's components by the given \a divisor, and
+ returns a reference to this quaternion.
+
+ \sa operator*=()
+*/
+
+#ifndef QT_NO_VECTOR3D
+
+/*!
+ Creates a normalized quaternion that corresponds to rotating through
+ \a angle degrees about the specified 3D \a axis.
+*/
+QQuaternion QQuaternion::fromAxisAndAngle(const QVector3D& axis, qreal angle)
+{
+ // Algorithm from:
+ // http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q56
+ // We normalize the result just in case the values are close
+ // to zero, as suggested in the above FAQ.
+ qrealinner s, c;
+ QVector3D ax = axis.normalized();
+ qt_math3d_sincos(angle / 2.0f, &s, &c);
+ return QQuaternion(c, ax.xp * s, ax.yp * s, ax.zp * s, 1).normalized();
+}
+
+#endif
+
+/*!
+ Creates a normalized quaternion that corresponds to rotating through
+ \a angle degrees about the 3D axis (\a x, \a y, \a z).
+*/
+QQuaternion QQuaternion::fromAxisAndAngle
+ (qreal x, qreal y, qreal z, qreal angle)
+{
+ qrealinner xp = x;
+ qrealinner yp = y;
+ qrealinner zp = z;
+ qrealinner s, c;
+ qreal length = qvtsqrt(xp * xp + yp * yp + zp * zp);
+ if (!qIsNull(length)) {
+ xp /= length;
+ yp /= length;
+ zp /= length;
+ }
+ qt_math3d_sincos(angle / 2.0f, &s, &c);
+ return QQuaternion(c, xp * s, yp * s, zp * s, 1).normalized();
+}
+
+/*!
+ \fn bool operator==(const QQuaternion &q1, const QQuaternion &q2)
+ \relates QQuaternion
+
+ Returns true if \a q1 is equal to \a q2; otherwise returns false.
+ This operator uses an exact floating-point comparison.
+*/
+
+/*!
+ \fn bool operator!=(const QQuaternion &q1, const QQuaternion &q2)
+ \relates QQuaternion
+
+ Returns true if \a q1 is not equal to \a q2; otherwise returns false.
+ This operator uses an exact floating-point comparison.
+*/
+
+/*!
+ \fn const QQuaternion operator+(const QQuaternion &q1, const QQuaternion &q2)
+ \relates QQuaternion
+
+ Returns a QQuaternion object that is the sum of the given quaternions,
+ \a q1 and \a q2; each component is added separately.
+
+ \sa QQuaternion::operator+=()
+*/
+
+/*!
+ \fn const QQuaternion operator-(const QQuaternion &q1, const QQuaternion &q2)
+ \relates QQuaternion
+
+ Returns a QQuaternion object that is formed by subtracting
+ \a q2 from \a q1; each component is subtracted separately.
+
+ \sa QQuaternion::operator-=()
+*/
+
+/*!
+ \fn const QQuaternion operator*(qreal factor, const QQuaternion &quaternion)
+ \relates QQuaternion
+
+ Returns a copy of the given \a quaternion, multiplied by the
+ given \a factor.
+
+ \sa QQuaternion::operator*=()
+*/
+
+/*!
+ \fn const QQuaternion operator*(const QQuaternion &quaternion, qreal factor)
+ \relates QQuaternion
+
+ Returns a copy of the given \a quaternion, multiplied by the
+ given \a factor.
+
+ \sa QQuaternion::operator*=()
+*/
+
+/*!
+ \fn const QQuaternion operator*(const QQuaternion &q1, const QQuaternion& q2)
+ \relates QQuaternion
+
+ Multiplies \a q1 and \a q2 using quaternion multiplication.
+ The result corresponds to applying both of the rotations specified
+ by \a q1 and \a q2.
+
+ \sa QQuaternion::operator*=()
+*/
+
+/*!
+ \fn const QQuaternion operator-(const QQuaternion &quaternion)
+ \relates QQuaternion
+ \overload
+
+ Returns a QQuaternion object that is formed by changing the sign of
+ all three components of the given \a quaternion.
+
+ Equivalent to \c {QQuaternion(0,0,0,0) - quaternion}.
+*/
+
+/*!
+ \fn const QQuaternion operator/(const QQuaternion &quaternion, qreal divisor)
+ \relates QQuaternion
+
+ Returns the QQuaternion object formed by dividing all components of
+ the given \a quaternion by the given \a divisor.
+
+ \sa QQuaternion::operator/=()
+*/
+
+/*!
+ \fn bool qFuzzyCompare(const QQuaternion& q1, const QQuaternion& q2)
+ \relates QQuaternion
+
+ Returns true if \a q1 and \a q2 are equal, allowing for a small
+ fuzziness factor for floating-point comparisons; false otherwise.
+*/
+
+/*!
+ Interpolates along the shortest spherical path between the
+ rotational positions \a q1 and \a q2. The value \a t should
+ be between 0 and 1, indicating the spherical distance to travel
+ between \a q1 and \a q2.
+
+ If \a t is less than or equal to 0, then \a q1 will be returned.
+ If \a t is greater than or equal to 1, then \a q2 will be returned.
+*/
+QQuaternion QQuaternion::interpolate
+ (const QQuaternion& q1, const QQuaternion& q2, qreal t)
+{
+ // Handle the easy cases first.
+ if (t <= 0.0f)
+ return q1;
+ else if (t >= 1.0f)
+ return q2;
+
+ // Determine the angle between the two quaternions.
+ QQuaternion q2b;
+ qreal dot;
+ dot = qvtdot64(qvtmul64(q1.xp, q2.xp) + qvtmul64(q1.yp, q2.yp) +
+ qvtmul64(q1.zp, q2.zp) + qvtmul64(q1.wp, q2.wp));
+ if (dot >= 0.0f) {
+ q2b = q2;
+ } else {
+ q2b = -q2;
+ dot = -dot;
+ }
+
+ // Get the scale factors. If they are too small,
+ // then revert to simple linear interpolation.
+ qreal factor1 = 1.0f - t;
+ qreal factor2 = t;
+ if ((1.0f - dot) > 0.0000001) {
+ qreal angle = qreal(qAcos(dot));
+ qreal sinOfAngle = qreal(qSin(angle));
+ if (sinOfAngle > 0.0000001) {
+ factor1 = qreal(qSin((1.0f - t) * angle)) / sinOfAngle;
+ factor2 = qreal(qSin(t * angle)) / sinOfAngle;
+ }
+ }
+
+ // Construct the result quaternion.
+ return q1 * factor1 + q2b * factor2;
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+
+QDebug operator<<(QDebug dbg, const QQuaternion &q)
+{
+ dbg.nospace() << "QQuaternion(scalar:" << q.scalar()
+ << ", vector:(" << q.x() << ", "
+ << q.y() << ", " << q.z() << "))";
+ return dbg.space();
+}
+
+#endif
+
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/gui/math3d/qquaternion.h b/src/gui/math3d/qquaternion.h
new file mode 100644
index 0000000..cc71b7d
--- /dev/null
+++ b/src/gui/math3d/qquaternion.h
@@ -0,0 +1,313 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QQUATERNION_H
+#define QQUATERNION_H
+
+#include <QtGui/qvector3d.h>
+#include <QtGui/qvector4d.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+#ifndef QT_NO_QUATERNION
+
+class QMatrix4x4;
+
+class Q_GUI_EXPORT QQuaternion
+{
+public:
+ QQuaternion();
+ QQuaternion(qreal scalar, qreal xpos, qreal ypos, qreal zpos);
+ QQuaternion(int scalar, int xpos, int ypos, int zpos);
+#ifndef QT_NO_VECTOR3D
+ QQuaternion(qreal scalar, const QVector3D& vector);
+#endif
+#ifndef QT_NO_VECTOR4D
+ explicit QQuaternion(const QVector4D& vector);
+#endif
+
+ bool isNull() const;
+ bool isIdentity() const;
+
+#ifndef QT_NO_VECTOR3D
+ QVector3D vector() const;
+ void setVector(const QVector3D& vector);
+#endif
+ void setVector(qreal x, qreal y, qreal z);
+
+ qreal x() const;
+ qreal y() const;
+ qreal z() const;
+ qreal scalar() const;
+
+ void setX(qreal x);
+ void setY(qreal y);
+ void setZ(qreal z);
+ void setScalar(qreal scalar);
+
+ qreal length() const;
+ qreal lengthSquared() const;
+
+ QQuaternion normalized() const;
+ void normalize();
+
+ QQuaternion conjugate() const;
+
+ QVector3D rotateVector(const QVector3D& vector) const;
+
+ QQuaternion &operator+=(const QQuaternion &quaternion);
+ QQuaternion &operator-=(const QQuaternion &quaternion);
+ QQuaternion &operator*=(qreal factor);
+ QQuaternion &operator*=(const QQuaternion &quaternion);
+ QQuaternion &operator/=(qreal divisor);
+
+ friend inline bool operator==(const QQuaternion &q1, const QQuaternion &q2);
+ friend inline bool operator!=(const QQuaternion &q1, const QQuaternion &q2);
+ friend inline const QQuaternion operator+(const QQuaternion &q1, const QQuaternion &q2);
+ friend inline const QQuaternion operator-(const QQuaternion &q1, const QQuaternion &q2);
+ friend inline const QQuaternion operator*(qreal factor, const QQuaternion &quaternion);
+ friend inline const QQuaternion operator*(const QQuaternion &quaternion, qreal factor);
+ friend inline const QQuaternion operator*(const QQuaternion &q1, const QQuaternion& q2);
+ friend inline const QQuaternion operator-(const QQuaternion &quaternion);
+ friend inline const QQuaternion operator/(const QQuaternion &quaternion, qreal divisor);
+
+ friend inline bool qFuzzyCompare(const QQuaternion& q1, const QQuaternion& q2);
+
+#ifndef QT_NO_VECTOR4D
+ QVector4D toVector4D() const;
+#endif
+
+#ifndef QT_NO_VECTOR3D
+ static QQuaternion fromAxisAndAngle(const QVector3D& axis, qreal angle);
+#endif
+ static QQuaternion fromAxisAndAngle
+ (qreal x, qreal y, qreal z, qreal angle);
+
+ static QQuaternion interpolate
+ (const QQuaternion& q1, const QQuaternion& q2, qreal t);
+
+private:
+ qrealinner wp, xp, yp, zp;
+
+ friend class QMatrix4x4;
+
+ QQuaternion(qrealinner scalar, qrealinner xpos, qrealinner ypos, qrealinner zpos, int dummy);
+};
+
+inline QQuaternion::QQuaternion() : wp(1.0f), xp(0.0f), yp(0.0f), zp(0.0f) {}
+
+inline QQuaternion::QQuaternion(qreal scalar, qreal xpos, qreal ypos, qreal zpos) : wp(scalar), xp(xpos), yp(ypos), zp(zpos) {}
+
+
+inline QQuaternion::QQuaternion(qrealinner scalar, qrealinner xpos, qrealinner ypos, qrealinner zpos, int) : wp(scalar), xp(xpos), yp(ypos), zp(zpos) {}
+
+inline QQuaternion::QQuaternion(int scalar, int xpos, int ypos, int zpos) : wp(scalar), xp(xpos), yp(ypos), zp(zpos) {}
+
+inline bool QQuaternion::isNull() const
+{
+ return qIsNull(xp) && qIsNull(yp) && qIsNull(zp) && qIsNull(wp);
+}
+
+inline bool QQuaternion::isIdentity() const
+{
+ return qIsNull(xp) && qIsNull(yp) && qIsNull(zp) && wp == 1.0f;
+}
+
+inline qreal QQuaternion::x() const { return qt_math3d_convert<qreal, qrealinner>(xp); }
+inline qreal QQuaternion::y() const { return qt_math3d_convert<qreal, qrealinner>(yp); }
+inline qreal QQuaternion::z() const { return qt_math3d_convert<qreal, qrealinner>(zp); }
+inline qreal QQuaternion::scalar() const { return qt_math3d_convert<qreal, qrealinner>(wp); }
+
+inline void QQuaternion::setX(qreal x) { xp = x; }
+inline void QQuaternion::setY(qreal y) { yp = y; }
+inline void QQuaternion::setZ(qreal z) { zp = z; }
+inline void QQuaternion::setScalar(qreal scalar) { wp = scalar; }
+
+inline QQuaternion QQuaternion::conjugate() const
+{
+ return QQuaternion(wp, -xp, -yp, -zp, 1);
+}
+
+inline QQuaternion &QQuaternion::operator+=(const QQuaternion &quaternion)
+{
+ xp += quaternion.xp;
+ yp += quaternion.yp;
+ zp += quaternion.zp;
+ wp += quaternion.wp;
+ return *this;
+}
+
+inline QQuaternion &QQuaternion::operator-=(const QQuaternion &quaternion)
+{
+ xp -= quaternion.xp;
+ yp -= quaternion.yp;
+ zp -= quaternion.zp;
+ wp -= quaternion.wp;
+ return *this;
+}
+
+inline QQuaternion &QQuaternion::operator*=(qreal factor)
+{
+ qrealinner f(factor);
+ xp *= f;
+ yp *= f;
+ zp *= f;
+ wp *= f;
+ return *this;
+}
+
+inline const QQuaternion operator*(const QQuaternion &q1, const QQuaternion& q2)
+{
+ // Algorithm from:
+ // http://www.j3d.org/matrix_faq/matrfaq_latest.html#Q53
+ qrealinner x = q1.wp * q2.xp +
+ q1.xp * q2.wp +
+ q1.yp * q2.zp -
+ q1.zp * q2.yp;
+ qrealinner y = q1.wp * q2.yp +
+ q1.yp * q2.wp +
+ q1.zp * q2.xp -
+ q1.xp * q2.zp;
+ qrealinner z = q1.wp * q2.zp +
+ q1.zp * q2.wp +
+ q1.xp * q2.yp -
+ q1.yp * q2.xp;
+ qrealinner w = q1.wp * q2.wp -
+ q1.xp * q2.xp -
+ q1.yp * q2.yp -
+ q1.zp * q2.zp;
+ return QQuaternion(w, x, y, z, 1);
+}
+
+inline QQuaternion &QQuaternion::operator*=(const QQuaternion &quaternion)
+{
+ *this = *this * quaternion;
+ return *this;
+}
+
+inline QQuaternion &QQuaternion::operator/=(qreal divisor)
+{
+ qrealinner d(divisor);
+ xp /= d;
+ yp /= d;
+ zp /= d;
+ wp /= d;
+ return *this;
+}
+
+inline bool operator==(const QQuaternion &q1, const QQuaternion &q2)
+{
+ return q1.xp == q2.xp && q1.yp == q2.yp && q1.zp == q2.zp && q1.wp == q2.wp;
+}
+
+inline bool operator!=(const QQuaternion &q1, const QQuaternion &q2)
+{
+ return q1.xp != q2.xp || q1.yp != q2.yp || q1.zp != q2.zp || q1.wp != q2.wp;
+}
+
+inline const QQuaternion operator+(const QQuaternion &q1, const QQuaternion &q2)
+{
+ return QQuaternion(q1.wp + q2.wp, q1.xp + q2.xp, q1.yp + q2.yp, q1.zp + q2.zp, 1);
+}
+
+inline const QQuaternion operator-(const QQuaternion &q1, const QQuaternion &q2)
+{
+ return QQuaternion(q1.wp - q2.wp, q1.xp - q2.xp, q1.yp - q2.yp, q1.zp - q2.zp, 1);
+}
+
+inline const QQuaternion operator*(qreal factor, const QQuaternion &quaternion)
+{
+ qrealinner f(factor);
+ return QQuaternion(quaternion.wp * f, quaternion.xp * f, quaternion.yp * f, quaternion.zp * f, 1);
+}
+
+inline const QQuaternion operator*(const QQuaternion &quaternion, qreal factor)
+{
+ qrealinner f(factor);
+ return QQuaternion(quaternion.wp * f, quaternion.xp * f, quaternion.yp * f, quaternion.zp * f, 1);
+}
+
+inline const QQuaternion operator-(const QQuaternion &quaternion)
+{
+ return QQuaternion(-quaternion.wp, -quaternion.xp, -quaternion.yp, -quaternion.zp, 1);
+}
+
+inline const QQuaternion operator/(const QQuaternion &quaternion, qreal divisor)
+{
+ qrealinner d(divisor);
+ return QQuaternion(quaternion.wp / d, quaternion.xp / d, quaternion.yp / d, quaternion.zp / d, 1);
+}
+
+inline bool qFuzzyCompare(const QQuaternion& q1, const QQuaternion& q2)
+{
+ return qFuzzyCompare(q1.xp, q2.xp) &&
+ qFuzzyCompare(q1.yp, q2.yp) &&
+ qFuzzyCompare(q1.zp, q2.zp) &&
+ qFuzzyCompare(q1.wp, q2.wp);
+}
+
+#ifndef QT_NO_VECTOR3D
+
+inline QQuaternion::QQuaternion(qreal scalar, const QVector3D& vector)
+ : wp(scalar), xp(vector.xp), yp(vector.yp), zp(vector.zp) {}
+
+inline void QQuaternion::setVector(const QVector3D& vector)
+{
+ xp = vector.xp;
+ yp = vector.yp;
+ zp = vector.zp;
+}
+
+inline QVector3D QQuaternion::vector() const
+{
+ return QVector3D(xp, yp, zp, 1);
+}
+
+#endif
+
+inline void QQuaternion::setVector(qreal x, qreal y, qreal z)
+{
+ xp = x;
+ yp = y;
+ zp = z;
+}
+
+#ifndef QT_NO_VECTOR4D
+
+inline QQuaternion::QQuaternion(const QVector4D& vector)
+ : wp(vector.wp), xp(vector.xp), yp(vector.yp), zp(vector.zp) {}
+
+inline QVector4D QQuaternion::toVector4D() const
+{
+ return QVector4D(xp, yp, zp, wp, 1);
+}
+
+#endif
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QQuaternion &q);
+#endif
+
+#endif
+
+QT_END_NAMESPACE
+
+#ifndef QT_NO_QUATERNION
+Q_DECLARE_METATYPE(QQuaternion)
+#endif
+
+QT_END_HEADER
+
+#endif
diff --git a/src/gui/math3d/qvector2d.cpp b/src/gui/math3d/qvector2d.cpp
new file mode 100644
index 0000000..13d6cc9
--- /dev/null
+++ b/src/gui/math3d/qvector2d.cpp
@@ -0,0 +1,386 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qvector2d.h"
+#include "qvector3d.h"
+#include "qvector4d.h"
+#include "qmath3dutil_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_VECTOR2D
+
+/*!
+ \class QVector2D
+ \brief The QVector2D class represents a vector or vertex in 2D space.
+ \since 4.6
+
+ The QVector2D class can also be used to represent vertices in 2D space.
+ We therefore do not need to provide a separate vertex class.
+
+ The coordinates are stored internally using the most efficient
+ representation for the GL rendering engine, which will be either
+ floating-point or fixed-point.
+*/
+
+/*!
+ \fn QVector2D::QVector2D()
+
+ Constructs a null vector, i.e. with coordinates (0, 0, 0).
+*/
+
+/*!
+ \fn QVector2D::QVector2D(qreal xpos, qreal ypos)
+
+ Constructs a vector with coordinates (\a xpos, \a ypos).
+*/
+
+/*!
+ \fn QVector2D::QVector2D(int xpos, int ypos)
+
+ Constructs a vector with coordinates (\a xpos, \a ypos).
+*/
+
+/*!
+ \fn QVector2D::QVector2D(const QPoint& point)
+
+ Constructs a vector with x and y coordinates from a 2D \a point.
+*/
+
+/*!
+ \fn QVector2D::QVector2D(const QPointF& point)
+
+ Constructs a vector with x and y coordinates from a 2D \a point.
+*/
+
+#ifndef QT_NO_VECTOR3D
+
+/*!
+ Constructs a vector with x and y coordinates from a 3D \a vector.
+ The z coordinate of \a vector is dropped.
+
+ \sa toVector3D()
+*/
+QVector2D::QVector2D(const QVector3D& vector)
+{
+ xp = vector.xp;
+ yp = vector.yp;
+}
+
+#endif
+
+#ifndef QT_NO_VECTOR4D
+
+/*!
+ Constructs a vector with x and y coordinates from a 3D \a vector.
+ The z and w coordinates of \a vector are dropped.
+
+ \sa toVector4D()
+*/
+QVector2D::QVector2D(const QVector4D& vector)
+{
+ xp = vector.xp;
+ yp = vector.yp;
+}
+
+#endif
+
+/*!
+ \fn bool QVector2D::isNull() const
+
+ Returns true if the x and y coordinates are set to 0.0,
+ otherwise returns false.
+*/
+
+/*!
+ \fn qreal QVector2D::x() const
+
+ Returns the x coordinate of this point.
+
+ \sa setX(), y()
+*/
+
+/*!
+ \fn qreal QVector2D::y() const
+
+ Returns the y coordinate of this point.
+
+ \sa setY(), x()
+*/
+
+/*!
+ \fn void QVector2D::setX(qreal x)
+
+ Sets the x coordinate of this point to the given \a x coordinate.
+
+ \sa x(), setY()
+*/
+
+/*!
+ \fn void QVector2D::setY(qreal y)
+
+ Sets the y coordinate of this point to the given \a y coordinate.
+
+ \sa y(), setX()
+*/
+
+/*!
+ Returns the length of the vector from the origin.
+
+ \sa lengthSquared(), normalized()
+*/
+qreal QVector2D::length() const
+{
+ return qvtsqrt64(qvtmul64(xp, xp) + qvtmul64(yp, yp));
+}
+
+/*!
+ Returns the squared length of the vector from the origin.
+ This is equivalent to the dot product of the vector with itself.
+
+ \sa length(), dotProduct()
+*/
+qreal QVector2D::lengthSquared() const
+{
+ return qvtdot64(qvtmul64(xp, xp) + qvtmul64(yp, yp));
+}
+
+/*!
+ Returns the normalized unit vector form of this vector. If this vector
+ is not null, the returned vector is guaranteed to be 1.0 in length.
+ If this vector is null, then a null vector is returned.
+
+ \sa length(), normalize()
+*/
+QVector2D QVector2D::normalized() const
+{
+ qreal len = length();
+ if (!qIsNull(len))
+ return *this / len;
+ else
+ return QVector2D();
+}
+
+/*!
+ Normalizes the currect vector in place. Nothing happens if this
+ vector is a null vector.
+
+ \sa length(), normalized()
+*/
+void QVector2D::normalize()
+{
+ qreal len = length();
+ if (qIsNull(len))
+ return;
+
+ xp /= len;
+ yp /= len;
+}
+
+/*!
+ \fn QVector2D &QVector2D::operator+=(const QVector2D &vector)
+
+ Adds the given \a vector to this vector and returns a reference to
+ this vector.
+
+ \sa operator-=()
+*/
+
+/*!
+ \fn QVector2D &QVector2D::operator-=(const QVector2D &vector)
+
+ Subtracts the given \a vector from this vector and returns a reference to
+ this vector.
+
+ \sa operator+=()
+*/
+
+/*!
+ \fn QVector2D &QVector2D::operator*=(qreal factor)
+
+ Multiplies this vector's coordinates by the given \a factor, and
+ returns a reference to this vector.
+
+ \sa operator/=()
+*/
+
+/*!
+ \fn QVector2D &QVector2D::operator*=(const QVector2D &vector)
+
+ Multiplies the components of this vector by the corresponding
+ components in \a vector.
+*/
+
+/*!
+ \fn QVector2D &QVector2D::operator/=(qreal divisor)
+
+ Divides this vector's coordinates by the given \a divisor, and
+ returns a reference to this vector.
+
+ \sa operator*=()
+*/
+
+/*!
+ Returns the dot product of \a v1 and \a v2.
+*/
+qreal QVector2D::dotProduct(const QVector2D& v1, const QVector2D& v2)
+{
+ return qvtdot64(qvtmul64(v1.xp, v2.xp) + qvtmul64(v1.yp, v2.yp));
+}
+
+/*!
+ \fn bool operator==(const QVector2D &v1, const QVector2D &v2)
+ \relates QVector2D
+
+ Returns true if \a v1 is equal to \a v2; otherwise returns false.
+ This operator uses an exact floating-point comparison.
+*/
+
+/*!
+ \fn bool operator!=(const QVector2D &v1, const QVector2D &v2)
+ \relates QVector2D
+
+ Returns true if \a v1 is not equal to \a v2; otherwise returns false.
+ This operator uses an exact floating-point comparison.
+*/
+
+/*!
+ \fn const QVector2D operator+(const QVector2D &v1, const QVector2D &v2)
+ \relates QVector2D
+
+ Returns a QVector2D object that is the sum of the given vectors, \a v1
+ and \a v2; each component is added separately.
+
+ \sa QVector2D::operator+=()
+*/
+
+/*!
+ \fn const QVector2D operator-(const QVector2D &v1, const QVector2D &v2)
+ \relates QVector2D
+
+ Returns a QVector2D object that is formed by subtracting \a v2 from \a v1;
+ each component is subtracted separately.
+
+ \sa QVector2D::operator-=()
+*/
+
+/*!
+ \fn const QVector2D operator*(qreal factor, const QVector2D &vector)
+ \relates QVector2D
+
+ Returns a copy of the given \a vector, multiplied by the given \a factor.
+
+ \sa QVector2D::operator*=()
+*/
+
+/*!
+ \fn const QVector2D operator*(const QVector2D &vector, qreal factor)
+ \relates QVector2D
+
+ Returns a copy of the given \a vector, multiplied by the given \a factor.
+
+ \sa QVector2D::operator*=()
+*/
+
+/*!
+ \fn const QVector2D operator*(const QVector2D &v1, const QVector2D &v2)
+ \relates QVector2D
+
+ Multiplies the components of \a v1 by the corresponding
+ components in \a v2.
+*/
+
+/*!
+ \fn const QVector2D operator-(const QVector2D &vector)
+ \relates QVector2D
+ \overload
+
+ Returns a QVector2D object that is formed by changing the sign of
+ the components of the given \a vector.
+
+ Equivalent to \c {QVector2D(0,0) - vector}.
+*/
+
+/*!
+ \fn const QVector2D operator/(const QVector2D &vector, qreal divisor)
+ \relates QVector2D
+
+ Returns the QVector2D object formed by dividing all three components of
+ the given \a vector by the given \a divisor.
+
+ \sa QVector2D::operator/=()
+*/
+
+/*!
+ \fn bool qFuzzyCompare(const QVector2D& v1, const QVector2D& v2)
+ \relates QVector2D
+
+ Returns true if \a v1 and \a v2 are equal, allowing for a small
+ fuzziness factor for floating-point comparisons; false otherwise.
+*/
+
+#ifndef QT_NO_VECTOR3D
+
+/*!
+ Returns the 3D form of this 2D vector, with the z coordinate set to zero.
+
+ \sa toVector4D(), toPoint()
+*/
+QVector3D QVector2D::toVector3D() const
+{
+ return QVector3D(xp, yp, 0.0f, 1);
+}
+
+#endif
+
+#ifndef QT_NO_VECTOR4D
+
+/*!
+ Returns the 4D form of this 2D vector, with the z and w coordinates set to zero.
+
+ \sa toVector3D(), toPoint()
+*/
+QVector4D QVector2D::toVector4D() const
+{
+ return QVector4D(xp, yp, 0.0f, 0.0f, 1);
+}
+
+#endif
+
+/*!
+ \fn QPoint QVector2D::toPoint() const
+
+ Returns the QPoint form of this 2D vector.
+
+ \sa toPointF(), toVector3D()
+*/
+
+/*!
+ \fn QPointF QVector2D::toPointF() const
+
+ Returns the QPointF form of this 2D vector.
+
+ \sa toPoint(), toVector3D()
+*/
+
+#ifndef QT_NO_DEBUG_STREAM
+
+QDebug operator<<(QDebug dbg, const QVector2D &vector)
+{
+ dbg.nospace() << "QVector2D(" << vector.x() << ", " << vector.y() << ')';
+ return dbg.space();
+}
+
+#endif
+
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/gui/math3d/qvector2d.h b/src/gui/math3d/qvector2d.h
new file mode 100644
index 0000000..55452b0
--- /dev/null
+++ b/src/gui/math3d/qvector2d.h
@@ -0,0 +1,237 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QVECTOR2D_H
+#define QVECTOR2D_H
+
+#include <QtGui/qmath3dglobal.h>
+#include <QtCore/qpoint.h>
+#include <QtCore/qmetatype.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QVector3D;
+class QVector4D;
+
+#ifndef QT_NO_VECTOR2D
+
+class Q_GUI_EXPORT QVector2D
+{
+public:
+ QVector2D();
+ QVector2D(qreal xpos, qreal ypos);
+ QVector2D(int xpos, int ypos);
+ explicit QVector2D(const QPoint& point);
+ explicit QVector2D(const QPointF& point);
+#ifndef QT_NO_VECTOR3D
+ explicit QVector2D(const QVector3D& vector);
+#endif
+#ifndef QT_NO_VECTOR4D
+ explicit QVector2D(const QVector4D& vector);
+#endif
+
+ bool isNull() const;
+
+ qreal x() const;
+ qreal y() const;
+
+ void setX(qreal x);
+ void setY(qreal y);
+
+ qreal length() const;
+ qreal lengthSquared() const;
+
+ QVector2D normalized() const;
+ void normalize();
+
+ QVector2D &operator+=(const QVector2D &vector);
+ QVector2D &operator-=(const QVector2D &vector);
+ QVector2D &operator*=(qreal factor);
+ QVector2D &operator*=(const QVector2D &vector);
+ QVector2D &operator/=(qreal divisor);
+
+ static qreal dotProduct(const QVector2D& v1, const QVector2D& v2);
+
+ friend inline bool operator==(const QVector2D &v1, const QVector2D &v2);
+ friend inline bool operator!=(const QVector2D &v1, const QVector2D &v2);
+ friend inline const QVector2D operator+(const QVector2D &v1, const QVector2D &v2);
+ friend inline const QVector2D operator-(const QVector2D &v1, const QVector2D &v2);
+ friend inline const QVector2D operator*(qreal factor, const QVector2D &vector);
+ friend inline const QVector2D operator*(const QVector2D &vector, qreal factor);
+ friend inline const QVector2D operator*(const QVector2D &v1, const QVector2D &v2);
+ friend inline const QVector2D operator-(const QVector2D &vector);
+ friend inline const QVector2D operator/(const QVector2D &vector, qreal divisor);
+
+ friend inline bool qFuzzyCompare(const QVector2D& v1, const QVector2D& v2);
+
+#ifndef QT_NO_VECTOR3D
+ QVector3D toVector3D() const;
+#endif
+#ifndef QT_NO_VECTOR4D
+ QVector4D toVector4D() const;
+#endif
+
+ QPoint toPoint() const;
+ QPointF toPointF() const;
+
+private:
+ qrealinner xp, yp;
+
+ QVector2D(qrealinner xpos, qrealinner ypos, int dummy);
+
+ friend class QVector3D;
+ friend class QVector4D;
+ friend class QVertexArray;
+};
+
+inline QVector2D::QVector2D() : xp(0.0f), yp(0.0f) {}
+
+inline QVector2D::QVector2D(qrealinner xpos, qrealinner ypos, int) : xp(xpos), yp(ypos) {}
+
+inline QVector2D::QVector2D(qreal xpos, qreal ypos) : xp(xpos), yp(ypos) {}
+
+inline QVector2D::QVector2D(int xpos, int ypos) : xp(xpos), yp(ypos) {}
+
+inline QVector2D::QVector2D(const QPoint& point) : xp(point.x()), yp(point.y()) {}
+
+inline QVector2D::QVector2D(const QPointF& point) : xp(point.x()), yp(point.y()) {}
+
+inline bool QVector2D::isNull() const
+{
+ return qIsNull(xp) && qIsNull(yp);
+}
+
+inline qreal QVector2D::x() const { return qt_math3d_convert<qreal, qrealinner>(xp); }
+inline qreal QVector2D::y() const { return qt_math3d_convert<qreal, qrealinner>(yp); }
+
+inline void QVector2D::setX(qreal x) { xp = x; }
+inline void QVector2D::setY(qreal y) { yp = y; }
+
+inline QVector2D &QVector2D::operator+=(const QVector2D &vector)
+{
+ xp += vector.xp;
+ yp += vector.yp;
+ return *this;
+}
+
+inline QVector2D &QVector2D::operator-=(const QVector2D &vector)
+{
+ xp -= vector.xp;
+ yp -= vector.yp;
+ return *this;
+}
+
+inline QVector2D &QVector2D::operator*=(qreal factor)
+{
+ qrealinner f(factor);
+ xp *= f;
+ yp *= f;
+ return *this;
+}
+
+inline QVector2D &QVector2D::operator*=(const QVector2D &vector)
+{
+ xp *= vector.xp;
+ yp *= vector.yp;
+ return *this;
+}
+
+inline QVector2D &QVector2D::operator/=(qreal divisor)
+{
+ qrealinner d(divisor);
+ xp /= d;
+ yp /= d;
+ return *this;
+}
+
+inline bool operator==(const QVector2D &v1, const QVector2D &v2)
+{
+ return v1.xp == v2.xp && v1.yp == v2.yp;
+}
+
+inline bool operator!=(const QVector2D &v1, const QVector2D &v2)
+{
+ return v1.xp != v2.xp || v1.yp != v2.yp;
+}
+
+inline const QVector2D operator+(const QVector2D &v1, const QVector2D &v2)
+{
+ return QVector2D(v1.xp + v2.xp, v1.yp + v2.yp, 1);
+}
+
+inline const QVector2D operator-(const QVector2D &v1, const QVector2D &v2)
+{
+ return QVector2D(v1.xp - v2.xp, v1.yp - v2.yp, 1);
+}
+
+inline const QVector2D operator*(qreal factor, const QVector2D &vector)
+{
+ qrealinner f(factor);
+ return QVector2D(vector.xp * f, vector.yp * f, 1);
+}
+
+inline const QVector2D operator*(const QVector2D &vector, qreal factor)
+{
+ qrealinner f(factor);
+ return QVector2D(vector.xp * f, vector.yp * f, 1);
+}
+
+inline const QVector2D operator*(const QVector2D &v1, const QVector2D &v2)
+{
+ return QVector2D(v1.xp * v2.xp, v1.yp * v2.yp, 1);
+}
+
+inline const QVector2D operator-(const QVector2D &vector)
+{
+ return QVector2D(-vector.xp, -vector.yp, 1);
+}
+
+inline const QVector2D operator/(const QVector2D &vector, qreal divisor)
+{
+ qrealinner d(divisor);
+ return QVector2D(vector.xp / d, vector.yp / d, 1);
+}
+
+inline bool qFuzzyCompare(const QVector2D& v1, const QVector2D& v2)
+{
+ return qFuzzyCompare(v1.xp, v2.xp) && qFuzzyCompare(v1.yp, v2.yp);
+}
+
+inline QPoint QVector2D::toPoint() const
+{
+ return QPoint(qRound(xp), qRound(yp));
+}
+
+inline QPointF QVector2D::toPointF() const
+{
+ return QPointF(qt_math3d_convert<qreal, qrealinner>(xp),
+ qt_math3d_convert<qreal, qrealinner>(yp));
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QVector2D &vector);
+#endif
+
+#endif
+
+QT_END_NAMESPACE
+
+#ifndef QT_NO_VECTOR2D
+Q_DECLARE_METATYPE(QVector2D)
+#endif
+
+QT_END_HEADER
+
+#endif
diff --git a/src/gui/math3d/qvector3d.cpp b/src/gui/math3d/qvector3d.cpp
new file mode 100644
index 0000000..f0b3aeb
--- /dev/null
+++ b/src/gui/math3d/qvector3d.cpp
@@ -0,0 +1,535 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qvector3d.h"
+#include "qvector2d.h"
+#include "qvector4d.h"
+#include "qmath3dutil_p.h"
+#include <QtCore/qmath.h>
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_VECTOR3D
+
+/*!
+ \class QVector3D
+ \brief The QVector3D class represents a vector or vertex in 3D space.
+ \since 4.6
+
+ Vectors are one of the main building blocks of 3D representation and
+ drawing. They consist of three coordinates, traditionally called
+ x, y, and z.
+
+ The QVector3D class can also be used to represent vertices in 3D space.
+ We therefore do not need to provide a separate vertex class.
+
+ The coordinates are stored internally using the most efficient
+ representation for the GL rendering engine, which will be either
+ floating-point or fixed-point.
+*/
+
+/*!
+ \fn QVector3D::QVector3D()
+
+ Constructs a null vector, i.e. with coordinates (0, 0, 0).
+*/
+
+/*!
+ \fn QVector3D::QVector3D(qreal xpos, qreal ypos, qreal zpos)
+
+ Constructs a vector with coordinates (\a xpos, \a ypos, \a zpos).
+*/
+
+/*!
+ \fn QVector3D::QVector3D(int xpos, int ypos, int zpos)
+
+ Constructs a vector with coordinates (\a xpos, \a ypos, \a zpos).
+*/
+
+/*!
+ \fn QVector3D::QVector3D(const QPoint& point)
+
+ Constructs a vector with x and y coordinates from a 2D \a point, and a
+ z coordinate of 0.
+*/
+
+/*!
+ \fn QVector3D::QVector3D(const QPointF& point)
+
+ Constructs a vector with x and y coordinates from a 2D \a point, and a
+ z coordinate of 0.
+*/
+
+#ifndef QT_NO_VECTOR2D
+
+/*!
+ Constructs a 3D vector from the specified 2D \a vector. The z
+ coordinate is set to zero.
+
+ \sa toVector2D()
+*/
+QVector3D::QVector3D(const QVector2D& vector)
+{
+ xp = vector.xp;
+ yp = vector.yp;
+ zp = 0.0f;
+}
+
+/*!
+ Constructs a 3D vector from the specified 2D \a vector. The z
+ coordinate is set to \a zpos.
+
+ \sa toVector2D()
+*/
+QVector3D::QVector3D(const QVector2D& vector, qreal zpos)
+{
+ xp = vector.xp;
+ yp = vector.yp;
+ zp = zpos;
+}
+
+#endif
+
+#ifndef QT_NO_VECTOR4D
+
+/*!
+ Constructs a 3D vector from the specified 4D \a vector. The w
+ coordinate is dropped.
+
+ \sa toVector4D()
+*/
+QVector3D::QVector3D(const QVector4D& vector)
+{
+ xp = vector.xp;
+ yp = vector.yp;
+ zp = vector.zp;
+}
+
+#endif
+
+/*!
+ \fn bool QVector3D::isNull() const
+
+ Returns true if the x, y, and z coordinates are set to 0.0,
+ otherwise returns false.
+*/
+
+/*!
+ \fn qreal QVector3D::x() const
+
+ Returns the x coordinate of this point.
+
+ \sa setX(), y(), z()
+*/
+
+/*!
+ \fn qreal QVector3D::y() const
+
+ Returns the y coordinate of this point.
+
+ \sa setY(), x(), z()
+*/
+
+/*!
+ \fn qreal QVector3D::z() const
+
+ Returns the z coordinate of this point.
+
+ \sa setZ(), x(), y()
+*/
+
+/*!
+ \fn void QVector3D::setX(qreal x)
+
+ Sets the x coordinate of this point to the given \a x coordinate.
+
+ \sa x(), setY(), setZ()
+*/
+
+/*!
+ \fn void QVector3D::setY(qreal y)
+
+ Sets the y coordinate of this point to the given \a y coordinate.
+
+ \sa y(), setX(), setZ()
+*/
+
+/*!
+ \fn void QVector3D::setZ(qreal z)
+
+ Sets the z coordinate of this point to the given \a z coordinate.
+
+ \sa z(), setX(), setY()
+*/
+
+/*!
+ Returns the normalized unit vector form of this vector. If this vector
+ is not null, the returned vector is guaranteed to be 1.0 in length.
+ If this vector is null, then a null vector is returned.
+
+ \sa length(), normalize()
+*/
+QVector3D QVector3D::normalized() const
+{
+ qreal len = length();
+ if (!qIsNull(len))
+ return *this / len;
+ else
+ return QVector3D();
+}
+
+/*!
+ Normalizes the currect vector in place. Nothing happens if this
+ vector is a null vector.
+
+ \sa length(), normalized()
+*/
+void QVector3D::normalize()
+{
+ qreal len = length();
+ if (qIsNull(len))
+ return;
+
+ xp /= len;
+ yp /= len;
+ zp /= len;
+}
+
+/*!
+ \fn QVector3D &QVector3D::operator+=(const QVector3D &vector)
+
+ Adds the given \a vector to this vector and returns a reference to
+ this vector.
+
+ \sa operator-=()
+*/
+
+/*!
+ \fn QVector3D &QVector3D::operator-=(const QVector3D &vector)
+
+ Subtracts the given \a vector from this vector and returns a reference to
+ this vector.
+
+ \sa operator+=()
+*/
+
+/*!
+ \fn QVector3D &QVector3D::operator*=(qreal factor)
+
+ Multiplies this vector's coordinates by the given \a factor, and
+ returns a reference to this vector.
+
+ \sa operator/=()
+*/
+
+/*!
+ \fn QVector3D &QVector3D::operator*=(const QVector3D& vector)
+ \overload
+
+ Multiplies the components of this vector by the corresponding
+ components in \a vector.
+
+ Note: this is not the same as the crossProduct() of this
+ vector and \a vector.
+
+ \sa crossProduct()
+*/
+
+/*!
+ \fn QVector3D &QVector3D::operator/=(qreal divisor)
+
+ Divides this vector's coordinates by the given \a divisor, and
+ returns a reference to this vector.
+
+ \sa operator*=()
+*/
+
+/*!
+ Returns the dot product of \a v1 and \a v2.
+*/
+qreal QVector3D::dotProduct(const QVector3D& v1, const QVector3D& v2)
+{
+ return qvtdot64(qvtmul64(v1.xp, v2.xp) + qvtmul64(v1.yp, v2.yp) + qvtmul64(v1.zp, v2.zp));
+}
+
+/*!
+ Returns the cross-product of vectors \a v1 and \a v2, which corresponds
+ to the normal vector of a plane defined by \a v1 and \a v2.
+
+ \sa normal()
+*/
+QVector3D QVector3D::crossProduct(const QVector3D& v1, const QVector3D& v2)
+{
+ return QVector3D(v1.yp * v2.zp - v1.zp * v2.yp,
+ v1.zp * v2.xp - v1.xp * v2.zp,
+ v1.xp * v2.yp - v1.yp * v2.xp, 1);
+}
+
+/*!
+ Returns the normal vector of a plane defined by vectors \a v1 and \a v2,
+ normalized to be a unit vector.
+
+ Use crossProduct() to compute the cross-product of \a v1 and \a v2 if you
+ do not need the result to be normalized to a unit vector.
+
+ \sa crossProduct(), distanceToPlane()
+*/
+QVector3D QVector3D::normal(const QVector3D& v1, const QVector3D& v2)
+{
+ return crossProduct(v1, v2).normalized();
+}
+
+/*!
+ \overload
+
+ Returns the normal vector of a plane defined by vectors
+ \a v2 - \a v1 and \a v3 - \a v1, normalized to be a unit vector.
+
+ Use crossProduct() to compute the cross-product of \a v2 - \a v1 and
+ \a v3 - \a v1 if you do not need the result to be normalized to a
+ unit vector.
+
+ \sa crossProduct(), distanceToPlane()
+*/
+QVector3D QVector3D::normal
+ (const QVector3D& v1, const QVector3D& v2, const QVector3D& v3)
+{
+ return crossProduct((v2 - v1), (v3 - v1)).normalized();
+}
+
+/*!
+ Returns the distance from this vertex to a plane defined by
+ the vertex \a plane and a \a normal unit vector. The \a normal
+ parameter is assumed to have been normalized to a unit vector.
+
+ The return value will be negative if the vertex is below the plane,
+ or zero if it is on the plane.
+
+ \sa normal(), distanceToLine()
+*/
+qreal QVector3D::distanceToPlane
+ (const QVector3D& plane, const QVector3D& normal) const
+{
+ return dotProduct(*this - plane, normal);
+}
+
+/*!
+ \overload
+
+ Returns the distance from this vertex a plane defined by
+ the vertices \a plane1, \a plane2 and \a plane3.
+
+ The return value will be negative if the vertex is below the plane,
+ or zero if it is on the plane.
+
+ The two vectors that define the plane are \a plane2 - \a plane1
+ and \a plane3 - \a plane1.
+
+ \sa normal(), distanceToLine()
+*/
+qreal QVector3D::distanceToPlane
+ (const QVector3D& plane1, const QVector3D& plane2, const QVector3D& plane3) const
+{
+ QVector3D n = normal(plane2 - plane1, plane3 - plane1);
+ return dotProduct(*this - plane1, n);
+}
+
+/*!
+ Returns the distance that this vertex is from a line defined
+ by \a point and the unit vector \a direction.
+
+ If \a direction is a null vector, then it does not define a line.
+ In that case, the distance from \a point to this vertex is returned.
+
+ \sa distanceToPlane()
+*/
+qreal QVector3D::distanceToLine
+ (const QVector3D& point, const QVector3D& direction) const
+{
+ if (direction.isNull())
+ return (*this - point).length();
+ QVector3D p = point + dotProduct(*this - point, direction) * direction;
+ return (*this - p).length();
+}
+
+/*!
+ \fn bool operator==(const QVector3D &v1, const QVector3D &v2)
+ \relates QVector3D
+
+ Returns true if \a v1 is equal to \a v2; otherwise returns false.
+ This operator uses an exact floating-point comparison.
+*/
+
+/*!
+ \fn bool operator!=(const QVector3D &v1, const QVector3D &v2)
+ \relates QVector3D
+
+ Returns true if \a v1 is not equal to \a v2; otherwise returns false.
+ This operator uses an exact floating-point comparison.
+*/
+
+/*!
+ \fn const QVector3D operator+(const QVector3D &v1, const QVector3D &v2)
+ \relates QVector3D
+
+ Returns a QVector3D object that is the sum of the given vectors, \a v1
+ and \a v2; each component is added separately.
+
+ \sa QVector3D::operator+=()
+*/
+
+/*!
+ \fn const QVector3D operator-(const QVector3D &v1, const QVector3D &v2)
+ \relates QVector3D
+
+ Returns a QVector3D object that is formed by subtracting \a v2 from \a v1;
+ each component is subtracted separately.
+
+ \sa QVector3D::operator-=()
+*/
+
+/*!
+ \fn const QVector3D operator*(qreal factor, const QVector3D &vector)
+ \relates QVector3D
+
+ Returns a copy of the given \a vector, multiplied by the given \a factor.
+
+ \sa QVector3D::operator*=()
+*/
+
+/*!
+ \fn const QVector3D operator*(const QVector3D &vector, qreal factor)
+ \relates QVector3D
+
+ Returns a copy of the given \a vector, multiplied by the given \a factor.
+
+ \sa QVector3D::operator*=()
+*/
+
+/*!
+ \fn const QVector3D operator*(const QVector3D &v1, const QVector3D& v2)
+ \relates QVector3D
+
+ Multiplies the components of \a v1 by the corresponding components in \a v2.
+
+ Note: this is not the same as the crossProduct() of \a v1 and \a v2.
+
+ \sa QVector3D::crossProduct()
+*/
+
+/*!
+ \fn const QVector3D operator-(const QVector3D &vector)
+ \relates QVector3D
+ \overload
+
+ Returns a QVector3D object that is formed by changing the sign of
+ all three components of the given \a vector.
+
+ Equivalent to \c {QVector3D(0,0,0) - vector}.
+*/
+
+/*!
+ \fn const QVector3D operator/(const QVector3D &vector, qreal divisor)
+ \relates QVector3D
+
+ Returns the QVector3D object formed by dividing all three components of
+ the given \a vector by the given \a divisor.
+
+ \sa QVector3D::operator/=()
+*/
+
+/*!
+ \fn bool qFuzzyCompare(const QVector3D& v1, const QVector3D& v2)
+ \relates QVector3D
+
+ Returns true if \a v1 and \a v2 are equal, allowing for a small
+ fuzziness factor for floating-point comparisons; false otherwise.
+*/
+
+#ifndef QT_NO_VECTOR2D
+
+/*!
+ Returns the 2D vector form of this 3D vector, dropping the z coordinate.
+
+ \sa toVector4D(), toPoint()
+*/
+QVector2D QVector3D::toVector2D() const
+{
+ return QVector2D(xp, yp, 1);
+}
+
+#endif
+
+#ifndef QT_NO_VECTOR4D
+
+/*!
+ Returns the 4D form of this 3D vector, with the w coordinate set to zero.
+
+ \sa toVector2D(), toPoint()
+*/
+QVector4D QVector3D::toVector4D() const
+{
+ return QVector4D(xp, yp, zp, 0.0f, 1);
+}
+
+#endif
+
+/*!
+ \fn QPoint QVector3D::toPoint() const
+
+ Returns the QPoint form of this 3D vector.
+
+ \sa toPointF(), toVector2D()
+*/
+
+/*!
+ \fn QPointF QVector3D::toPointF() const
+
+ Returns the QPointF form of this 3D vector.
+
+ \sa toPoint(), toVector2D()
+*/
+
+/*!
+ Returns the length of the vector from the origin.
+
+ \sa lengthSquared(), normalized()
+*/
+qreal QVector3D::length() const
+{
+ return qvtsqrt64(qvtmul64(xp, xp) + qvtmul64(yp, yp) + qvtmul64(zp, zp));
+}
+
+/*!
+ Returns the squared length of the vector from the origin.
+ This is equivalent to the dot product of the vector with itself.
+
+ \sa length(), dotProduct()
+*/
+qreal QVector3D::lengthSquared() const
+{
+ return qvtdot64(qvtmul64(xp, xp) + qvtmul64(yp, yp) + qvtmul64(zp, zp));
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+
+QDebug operator<<(QDebug dbg, const QVector3D &vector)
+{
+ dbg.nospace() << "QVector3D("
+ << vector.x() << ", " << vector.y() << ", " << vector.z() << ')';
+ return dbg.space();
+}
+
+#endif
+
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/gui/math3d/qvector3d.h b/src/gui/math3d/qvector3d.h
new file mode 100644
index 0000000..dd1d014
--- /dev/null
+++ b/src/gui/math3d/qvector3d.h
@@ -0,0 +1,266 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QVECTOR3D_H
+#define QVECTOR3D_H
+
+#include <QtGui/qmath3dglobal.h>
+#include <QtCore/qpoint.h>
+#include <QtCore/qmetatype.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QMatrix4x4;
+class QVector2D;
+class QVector4D;
+class QQuaternion;
+
+#ifndef QT_NO_VECTOR3D
+
+class Q_GUI_EXPORT QVector3D
+{
+public:
+ QVector3D();
+ QVector3D(qreal xpos, qreal ypos, qreal zpos);
+ QVector3D(int xpos, int ypos, int zpos);
+ explicit QVector3D(const QPoint& point);
+ explicit QVector3D(const QPointF& point);
+#ifndef QT_NO_VECTOR2D
+ QVector3D(const QVector2D& vector);
+ QVector3D(const QVector2D& vector, qreal zpos);
+#endif
+#ifndef QT_NO_VECTOR4D
+ explicit QVector3D(const QVector4D& vector);
+#endif
+
+ bool isNull() const;
+
+ qreal x() const;
+ qreal y() const;
+ qreal z() const;
+
+ void setX(qreal x);
+ void setY(qreal y);
+ void setZ(qreal z);
+
+ qreal length() const;
+ qreal lengthSquared() const;
+
+ QVector3D normalized() const;
+ void normalize();
+
+ QVector3D &operator+=(const QVector3D &vector);
+ QVector3D &operator-=(const QVector3D &vector);
+ QVector3D &operator*=(qreal factor);
+ QVector3D &operator*=(const QVector3D& vector);
+ QVector3D &operator/=(qreal divisor);
+
+ static qreal dotProduct(const QVector3D& v1, const QVector3D& v2);
+ static QVector3D crossProduct(const QVector3D& v1, const QVector3D& v2);
+ static QVector3D normal(const QVector3D& v1, const QVector3D& v2);
+ static QVector3D normal
+ (const QVector3D& v1, const QVector3D& v2, const QVector3D& v3);
+
+ qreal distanceToPlane(const QVector3D& plane, const QVector3D& normal) const;
+ qreal distanceToPlane(const QVector3D& plane1, const QVector3D& plane2, const QVector3D& plane3) const;
+ qreal distanceToLine(const QVector3D& point, const QVector3D& direction) const;
+
+ friend inline bool operator==(const QVector3D &v1, const QVector3D &v2);
+ friend inline bool operator!=(const QVector3D &v1, const QVector3D &v2);
+ friend inline const QVector3D operator+(const QVector3D &v1, const QVector3D &v2);
+ friend inline const QVector3D operator-(const QVector3D &v1, const QVector3D &v2);
+ friend inline const QVector3D operator*(qreal factor, const QVector3D &vector);
+ friend inline const QVector3D operator*(const QVector3D &vector, qreal factor);
+ friend const QVector3D operator*(const QVector3D &v1, const QVector3D& v2);
+ friend inline const QVector3D operator-(const QVector3D &vector);
+ friend inline const QVector3D operator/(const QVector3D &vector, qreal divisor);
+
+ friend inline bool qFuzzyCompare(const QVector3D& v1, const QVector3D& v2);
+
+#ifndef QT_NO_VECTOR2D
+ QVector2D toVector2D() const;
+#endif
+#ifndef QT_NO_VECTOR4D
+ QVector4D toVector4D() const;
+#endif
+
+ QPoint toPoint() const;
+ QPointF toPointF() const;
+
+private:
+ qrealinner xp, yp, zp;
+
+ QVector3D(qrealinner xpos, qrealinner ypos, qrealinner zpos, int dummy);
+
+ friend class QVector2D;
+ friend class QVector4D;
+ friend class QQuaternion;
+ friend class QMatrix4x4;
+ friend class QVertexArray;
+ friend class QGLPainter;
+#ifndef QT_NO_MATRIX4X4
+ friend QVector3D operator*(const QVector3D& vector, const QMatrix4x4& matrix);
+ friend QVector3D operator*(const QMatrix4x4& matrix, const QVector3D& vector);
+#endif
+};
+
+inline QVector3D::QVector3D() : xp(0.0f), yp(0.0f), zp(0.0f) {}
+
+inline QVector3D::QVector3D(qreal xpos, qreal ypos, qreal zpos) : xp(xpos), yp(ypos), zp(zpos) {}
+
+inline QVector3D::QVector3D(qrealinner xpos, qrealinner ypos, qrealinner zpos, int) : xp(xpos), yp(ypos), zp(zpos) {}
+
+inline QVector3D::QVector3D(int xpos, int ypos, int zpos) : xp(xpos), yp(ypos), zp(zpos) {}
+
+inline QVector3D::QVector3D(const QPoint& point) : xp(point.x()), yp(point.y()), zp(0.0f) {}
+
+inline QVector3D::QVector3D(const QPointF& point) : xp(point.x()), yp(point.y()), zp(0.0f) {}
+
+inline bool QVector3D::isNull() const
+{
+ return qIsNull(xp) && qIsNull(yp) && qIsNull(zp);
+}
+
+inline qreal QVector3D::x() const { return qt_math3d_convert<qreal, qrealinner>(xp); }
+inline qreal QVector3D::y() const { return qt_math3d_convert<qreal, qrealinner>(yp); }
+inline qreal QVector3D::z() const { return qt_math3d_convert<qreal, qrealinner>(zp); }
+
+inline void QVector3D::setX(qreal x) { xp = x; }
+inline void QVector3D::setY(qreal y) { yp = y; }
+inline void QVector3D::setZ(qreal z) { zp = z; }
+
+inline QVector3D &QVector3D::operator+=(const QVector3D &vector)
+{
+ xp += vector.xp;
+ yp += vector.yp;
+ zp += vector.zp;
+ return *this;
+}
+
+inline QVector3D &QVector3D::operator-=(const QVector3D &vector)
+{
+ xp -= vector.xp;
+ yp -= vector.yp;
+ zp -= vector.zp;
+ return *this;
+}
+
+inline QVector3D &QVector3D::operator*=(qreal factor)
+{
+ qrealinner f(factor);
+ xp *= f;
+ yp *= f;
+ zp *= f;
+ return *this;
+}
+
+inline QVector3D &QVector3D::operator*=(const QVector3D& vector)
+{
+ xp *= vector.xp;
+ yp *= vector.yp;
+ zp *= vector.zp;
+ return *this;
+}
+
+inline QVector3D &QVector3D::operator/=(qreal divisor)
+{
+ qrealinner d(divisor);
+ xp /= d;
+ yp /= d;
+ zp /= d;
+ return *this;
+}
+
+inline bool operator==(const QVector3D &v1, const QVector3D &v2)
+{
+ return v1.xp == v2.xp && v1.yp == v2.yp && v1.zp == v2.zp;
+}
+
+inline bool operator!=(const QVector3D &v1, const QVector3D &v2)
+{
+ return v1.xp != v2.xp || v1.yp != v2.yp || v1.zp != v2.zp;
+}
+
+inline const QVector3D operator+(const QVector3D &v1, const QVector3D &v2)
+{
+ return QVector3D(v1.xp + v2.xp, v1.yp + v2.yp, v1.zp + v2.zp, 1);
+}
+
+inline const QVector3D operator-(const QVector3D &v1, const QVector3D &v2)
+{
+ return QVector3D(v1.xp - v2.xp, v1.yp - v2.yp, v1.zp - v2.zp, 1);
+}
+
+inline const QVector3D operator*(qreal factor, const QVector3D &vector)
+{
+ qrealinner f(factor);
+ return QVector3D(vector.xp * f, vector.yp * f, vector.zp * f, 1);
+}
+
+inline const QVector3D operator*(const QVector3D &vector, qreal factor)
+{
+ qrealinner f(factor);
+ return QVector3D(vector.xp * f, vector.yp * f, vector.zp * f, 1);
+}
+
+inline const QVector3D operator*(const QVector3D &v1, const QVector3D& v2)
+{
+ return QVector3D(v1.xp * v2.xp, v1.yp * v2.yp, v1.zp * v2.zp, 1);
+}
+
+inline const QVector3D operator-(const QVector3D &vector)
+{
+ return QVector3D(-vector.xp, -vector.yp, -vector.zp, 1);
+}
+
+inline const QVector3D operator/(const QVector3D &vector, qreal divisor)
+{
+ qrealinner d(divisor);
+ return QVector3D(vector.xp / d, vector.yp / d, vector.zp / d, 1);
+}
+
+inline bool qFuzzyCompare(const QVector3D& v1, const QVector3D& v2)
+{
+ return qFuzzyCompare(v1.xp, v2.xp) &&
+ qFuzzyCompare(v1.yp, v2.yp) &&
+ qFuzzyCompare(v1.zp, v2.zp);
+}
+
+inline QPoint QVector3D::toPoint() const
+{
+ return QPoint(qRound(xp), qRound(yp));
+}
+
+inline QPointF QVector3D::toPointF() const
+{
+ return QPointF(qt_math3d_convert<qreal, qrealinner>(xp),
+ qt_math3d_convert<qreal, qrealinner>(yp));
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QVector3D &vector);
+#endif
+
+#endif
+
+QT_END_NAMESPACE
+
+#ifndef QT_NO_VECTOR3D
+Q_DECLARE_METATYPE(QVector3D)
+#endif
+
+QT_END_HEADER
+
+#endif
diff --git a/src/gui/math3d/qvector4d.cpp b/src/gui/math3d/qvector4d.cpp
new file mode 100644
index 0000000..1239df0
--- /dev/null
+++ b/src/gui/math3d/qvector4d.cpp
@@ -0,0 +1,491 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#include "qvector4d.h"
+#include "qvector3d.h"
+#include "qvector2d.h"
+#include "qmath3dutil_p.h"
+
+QT_BEGIN_NAMESPACE
+
+#ifndef QT_NO_VECTOR4D
+
+/*!
+ \class QVector4D
+ \brief The QVector4D class represents a vector or vertex in 4D space.
+ \since 4.6
+
+ The QVector4D class can also be used to represent vertices in 4D space.
+ We therefore do not need to provide a separate vertex class.
+
+ The coordinates are stored internally using the most efficient
+ representation for the GL rendering engine, which will be either
+ floating-point or fixed-point.
+
+ \sa QQuaternion, QVector2D, QVector3D
+*/
+
+/*!
+ \fn QVector4D::QVector4D()
+
+ Constructs a null vector, i.e. with coordinates (0, 0, 0, 0).
+*/
+
+/*!
+ \fn QVector4D::QVector4D(qreal xpos, qreal ypos, qreal zpos, qreal wpos)
+
+ Constructs a vector with coordinates (\a xpos, \a ypos, \a zpos, \a wpos).
+*/
+
+/*!
+ \fn QVector4D::QVector4D(int xpos, int ypos, int zpos, int wpos)
+
+ Constructs a vector with coordinates (\a xpos, \a ypos, \a zpos, \a wpos).
+*/
+
+/*!
+ \fn QVector4D::QVector4D(const QPoint& point)
+
+ Constructs a vector with x and y coordinates from a 2D \a point, and
+ z and w coordinates of 0.
+*/
+
+/*!
+ \fn QVector4D::QVector4D(const QPointF& point)
+
+ Constructs a vector with x and y coordinates from a 2D \a point, and
+ z and w coordinates of 0.
+*/
+
+#ifndef QT_NO_VECTOR2D
+
+/*!
+ Constructs a 4D vector from the specified 2D \a vector. The z
+ and w coordinates are set to zero.
+
+ \sa toVector2D()
+*/
+QVector4D::QVector4D(const QVector2D& vector)
+{
+ xp = vector.xp;
+ yp = vector.yp;
+ zp = 0.0f;
+ wp = 0.0f;
+}
+
+/*!
+ Constructs a 4D vector from the specified 2D \a vector. The z
+ and w coordinates are set to \a zpos and \a wpos respectively.
+
+ \sa toVector2D()
+*/
+QVector4D::QVector4D(const QVector2D& vector, qreal zpos, qreal wpos)
+{
+ xp = vector.xp;
+ yp = vector.yp;
+ zp = zpos;
+ wp = wpos;
+}
+
+#endif
+
+#ifndef QT_NO_VECTOR3D
+
+/*!
+ Constructs a 4D vector from the specified 3D \a vector. The w
+ coordinate is set to zero.
+
+ \sa toVector3D()
+*/
+QVector4D::QVector4D(const QVector3D& vector)
+{
+ xp = vector.xp;
+ yp = vector.yp;
+ zp = vector.zp;
+ wp = 0.0f;
+}
+
+/*!
+ Constructs a 4D vector from the specified 3D \a vector. The w
+ coordinate is set to \a wpos.
+
+ \sa toVector3D()
+*/
+QVector4D::QVector4D(const QVector3D& vector, qreal wpos)
+{
+ xp = vector.xp;
+ yp = vector.yp;
+ zp = vector.zp;
+ wp = wpos;
+}
+
+#endif
+
+/*!
+ \fn bool QVector4D::isNull() const
+
+ Returns true if the x, y, z, and w coordinates are set to 0.0,
+ otherwise returns false.
+*/
+
+/*!
+ \fn qreal QVector4D::x() const
+
+ Returns the x coordinate of this point.
+
+ \sa setX(), y(), z(), w()
+*/
+
+/*!
+ \fn qreal QVector4D::y() const
+
+ Returns the y coordinate of this point.
+
+ \sa setY(), x(), z(), w()
+*/
+
+/*!
+ \fn qreal QVector4D::z() const
+
+ Returns the z coordinate of this point.
+
+ \sa setZ(), x(), y(), w()
+*/
+
+/*!
+ \fn qreal QVector4D::w() const
+
+ Returns the w coordinate of this point.
+
+ \sa setW(), x(), y(), z()
+*/
+
+/*!
+ \fn void QVector4D::setX(qreal x)
+
+ Sets the x coordinate of this point to the given \a x coordinate.
+
+ \sa x(), setY(), setZ(), setW()
+*/
+
+/*!
+ \fn void QVector4D::setY(qreal y)
+
+ Sets the y coordinate of this point to the given \a y coordinate.
+
+ \sa y(), setX(), setZ(), setW()
+*/
+
+/*!
+ \fn void QVector4D::setZ(qreal z)
+
+ Sets the z coordinate of this point to the given \a z coordinate.
+
+ \sa z(), setX(), setY(), setW()
+*/
+
+/*!
+ \fn void QVector4D::setW(qreal w)
+
+ Sets the w coordinate of this point to the given \a w coordinate.
+
+ \sa w(), setX(), setY(), setZ()
+*/
+
+/*!
+ Returns the length of the vector from the origin.
+
+ \sa lengthSquared(), normalized()
+*/
+qreal QVector4D::length() const
+{
+ return qvtsqrt64(qvtmul64(xp, xp) + qvtmul64(yp, yp) +
+ qvtmul64(zp, zp) + qvtmul64(wp, wp));
+}
+
+/*!
+ Returns the squared length of the vector from the origin.
+ This is equivalent to the dot product of the vector with itself.
+
+ \sa length(), dotProduct()
+*/
+qreal QVector4D::lengthSquared() const
+{
+ return qvtdot64(qvtmul64(xp, xp) + qvtmul64(yp, yp) +
+ qvtmul64(zp, zp) + qvtmul64(wp, wp));
+}
+
+/*!
+ Returns the normalized unit vector form of this vector. If this vector
+ is not null, the returned vector is guaranteed to be 1.0 in length.
+ If this vector is null, then a null vector is returned.
+
+ \sa length(), normalize()
+*/
+QVector4D QVector4D::normalized() const
+{
+ qreal len = length();
+ if (!qIsNull(len))
+ return *this / len;
+ else
+ return QVector4D();
+}
+
+/*!
+ Normalizes the currect vector in place. Nothing happens if this
+ vector is a null vector.
+
+ \sa length(), normalized()
+*/
+void QVector4D::normalize()
+{
+ qreal len = length();
+ if (qIsNull(len))
+ return;
+
+ xp /= len;
+ yp /= len;
+ zp /= len;
+ wp /= len;
+}
+
+
+/*!
+ \fn QVector4D &QVector4D::operator+=(const QVector4D &vector)
+
+ Adds the given \a vector to this vector and returns a reference to
+ this vector.
+
+ \sa operator-=()
+*/
+
+/*!
+ \fn QVector4D &QVector4D::operator-=(const QVector4D &vector)
+
+ Subtracts the given \a vector from this vector and returns a reference to
+ this vector.
+
+ \sa operator+=()
+*/
+
+/*!
+ \fn QVector4D &QVector4D::operator*=(qreal factor)
+
+ Multiplies this vector's coordinates by the given \a factor, and
+ returns a reference to this vector.
+
+ \sa operator/=()
+*/
+
+/*!
+ \fn QVector4D &QVector4D::operator*=(const QVector4D &vector)
+
+ Multiplies the components of this vector by the corresponding
+ components in \a vector.
+*/
+
+/*!
+ \fn QVector4D &QVector4D::operator/=(qreal divisor)
+
+ Divides this vector's coordinates by the given \a divisor, and
+ returns a reference to this vector.
+
+ \sa operator*=()
+*/
+
+/*!
+ Returns the dot product of \a v1 and \a v2.
+*/
+qreal QVector4D::dotProduct(const QVector4D& v1, const QVector4D& v2)
+{
+ return qvtdot64(qvtmul64(v1.xp, v2.xp) + qvtmul64(v1.yp, v2.yp) +
+ qvtmul64(v1.zp, v2.zp) + qvtmul64(v1.wp, v2.wp));
+}
+
+/*!
+ \fn bool operator==(const QVector4D &v1, const QVector4D &v2)
+ \relates QVector4D
+
+ Returns true if \a v1 is equal to \a v2; otherwise returns false.
+ This operator uses an exact floating-point comparison.
+*/
+
+/*!
+ \fn bool operator!=(const QVector4D &v1, const QVector4D &v2)
+ \relates QVector4D
+
+ Returns true if \a v1 is not equal to \a v2; otherwise returns false.
+ This operator uses an exact floating-point comparison.
+*/
+
+/*!
+ \fn const QVector4D operator+(const QVector4D &v1, const QVector4D &v2)
+ \relates QVector4D
+
+ Returns a QVector4D object that is the sum of the given vectors, \a v1
+ and \a v2; each component is added separately.
+
+ \sa QVector4D::operator+=()
+*/
+
+/*!
+ \fn const QVector4D operator-(const QVector4D &v1, const QVector4D &v2)
+ \relates QVector4D
+
+ Returns a QVector4D object that is formed by subtracting \a v2 from \a v1;
+ each component is subtracted separately.
+
+ \sa QVector4D::operator-=()
+*/
+
+/*!
+ \fn const QVector4D operator*(qreal factor, const QVector4D &vector)
+ \relates QVector4D
+
+ Returns a copy of the given \a vector, multiplied by the given \a factor.
+
+ \sa QVector4D::operator*=()
+*/
+
+/*!
+ \fn const QVector4D operator*(const QVector4D &vector, qreal factor)
+ \relates QVector4D
+
+ Returns a copy of the given \a vector, multiplied by the given \a factor.
+
+ \sa QVector4D::operator*=()
+*/
+
+/*!
+ \fn const QVector4D operator*(const QVector4D &v1, const QVector4D& v2)
+ \relates QVector4D
+
+ Returns the vector consisting of the multiplication of the
+ components from \a v1 and \a v2.
+
+ \sa QVector4D::operator*=()
+*/
+
+/*!
+ \fn const QVector4D operator-(const QVector4D &vector)
+ \relates QVector4D
+ \overload
+
+ Returns a QVector4D object that is formed by changing the sign of
+ all three components of the given \a vector.
+
+ Equivalent to \c {QVector4D(0,0,0,0) - vector}.
+*/
+
+/*!
+ \fn const QVector4D operator/(const QVector4D &vector, qreal divisor)
+ \relates QVector4D
+
+ Returns the QVector4D object formed by dividing all four components of
+ the given \a vector by the given \a divisor.
+
+ \sa QVector4D::operator/=()
+*/
+
+/*!
+ \fn bool qFuzzyCompare(const QVector4D& v1, const QVector4D& v2)
+ \relates QVector4D
+
+ Returns true if \a v1 and \a v2 are equal, allowing for a small
+ fuzziness factor for floating-point comparisons; false otherwise.
+*/
+
+#ifndef QT_NO_VECTOR2D
+
+/*!
+ Returns the 2D vector form of this 4D vector, dropping the z and w coordinates.
+
+ \sa toVector2DAffine(), toVector3D(), toPoint()
+*/
+QVector2D QVector4D::toVector2D() const
+{
+ return QVector2D(xp, yp, 1);
+}
+
+/*!
+ Returns the 2D vector form of this 4D vector, dividing the x and y
+ coordinates by the w coordinate and dropping the z coordinate.
+ Returns a null vector if w is zero.
+
+ \sa toVector2D(), toVector3DAffine(), toPoint()
+*/
+QVector2D QVector4D::toVector2DAffine() const
+{
+ if (qIsNull(wp))
+ return QVector2D();
+ return QVector2D(xp / wp, yp / wp, 1);
+}
+
+#endif
+
+#ifndef QT_NO_VECTOR3D
+
+/*!
+ Returns the 3D vector form of this 4D vector, dropping the w coordinate.
+
+ \sa toVector3DAffine(), toVector2D(), toPoint()
+*/
+QVector3D QVector4D::toVector3D() const
+{
+ return QVector3D(xp, yp, zp, 1);
+}
+
+/*!
+ Returns the 3D vector form of this 4D vector, dividing the x, y, and
+ z coordinates by the w coordinate. Returns a null vector if w is zero.
+
+ \sa toVector3D(), toVector2DAffine(), toPoint()
+*/
+QVector3D QVector4D::toVector3DAffine() const
+{
+ if (qIsNull(wp))
+ return QVector3D();
+ return QVector3D(xp / wp, yp / wp, zp / wp, 1);
+}
+
+#endif
+
+/*!
+ \fn QPoint QVector4D::toPoint() const
+
+ Returns the QPoint form of this 4D vector.
+
+ \sa toPointF(), toVector2D()
+*/
+
+/*!
+ \fn QPointF QVector4D::toPointF() const
+
+ Returns the QPointF form of this 4D vector.
+
+ \sa toPoint(), toVector2D()
+*/
+
+#ifndef QT_NO_DEBUG_STREAM
+
+QDebug operator<<(QDebug dbg, const QVector4D &vector)
+{
+ dbg.nospace() << "QVector4D("
+ << vector.x() << ", " << vector.y() << ", "
+ << vector.z() << ", " << vector.w() << ')';
+ return dbg.space();
+}
+
+#endif
+
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/gui/math3d/qvector4d.h b/src/gui/math3d/qvector4d.h
new file mode 100644
index 0000000..078c328
--- /dev/null
+++ b/src/gui/math3d/qvector4d.h
@@ -0,0 +1,270 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the $MODULE$ of the Qt Toolkit.
+**
+** $TROLLTECH_DUAL_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QVECTOR4D_H
+#define QVECTOR4D_H
+
+#include <QtGui/qmath3dglobal.h>
+#include <QtCore/qpoint.h>
+#include <QtCore/qmetatype.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(Gui)
+
+class QMatrix4x4;
+class QVector2D;
+class QVector3D;
+class QQuaternion;
+
+#ifndef QT_NO_VECTOR4D
+
+class Q_GUI_EXPORT QVector4D
+{
+public:
+ QVector4D();
+ QVector4D(qreal xpos, qreal ypos, qreal zpos, qreal wpos);
+ QVector4D(int xpos, int ypos, int zpos, int wpos);
+ explicit QVector4D(const QPoint& point);
+ explicit QVector4D(const QPointF& point);
+#ifndef QT_NO_VECTOR2D
+ QVector4D(const QVector2D& vector);
+ QVector4D(const QVector2D& vector, qreal zpos, qreal wpos);
+#endif
+#ifndef QT_NO_VECTOR3D
+ QVector4D(const QVector3D& vector);
+ QVector4D(const QVector3D& vector, qreal wpos);
+#endif
+
+ bool isNull() const;
+
+ qreal x() const;
+ qreal y() const;
+ qreal z() const;
+ qreal w() const;
+
+ void setX(qreal x);
+ void setY(qreal y);
+ void setZ(qreal z);
+ void setW(qreal w);
+
+ qreal length() const;
+ qreal lengthSquared() const;
+
+ QVector4D normalized() const;
+ void normalize();
+
+ QVector4D &operator+=(const QVector4D &vector);
+ QVector4D &operator-=(const QVector4D &vector);
+ QVector4D &operator*=(qreal factor);
+ QVector4D &operator*=(const QVector4D &vector);
+ QVector4D &operator/=(qreal divisor);
+
+ static qreal dotProduct(const QVector4D& v1, const QVector4D& v2);
+
+ friend inline bool operator==(const QVector4D &v1, const QVector4D &v2);
+ friend inline bool operator!=(const QVector4D &v1, const QVector4D &v2);
+ friend inline const QVector4D operator+(const QVector4D &v1, const QVector4D &v2);
+ friend inline const QVector4D operator-(const QVector4D &v1, const QVector4D &v2);
+ friend inline const QVector4D operator*(qreal factor, const QVector4D &vector);
+ friend inline const QVector4D operator*(const QVector4D &vector, qreal factor);
+ friend inline const QVector4D operator*(const QVector4D &v1, const QVector4D& v2);
+ friend inline const QVector4D operator-(const QVector4D &vector);
+ friend inline const QVector4D operator/(const QVector4D &vector, qreal divisor);
+
+ friend inline bool qFuzzyCompare(const QVector4D& v1, const QVector4D& v2);
+
+#ifndef QT_NO_VECTOR2D
+ QVector2D toVector2D() const;
+ QVector2D toVector2DAffine() const;
+#endif
+#ifndef QT_NO_VECTOR3D
+ QVector3D toVector3D() const;
+ QVector3D toVector3DAffine() const;
+#endif
+
+ QPoint toPoint() const;
+ QPointF toPointF() const;
+
+private:
+ qrealinner xp, yp, zp, wp;
+
+ QVector4D(qrealinner xpos, qrealinner ypos, qrealinner zpos, qrealinner wpos, int dummy);
+
+ friend class QVector2D;
+ friend class QVector3D;
+ friend class QQuaternion;
+ friend class QMatrix4x4;
+ friend class QVertexArray;
+#ifndef QT_NO_MATRIX4X4
+ friend QVector4D operator*(const QVector4D& vector, const QMatrix4x4& matrix);
+ friend QVector4D operator*(const QMatrix4x4& matrix, const QVector4D& vector);
+#endif
+};
+
+inline QVector4D::QVector4D() : xp(0.0f), yp(0.0f), zp(0.0f), wp(0.0f) {}
+
+inline QVector4D::QVector4D(qreal xpos, qreal ypos, qreal zpos, qreal wpos) : xp(xpos), yp(ypos), zp(zpos), wp(wpos) {}
+
+inline QVector4D::QVector4D(qrealinner xpos, qrealinner ypos, qrealinner zpos, qrealinner wpos, int) : xp(xpos), yp(ypos), zp(zpos), wp(wpos) {}
+
+inline QVector4D::QVector4D(int xpos, int ypos, int zpos, int wpos) : xp(xpos), yp(ypos), zp(zpos), wp(wpos) {}
+
+inline QVector4D::QVector4D(const QPoint& point) : xp(point.x()), yp(point.y()), zp(0.0f), wp(0.0f) {}
+
+inline QVector4D::QVector4D(const QPointF& point) : xp(point.x()), yp(point.y()), zp(0.0f), wp(0.0f) {}
+
+inline bool QVector4D::isNull() const
+{
+ return qIsNull(xp) && qIsNull(yp) && qIsNull(zp) && qIsNull(wp);
+}
+
+inline qreal QVector4D::x() const { return qt_math3d_convert<qreal, qrealinner>(xp); }
+inline qreal QVector4D::y() const { return qt_math3d_convert<qreal, qrealinner>(yp); }
+inline qreal QVector4D::z() const { return qt_math3d_convert<qreal, qrealinner>(zp); }
+inline qreal QVector4D::w() const { return qt_math3d_convert<qreal, qrealinner>(wp); }
+
+inline void QVector4D::setX(qreal x) { xp = x; }
+inline void QVector4D::setY(qreal y) { yp = y; }
+inline void QVector4D::setZ(qreal z) { zp = z; }
+inline void QVector4D::setW(qreal w) { wp = w; }
+
+inline QVector4D &QVector4D::operator+=(const QVector4D &vector)
+{
+ xp += vector.xp;
+ yp += vector.yp;
+ zp += vector.zp;
+ wp += vector.wp;
+ return *this;
+}
+
+inline QVector4D &QVector4D::operator-=(const QVector4D &vector)
+{
+ xp -= vector.xp;
+ yp -= vector.yp;
+ zp -= vector.zp;
+ wp -= vector.wp;
+ return *this;
+}
+
+inline QVector4D &QVector4D::operator*=(qreal factor)
+{
+ qrealinner f(factor);
+ xp *= f;
+ yp *= f;
+ zp *= f;
+ wp *= f;
+ return *this;
+}
+
+inline QVector4D &QVector4D::operator*=(const QVector4D &vector)
+{
+ xp *= vector.xp;
+ yp *= vector.yp;
+ zp *= vector.zp;
+ wp *= vector.wp;
+ return *this;
+}
+
+inline QVector4D &QVector4D::operator/=(qreal divisor)
+{
+ qrealinner d(divisor);
+ xp /= d;
+ yp /= d;
+ zp /= d;
+ wp /= d;
+ return *this;
+}
+
+inline bool operator==(const QVector4D &v1, const QVector4D &v2)
+{
+ return v1.xp == v2.xp && v1.yp == v2.yp && v1.zp == v2.zp && v1.wp == v2.wp;
+}
+
+inline bool operator!=(const QVector4D &v1, const QVector4D &v2)
+{
+ return v1.xp != v2.xp || v1.yp != v2.yp || v1.zp != v2.zp || v1.wp != v2.wp;
+}
+
+inline const QVector4D operator+(const QVector4D &v1, const QVector4D &v2)
+{
+ return QVector4D(v1.xp + v2.xp, v1.yp + v2.yp, v1.zp + v2.zp, v1.wp + v2.wp, 1);
+}
+
+inline const QVector4D operator-(const QVector4D &v1, const QVector4D &v2)
+{
+ return QVector4D(v1.xp - v2.xp, v1.yp - v2.yp, v1.zp - v2.zp, v1.wp - v2.wp, 1);
+}
+
+inline const QVector4D operator*(qreal factor, const QVector4D &vector)
+{
+ qrealinner f(factor);
+ return QVector4D(vector.xp * f, vector.yp * f, vector.zp * f, vector.wp * f, 1);
+}
+
+inline const QVector4D operator*(const QVector4D &vector, qreal factor)
+{
+ qrealinner f(factor);
+ return QVector4D(vector.xp * f, vector.yp * f, vector.zp * f, vector.wp * f, 1);
+}
+
+inline const QVector4D operator*(const QVector4D &v1, const QVector4D& v2)
+{
+ return QVector4D(v1.xp * v2.xp, v1.yp * v2.yp, v1.zp * v2.zp, v1.wp * v2.wp, 1);
+}
+
+inline const QVector4D operator-(const QVector4D &vector)
+{
+ return QVector4D(-vector.xp, -vector.yp, -vector.zp, -vector.wp, 1);
+}
+
+inline const QVector4D operator/(const QVector4D &vector, qreal divisor)
+{
+ qrealinner d(divisor);
+ return QVector4D(vector.xp / d, vector.yp / d, vector.zp / d, vector.wp / d, 1);
+}
+
+inline bool qFuzzyCompare(const QVector4D& v1, const QVector4D& v2)
+{
+ return qFuzzyCompare(v1.xp, v2.xp) &&
+ qFuzzyCompare(v1.yp, v2.yp) &&
+ qFuzzyCompare(v1.zp, v2.zp) &&
+ qFuzzyCompare(v1.wp, v2.wp);
+}
+
+inline QPoint QVector4D::toPoint() const
+{
+ return QPoint(qRound(xp), qRound(yp));
+}
+
+inline QPointF QVector4D::toPointF() const
+{
+ return QPointF(qt_math3d_convert<qreal, qrealinner>(xp),
+ qt_math3d_convert<qreal, qrealinner>(yp));
+}
+
+#ifndef QT_NO_DEBUG_STREAM
+Q_GUI_EXPORT QDebug operator<<(QDebug dbg, const QVector4D &vector);
+#endif
+
+#endif
+
+QT_END_NAMESPACE
+
+#ifndef QT_NO_VECTOR4D
+Q_DECLARE_METATYPE(QVector4D)
+#endif
+
+QT_END_HEADER
+
+#endif
diff --git a/src/opengl/gl2paintengineex/qglshader_p.h b/src/opengl/gl2paintengineex/qglshader_p.h
index 1625b84..64c9a42 100644
--- a/src/opengl/gl2paintengineex/qglshader_p.h
+++ b/src/opengl/gl2paintengineex/qglshader_p.h
@@ -81,6 +81,8 @@ SAMPLER_2D_SHADOW.
#include <QtOpenGL>
+#define QGLShader QGLEngineShader
+#define QGLShaderProgram QGLEngineShaderProgram
typedef struct {
GLfloat a;
diff --git a/src/opengl/opengl.pro b/src/opengl/opengl.pro
index 48d7caf..5be48ba 100644
--- a/src/opengl/opengl.pro
+++ b/src/opengl/opengl.pro
@@ -25,14 +25,16 @@ HEADERS += qgl.h \
qglcolormap.h \
qglpixelbuffer.h \
qglframebufferobject.h \
- qglpixmapfilter_p.h
+ qglpixmapfilter_p.h \
+ qglshaderprogram.h
SOURCES += qgl.cpp \
qglcolormap.cpp \
qglpixelbuffer.cpp \
qglframebufferobject.cpp \
qglextensions.cpp \
- qglpixmapfilter.cpp
+ qglpixmapfilter.cpp \
+ qglshaderprogram.cpp
!contains(QT_CONFIG, opengles2) {
HEADERS += qpaintengine_opengl_p.h
diff --git a/src/opengl/qglextensions.cpp b/src/opengl/qglextensions.cpp
index 8357cf9..5ba669b 100644
--- a/src/opengl/qglextensions.cpp
+++ b/src/opengl/qglextensions.cpp
@@ -150,36 +150,158 @@ bool qt_resolve_buffer_extensions(QGLContext *ctx)
bool qt_resolve_glsl_extensions(QGLContext *ctx)
{
+#if defined(QT_OPENGL_ES_2)
+ // The GLSL shader functions are always present in OpenGL/ES 2.0.
+ // The only exceptions are glGetProgramBinaryOES and glProgramBinaryOES.
+ if (!QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glslResolved) {
+ glGetProgramBinaryOES = (_glGetProgramBinaryOES) ctx->getProcAddress(QLatin1String("glGetProgramBinaryOES"));
+ glProgramBinaryOES = (_glProgramBinaryOES) ctx->getProcAddress(QLatin1String("glProgramBinaryOES"));
+ QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glslResolved = true;
+ }
+ return true;
+#else
if (glCreateShader)
return true;
glCreateShader = (_glCreateShader) ctx->getProcAddress(QLatin1String("glCreateShader"));
- glShaderSource = (_glShaderSource) ctx->getProcAddress(QLatin1String("glShaderSource"));
- glCompileShader = (_glCompileShader) ctx->getProcAddress(QLatin1String("glCompileShader"));
- glDeleteShader = (_glDeleteShader) ctx->getProcAddress(QLatin1String("glDeleteShader"));
-
- glCreateProgram = (_glCreateProgram) ctx->getProcAddress(QLatin1String("glCreateProgram"));
- glAttachShader = (_glAttachShader) ctx->getProcAddress(QLatin1String("glAttachShader"));
- glDetachShader = (_glDetachShader) ctx->getProcAddress(QLatin1String("glDetachShader"));
- glLinkProgram = (_glLinkProgram) ctx->getProcAddress(QLatin1String("glLinkProgram"));
- glUseProgram = (_glUseProgram) ctx->getProcAddress(QLatin1String("glUseProgram"));
- glDeleteProgram = (_glDeleteProgram) ctx->getProcAddress(QLatin1String("glDeleteProgram"));
-
- glGetShaderInfoLog = (_glGetShaderInfoLog) ctx->getProcAddress(QLatin1String("glGetShaderInfoLog"));
- glGetShaderiv = (_glGetShaderiv) ctx->getProcAddress(QLatin1String("glGetShaderiv"));
- glGetProgramiv = (_glGetProgramiv) ctx->getProcAddress(QLatin1String("glGetProgramiv"));
-
- glGetUniformLocation = (_glGetUniformLocation) ctx->getProcAddress(QLatin1String("glGetUniformLocation"));
- glUniform4fv = (_glUniform4fv) ctx->getProcAddress(QLatin1String("glUniform4fv"));
- glUniform3fv = (_glUniform3fv) ctx->getProcAddress(QLatin1String("glUniform3fv"));
- glUniform2fv = (_glUniform2fv) ctx->getProcAddress(QLatin1String("glUniform2fv"));
- glUniform1fv = (_glUniform1fv) ctx->getProcAddress(QLatin1String("glUniform1fv"));
- glUniform1i = (_glUniform1i) ctx->getProcAddress(QLatin1String("glUniform1i"));
-
- return glCreateShader && glShaderSource && glCompileShader && glDeleteProgram &&
- glCreateProgram && glAttachShader && glDetachShader && glLinkProgram && glUseProgram &&
- glDeleteProgram && glGetShaderInfoLog && glGetShaderiv && glGetProgramiv && glGetUniformLocation &&
- glUniform1i && glUniform1fv && glUniform2fv && glUniform3fv && glUniform4fv;
+ if (glCreateShader) {
+ glShaderSource = (_glShaderSource) ctx->getProcAddress(QLatin1String("glShaderSource"));
+ glShaderBinary = (_glShaderBinary) ctx->getProcAddress(QLatin1String("glShaderBinary"));
+ glCompileShader = (_glCompileShader) ctx->getProcAddress(QLatin1String("glCompileShader"));
+ glDeleteShader = (_glDeleteShader) ctx->getProcAddress(QLatin1String("glDeleteShader"));
+ glIsShader = (_glIsShader) ctx->getProcAddress(QLatin1String("glIsShader"));
+
+ glCreateProgram = (_glCreateProgram) ctx->getProcAddress(QLatin1String("glCreateProgram"));
+ glAttachShader = (_glAttachShader) ctx->getProcAddress(QLatin1String("glAttachShader"));
+ glDetachShader = (_glDetachShader) ctx->getProcAddress(QLatin1String("glDetachShader"));
+ glLinkProgram = (_glLinkProgram) ctx->getProcAddress(QLatin1String("glLinkProgram"));
+ glUseProgram = (_glUseProgram) ctx->getProcAddress(QLatin1String("glUseProgram"));
+ glDeleteProgram = (_glDeleteProgram) ctx->getProcAddress(QLatin1String("glDeleteProgram"));
+ glIsProgram = (_glIsProgram) ctx->getProcAddress(QLatin1String("glIsProgram"));
+
+ glGetShaderInfoLog = (_glGetShaderInfoLog) ctx->getProcAddress(QLatin1String("glGetShaderInfoLog"));
+ glGetShaderiv = (_glGetShaderiv) ctx->getProcAddress(QLatin1String("glGetShaderiv"));
+ glGetShaderSource = (_glGetShaderSource) ctx->getProcAddress(QLatin1String("glGetShaderSource"));
+ glGetProgramiv = (_glGetProgramiv) ctx->getProcAddress(QLatin1String("glGetProgramiv"));
+ glGetProgramInfoLog = (_glGetProgramInfoLog) ctx->getProcAddress(QLatin1String("glGetProgramInfoLog"));
+
+ glGetUniformLocation = (_glGetUniformLocation) ctx->getProcAddress(QLatin1String("glGetUniformLocation"));
+ glUniform4fv = (_glUniform4fv) ctx->getProcAddress(QLatin1String("glUniform4fv"));
+ glUniform3fv = (_glUniform3fv) ctx->getProcAddress(QLatin1String("glUniform3fv"));
+ glUniform2fv = (_glUniform2fv) ctx->getProcAddress(QLatin1String("glUniform2fv"));
+ glUniform1fv = (_glUniform1fv) ctx->getProcAddress(QLatin1String("glUniform1fv"));
+ glUniform1i = (_glUniform1i) ctx->getProcAddress(QLatin1String("glUniform1i"));
+ glUniform1iv = (_glUniform1iv) ctx->getProcAddress(QLatin1String("glUniform1iv"));
+ glUniformMatrix2fv = (_glUniformMatrix2fv) ctx->getProcAddress(QLatin1String("glUniformMatrix2fv"));
+ glUniformMatrix3fv = (_glUniformMatrix3fv) ctx->getProcAddress(QLatin1String("glUniformMatrix3fv"));
+ glUniformMatrix4fv = (_glUniformMatrix4fv) ctx->getProcAddress(QLatin1String("glUniformMatrix4fv"));
+ glUniformMatrix2x3fv = (_glUniformMatrix2x3fv) ctx->getProcAddress(QLatin1String("glUniformMatrix2x3fv"));
+ glUniformMatrix2x4fv = (_glUniformMatrix2x4fv) ctx->getProcAddress(QLatin1String("glUniformMatrix2x4fv"));
+ glUniformMatrix3x2fv = (_glUniformMatrix3x2fv) ctx->getProcAddress(QLatin1String("glUniformMatrix3x2fv"));
+ glUniformMatrix3x4fv = (_glUniformMatrix3x4fv) ctx->getProcAddress(QLatin1String("glUniformMatrix3x4fv"));
+ glUniformMatrix4x2fv = (_glUniformMatrix4x2fv) ctx->getProcAddress(QLatin1String("glUniformMatrix4x2fv"));
+ glUniformMatrix4x3fv = (_glUniformMatrix4x3fv) ctx->getProcAddress(QLatin1String("glUniformMatrix4x3fv"));
+
+ glBindAttribLocation = (_glBindAttribLocation) ctx->getProcAddress(QLatin1String("glBindAttribLocation"));
+ glGetAttribLocation = (_glGetAttribLocation) ctx->getProcAddress(QLatin1String("glGetAttribLocation"));
+ glVertexAttrib1fv = (_glVertexAttrib1fv) ctx->getProcAddress(QLatin1String("glVertexAttrib1fv"));
+ glVertexAttrib2fv = (_glVertexAttrib2fv) ctx->getProcAddress(QLatin1String("glVertexAttrib2fv"));
+ glVertexAttrib3fv = (_glVertexAttrib3fv) ctx->getProcAddress(QLatin1String("glVertexAttrib3fv"));
+ glVertexAttrib4fv = (_glVertexAttrib4fv) ctx->getProcAddress(QLatin1String("glVertexAttrib4fv"));
+ glVertexAttribPointer = (_glVertexAttribPointer) ctx->getProcAddress(QLatin1String("glVertexAttribPointer"));
+ glDisableVertexAttribArray = (_glDisableVertexAttribArray) ctx->getProcAddress(QLatin1String("glDisableVertexAttribArray"));
+ glEnableVertexAttribArray = (_glEnableVertexAttribArray) ctx->getProcAddress(QLatin1String("glEnableVertexAttribArray"));
+ } else {
+ // We may not have the standard shader functions, but we might
+ // have the older ARB functions instead.
+ glCreateShader = (_glCreateShader) ctx->getProcAddress(QLatin1String("glCreateShaderObjectARB"));
+ glShaderSource = (_glShaderSource) ctx->getProcAddress(QLatin1String("glShaderSourceARB"));
+ glShaderBinary = (_glShaderBinary) ctx->getProcAddress(QLatin1String("glShaderBinaryARB"));
+ glCompileShader = (_glCompileShader) ctx->getProcAddress(QLatin1String("glCompileShaderARB"));
+ glDeleteShader = (_glDeleteShader) ctx->getProcAddress(QLatin1String("glDeleteObjectARB"));
+ glIsShader = 0;
+
+ glCreateProgram = (_glCreateProgram) ctx->getProcAddress(QLatin1String("glCreateProgramObjectARB"));
+ glAttachShader = (_glAttachShader) ctx->getProcAddress(QLatin1String("glAttachObjectARB"));
+ glDetachShader = (_glDetachShader) ctx->getProcAddress(QLatin1String("glDetachObjectARB"));
+ glLinkProgram = (_glLinkProgram) ctx->getProcAddress(QLatin1String("glLinkProgramARB"));
+ glUseProgram = (_glUseProgram) ctx->getProcAddress(QLatin1String("glUseProgramObjectARB"));
+ glDeleteProgram = (_glDeleteProgram) ctx->getProcAddress(QLatin1String("glDeleteObjectARB"));
+ glIsProgram = 0;
+
+ glGetShaderInfoLog = (_glGetShaderInfoLog) ctx->getProcAddress(QLatin1String("glGetInfoLogARB"));
+ glGetShaderiv = (_glGetShaderiv) ctx->getProcAddress(QLatin1String("glGetObjectParameterivARB"));
+ glGetShaderSource = (_glGetShaderSource) ctx->getProcAddress(QLatin1String("glGetShaderSourceARB"));
+ glGetProgramiv = (_glGetProgramiv) ctx->getProcAddress(QLatin1String("glGetObjectParameterivARB"));
+ glGetProgramInfoLog = (_glGetProgramInfoLog) ctx->getProcAddress(QLatin1String("glGetInfoLogARB"));
+
+ glGetUniformLocation = (_glGetUniformLocation) ctx->getProcAddress(QLatin1String("glGetUniformLocationARB"));
+ glUniform4fv = (_glUniform4fv) ctx->getProcAddress(QLatin1String("glUniform4fvARB"));
+ glUniform3fv = (_glUniform3fv) ctx->getProcAddress(QLatin1String("glUniform3fvARB"));
+ glUniform2fv = (_glUniform2fv) ctx->getProcAddress(QLatin1String("glUniform2fvARB"));
+ glUniform1fv = (_glUniform1fv) ctx->getProcAddress(QLatin1String("glUniform1fvARB"));
+ glUniform1i = (_glUniform1i) ctx->getProcAddress(QLatin1String("glUniform1iARB"));
+ glUniform1iv = (_glUniform1iv) ctx->getProcAddress(QLatin1String("glUniform1ivARB"));
+ glUniformMatrix2fv = (_glUniformMatrix2fv) ctx->getProcAddress(QLatin1String("glUniformMatrix2fvARB"));
+ glUniformMatrix3fv = (_glUniformMatrix3fv) ctx->getProcAddress(QLatin1String("glUniformMatrix3fvARB"));
+ glUniformMatrix4fv = (_glUniformMatrix4fv) ctx->getProcAddress(QLatin1String("glUniformMatrix4fvARB"));
+ glUniformMatrix2x3fv = (_glUniformMatrix2x3fv) ctx->getProcAddress(QLatin1String("glUniformMatrix2x3fvARB"));
+ glUniformMatrix2x4fv = (_glUniformMatrix2x4fv) ctx->getProcAddress(QLatin1String("glUniformMatrix2x4fvARB"));
+ glUniformMatrix3x2fv = (_glUniformMatrix3x2fv) ctx->getProcAddress(QLatin1String("glUniformMatrix3x2fvARB"));
+ glUniformMatrix3x4fv = (_glUniformMatrix3x4fv) ctx->getProcAddress(QLatin1String("glUniformMatrix3x4fvARB"));
+ glUniformMatrix4x2fv = (_glUniformMatrix4x2fv) ctx->getProcAddress(QLatin1String("glUniformMatrix4x2fvARB"));
+ glUniformMatrix4x3fv = (_glUniformMatrix4x3fv) ctx->getProcAddress(QLatin1String("glUniformMatrix4x3fvARB"));
+
+ glBindAttribLocation = (_glBindAttribLocation) ctx->getProcAddress(QLatin1String("glBindAttribLocationARB"));
+ glGetAttribLocation = (_glGetAttribLocation) ctx->getProcAddress(QLatin1String("glGetAttribLocationARB"));
+ glVertexAttrib1fv = (_glVertexAttrib1fv) ctx->getProcAddress(QLatin1String("glVertexAttrib1fvARB"));
+ glVertexAttrib2fv = (_glVertexAttrib2fv) ctx->getProcAddress(QLatin1String("glVertexAttrib2fvARB"));
+ glVertexAttrib3fv = (_glVertexAttrib3fv) ctx->getProcAddress(QLatin1String("glVertexAttrib3fvARB"));
+ glVertexAttrib4fv = (_glVertexAttrib4fv) ctx->getProcAddress(QLatin1String("glVertexAttrib4fvARB"));
+ glVertexAttribPointer = (_glVertexAttribPointer) ctx->getProcAddress(QLatin1String("glVertexAttribPointerARB"));
+ glDisableVertexAttribArray = (_glDisableVertexAttribArray) ctx->getProcAddress(QLatin1String("glDisableVertexAttribArrayARB"));
+ glEnableVertexAttribArray = (_glEnableVertexAttribArray) ctx->getProcAddress(QLatin1String("glEnableVertexAttribArrayARB"));
+ }
+
+ // Note: glShaderBinary(), glIsShader(), glIsProgram(), and
+ // glUniformMatrixNxMfv() are optional, but all other functions
+ // are required.
+
+ return glCreateShader &&
+ glShaderSource &&
+ glCompileShader &&
+ glDeleteProgram &&
+ glCreateProgram &&
+ glAttachShader &&
+ glDetachShader &&
+ glLinkProgram &&
+ glUseProgram &&
+ glDeleteProgram &&
+ glGetShaderInfoLog &&
+ glGetShaderiv &&
+ glGetShaderSource &&
+ glGetProgramiv &&
+ glGetProgramInfoLog &&
+ glGetUniformLocation &&
+ glUniform1fv &&
+ glUniform2fv &&
+ glUniform3fv &&
+ glUniform4fv &&
+ glUniform1i &&
+ glUniform1iv &&
+ glUniformMatrix2fv &&
+ glUniformMatrix3fv &&
+ glUniformMatrix4fv &&
+ glBindAttribLocation &&
+ glGetAttribLocation &&
+ glVertexAttrib1fv &&
+ glVertexAttrib2fv &&
+ glVertexAttrib3fv &&
+ glVertexAttrib4fv &&
+ glVertexAttribPointer &&
+ glDisableVertexAttribArray &&
+ glEnableVertexAttribArray;
+#endif
}
QT_END_NAMESPACE
diff --git a/src/opengl/qglextensions_p.h b/src/opengl/qglextensions_p.h
index a0517f5..f71ae9d 100644
--- a/src/opengl/qglextensions_p.h
+++ b/src/opengl/qglextensions_p.h
@@ -92,8 +92,10 @@ typedef void (APIENTRY *_glProgramLocalParameter4fvARB) (GLenum, GLuint, const G
// GLSL
typedef GLuint (APIENTRY *_glCreateShader) (GLenum);
typedef void (APIENTRY *_glShaderSource) (GLuint, GLsizei, const char **, const GLint *);
+typedef void (APIENTRY *_glShaderBinary) (GLint, const GLuint*, GLenum, const void*, GLint);
typedef void (APIENTRY *_glCompileShader) (GLuint);
typedef void (APIENTRY *_glDeleteShader) (GLuint);
+typedef GLboolean (APIENTRY *_glIsShader) (GLuint);
typedef GLuint (APIENTRY *_glCreateProgram) ();
typedef void (APIENTRY *_glAttachShader) (GLuint, GLuint);
@@ -101,17 +103,43 @@ typedef void (APIENTRY *_glDetachShader) (GLuint, GLuint);
typedef void (APIENTRY *_glLinkProgram) (GLuint);
typedef void (APIENTRY *_glUseProgram) (GLuint);
typedef void (APIENTRY *_glDeleteProgram) (GLuint);
+typedef GLboolean (APIENTRY *_glIsProgram) (GLuint);
typedef void (APIENTRY *_glGetShaderInfoLog) (GLuint, GLsizei, GLsizei *, char *);
typedef void (APIENTRY *_glGetShaderiv) (GLuint, GLenum, GLint *);
+typedef void (APIENTRY *_glGetShaderSource) (GLuint, GLsizei, GLsizei *, char *);
typedef void (APIENTRY *_glGetProgramiv) (GLuint, GLenum, GLint *);
+typedef void (APIENTRY *_glGetProgramInfoLog) (GLuint, GLsizei, GLsizei *, char *);
typedef GLuint (APIENTRY *_glGetUniformLocation) (GLuint, const char*);
-typedef void (APIENTRY *_glUniform4fv) (GLint, GLsizei, GLfloat *);
-typedef void (APIENTRY *_glUniform3fv) (GLint, GLsizei, GLfloat *);
-typedef void (APIENTRY *_glUniform2fv) (GLint, GLsizei, GLfloat *);
-typedef void (APIENTRY *_glUniform1fv) (GLint, GLsizei, GLfloat *);
+typedef void (APIENTRY *_glUniform4fv) (GLint, GLsizei, const GLfloat *);
+typedef void (APIENTRY *_glUniform3fv) (GLint, GLsizei, const GLfloat *);
+typedef void (APIENTRY *_glUniform2fv) (GLint, GLsizei, const GLfloat *);
+typedef void (APIENTRY *_glUniform1fv) (GLint, GLsizei, const GLfloat *);
typedef void (APIENTRY *_glUniform1i) (GLint, GLint);
+typedef void (APIENTRY *_glUniform1iv) (GLint, GLsizei, const GLint *);
+typedef void (APIENTRY *_glUniformMatrix2fv) (GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (APIENTRY *_glUniformMatrix3fv) (GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (APIENTRY *_glUniformMatrix4fv) (GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (APIENTRY *_glUniformMatrix2x3fv) (GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (APIENTRY *_glUniformMatrix2x4fv) (GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (APIENTRY *_glUniformMatrix3x2fv) (GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (APIENTRY *_glUniformMatrix3x4fv) (GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (APIENTRY *_glUniformMatrix4x2fv) (GLint, GLsizei, GLboolean, const GLfloat *);
+typedef void (APIENTRY *_glUniformMatrix4x3fv) (GLint, GLsizei, GLboolean, const GLfloat *);
+
+typedef void (APIENTRY *_glBindAttribLocation) (GLuint, GLuint, const char *);
+typedef GLint (APIENTRY *_glGetAttribLocation) (GLuint, const char *);
+typedef void (APIENTRY *_glVertexAttrib1fv) (GLuint, const GLfloat *);
+typedef void (APIENTRY *_glVertexAttrib2fv) (GLuint, const GLfloat *);
+typedef void (APIENTRY *_glVertexAttrib3fv) (GLuint, const GLfloat *);
+typedef void (APIENTRY *_glVertexAttrib4fv) (GLuint, const GLfloat *);
+typedef void (APIENTRY *_glVertexAttribPointer) (GLuint, GLint, GLenum, GLboolean, GLsizei, const GLvoid *);
+typedef void (APIENTRY *_glDisableVertexAttribArray) (GLuint);
+typedef void (APIENTRY *_glEnableVertexAttribArray) (GLuint);
+
+typedef void (APIENTRY *_glGetProgramBinaryOES) (GLuint, GLsizei, GLsizei *, GLenum *, void *);
+typedef void (APIENTRY *_glProgramBinaryOES) (GLuint, GLenum, const void *, GLint);
typedef void (APIENTRY *_glActiveStencilFaceEXT) (GLenum );
@@ -153,10 +181,13 @@ struct QGLExtensionFuncs
qt_glGenProgramsARB = 0;
qt_glProgramLocalParameter4fvARB = 0;
+#if !defined(QT_OPENGL_ES_2)
qt_glCreateShader = 0;
qt_glShaderSource = 0;
+ qt_glShaderBinary = 0;
qt_glCompileShader = 0;
qt_glDeleteShader = 0;
+ qt_glIsShader = 0;
qt_glCreateProgram = 0;
qt_glAttachShader = 0;
@@ -164,10 +195,13 @@ struct QGLExtensionFuncs
qt_glLinkProgram = 0;
qt_glUseProgram = 0;
qt_glDeleteProgram = 0;
+ qt_glIsProgram = 0;
qt_glGetShaderInfoLog = 0;
qt_glGetShaderiv = 0;
+ qt_glGetShaderSource = 0;
qt_glGetProgramiv = 0;
+ qt_glGetProgramInfoLog = 0;
qt_glGetUniformLocation = 0;
qt_glUniform4fv = 0;
@@ -175,6 +209,32 @@ struct QGLExtensionFuncs
qt_glUniform2fv = 0;
qt_glUniform1fv = 0;
qt_glUniform1i = 0;
+ qt_glUniform1iv = 0;
+ qt_glUniformMatrix2fv = 0;
+ qt_glUniformMatrix3fv = 0;
+ qt_glUniformMatrix4fv = 0;
+ qt_glUniformMatrix2x3fv = 0;
+ qt_glUniformMatrix2x4fv = 0;
+ qt_glUniformMatrix3x2fv = 0;
+ qt_glUniformMatrix3x4fv = 0;
+ qt_glUniformMatrix4x2fv = 0;
+ qt_glUniformMatrix4x3fv = 0;
+
+ qt_glBindAttribLocation = 0;
+ qt_glGetAttribLocation = 0;
+ qt_glVertexAttrib1fv = 0;
+ qt_glVertexAttrib2fv = 0;
+ qt_glVertexAttrib3fv = 0;
+ qt_glVertexAttrib4fv = 0;
+ qt_glVertexAttribPointer = 0;
+ qt_glDisableVertexAttribArray = 0;
+ qt_glEnableVertexAttribArray = 0;
+#else
+ qt_glslResolved = false;
+
+ qt_glGetProgramBinaryOES = 0;
+ qt_glProgramBinaryOES = 0;
+#endif
qt_glActiveStencilFaceEXT = 0;
@@ -215,11 +275,14 @@ struct QGLExtensionFuncs
_glGenProgramsARB qt_glGenProgramsARB;
_glProgramLocalParameter4fvARB qt_glProgramLocalParameter4fvARB;
+#if !defined(QT_OPENGL_ES_2)
// GLSL definitions
_glCreateShader qt_glCreateShader;
_glShaderSource qt_glShaderSource;
+ _glShaderBinary qt_glShaderBinary;
_glCompileShader qt_glCompileShader;
_glDeleteShader qt_glDeleteShader;
+ _glIsShader qt_glIsShader;
_glCreateProgram qt_glCreateProgram;
_glAttachShader qt_glAttachShader;
@@ -227,10 +290,13 @@ struct QGLExtensionFuncs
_glLinkProgram qt_glLinkProgram;
_glUseProgram qt_glUseProgram;
_glDeleteProgram qt_glDeleteProgram;
+ _glIsProgram qt_glIsProgram;
_glGetShaderInfoLog qt_glGetShaderInfoLog;
_glGetShaderiv qt_glGetShaderiv;
+ _glGetShaderSource qt_glGetShaderSource;
_glGetProgramiv qt_glGetProgramiv;
+ _glGetProgramInfoLog qt_glGetProgramInfoLog;
_glGetUniformLocation qt_glGetUniformLocation;
_glUniform4fv qt_glUniform4fv;
@@ -238,6 +304,32 @@ struct QGLExtensionFuncs
_glUniform2fv qt_glUniform2fv;
_glUniform1fv qt_glUniform1fv;
_glUniform1i qt_glUniform1i;
+ _glUniform1iv qt_glUniform1iv;
+ _glUniformMatrix2fv qt_glUniformMatrix2fv;
+ _glUniformMatrix3fv qt_glUniformMatrix3fv;
+ _glUniformMatrix4fv qt_glUniformMatrix4fv;
+ _glUniformMatrix2x3fv qt_glUniformMatrix2x3fv;
+ _glUniformMatrix2x4fv qt_glUniformMatrix2x4fv;
+ _glUniformMatrix3x2fv qt_glUniformMatrix3x2fv;
+ _glUniformMatrix3x4fv qt_glUniformMatrix3x4fv;
+ _glUniformMatrix4x2fv qt_glUniformMatrix4x2fv;
+ _glUniformMatrix4x3fv qt_glUniformMatrix4x3fv;
+
+ _glBindAttribLocation qt_glBindAttribLocation;
+ _glGetAttribLocation qt_glGetAttribLocation;
+ _glVertexAttrib1fv qt_glVertexAttrib1fv;
+ _glVertexAttrib2fv qt_glVertexAttrib2fv;
+ _glVertexAttrib3fv qt_glVertexAttrib3fv;
+ _glVertexAttrib4fv qt_glVertexAttrib4fv;
+ _glVertexAttribPointer qt_glVertexAttribPointer;
+ _glDisableVertexAttribArray qt_glDisableVertexAttribArray;
+ _glEnableVertexAttribArray qt_glEnableVertexAttribArray;
+#else
+ bool qt_glslResolved;
+
+ _glGetProgramBinaryOES qt_glGetProgramBinaryOES;
+ _glProgramBinaryOES qt_glProgramBinaryOES;
+#endif
_glActiveStencilFaceEXT qt_glActiveStencilFaceEXT;
@@ -479,10 +571,14 @@ struct QGLExtensionFuncs
#define glMapBufferARB QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glMapBufferARB
#define glUnmapBufferARB QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUnmapBufferARB
+#if !defined(QT_OPENGL_ES_2)
+
#define glCreateShader QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glCreateShader
#define glShaderSource QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glShaderSource
+#define glShaderBinary QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glShaderBinary
#define glCompileShader QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glCompileShader
#define glDeleteShader QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glDeleteShader
+#define glIsShader QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glIsShader
#define glCreateProgram QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glCreateProgram
#define glAttachShader QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glAttachShader
@@ -490,10 +586,13 @@ struct QGLExtensionFuncs
#define glLinkProgram QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glLinkProgram
#define glUseProgram QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUseProgram
#define glDeleteProgram QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glDeleteProgram
+#define glIsProgram QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glIsProgram
#define glGetShaderInfoLog QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetShaderInfoLog
#define glGetShaderiv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetShaderiv
+#define glGetShaderSource QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetShaderSource
#define glGetProgramiv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetProgramiv
+#define glGetProgramInfoLog QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetProgramInfoLog
#define glGetUniformLocation QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetUniformLocation
#define glUniform4fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniform4fv
@@ -501,6 +600,33 @@ struct QGLExtensionFuncs
#define glUniform2fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniform2fv
#define glUniform1fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniform1fv
#define glUniform1i QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniform1i
+#define glUniform1iv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniform1iv
+#define glUniformMatrix2fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniformMatrix2fv
+#define glUniformMatrix3fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniformMatrix3fv
+#define glUniformMatrix4fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniformMatrix4fv
+#define glUniformMatrix2x3fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniformMatrix2x3fv
+#define glUniformMatrix2x4fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniformMatrix2x4fv
+#define glUniformMatrix3x2fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniformMatrix3x2fv
+#define glUniformMatrix3x4fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniformMatrix3x4fv
+#define glUniformMatrix4x2fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniformMatrix4x2fv
+#define glUniformMatrix4x3fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glUniformMatrix4x3fv
+
+#define glBindAttribLocation QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glBindAttribLocation
+#define glGetAttribLocation QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetAttribLocation
+#define glVertexAttrib1fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glVertexAttrib1fv
+#define glVertexAttrib2fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glVertexAttrib2fv
+#define glVertexAttrib3fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glVertexAttrib3fv
+#define glVertexAttrib4fv QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glVertexAttrib4fv
+#define glVertexAttribPointer QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glVertexAttribPointer
+#define glDisableVertexAttribArray QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glDisableVertexAttribArray
+#define glEnableVertexAttribArray QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glEnableVertexAttribArray
+
+#else // QT_OPENGL_ES_2
+
+#define glGetProgramBinaryOES QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glGetProgramBinaryOES
+#define glProgramBinaryOES QGLContextPrivate::qt_get_extension_funcs(ctx).qt_glProgramBinaryOES
+
+#endif // QT_OPENGL_ES_2
extern bool qt_resolve_framebufferobject_extensions(QGLContext *ctx);
bool qt_resolve_buffer_extensions(QGLContext *ctx);
diff --git a/src/opengl/qglpixmapfilter.cpp b/src/opengl/qglpixmapfilter.cpp
index ff23948..4b811e5 100644
--- a/src/opengl/qglpixmapfilter.cpp
+++ b/src/opengl/qglpixmapfilter.cpp
@@ -45,27 +45,12 @@
#include "qpaintengine_opengl_p.h"
#include "qglpixelbuffer.h"
-#include "qglextensions_p.h"
+#include "qglshaderprogram.h"
#include "qgl_p.h"
#include "private/qapplication_p.h"
-#ifndef GL_FRAGMENT_SHADER
-#define GL_FRAGMENT_SHADER 0x8B30
-#endif
-
-#ifndef GL_COMPILE_STATUS
-#define GL_COMPILE_STATUS 0x8B81
-#endif
-
-#ifndef GL_LINK_STATUS
-#define GL_LINK_STATUS 0x8B82
-#endif
-
-
-
-
QT_BEGIN_NAMESPACE
@@ -79,117 +64,6 @@ void QGLPixmapFilterBase::drawImpl(QPainter *painter, const QPointF &pos, const
processGL(painter, pos, src, source);
}
-QGLSLProgram::QGLSLProgram(const QString &src)
- : ctx(QGLContext::currentContext())
-{
- if (!qt_resolve_glsl_extensions(const_cast<QGLContext *>(ctx))) {
- qWarning("Failed to resolve GLSL functions");
- m_valid = false;
- return;
- }
-
- m_shader = glCreateShader(GL_FRAGMENT_SHADER);
-
- const QByteArray src_ba = src.toAscii();
- const char *src_cstr = src_ba.constData();
-
- glShaderSource(m_shader, 1, &src_cstr, 0);
- glCompileShader(m_shader);
- glGetShaderiv(m_shader, GL_COMPILE_STATUS, &m_valid);
- if (!m_valid) {
- char data[4096];
- GLsizei len;
- glGetShaderInfoLog(m_shader, 4096, &len, data);
- qWarning("Failed to compile GLSL shader:\n%s\nCODE:\n%s\n", data, src_cstr);
- return;
- }
-
- m_program = glCreateProgram();
- glAttachShader(m_program, m_shader);
- glLinkProgram(m_program);
- glGetProgramiv(m_program, GL_LINK_STATUS, &m_valid);
- if (!m_valid) {
- char data[4096];
- GLsizei len;
- glGetShaderInfoLog(m_shader, 4096, &len, data);
- qWarning("Failed to link GLSL program:\n%s\nCODE:\n%s\n", data, src_cstr);
- return;
- }
-}
-
-QGLSLProgram::~QGLSLProgram()
-{
- glDeleteProgram(m_program);
- glDeleteShader(m_shader);
-}
-
-bool QGLSLProgram::success() const
-{
- return m_valid;
-}
-
-void QGLSLProgram::enable()
-{
- glUseProgram(m_program);
-}
-
-void QGLSLProgram::disable()
-{
- glUseProgram(0);
-}
-
-typedef GLuint (APIENTRY *_glGetUniformLocation) (GLuint, const char*);
-typedef void (APIENTRY *_glUniform4fv) (GLint, GLsizei, GLfloat *);
-typedef void (APIENTRY *_glUniform3fv) (GLint, GLsizei, GLfloat *);
-typedef void (APIENTRY *_glUniform2fv) (GLint, GLsizei, GLfloat *);
-typedef void (APIENTRY *_glUniform1fv) (GLint, GLsizei, GLfloat *);
-typedef void (APIENTRY *_glUniform1i) (GLint, GLint);
-
-int QGLSLProgram::getUniformLocation(const QString &name)
-{
- return glGetUniformLocation(m_program, name.toAscii().constData());
-}
-
-void QGLSLProgram::setUniform(int uniform, int value)
-{
- enable();
- glUniform1i(uniform, value);
-}
-
-void QGLSLProgram::setUniform(int uniform, qreal value)
-{
- enable();
- GLfloat v[] = { value };
- glUniform1fv(uniform, 1, v);
-}
-
-void QGLSLProgram::setUniform(int uniform, qreal v1, qreal v2)
-{
- enable();
- GLfloat v[] = { v1, v2 };
- glUniform2fv(uniform, 1, v);
-}
-
-void QGLSLProgram::setUniform(int uniform, qreal v1, qreal v2, qreal v3)
-{
- enable();
- GLfloat v[] = { v1, v2, v3 };
- glUniform3fv(uniform, 1, v);
-}
-
-void QGLSLProgram::setUniform(int uniform, qreal v1, qreal v2, qreal v3, qreal v4)
-{
- enable();
- GLfloat v[] = { v1, v2, v3, v4 };
- glUniform4fv(uniform, 1, v);
-}
-
-void QGLSLProgram::setUniform(int uniform, int count, float *v)
-{
- enable();
- glUniform1fv(uniform, count, v);
-}
-
class QGLPixmapColorizeFilter: public QGLPixmapFilter<QPixmapColorizeFilter>
{
public:
@@ -199,8 +73,8 @@ protected:
bool processGL(QPainter *painter, const QPointF &pos, const QPixmap &pixmap, const QRectF &srcRect) const;
private:
- mutable QGLSLProgram m_program;
- uint m_colorUniform;
+ mutable QGLShaderProgram m_program;
+ int m_colorUniform;
};
class QGLPixmapConvolutionFilter: public QGLPixmapFilter<QPixmapConvolutionFilter>
@@ -213,11 +87,11 @@ protected:
bool processGL(QPainter *painter, const QPointF &pos, const QPixmap &src, const QRectF &srcRect) const;
private:
- QString generateConvolutionShader() const;
+ QByteArray generateConvolutionShader() const;
- mutable QGLSLProgram *m_program;
- mutable uint m_scaleUniform;
- mutable uint m_matrixUniform;
+ mutable QGLShaderProgram *m_program;
+ mutable int m_scaleUniform;
+ mutable int m_matrixUniform;
mutable int m_kernelWidth;
mutable int m_kernelHeight;
@@ -294,10 +168,12 @@ static const char *qt_gl_colorize_filter =
"}";
QGLPixmapColorizeFilter::QGLPixmapColorizeFilter()
- : m_program(QLatin1String(qt_gl_colorize_filter))
{
- m_program.setUniform(m_program.getUniformLocation(QLatin1String("texture")), 0); // GL_TEXTURE_0
- m_colorUniform = m_program.getUniformLocation(QLatin1String("color"));
+ m_program.addShader(QGLShader::FragmentShader, qt_gl_colorize_filter);
+ m_program.link();
+ m_program.enable();
+ m_program.setUniformValue(m_program.uniformLocation("texture"), 0); // GL_TEXTURE_0
+ m_colorUniform = m_program.uniformLocation("color");
}
bool QGLPixmapColorizeFilter::processGL(QPainter *, const QPointF &pos, const QPixmap &src, const QRectF &srcRect) const
@@ -305,10 +181,10 @@ bool QGLPixmapColorizeFilter::processGL(QPainter *, const QPointF &pos, const QP
bindTexture(src);
QColor col = color();
- m_program.setUniform(m_colorUniform, col.redF(), col.greenF(), col.blueF());
+ m_program.enable();
+ m_program.setUniformValue(m_colorUniform, col.redF(), col.greenF(), col.blueF());
QRectF target = (srcRect.isNull() ? QRectF(src.rect()) : srcRect).translated(pos);
- m_program.enable();
qgl_drawTexture(target, src.width(), src.height(), srcRect);
m_program.disable();
@@ -316,7 +192,7 @@ bool QGLPixmapColorizeFilter::processGL(QPainter *, const QPointF &pos, const QP
}
// generates convolution filter code for arbitrary sized kernel
-QString QGLPixmapConvolutionFilter::generateConvolutionShader() const {
+QByteArray QGLPixmapConvolutionFilter::generateConvolutionShader() const {
QByteArray code;
code.append("uniform sampler2D texture;\n");
code.append("uniform vec2 inv_texture_size;\n");
@@ -352,7 +228,7 @@ QString QGLPixmapConvolutionFilter::generateConvolutionShader() const {
code.append(" }\n");
code.append(" gl_FragColor = sum;\n");
code.append("}");
- return QLatin1String(code);
+ return code;
}
QGLPixmapConvolutionFilter::QGLPixmapConvolutionFilter()
@@ -384,10 +260,12 @@ bool QGLPixmapConvolutionFilter::processGL(QPainter *, const QPointF &pos, const
m_kernelWidth = columns();
m_kernelHeight = rows();
- QString code = generateConvolutionShader();
- m_program = new QGLSLProgram(code);
- m_scaleUniform = m_program->getUniformLocation(QLatin1String("inv_texture_size"));
- m_matrixUniform = m_program->getUniformLocation(QLatin1String("matrix"));
+ QByteArray code = generateConvolutionShader();
+ m_program = new QGLShaderProgram();
+ m_program->addShader(QGLShader::FragmentShader, code);
+ m_program->link();
+ m_scaleUniform = m_program->uniformLocation("inv_texture_size");
+ m_matrixUniform = m_program->uniformLocation("matrix");
}
const qreal *kernel = convolutionKernel();
@@ -397,10 +275,10 @@ bool QGLPixmapConvolutionFilter::processGL(QPainter *, const QPointF &pos, const
const qreal iw = 1.0 / src.width();
const qreal ih = 1.0 / src.height();
- m_program->setUniform(m_scaleUniform, iw, ih);
- m_program->setUniform(m_matrixUniform, m_kernelWidth * m_kernelHeight, conv);
-
m_program->enable();
+ m_program->setUniformValue(m_scaleUniform, iw, ih);
+ m_program->setUniformValueArray(m_matrixUniform, conv, m_kernelWidth * m_kernelHeight, 1);
+
qgl_drawTexture(target, src.width(), src.height(), boundingRectFor(srcRect));
m_program->disable();
return true;
diff --git a/src/opengl/qglpixmapfilter_p.h b/src/opengl/qglpixmapfilter_p.h
index dc2eea6..d6742fc 100644
--- a/src/opengl/qglpixmapfilter_p.h
+++ b/src/opengl/qglpixmapfilter_p.h
@@ -87,35 +87,6 @@ public:
}
};
-class Q_OPENGL_EXPORT QGLSLProgram
-{
-public:
- QGLSLProgram(const QString &src);
- ~QGLSLProgram();
-
- bool success() const;
-
- void enable();
- void disable();
-
- int getUniformLocation(const QString &name);
-
- void setUniform(int uniform, int value);
- void setUniform(int uniform, qreal value);
- void setUniform(int uniform, qreal v1, qreal v2);
- void setUniform(int uniform, qreal v1, qreal v2, qreal v3);
- void setUniform(int uniform, qreal v1, qreal v2, qreal v3, qreal v4);
- void setUniform(int uniform, int count, float *v);
-
-private:
- GLuint m_shader;
- GLuint m_program;
-
- GLint m_valid;
-
- const QGLContext *ctx;
-};
-
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/opengl/qglshaderprogram.cpp b/src/opengl/qglshaderprogram.cpp
new file mode 100644
index 0000000..934b5a5
--- /dev/null
+++ b/src/opengl/qglshaderprogram.cpp
@@ -0,0 +1,2828 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtOpenGL 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 "qglshaderprogram.h"
+#include "qglextensions_p.h"
+#include "qgl_p.h"
+#include <QtCore/qdebug.h>
+#include <QtCore/qfile.h>
+#include <QtCore/qvarlengtharray.h>
+#include <QtCore/qvector.h>
+
+QT_BEGIN_NAMESPACE
+
+#if !defined(QT_OPENGL_ES_1_CL)
+
+/*!
+ \class QGLShaderProgram
+ \brief The QGLShaderProgram class allows OpenGL shader programs to be linked and used.
+ \since 4.6
+
+ \section1 Introduction
+
+ This class supports shader programs written in the OpenGL Shading
+ Language (GLSL) and in the OpenGL/ES Shading Language (GLSL/ES).
+
+ QGLShader and QGLShaderProgram shelter the programmer from the details of
+ compiling and linking vertex and fragment shaders.
+
+ The following example creates a vertex shader program using the
+ supplied source \c{code}. Once compiled and linked, the shader
+ program is activated in the current QGLContext by calling
+ QGLShaderProgram::enable():
+
+ \code
+ QGLShader shader(QGLShader::VertexShader);
+ shader.setSourceCode(code);
+
+ QGLShaderProgram program(context);
+ program.addShader(shader);
+ program.link();
+
+ program.enable();
+ \endcode
+
+ \section1 Writing portable shaders
+
+ Shader programs can be difficult to reuse across OpenGL implementations
+ because of varying levels of support for standard vertex attributes and
+ uniform variables. In particular, GLSL/ES lacks all of the
+ standard variables that are present on desktop OpenGL systems:
+ \c{gl_Vertex}, \c{gl_Normal}, \c{gl_Color}, and so on. Desktop OpenGL
+ lacks the variable qualifiers \c{highp}, \c{mediump}, and \c{lowp}.
+
+ The QGLShaderProgram class makes the process of writing portable shaders
+ easier by prefixing all shader programs with the following lines on
+ desktop OpenGL:
+
+ \code
+ #define highp
+ #define mediump
+ #define lowp
+ \endcode
+
+ This makes it possible to run most GLSL/ES shader programs
+ on desktop systems. The programmer should restrict themselves
+ to just features that are present in GLSL/ES, and avoid
+ standard variable names that only work on the desktop.
+
+ \section1 Simple shader example
+
+ \code
+ program.addShader(QGLShader::VertexShader,
+ "attribute highp vec4 vertex;\n"
+ "attribute mediump mat4 matrix;\n"
+ "void main(void)\n"
+ "{\n"
+ " gl_Position = matrix * vertex;\n"
+ "}");
+ program.addShader(QGLShader::FragmentShader,
+ "uniform mediump vec4 color;\n"
+ "void main(void)\n"
+ "{\n"
+ " gl_FragColor = color;\n"
+ "}");
+ program.link();
+ program.enable();
+
+ int vertexLocation = program.attributeLocation("vertex");
+ int matrixLocation = program.attributeLocation("matrix");
+ int colorLocation = program.uniformLocation("color");
+ \endcode
+
+ With the above shader program active, we can draw a green triangle
+ as follows:
+
+ \code
+ static GLfloat const triangleVertices[] = {
+ 60.0f, 10.0f, 0.0f,
+ 110.0f, 110.0f, 0.0f,
+ 10.0f, 110.0f, 0.0f
+ };
+
+ QColor color(0, 255, 0, 255);
+
+ QMatrix4x4 pmvMatrix;
+ pmvMatrix.ortho(rect());
+
+ program.setAttributeArray(vertexLocation, triangleVertices, 3);
+ program.setUniformValue(matrixLocation, pmvMatrix);
+ program.setUniformValue(colorLocation, color);
+
+ glDrawArrays(GL_TRIANGLES, 0, 3);
+ \endcode
+
+ \section1 Partial shaders
+
+ Desktop GLSL can attach an arbitrary number of vertex and fragment
+ shaders to a shader program. Embedded GLSL/ES on the other hand
+ supports only a single shader of each type on a shader program.
+
+ Multiple shaders of the same type can be useful when large libraries
+ of shaders are needed. Common functions can be factored out into
+ library shaders that can be reused in multiple shader programs.
+
+ To support this use of shaders, the application programmer can
+ create shaders with the QGLShader::PartialVertexShader and
+ QGLShader::PartialFragmentShader types. These types direct
+ QGLShader and QGLShaderProgram to delay shader compilation until
+ link time.
+
+ When link() is called, the sources for the partial shaders are
+ concatenated, and a single vertex or fragment shader is compiled
+ and linked into the shader program.
+
+ It is more efficient to use the QGLShader::VertexShader and
+ QGLShader::FragmentShader when there is only one shader of that
+ type in the program.
+
+ \sa QGLShader
+*/
+
+/*!
+ \class QGLShader
+ \brief The QGLShader class allows OpenGL shaders to be compiled.
+ \since 4.6
+
+ This class supports shaders written in the OpenGL Shading Language (GLSL)
+ and in the OpenGL/ES Shading Language (GLSL/ES).
+
+ QGLShader and QGLShaderProgram shelter the programmer from the details of
+ compiling and linking vertex and fragment shaders.
+
+ \sa QGLShaderProgram
+*/
+
+/*!
+ \enum QGLShader::ShaderType
+ This enum specifies the type of QGLShader that is being created.
+
+ \value VertexShader Vertex shader written in the OpenGL Shading Language (GLSL).
+ \value FragmentShader Fragment shader written in the OpenGL Shading Language (GLSL).
+ \value PartialVertexShader Partial vertex shader that will be concatenated with all other partial vertex shaders at link time.
+ \value PartialFragmentShader Partial fragment shader that will be concatenated with all other partial fragment shaders at link time.
+*/
+
+#ifndef GL_FRAGMENT_SHADER
+#define GL_FRAGMENT_SHADER 0x8B30
+#endif
+#ifndef GL_VERTEX_SHADER
+#define GL_VERTEX_SHADER 0x8B31
+#endif
+#ifndef GL_COMPILE_STATUS
+#define GL_COMPILE_STATUS 0x8B81
+#endif
+#ifndef GL_LINK_STATUS
+#define GL_LINK_STATUS 0x8B82
+#endif
+#ifndef GL_INFO_LOG_LENGTH
+#define GL_INFO_LOG_LENGTH 0x8B84
+#endif
+#ifndef GL_ACTIVE_UNIFORMS
+#define GL_ACTIVE_UNIFORMS 0x8B86
+#endif
+#ifndef GL_ACTIVE_UNIFORM_MAX_LENGTH
+#define GL_ACTIVE_UNIFORM_MAX_LENGTH 0x8B87
+#endif
+#ifndef GL_ACTIVE_ATTRIBUTES
+#define GL_ACTIVE_ATTRIBUTES 0x8B89
+#endif
+#ifndef GL_ACTIVE_ATTRIBUTE_MAX_LENGTH
+#define GL_ACTIVE_ATTRIBUTE_MAX_LENGTH 0x8B8A
+#endif
+#ifndef GL_CURRENT_VERTEX_ATTRIB
+#define GL_CURRENT_VERTEX_ATTRIB 0x8626
+#endif
+#ifndef GL_SHADER_SOURCE_LENGTH
+#define GL_SHADER_SOURCE_LENGTH 0x8B88
+#endif
+#ifndef GL_SHADER_BINARY_FORMATS
+#define GL_SHADER_BINARY_FORMATS 0x8DF8
+#endif
+#ifndef GL_NUM_SHADER_BINARY_FORMATS
+#define GL_NUM_SHADER_BINARY_FORMATS 0x8DF9
+#endif
+
+class QGLShaderPrivate
+{
+public:
+ QGLShaderPrivate(QGLShader::ShaderType type, const QGLContext *ctx)
+ {
+ context = ctx;
+ shader = 0;
+ shaderType = type;
+ compiled = false;
+ isPartial = (type == QGLShader::PartialVertexShader ||
+ type == QGLShader::PartialFragmentShader);
+ hasPartialSource = false;
+ }
+
+ const QGLContext *context;
+ GLuint shader;
+ QGLShader::ShaderType shaderType;
+ bool compiled;
+ bool isPartial;
+ bool hasPartialSource;
+ QString errors;
+ QByteArray partialSource;
+
+ bool create();
+ bool compile();
+};
+
+#define ctx context
+
+bool QGLShaderPrivate::create()
+{
+ if (isPartial)
+ return true;
+ if (!context)
+ context = QGLContext::currentContext();
+ if (!context)
+ return false;
+ if (qt_resolve_glsl_extensions(const_cast<QGLContext *>(context))) {
+ if (shaderType == QGLShader::VertexShader)
+ shader = glCreateShader(GL_VERTEX_SHADER);
+ else
+ shader = glCreateShader(GL_FRAGMENT_SHADER);
+ if (!shader) {
+ qWarning() << "QGLShader: could not create shader";
+ return false;
+ }
+ return true;
+ } else {
+ return false;
+ }
+}
+
+bool QGLShaderPrivate::compile()
+{
+ // Partial shaders are compiled during QGLShaderProgram::link().
+ if (isPartial && hasPartialSource) {
+ compiled = true;
+ return true;
+ }
+ if (!shader)
+ return false;
+ glCompileShader(shader);
+ GLint value = 0;
+ glGetShaderiv(shader, GL_COMPILE_STATUS, &value);
+ compiled = (value != 0);
+ value = 0;
+ glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &value);
+ if (!compiled && value > 1) {
+ char *log = new char [value];
+ GLint len;
+ glGetShaderInfoLog(shader, value, &len, log);
+ errors = QString::fromLatin1(log);
+ qWarning() << "QGLShader::compile:" << errors;
+ delete [] log;
+ }
+ return compiled;
+}
+
+#undef ctx
+#define ctx d->context
+
+/*!
+ Constructs a new QGLShader object of the specified \a type
+ and attaches it to \a parent. If shader programs are not supported,
+ then isValid() will return false.
+
+ This constructor is normally followed by a call to setSourceCode()
+ or setSourceCodeFile().
+
+ The shader will be associated with the current QGLContext.
+
+ \sa setSourceCode(), setSourceCodeFile(), isValid()
+*/
+QGLShader::QGLShader(QGLShader::ShaderType type, QObject *parent)
+ : QObject(parent)
+{
+ d = new QGLShaderPrivate(type, QGLContext::currentContext());
+ d->create();
+}
+
+/*!
+ Constructs a new QGLShader object from the source code in \a fileName
+ and attaches it to \a parent. If the filename ends in \c{.fsh},
+ it is assumed to be a fragment shader, otherwise it is assumed to
+ be a vertex shader (normally the extension is \c{.vsh} for vertex shaders).
+ If the shader could not be loaded, then isValid() will return false.
+
+ The shader will be associated with the current QGLContext.
+
+ \sa isValid()
+*/
+QGLShader::QGLShader(const QString& fileName, QObject *parent)
+ : QObject(parent)
+{
+ if (fileName.endsWith(QLatin1String(".fsh"), Qt::CaseInsensitive))
+ d = new QGLShaderPrivate(QGLShader::FragmentShader, QGLContext::currentContext());
+ else
+ d = new QGLShaderPrivate(QGLShader::VertexShader, QGLContext::currentContext());
+ if (d->create() && !setSourceCodeFile(fileName)) {
+ if (d->shader)
+ glDeleteShader(d->shader);
+ d->shader = 0;
+ }
+}
+
+/*!
+ Constructs a new QGLShader object of the specified \a type from the
+ source code in \a fileName and attaches it to \a parent.
+ If the shader could not be loaded, then isValid() will return false.
+
+ The shader will be associated with the current QGLContext.
+
+ \sa isValid()
+*/
+QGLShader::QGLShader
+ (const QString& fileName, QGLShader::ShaderType type, QObject *parent)
+ : QObject(parent)
+{
+ d = new QGLShaderPrivate(type, QGLContext::currentContext());
+ if (d->create() && !setSourceCodeFile(fileName)) {
+ if (d->shader)
+ glDeleteShader(d->shader);
+ d->shader = 0;
+ }
+}
+
+/*!
+ Constructs a new QGLShader object of the specified \a type
+ and attaches it to \a parent. If shader programs are not supported,
+ then isValid() will return false.
+
+ This constructor is normally followed by a call to setSourceCode()
+ or setSourceCodeFile().
+
+ The shader will be associated with \a context.
+
+ \sa setSourceCode(), setSourceCodeFile(), isValid()
+*/
+QGLShader::QGLShader(QGLShader::ShaderType type, const QGLContext *context, QObject *parent)
+ : QObject(parent)
+{
+ d = new QGLShaderPrivate(type, context);
+ d->create();
+}
+
+/*!
+ Constructs a new QGLShader object from the source code in \a fileName
+ and attaches it to \a parent. If the filename ends in \c{.fsh},
+ it is assumed to be a fragment shader, otherwise it is assumed to
+ be a vertex shader (normally the extension is \c{.vsh} for vertex shaders).
+ If the shader could not be loaded, then isValid() will return false.
+
+ The shader will be associated with \a context.
+
+ \sa isValid()
+*/
+QGLShader::QGLShader(const QString& fileName, const QGLContext *context, QObject *parent)
+ : QObject(parent)
+{
+ if (fileName.endsWith(QLatin1String(".fsh"), Qt::CaseInsensitive))
+ d = new QGLShaderPrivate(QGLShader::FragmentShader, context);
+ else
+ d = new QGLShaderPrivate(QGLShader::VertexShader, context);
+ if (d->create() && !setSourceCodeFile(fileName)) {
+ if (d->shader)
+ glDeleteShader(d->shader);
+ d->shader = 0;
+ }
+}
+
+/*!
+ Constructs a new QGLShader object of the specified \a type from the
+ source code in \a fileName and attaches it to \a parent.
+ If the shader could not be loaded, then isValid() will return false.
+
+ The shader will be associated with \a context.
+
+ \sa isValid()
+*/
+QGLShader::QGLShader
+ (const QString& fileName, QGLShader::ShaderType type, const QGLContext *context, QObject *parent)
+ : QObject(parent)
+{
+ d = new QGLShaderPrivate(type, context);
+ if (d->create() && !setSourceCodeFile(fileName)) {
+ if (d->shader)
+ glDeleteShader(d->shader);
+ d->shader = 0;
+ }
+}
+
+/*!
+ Deletes this shader. If the shader has been attached to a
+ QGLShaderProgram object, then the actual shader will stay around
+ until the QGLShaderProgram is destroyed.
+*/
+QGLShader::~QGLShader()
+{
+ if (d->shader)
+ glDeleteShader(d->shader);
+ delete d;
+}
+
+/*!
+ Returns true if this shader is valid. Shaders become invalid
+ when they are destroyed and no longer attached to a QGLShaderProgram.
+*/
+bool QGLShader::isValid() const
+{
+ if (d->isPartial && d->hasPartialSource)
+ return true;
+ if (!d->shader)
+ return false;
+#if defined(QT_OPENGL_ES_2)
+ return glIsShader(d->shader);
+#else
+ // glIsShader() may not exist on some systems.
+ return (!glIsShader || glIsShader(d->shader));
+#endif
+}
+
+/*!
+ Returns the type of this shader.
+*/
+QGLShader::ShaderType QGLShader::shaderType() const
+{
+ return d->shaderType;
+}
+
+// The precision qualifiers are useful on OpenGL/ES systems,
+// but usually not present on desktop systems. Define the
+// keywords to empty strings on desktop systems.
+#ifndef QT_OPENGL_ES
+#define QGL_DEFINE_QUALIFIERS 1
+static const char qualifierDefines[] =
+ "#define lowp\n"
+ "#define mediump\n"
+ "#define highp\n";
+#endif
+
+/*!
+ Sets the \a source code for this shader and compiles it.
+ Returns true if the source was successfully compiled, false otherwise.
+
+ If shaderType() is PartialVertexShader or PartialFragmentShader,
+ then this function will always return true, even if the source code
+ is invalid. Partial shaders are compiled when QGLShaderProgram::link()
+ is called.
+*/
+bool QGLShader::setSourceCode(const char *source)
+{
+ if (d->isPartial) {
+ d->partialSource = QByteArray(source);
+ d->hasPartialSource = true;
+ return d->compile();
+ } else if (d->shader) {
+ QVarLengthArray<const char *> src;
+#ifdef QGL_DEFINE_QUALIFIERS
+ src.append(qualifierDefines);
+#endif
+ src.append(source);
+ glShaderSource(d->shader, src.size(), src.data(), 0);
+ return d->compile();
+ } else {
+ return false;
+ }
+}
+
+/*!
+ \overload
+
+ Sets the \a source code for this shader and compiles it.
+ Returns true if the source was successfully compiled, false otherwise.
+
+ If shaderType() is PartialVertexShader or PartialFragmentShader,
+ then this function will always return true, even if the source code
+ is invalid. Partial shaders are compiled when QGLShaderProgram::link()
+ is called.
+*/
+bool QGLShader::setSourceCode(const QByteArray& source)
+{
+ return setSourceCode(source.constData());
+}
+
+/*!
+ \overload
+
+ Sets the \a source code for this shader and compiles it.
+ Returns true if the source was successfully compiled, false otherwise.
+
+ If shaderType() is PartialVertexShader or PartialFragmentShader,
+ then this function will always return true, even if the source code
+ is invalid. Partial shaders are compiled when QGLShaderProgram::link()
+ is called.
+*/
+bool QGLShader::setSourceCode(const QString& source)
+{
+ return setSourceCode(source.toLatin1().constData());
+}
+
+/*!
+ Sets the source code for this shader to the contents of \a fileName
+ and compiles it. Returns true if the file could be opened and the
+ source compiled, false otherwise.
+
+ If shaderType() is PartialVertexShader or PartialFragmentShader,
+ then this function will always return true, even if the source code
+ is invalid. Partial shaders are compiled when QGLShaderProgram::link()
+ is called.
+*/
+bool QGLShader::setSourceCodeFile(const QString& fileName)
+{
+ if (!d->shader)
+ return false;
+
+ QFile file(fileName);
+ if (!file.open(QFile::ReadOnly)) {
+ qWarning() << "QGLShader: Unable to open file" << fileName;
+ return false;
+ }
+
+ QByteArray contents = file.readAll();
+ return setSourceCode(contents.constData());
+}
+
+/*!
+ Sets the binary code for this shader to the \a length bytes from
+ the array \a binary. The \a format specifies how the binary data
+ should be interpreted by the OpenGL engine. Returns true if the
+ binary was set on the shader; false otherwise.
+
+ This function cannot be used with PartialVertexShader or
+ PartialFragmentShader.
+
+ \sa shaderBinaryFormats()
+*/
+bool QGLShader::setBinaryCode(GLenum format, const void *binary, int length)
+{
+#if !defined(QT_OPENGL_ES_2)
+ if (!glShaderBinary)
+ return false;
+#endif
+ if (d->isPartial || !d->shader)
+ return false;
+ glGetError(); // Clear error state.
+ glShaderBinary(1, &(d->shader), format, binary, length);
+ return (glGetError() == GL_NO_ERROR);
+}
+
+/*!
+ Sets the binary code for this shader to the \a length bytes from
+ the array \a binary. The \a format specifies how the binary data
+ should be interpreted by the OpenGL engine. Returns true if the
+ binary was set on the shader; false otherwise.
+
+ The \a otherShader will also have binary code set on it. This is
+ for the case where \a binary contains both vertex and fragment
+ shader code.
+
+ This function cannot be used with PartialVertexShader or
+ PartialFragmentShader.
+
+ \sa shaderBinaryFormats()
+*/
+bool QGLShader::setBinaryCode
+ (QGLShader& otherShader, GLenum format, const void *binary, int length)
+{
+#if !defined(QT_OPENGL_ES_2)
+ if (!glShaderBinary)
+ return false;
+#endif
+ if (d->isPartial || !d->shader)
+ return false;
+ if (otherShader.d->isPartial || !otherShader.d->shader)
+ return false;
+ glGetError(); // Clear error state.
+ GLuint shaders[2];
+ shaders[0] = d->shader;
+ shaders[1] = otherShader.d->shader;
+ glShaderBinary(2, shaders, format, binary, length);
+ return (glGetError() == GL_NO_ERROR);
+}
+
+/*!
+ Returns a list of all binary formats that are supported by
+ setBinaryCode() on this system.
+
+ \sa setBinaryCode()
+*/
+QList<GLenum> QGLShader::shaderBinaryFormats()
+{
+ GLint num;
+ QList<GLenum> list;
+ glGetError(); // Clear error state.
+ glGetIntegerv(GL_NUM_SHADER_BINARY_FORMATS, &num);
+ if (glGetError() != GL_NO_ERROR || num <= 0)
+ return list;
+ QVarLengthArray<GLint> formats(num);
+ glGetIntegerv(GL_SHADER_BINARY_FORMATS, formats.data());
+ for (GLint i = 0; i < num; ++i)
+ list += (GLenum)(formats[i]);
+ return list;
+}
+
+/*!
+ Returns the source code for this shader.
+
+ \sa setSourceCode()
+*/
+QByteArray QGLShader::sourceCode() const
+{
+ if (d->isPartial)
+ return d->partialSource;
+ if (!d->shader)
+ return QByteArray();
+ GLint size = 0;
+ glGetShaderiv(d->shader, GL_SHADER_SOURCE_LENGTH, &size);
+ if (size <= 0)
+ return QByteArray();
+ GLint len = 0;
+ char *source = new char [size];
+ glGetShaderSource(d->shader, size, &len, source);
+ QByteArray src(source);
+ delete [] source;
+ return src;
+}
+
+/*!
+ Returns true if this shader has been compiled; false otherwise.
+
+ \sa setSourceCode()
+*/
+bool QGLShader::isCompiled() const
+{
+ return d->compiled;
+}
+
+/*!
+ Returns the errors that occurred during the last compile.
+
+ \sa setSourceCode()
+*/
+QString QGLShader::errors() const
+{
+ return d->errors;
+}
+
+/*!
+ Returns the OpenGL identifier associated with this shader.
+
+ If shaderType() is PartialVertexShader or PartialFragmentShader,
+ this function will always return zero. Partial shaders are
+ created and compiled when QGLShaderProgram::link() is called.
+
+ \sa QGLShaderProgram::programId()
+*/
+GLuint QGLShader::shaderId() const
+{
+ return d->shader;
+}
+
+#undef ctx
+#define ctx context
+
+class QGLShaderProgramPrivate
+{
+public:
+ QGLShaderProgramPrivate(const QGLContext *ctx)
+ {
+ context = ctx;
+ program = 0;
+ linked = false;
+ inited = false;
+ hasPartialShaders = false;
+ vertexShader = 0;
+ fragmentShader = 0;
+ }
+ ~QGLShaderProgramPrivate()
+ {
+ if (program)
+ glDeleteProgram(program);
+ }
+
+ const QGLContext *context;
+ GLuint program;
+ bool linked;
+ bool inited;
+ bool hasPartialShaders;
+ QString errors;
+ QList<QGLShader *> shaders;
+ QList<QGLShader *> anonShaders;
+ QGLShader *vertexShader;
+ QGLShader *fragmentShader;
+};
+
+#undef ctx
+#define ctx d->context
+
+/*!
+ Constructs a new shader program and attaches it to \a parent.
+ The program will be invalid until addShader() is called.
+
+ The shader program will be associated with the current QGLContext.
+
+ \sa isValid(), addShader()
+*/
+QGLShaderProgram::QGLShaderProgram(QObject *parent)
+ : QObject(parent)
+{
+ d = new QGLShaderProgramPrivate(QGLContext::currentContext());
+}
+
+/*!
+ Constructs a new shader program and attaches it to \a parent.
+ The program will be invalid until addShader() is called.
+
+ The shader program will be associated with \a context.
+
+ \sa isValid(), addShader()
+*/
+QGLShaderProgram::QGLShaderProgram(const QGLContext *context, QObject *parent)
+ : QObject(parent)
+{
+ d = new QGLShaderProgramPrivate(context);
+}
+
+/*!
+ Deletes this shader program.
+*/
+QGLShaderProgram::~QGLShaderProgram()
+{
+ delete d;
+}
+
+bool QGLShaderProgram::init()
+{
+ if (d->program || d->inited)
+ return true;
+ d->inited = true;
+ if (!d->context)
+ d->context = QGLContext::currentContext();
+ if (!d->context)
+ return false;
+ if (qt_resolve_glsl_extensions(const_cast<QGLContext *>(d->context))) {
+ d->program = glCreateProgram();
+ if (!(d->program)) {
+ qWarning() << "QGLShaderProgram: could not create shader program";
+ return false;
+ }
+ return true;
+ } else {
+ qWarning() << "QGLShaderProgram: shader programs are not supported";
+ return false;
+ }
+}
+
+/*!
+ Returns true if this shader program object is valid, false otherwise.
+*/
+bool QGLShaderProgram::isValid() const
+{
+ if (!d->program)
+ return false;
+#if defined(QT_OPENGL_ES_2)
+ return glIsProgram(d->program);
+#else
+ // glIsProgram() may not exist on some systems.
+ return (!glIsProgram || glIsProgram(d->program));
+#endif
+}
+
+/*!
+ Adds a compiled \a shader to this shader program. Returns true
+ if the shader could be added, or false otherwise.
+
+ Ownership of the \a shader object remains with the caller.
+ It will not be deleted when this QGLShaderProgram instance
+ is deleted. This allows the caller to add the same shader
+ to multiple shader programs.
+
+ \sa removeShader(), link(), removeAllShaders()
+*/
+bool QGLShaderProgram::addShader(QGLShader *shader)
+{
+ if (!init())
+ return false;
+ if (d->shaders.contains(shader))
+ return true; // Already added to this shader program.
+ if (d->program && shader && shader->d->shader) {
+ if (!shader->d->compiled)
+ return false;
+ if (!shader->d->isPartial)
+ glAttachShader(d->program, shader->d->shader);
+ else
+ d->hasPartialShaders = true;
+ d->linked = false; // Program needs to be relinked.
+ d->shaders.append(shader);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+/*!
+ Compiles \a source as a shader of the specified \a type and
+ adds it to this shader program. Returns true if compilation
+ was successful, false otherwise. The compilation errors
+ will be made available via errors().
+
+ This function is intended to be a short-cut for quickly
+ adding vertex and fragment shaders to a shader program without
+ creating an instance of QGLShader first.
+
+ \sa removeShader(), link(), errors(), removeAllShaders()
+*/
+bool QGLShaderProgram::addShader(QGLShader::ShaderType type, const char *source)
+{
+ if (!init())
+ return false;
+ QGLShader *shader = new QGLShader(type, this);
+ if (!shader->setSourceCode(source)) {
+ d->errors = shader->errors();
+ delete shader;
+ return false;
+ }
+ d->anonShaders.append(shader);
+ return addShader(shader);
+}
+
+/*!
+ \overload
+
+ Compiles \a source as a shader of the specified \a type and
+ adds it to this shader program. Returns true if compilation
+ was successful, false otherwise. The compilation errors
+ will be made available via errors().
+
+ This function is intended to be a short-cut for quickly
+ adding vertex and fragment shaders to a shader program without
+ creating an instance of QGLShader first.
+
+ \sa removeShader(), link(), errors(), removeAllShaders()
+*/
+bool QGLShaderProgram::addShader(QGLShader::ShaderType type, const QByteArray& source)
+{
+ return addShader(type, source.constData());
+}
+
+/*!
+ \overload
+
+ Compiles \a source as a shader of the specified \a type and
+ adds it to this shader program. Returns true if compilation
+ was successful, false otherwise. The compilation errors
+ will be made available via errors().
+
+ This function is intended to be a short-cut for quickly
+ adding vertex and fragment shaders to a shader program without
+ creating an instance of QGLShader first.
+
+ \sa removeShader(), link(), errors(), removeAllShaders()
+*/
+bool QGLShaderProgram::addShader(QGLShader::ShaderType type, const QString& source)
+{
+ return addShader(type, source.toLatin1().constData());
+}
+
+/*!
+ Removes \a shader from this shader program. The object is not deleted.
+
+ \sa addShader(), link(), removeAllShaders()
+*/
+void QGLShaderProgram::removeShader(QGLShader *shader)
+{
+ if (d->program && shader && shader->d->shader) {
+ glDetachShader(d->program, shader->d->shader);
+ d->linked = false; // Program needs to be relinked.
+ }
+ d->shaders.removeAll(shader);
+ d->anonShaders.removeAll(shader);
+}
+
+/*!
+ Returns a list of all shaders that have been added to this shader
+ program using addShader().
+
+ \sa addShader(), removeShader()
+*/
+QList<QGLShader *> QGLShaderProgram::shaders() const
+{
+ return d->shaders;
+}
+
+/*!
+ Removes all of the shaders that were added to this program previously.
+ The QGLShader objects for the shaders will not be deleted if they
+ were constructed externally. QGLShader objects that are constructed
+ internally by QGLShaderProgram will be deleted.
+
+ \sa addShader(), removeShader()
+*/
+void QGLShaderProgram::removeAllShaders()
+{
+ foreach (QGLShader *shader, d->shaders) {
+ if (d->program && shader && shader->d->shader)
+ glDetachShader(d->program, shader->d->shader);
+ }
+ foreach (QGLShader *shader, d->anonShaders) {
+ // Delete shader objects that were created anonymously.
+ delete shader;
+ }
+ d->shaders.clear();
+ d->anonShaders.clear();
+ d->linked = false; // Program needs to be relinked.
+}
+
+#if defined(QT_OPENGL_ES_2)
+
+#ifndef GL_PROGRAM_BINARY_LENGTH_OES
+#define GL_PROGRAM_BINARY_LENGTH_OES 0x8741
+#endif
+#ifndef GL_NUM_PROGRAM_BINARY_FORMATS_OES
+#define GL_NUM_PROGRAM_BINARY_FORMATS_OES 0x87FE
+#endif
+#ifndef GL_PROGRAM_BINARY_FORMATS_OES
+#define GL_PROGRAM_BINARY_FORMATS_OES 0x87FF
+#endif
+
+#endif
+
+/*!
+ Returns the program binary associated with this shader program.
+ The numeric identifier of the program binary format is returned
+ in \a format. The \c OES_get_program_binary extension will need
+ to be supported by the system for binary retrieval to succeed.
+
+ Returns an empty QByteArray if the program binary cannot be
+ retrieved on this system, or the shader program has not yet
+ been linked.
+
+ The returned binary can be supplied to setProgramBinary() on the
+ same machine at some future point to reload the program. It contains
+ the compiled code of all of the shaders that were attached to the
+ program at the time programBinary() is called.
+
+ \sa setProgramBinary(), programBinaryFormats()
+*/
+QByteArray QGLShaderProgram::programBinary(int *format) const
+{
+#if defined(QT_OPENGL_ES_2)
+ if (!isLinked())
+ return QByteArray();
+
+ // Get the length of the binary data, bailing out if there is none.
+ GLint length = 0;
+ glGetProgramiv(d->program, GL_PROGRAM_BINARY_LENGTH_OES, &length);
+ if (length <= 0)
+ return QByteArray();
+
+ // Retrieve the binary data.
+ QByteArray binary(length, 0);
+ GLenum binaryFormat;
+ glGetProgramBinaryOES(d->program, length, 0, &binaryFormat, binary.data());
+ if (format)
+ *format = (int)binaryFormat;
+ return binary;
+#else
+ Q_UNUSED(format);
+ return QByteArray();
+#endif
+}
+
+/*!
+ Sets the \a binary for this shader program according to \a format.
+ Returns true if the binary was set, or false if the binary format
+ is not supported or this system does not support program binaries.
+ The program will be linked if the load succeeds.
+
+ \sa programBinary(), programBinaryFormats(), isLinked()
+*/
+bool QGLShaderProgram::setProgramBinary(int format, const QByteArray& binary)
+{
+#if defined(QT_OPENGL_ES_2)
+ // Load the binary and check that it was linked correctly.
+ glProgramBinaryOES(d->program, (GLenum)format,
+ binary.constData(), binary.size());
+ GLint value = 0;
+ glGetProgramiv(d->program, GL_LINK_STATUS, &value);
+ d->linked = (value != 0);
+ value = 0;
+ glGetProgramiv(d->program, GL_INFO_LOG_LENGTH, &value);
+ d->errors = QString();
+ if (value > 1) {
+ char *log = new char [value];
+ GLint len;
+ glGetProgramInfoLog(d->program, value, &len, log);
+ d->errors = QString::fromLatin1(log);
+ qWarning() << "QGLShaderProgram::setProgramBinary:" << d->errors;
+ delete [] log;
+ }
+ return d->linked;
+#else
+ Q_UNUSED(format);
+ Q_UNUSED(binary);
+ return false;
+#endif
+}
+
+/*!
+ Returns the list of program binary formats that are accepted by
+ this system for use with setProgramBinary().
+
+ \sa programBinary, setProgramBinary()
+*/
+QList<int> QGLShaderProgram::programBinaryFormats()
+{
+#if defined(QT_OPENGL_ES_2)
+ GLint count = 0;
+ glGetIntegerv(GL_NUM_PROGRAM_BINARY_FORMATS_OES, &count);
+ if (count <= 0)
+ return QList<int>();
+ QVector<int> list;
+ list.resize(count);
+ glGetIntegerv(GL_PROGRAM_BINARY_FORMATS_OES, list.data());
+ return list.toList();
+#else
+ return QList<int>();
+#endif
+}
+
+/*!
+ Links together the shaders that were added to this program with
+ addShader(). Returns true if the link was successful or
+ false otherwise. If the link failed, the error messages can
+ be retrieved with errors().
+
+ Subclasses can override this function to initialize attributes
+ and uniform variables for use in specific shader programs.
+
+ If the shader program was already linked, calling this
+ function again will force it to be re-linked.
+
+ \sa addShader(), errors()
+*/
+bool QGLShaderProgram::link()
+{
+ if (!d->program)
+ return false;
+ if (d->hasPartialShaders) {
+ // Compile the partial vertex and fragment shaders.
+ QByteArray vertexSource;
+ QByteArray fragmentSource;
+ foreach (QGLShader *shader, d->shaders) {
+ if (shader->shaderType() == QGLShader::PartialVertexShader)
+ vertexSource += shader->sourceCode();
+ else if (shader->shaderType() == QGLShader::PartialFragmentShader)
+ fragmentSource += shader->sourceCode();
+ }
+ if (vertexSource.isEmpty()) {
+ if (d->vertexShader) {
+ glDetachShader(d->program, d->vertexShader->d->shader);
+ delete d->vertexShader;
+ d->vertexShader = 0;
+ }
+ } else {
+ if (!d->vertexShader) {
+ d->vertexShader =
+ new QGLShader(QGLShader::VertexShader, this);
+ }
+ if (!d->vertexShader->setSourceCode(vertexSource)) {
+ d->errors = d->vertexShader->errors();
+ return false;
+ }
+ glAttachShader(d->program, d->vertexShader->d->shader);
+ }
+ if (fragmentSource.isEmpty()) {
+ if (d->fragmentShader) {
+ glDetachShader(d->program, d->fragmentShader->d->shader);
+ delete d->fragmentShader;
+ d->fragmentShader = 0;
+ }
+ } else {
+ if (!d->fragmentShader) {
+ d->fragmentShader =
+ new QGLShader(QGLShader::FragmentShader, this);
+ }
+ if (!d->fragmentShader->setSourceCode(fragmentSource)) {
+ d->errors = d->fragmentShader->errors();
+ return false;
+ }
+ glAttachShader(d->program, d->fragmentShader->d->shader);
+ }
+ }
+ glLinkProgram(d->program);
+ GLint value = 0;
+ glGetProgramiv(d->program, GL_LINK_STATUS, &value);
+ d->linked = (value != 0);
+ value = 0;
+ glGetProgramiv(d->program, GL_INFO_LOG_LENGTH, &value);
+ d->errors = QString();
+ if (value > 1) {
+ char *log = new char [value];
+ GLint len;
+ glGetProgramInfoLog(d->program, value, &len, log);
+ d->errors = QString::fromLatin1(log);
+ qWarning() << "QGLShaderProgram::link:" << d->errors;
+ delete [] log;
+ }
+ return d->linked;
+}
+
+/*!
+ Returns true if this shader program has been linked; false otherwise.
+
+ \sa link()
+*/
+bool QGLShaderProgram::isLinked() const
+{
+ return d->linked;
+}
+
+/*!
+ Returns the errors that occurred during the last link()
+ or addShader() with explicitly specified source code.
+
+ \sa link()
+*/
+QString QGLShaderProgram::errors() const
+{
+ return d->errors;
+}
+
+/*!
+ Enable use of this shader program in the currently active QGLContext.
+ Returns true if the program was successfully enabled; false
+ otherwise. If the shader program has not yet been linked,
+ or it needs to be re-linked, this function will call link().
+
+ \sa link(), disable()
+*/
+bool QGLShaderProgram::enable()
+{
+ if (!d->program)
+ return false;
+ if (!d->linked && !link())
+ return false;
+ glUseProgram(d->program);
+ return true;
+}
+
+/*!
+ Disables this shader program in the currently active QGLContext.
+ This is equivalent to calling \c{glUseProgram(0)}.
+
+ \sa enable()
+*/
+void QGLShaderProgram::disable()
+{
+#if defined(QT_OPENGL_ES_2)
+ glUseProgram(0);
+#else
+ if (glUseProgram)
+ glUseProgram(0);
+#endif
+}
+
+/*!
+ Returns the OpenGL identifier associated with this shader program.
+
+ \sa QGLShader::shaderId()
+*/
+GLuint QGLShaderProgram::programId() const
+{
+ return d->program;
+}
+
+/*!
+ Binds the attribute \a name to the specified \a location. This
+ function can be called before or after the program has been linked.
+ Any attributes that have not been explicitly bound when the program
+ is linked will be assigned locations automatically.
+
+ \sa attributeLocation()
+*/
+void QGLShaderProgram::bindAttributeLocation(const char *name, int location)
+{
+ glBindAttribLocation(d->program, location, name);
+}
+
+/*!
+ \overload
+
+ Binds the attribute \a name to the specified \a location. This
+ function can be called before or after the program has been linked.
+ Any attributes that have not been explicitly bound when the program
+ is linked will be assigned locations automatically.
+
+ \sa attributeLocation()
+*/
+void QGLShaderProgram::bindAttributeLocation(const QByteArray& name, int location)
+{
+ glBindAttribLocation(d->program, location, name.constData());
+}
+
+/*!
+ \overload
+
+ Binds the attribute \a name to the specified \a location. This
+ function can be called before or after the program has been linked.
+ Any attributes that have not been explicitly bound when the program
+ is linked will be assigned locations automatically.
+
+ \sa attributeLocation()
+*/
+void QGLShaderProgram::bindAttributeLocation(const QString& name, int location)
+{
+ glBindAttribLocation(d->program, location, name.toLatin1().constData());
+}
+
+/*!
+ Returns the location of the attribute \a name within this shader
+ program's parameter list. Returns -1 if \a name is not a valid
+ attribute for this shader program.
+
+ \sa uniformLocation(), bindAttributeLocation()
+*/
+int QGLShaderProgram::attributeLocation(const char *name) const
+{
+ if (d->linked) {
+ return glGetAttribLocation(d->program, name);
+ } else {
+ qWarning() << "QGLShaderProgram::attributeLocation(" << name
+ << "): shader program is not linked";
+ return -1;
+ }
+}
+
+/*!
+ \overload
+
+ Returns the location of the attribute \a name within this shader
+ program's parameter list. Returns -1 if \a name is not a valid
+ attribute for this shader program.
+
+ \sa uniformLocation(), bindAttributeLocation()
+*/
+int QGLShaderProgram::attributeLocation(const QByteArray& name) const
+{
+ return attributeLocation(name.constData());
+}
+
+/*!
+ \overload
+
+ Returns the location of the attribute \a name within this shader
+ program's parameter list. Returns -1 if \a name is not a valid
+ attribute for this shader program.
+
+ \sa uniformLocation(), bindAttributeLocation()
+*/
+int QGLShaderProgram::attributeLocation(const QString& name) const
+{
+ return attributeLocation(name.toLatin1().constData());
+}
+
+/*!
+ Sets the attribute at \a location in the current context to \a value.
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue(int location, GLfloat value)
+{
+ if (location != -1)
+ glVertexAttrib1fv(location, &value);
+}
+
+/*!
+ \overload
+
+ Sets the attribute called \a name in the current context to \a value.
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue(const char *name, GLfloat value)
+{
+ setAttributeValue(attributeLocation(name), value);
+}
+
+/*!
+ Sets the attribute at \a location in the current context to
+ the 2D vector (\a x, \a y).
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue(int location, GLfloat x, GLfloat y)
+{
+ if (location != -1) {
+ GLfloat values[2] = {x, y};
+ glVertexAttrib2fv(location, values);
+ }
+}
+
+/*!
+ \overload
+
+ Sets the attribute called \a name in the current context to
+ the 2D vector (\a x, \a y).
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue(const char *name, GLfloat x, GLfloat y)
+{
+ setAttributeValue(attributeLocation(name), x, y);
+}
+
+/*!
+ Sets the attribute at \a location in the current context to
+ the 3D vector (\a x, \a y, \a z).
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue
+ (int location, GLfloat x, GLfloat y, GLfloat z)
+{
+ if (location != -1) {
+ GLfloat values[3] = {x, y, z};
+ glVertexAttrib3fv(location, values);
+ }
+}
+
+/*!
+ \overload
+
+ Sets the attribute called \a name in the current context to
+ the 3D vector (\a x, \a y, \a z).
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue
+ (const char *name, GLfloat x, GLfloat y, GLfloat z)
+{
+ setAttributeValue(attributeLocation(name), x, y, z);
+}
+
+/*!
+ Sets the attribute at \a location in the current context to
+ the 4D vector (\a x, \a y, \a z, \a w).
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue
+ (int location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ if (location != -1) {
+ GLfloat values[4] = {x, y, z, w};
+ glVertexAttrib4fv(location, values);
+ }
+}
+
+/*!
+ \overload
+
+ Sets the attribute called \a name in the current context to
+ the 4D vector (\a x, \a y, \a z, \a w).
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue
+ (const char *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ setAttributeValue(attributeLocation(name), x, y, z, w);
+}
+
+/*!
+ Sets the attribute at \a location in the current context to \a value.
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue(int location, const QVector2D& value)
+{
+ if (location != -1)
+ glVertexAttrib2fv(location, reinterpret_cast<const GLfloat *>(&value));
+}
+
+/*!
+ \overload
+
+ Sets the attribute called \a name in the current context to \a value.
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue(const char *name, const QVector2D& value)
+{
+ setAttributeValue(attributeLocation(name), value);
+}
+
+/*!
+ Sets the attribute at \a location in the current context to \a value.
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue(int location, const QVector3D& value)
+{
+ if (location != -1)
+ glVertexAttrib3fv(location, reinterpret_cast<const GLfloat *>(&value));
+}
+
+/*!
+ \overload
+
+ Sets the attribute called \a name in the current context to \a value.
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue(const char *name, const QVector3D& value)
+{
+ setAttributeValue(attributeLocation(name), value);
+}
+
+/*!
+ Sets the attribute at \a location in the current context to \a value.
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue(int location, const QVector4D& value)
+{
+ if (location != -1)
+ glVertexAttrib4fv(location, reinterpret_cast<const GLfloat *>(&value));
+}
+
+/*!
+ \overload
+
+ Sets the attribute called \a name in the current context to \a value.
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue(const char *name, const QVector4D& value)
+{
+ setAttributeValue(attributeLocation(name), value);
+}
+
+/*!
+ Sets the attribute at \a location in the current context to \a value.
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue(int location, const QColor& value)
+{
+ if (location != -1) {
+ GLfloat values[4] = {value.redF(), value.greenF(), value.blueF(), value.alphaF()};
+ glVertexAttrib4fv(location, values);
+ }
+}
+
+/*!
+ \overload
+
+ Sets the attribute called \a name in the current context to \a value.
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue(const char *name, const QColor& value)
+{
+ setAttributeValue(attributeLocation(name), value);
+}
+
+/*!
+ Sets the attribute at \a location in the current context to the
+ contents of \a values, which contains \a columns elements, each
+ consisting of \a rows elements. The \a rows value should be
+ 1, 2, 3, or 4. This function is typically used to set matrix
+ values and column vectors.
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue
+ (int location, const GLfloat *values, int columns, int rows)
+{
+ if (rows < 1 || rows > 4) {
+ qWarning() << "QGLShaderProgram::setAttributeValue: rows" << rows << "not supported";
+ return;
+ }
+ if (location != -1) {
+ while (columns-- > 0) {
+ if (rows == 1)
+ glVertexAttrib1fv(location, values);
+ else if (rows == 2)
+ glVertexAttrib2fv(location, values);
+ else if (rows == 3)
+ glVertexAttrib3fv(location, values);
+ else
+ glVertexAttrib4fv(location, values);
+ values += rows;
+ ++location;
+ }
+ }
+}
+
+/*!
+ \overload
+
+ Sets the attribute called \a name in the current context to the
+ contents of \a values, which contains \a columns elements, each
+ consisting of \a rows elements. The \a rows value should be
+ 1, 2, 3, or 4. This function is typically used to set matrix
+ values and column vectors.
+
+ \sa setUniformValue()
+*/
+void QGLShaderProgram::setAttributeValue
+ (const char *name, const GLfloat *values, int columns, int rows)
+{
+ setAttributeValue(attributeLocation(name), values, columns, rows);
+}
+
+/*!
+ Sets an array of vertex \a values on the attribute at \a location
+ in this shader program. The \a size indicates the number of
+ components per vertex (1, 2, 3, or 4), and the \a stride indicates
+ the number of bytes between vertices. A default \a stride value
+ of zero indicates that the vertices are densely packed in \a values.
+
+ \sa setAttributeValue(), setUniformValue(), disableAttributeArray()
+*/
+void QGLShaderProgram::setAttributeArray
+ (int location, const GLfloat *values, int size, int stride)
+{
+ if (location != -1) {
+ glVertexAttribPointer(location, size, GL_FLOAT, GL_FALSE,
+ stride, values);
+ glEnableVertexAttribArray(location);
+ }
+}
+
+/*!
+ Sets an array of 2D vertex \a values on the attribute at \a location
+ in this shader program. The \a stride indicates the number of bytes
+ between vertices. A default \a stride value of zero indicates that
+ the vertices are densely packed in \a values.
+
+ \sa setAttributeValue(), setUniformValue(), disableAttributeArray()
+*/
+void QGLShaderProgram::setAttributeArray
+ (int location, const QVector2D *values, int stride)
+{
+ if (location != -1) {
+ glVertexAttribPointer(location, 2, GL_FLOAT, GL_FALSE,
+ stride, values);
+ glEnableVertexAttribArray(location);
+ }
+}
+
+/*!
+ Sets an array of 3D vertex \a values on the attribute at \a location
+ in this shader program. The \a stride indicates the number of bytes
+ between vertices. A default \a stride value of zero indicates that
+ the vertices are densely packed in \a values.
+
+ \sa setAttributeValue(), setUniformValue(), disableAttributeArray()
+*/
+void QGLShaderProgram::setAttributeArray
+ (int location, const QVector3D *values, int stride)
+{
+ if (location != -1) {
+ glVertexAttribPointer(location, 3, GL_FLOAT, GL_FALSE,
+ stride, values);
+ glEnableVertexAttribArray(location);
+ }
+}
+
+/*!
+ Sets an array of 4D vertex \a values on the attribute at \a location
+ in this shader program. The \a stride indicates the number of bytes
+ between vertices. A default \a stride value of zero indicates that
+ the vertices are densely packed in \a values.
+
+ \sa setAttributeValue(), setUniformValue(), disableAttributeArray()
+*/
+void QGLShaderProgram::setAttributeArray
+ (int location, const QVector4D *values, int stride)
+{
+ if (location != -1) {
+ glVertexAttribPointer(location, 4, GL_FLOAT, GL_FALSE,
+ stride, values);
+ glEnableVertexAttribArray(location);
+ }
+}
+
+/*!
+ \overload
+
+ Sets an array of vertex \a values on the attribute called \a name
+ in this shader program. The \a size indicates the number of
+ components per vertex (1, 2, 3, or 4), and the \a stride indicates
+ the number of bytes between vertices. A default \a stride value
+ of zero indicates that the vertices are densely packed in \a values.
+
+ \sa setAttributeValue(), setUniformValue(), disableAttributeArray()
+*/
+void QGLShaderProgram::setAttributeArray
+ (const char *name, const GLfloat *values, int size, int stride)
+{
+ setAttributeArray(attributeLocation(name), values, size, stride);
+}
+
+/*!
+ \overload
+
+ Sets an array of 2D vertex \a values on the attribute called \a name
+ in this shader program. The \a stride indicates the number of bytes
+ between vertices. A default \a stride value of zero indicates that
+ the vertices are densely packed in \a values.
+
+ \sa setAttributeValue(), setUniformValue(), disableAttributeArray()
+*/
+void QGLShaderProgram::setAttributeArray
+ (const char *name, const QVector2D *values, int stride)
+{
+ setAttributeArray(attributeLocation(name), values, stride);
+}
+
+/*!
+ \overload
+
+ Sets an array of 3D vertex \a values on the attribute called \a name
+ in this shader program. The \a stride indicates the number of bytes
+ between vertices. A default \a stride value of zero indicates that
+ the vertices are densely packed in \a values.
+
+ \sa setAttributeValue(), setUniformValue(), disableAttributeArray()
+*/
+void QGLShaderProgram::setAttributeArray
+ (const char *name, const QVector3D *values, int stride)
+{
+ setAttributeArray(attributeLocation(name), values, stride);
+}
+
+/*!
+ \overload
+
+ Sets an array of 4D vertex \a values on the attribute called \a name
+ in this shader program. The \a stride indicates the number of bytes
+ between vertices. A default \a stride value of zero indicates that
+ the vertices are densely packed in \a values.
+
+ \sa setAttributeValue(), setUniformValue(), disableAttributeArray()
+*/
+void QGLShaderProgram::setAttributeArray
+ (const char *name, const QVector4D *values, int stride)
+{
+ setAttributeArray(attributeLocation(name), values, stride);
+}
+
+/*!
+ Disables the vertex array at \a location in this shader program
+ that was enabled by a previous call to setAttributeArray().
+
+ \sa setAttributeArray(), setAttributeValue(), setUniformValue()
+*/
+void QGLShaderProgram::disableAttributeArray(int location)
+{
+ if (location != -1)
+ glDisableVertexAttribArray(location);
+}
+
+/*!
+ \overload
+
+ Disables the vertex array called \a name in this shader program
+ that was enabled by a previous call to setAttributeArray().
+
+ \sa setAttributeArray(), setAttributeValue(), setUniformValue()
+*/
+void QGLShaderProgram::disableAttributeArray(const char *name)
+{
+ disableAttributeArray(attributeLocation(name));
+}
+
+/*!
+ Returns the location of the uniform variable \a name within this shader
+ program's parameter list. Returns -1 if \a name is not a valid
+ uniform variable for this shader program.
+
+ \sa attributeLocation()
+*/
+int QGLShaderProgram::uniformLocation(const char *name) const
+{
+ if (d->linked) {
+ return glGetUniformLocation(d->program, name);
+ } else {
+ qWarning() << "QGLShaderProgram::uniformLocation(" << name
+ << "): shader program is not linked";
+ return -1;
+ }
+}
+
+/*!
+ \overload
+
+ Returns the location of the uniform variable \a name within this shader
+ program's parameter list. Returns -1 if \a name is not a valid
+ uniform variable for this shader program.
+
+ \sa attributeLocation()
+*/
+int QGLShaderProgram::uniformLocation(const QByteArray& name) const
+{
+ return uniformLocation(name.constData());
+}
+
+/*!
+ \overload
+
+ Returns the location of the uniform variable \a name within this shader
+ program's parameter list. Returns -1 if \a name is not a valid
+ uniform variable for this shader program.
+
+ \sa attributeLocation()
+*/
+int QGLShaderProgram::uniformLocation(const QString& name) const
+{
+ return uniformLocation(name.toLatin1().constData());
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, GLfloat value)
+{
+ if (location != -1)
+ glUniform1fv(location, 1, &value);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, GLfloat value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to \a value.
+ This function must be used when setting sampler values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, GLint value)
+{
+ if (location != -1)
+ glUniform1i(location, value);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to \a value. This function must be used when setting sampler values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, GLint value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to
+ the 2D vector (\a x, \a y).
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, GLfloat x, GLfloat y)
+{
+ if (location != -1) {
+ GLfloat values[2] = {x, y};
+ glUniform2fv(location, 1, values);
+ }
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context to
+ the 2D vector (\a x, \a y).
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, GLfloat x, GLfloat y)
+{
+ setUniformValue(uniformLocation(name), x, y);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to
+ the 3D vector (\a x, \a y, \a z).
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue
+ (int location, GLfloat x, GLfloat y, GLfloat z)
+{
+ if (location != -1) {
+ GLfloat values[3] = {x, y, z};
+ glUniform3fv(location, 1, values);
+ }
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context to
+ the 3D vector (\a x, \a y, \a z).
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue
+ (const char *name, GLfloat x, GLfloat y, GLfloat z)
+{
+ setUniformValue(uniformLocation(name), x, y, z);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to
+ the 4D vector (\a x, \a y, \a z, \a w).
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue
+ (int location, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ if (location != -1) {
+ GLfloat values[4] = {x, y, z, w};
+ glUniform4fv(location, 1, values);
+ }
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context to
+ the 4D vector (\a x, \a y, \a z, \a w).
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue
+ (const char *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w)
+{
+ setUniformValue(uniformLocation(name), x, y, z, w);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QVector2D& value)
+{
+ if (location != -1)
+ glUniform2fv(location, 1, reinterpret_cast<const GLfloat *>(&value));
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QVector2D& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QVector3D& value)
+{
+ if (location != -1)
+ glUniform3fv(location, 1, reinterpret_cast<const GLfloat *>(&value));
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QVector3D& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QVector4D& value)
+{
+ if (location != -1)
+ glUniform4fv(location, 1, reinterpret_cast<const GLfloat *>(&value));
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QVector4D& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to
+ the red, green, blue, and alpha components of \a color.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QColor& color)
+{
+ if (location != -1) {
+ GLfloat values[4] = {color.redF(), color.greenF(), color.blueF(), color.alphaF()};
+ glUniform4fv(location, 1, values);
+ }
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context to
+ the red, green, blue, and alpha components of \a color.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QColor& color)
+{
+ setUniformValue(uniformLocation(name), color);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context
+ to a 2x2 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QMatrix2x2& value)
+{
+ if (location != -1)
+ glUniformMatrix2fv(location, 1, GL_FALSE, value.data());
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 2x2 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QMatrix2x2& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context
+ to a 2x3 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QMatrix2x3& value)
+{
+#if !defined(QT_OPENGL_ES_2)
+ if (location != -1) {
+ if (glUniformMatrix2x3fv) {
+ // OpenGL 2.1+: pass the matrix directly.
+ glUniformMatrix2x3fv(location, 1, GL_FALSE, value.data());
+ } else {
+ // OpenGL 2.0: pass the matrix columns as a vector.
+ glUniform3fv(location, 2, value.data());
+ }
+ }
+#else
+ if (location != -1)
+ glUniform3fv(location, 2, value.data());
+#endif
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 2x3 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QMatrix2x3& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context
+ to a 2x4 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QMatrix2x4& value)
+{
+#if !defined(QT_OPENGL_ES_2)
+ if (location != -1) {
+ if (glUniformMatrix2x4fv) {
+ // OpenGL 2.1+: pass the matrix directly.
+ glUniformMatrix2x4fv(location, 1, GL_FALSE, value.data());
+ } else {
+ // OpenGL 2.0: pass the matrix columns as a vector.
+ glUniform4fv(location, 2, value.data());
+ }
+ }
+#else
+ if (location != -1)
+ glUniform4fv(location, 2, value.data());
+#endif
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 2x4 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QMatrix2x4& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context
+ to a 3x2 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QMatrix3x2& value)
+{
+#if !defined(QT_OPENGL_ES_2)
+ if (location != -1) {
+ if (glUniformMatrix3x2fv) {
+ // OpenGL 2.1+: pass the matrix directly.
+ glUniformMatrix3x2fv(location, 1, GL_FALSE, value.data());
+ } else {
+ // OpenGL 2.0: pass the matrix columns as a vector.
+ glUniform2fv(location, 3, value.data());
+ }
+ }
+#else
+ if (location != -1)
+ glUniform2fv(location, 3, value.data());
+#endif
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 3x2 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QMatrix3x2& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context
+ to a 3x3 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QMatrix3x3& value)
+{
+ if (location != -1)
+ glUniformMatrix3fv(location, 1, GL_FALSE, value.data());
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 3x3 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QMatrix3x3& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context
+ to a 3x4 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QMatrix3x4& value)
+{
+#if !defined(QT_OPENGL_ES_2)
+ if (location != -1) {
+ if (glUniformMatrix3x4fv) {
+ // OpenGL 2.1+: pass the matrix directly.
+ glUniformMatrix3x4fv(location, 1, GL_FALSE, value.data());
+ } else {
+ // OpenGL 2.0: pass the matrix columns as a vector.
+ glUniform4fv(location, 3, value.data());
+ }
+ }
+#else
+ if (location != -1)
+ glUniform4fv(location, 3, value.data());
+#endif
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 3x4 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QMatrix3x4& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context
+ to a 4x2 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QMatrix4x2& value)
+{
+#if !defined(QT_OPENGL_ES_2)
+ if (location != -1) {
+ if (glUniformMatrix4x2fv) {
+ // OpenGL 2.1+: pass the matrix directly.
+ glUniformMatrix4x2fv(location, 1, GL_FALSE, value.data());
+ } else {
+ // OpenGL 2.0: pass the matrix columns as a vector.
+ glUniform2fv(location, 4, value.data());
+ }
+ }
+#else
+ if (location != -1)
+ glUniform2fv(location, 4, value.data());
+#endif
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 4x2 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QMatrix4x2& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context
+ to a 4x3 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QMatrix4x3& value)
+{
+#if !defined(QT_OPENGL_ES_2)
+ if (location != -1) {
+ if (glUniformMatrix4x3fv) {
+ // OpenGL 2.1+: pass the matrix directly.
+ glUniformMatrix4x3fv(location, 1, GL_FALSE, value.data());
+ } else {
+ // OpenGL 2.0: pass the matrix columns as a vector.
+ glUniform3fv(location, 4, value.data());
+ }
+ }
+#else
+ if (location != -1)
+ glUniform3fv(location, 4, value.data());
+#endif
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 4x3 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QMatrix4x3& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context
+ to a 4x4 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const QMatrix4x4& value)
+{
+ if (location != -1)
+ glUniformMatrix4fv(location, 1, GL_FALSE, value.data());
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 4x4 matrix \a value.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const QMatrix4x4& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable at \a location in the current context
+ to a 4x4 matrix \a value. The matrix elements must be specified
+ in column-major order.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(int location, const GLfloat value[4][4])
+{
+ if (location != -1)
+ glUniformMatrix4fv(location, 1, GL_FALSE, value[0]);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context
+ to a 4x4 matrix \a value. The matrix elements must be specified
+ in column-major order.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValue(const char *name, const GLfloat value[4][4])
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable at \a location in the current context to a
+ 3x3 transformation matrix \a value that is specified as a QTransform value.
+
+ To set a QTransform value as a 4x4 matrix in a shader, use
+ \c{setUniformValue(location, QMatrix4x4(value))}.
+*/
+void QGLShaderProgram::setUniformValue(int location, const QTransform& value)
+{
+ if (location != -1) {
+ GLfloat mat[3][3] = {
+ {value.m11(), value.m12(), value.m13()},
+ {value.m21(), value.m22(), value.m23()},
+ {value.m31(), value.m32(), value.m33()}
+ };
+ glUniformMatrix3fv(location, 1, GL_FALSE, mat[0]);
+ }
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable called \a name in the current context to a
+ 3x3 transformation matrix \a value that is specified as a QTransform value.
+
+ To set a QTransform value as a 4x4 matrix in a shader, use
+ \c{setUniformValue(name, QMatrix4x4(value))}.
+*/
+void QGLShaderProgram::setUniformValue
+ (const char *name, const QTransform& value)
+{
+ setUniformValue(uniformLocation(name), value);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count elements of \a values. This overload
+ must be used when setting an array of sampler values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const GLint *values, int count)
+{
+ if (location != -1)
+ glUniform1iv(location, count, values);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count elements of \a values. This overload
+ must be used when setting an array of sampler values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray
+ (const char *name, const GLint *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count elements of \a values. Each element
+ has \a size components. The \a size must be 1, 2, 3, or 4.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const GLfloat *values, int count, int size)
+{
+ if (location != -1) {
+ if (size == 1)
+ glUniform1fv(location, count, values);
+ else if (size == 2)
+ glUniform2fv(location, count, values);
+ else if (size == 3)
+ glUniform3fv(location, count, values);
+ else if (size == 4)
+ glUniform4fv(location, count, values);
+ else
+ qWarning() << "QGLShaderProgram::setUniformValue: size" << size << "not supported";
+ }
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count elements of \a values. Each element
+ has \a size components. The \a size must be 1, 2, 3, or 4.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray
+ (const char *name, const GLfloat *values, int count, int size)
+{
+ setUniformValueArray(uniformLocation(name), values, count, size);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count 2D vector elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const QVector2D *values, int count)
+{
+ if (location != -1)
+ glUniform2fv(location, count, reinterpret_cast<const GLfloat *>(values));
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count 2D vector elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(const char *name, const QVector2D *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count 3D vector elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const QVector3D *values, int count)
+{
+ if (location != -1)
+ glUniform3fv(location, count, reinterpret_cast<const GLfloat *>(values));
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count 3D vector elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(const char *name, const QVector3D *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count 4D vector elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const QVector4D *values, int count)
+{
+ if (location != -1)
+ glUniform4fv(location, count, reinterpret_cast<const GLfloat *>(values));
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count 4D vector elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(const char *name, const QVector4D *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+// We may have to repack matrix arrays if the matrix types
+// contain additional flag bits. Especially QMatrix4x4.
+#define setUniformMatrixArray(func,location,values,count,type,cols,rows) \
+ if (location == -1 || count <= 0) \
+ return; \
+ if (count == 1 || sizeof(type) == cols * rows * sizeof(GLfloat)) { \
+ func(location, count, GL_FALSE, values->constData()); \
+ } else { \
+ QVarLengthArray<GLfloat> temp(cols * rows * count); \
+ for (int index = 0; index < count; ++index) { \
+ qMemCopy(temp.data() + cols * rows * index, \
+ values[index].constData(), cols * rows * sizeof(GLfloat)); \
+ } \
+ func(location, count, GL_FALSE, temp.constData()); \
+ }
+#if !defined(QT_OPENGL_ES_2)
+#define setUniformGenericMatrixArray(func,colfunc,location,values,count,type,cols,rows) \
+ if (location == -1 || count <= 0) \
+ return; \
+ if (count == 1 || sizeof(type) == cols * rows * sizeof(GLfloat)) { \
+ if (func) \
+ func(location, count, GL_FALSE, values->constData()); \
+ else \
+ colfunc(location, cols * count, values->constData()); \
+ } else { \
+ QVarLengthArray<GLfloat> temp(cols * rows * count); \
+ for (int index = 0; index < count; ++index) { \
+ qMemCopy(temp.data() + cols * rows * index, \
+ values[index].constData(), cols * rows * sizeof(GLfloat)); \
+ } \
+ if (func) \
+ func(location, count, GL_FALSE, temp.constData()); \
+ else \
+ colfunc(location, count * cols, temp.constData()); \
+ }
+#else
+#define setUniformGenericMatrixArray(func,colfunc,location,values,count,type,cols,rows) \
+ if (location == -1 || count <= 0) \
+ return; \
+ if (count == 1 || sizeof(type) == cols * rows * sizeof(GLfloat)) { \
+ colfunc(location, cols * count, values->constData()); \
+ } else { \
+ QVarLengthArray<GLfloat> temp(cols * rows * count); \
+ for (int index = 0; index < count; ++index) { \
+ qMemCopy(temp.data() + cols * rows * index, \
+ values[index].constData(), cols * rows * sizeof(GLfloat)); \
+ } \
+ colfunc(location, count * cols, temp.constData()); \
+ }
+#endif
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count 2x2 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const QMatrix2x2 *values, int count)
+{
+ setUniformMatrixArray
+ (glUniformMatrix2fv, location, values, count, QMatrix2x2, 2, 2);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count 2x2 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix2x2 *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count 2x3 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const QMatrix2x3 *values, int count)
+{
+ setUniformGenericMatrixArray
+ (glUniformMatrix2x3fv, glUniform3fv, location, values, count,
+ QMatrix2x3, 2, 3);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count 2x3 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix2x3 *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count 2x4 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const QMatrix2x4 *values, int count)
+{
+ setUniformGenericMatrixArray
+ (glUniformMatrix2x4fv, glUniform4fv, location, values, count,
+ QMatrix2x4, 2, 4);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count 2x4 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix2x4 *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count 3x2 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const QMatrix3x2 *values, int count)
+{
+ setUniformGenericMatrixArray
+ (glUniformMatrix3x2fv, glUniform2fv, location, values, count,
+ QMatrix3x2, 3, 2);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count 3x2 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix3x2 *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count 3x3 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const QMatrix3x3 *values, int count)
+{
+ setUniformMatrixArray
+ (glUniformMatrix3fv, location, values, count, QMatrix3x3, 3, 3);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count 3x3 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix3x3 *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count 3x4 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const QMatrix3x4 *values, int count)
+{
+ setUniformGenericMatrixArray
+ (glUniformMatrix3x4fv, glUniform4fv, location, values, count,
+ QMatrix3x4, 3, 4);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count 3x4 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix3x4 *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count 4x2 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const QMatrix4x2 *values, int count)
+{
+ setUniformGenericMatrixArray
+ (glUniformMatrix4x2fv, glUniform2fv, location, values, count,
+ QMatrix4x2, 4, 2);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count 4x2 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix4x2 *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count 4x3 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const QMatrix4x3 *values, int count)
+{
+ setUniformGenericMatrixArray
+ (glUniformMatrix4x3fv, glUniform3fv, location, values, count,
+ QMatrix4x3, 4, 3);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count 4x3 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix4x3 *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Sets the uniform variable array at \a location in the current
+ context to the \a count 4x4 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(int location, const QMatrix4x4 *values, int count)
+{
+ setUniformMatrixArray
+ (glUniformMatrix4fv, location, values, count, QMatrix4x4, 4, 4);
+}
+
+/*!
+ \overload
+
+ Sets the uniform variable array called \a name in the current
+ context to the \a count 4x4 matrix elements of \a values.
+
+ \sa setAttributeValue()
+*/
+void QGLShaderProgram::setUniformValueArray(const char *name, const QMatrix4x4 *values, int count)
+{
+ setUniformValueArray(uniformLocation(name), values, count);
+}
+
+/*!
+ Returns true if shader programs written in the OpenGL Shading
+ Language (GLSL) are supported on this system; false otherwise.
+
+ The \a context is used to resolve the GLSL extensions.
+ If \a context is null, then QGLContext::currentContext() is used.
+*/
+bool QGLShaderProgram::hasShaderPrograms(const QGLContext *context)
+{
+#if !defined(QT_OPENGL_ES_2)
+ if (!context)
+ context = QGLContext::currentContext();
+ if (!context)
+ return false;
+ return qt_resolve_glsl_extensions(const_cast<QGLContext *>(context));
+#else
+ Q_UNUSED(context);
+ return true;
+#endif
+}
+
+#endif
+
+QT_END_NAMESPACE
diff --git a/src/opengl/qglshaderprogram.h b/src/opengl/qglshaderprogram.h
new file mode 100644
index 0000000..ec6faaf
--- /dev/null
+++ b/src/opengl/qglshaderprogram.h
@@ -0,0 +1,285 @@
+/****************************************************************************
+**
+** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: Qt Software Information (qt-info@nokia.com)
+**
+** This file is part of the QtOpenGL 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$
+**
+****************************************************************************/
+
+#ifndef QGLSHADERPROGRAM_H
+#define QGLSHADERPROGRAM_H
+
+#include <QtOpenGL/qgl.h>
+#include <QtGui/qvector2d.h>
+#include <QtGui/qvector3d.h>
+#include <QtGui/qvector4d.h>
+#include <QtGui/qmatrix4x4.h>
+
+QT_BEGIN_HEADER
+
+QT_BEGIN_NAMESPACE
+
+QT_MODULE(OpenGL)
+
+#if !defined(QT_OPENGL_ES_1_CL) && !defined(QT_GL_FIXED_PREFERRED)
+
+class QGLShaderProgram;
+class QGLShaderPrivate;
+
+class Q_OPENGL_EXPORT QGLShader : public QObject
+{
+ Q_OBJECT
+public:
+ enum ShaderType
+ {
+ VertexShader,
+ FragmentShader,
+ PartialVertexShader,
+ PartialFragmentShader
+ };
+
+ explicit QGLShader(QGLShader::ShaderType type, QObject *parent = 0);
+ explicit QGLShader(const QString& fileName, QObject *parent = 0);
+ QGLShader(const QString& fileName, QGLShader::ShaderType type, QObject *parent = 0);
+ QGLShader(QGLShader::ShaderType type, const QGLContext *context, QObject *parent = 0);
+ QGLShader(const QString& fileName, const QGLContext *context, QObject *parent = 0);
+ QGLShader(const QString& fileName, QGLShader::ShaderType type, const QGLContext *context, QObject *parent = 0);
+ virtual ~QGLShader();
+
+ bool isValid() const;
+
+ QGLShader::ShaderType shaderType() const;
+
+ bool setSourceCode(const char *source);
+ bool setSourceCode(const QByteArray& source);
+ bool setSourceCode(const QString& source);
+ bool setSourceCodeFile(const QString& fileName);
+
+ bool setBinaryCode(GLenum format, const void *binary, int length);
+ bool setBinaryCode(QGLShader& otherShader, GLenum format, const void *binary, int length);
+
+ static QList<GLenum> shaderBinaryFormats();
+
+ QByteArray sourceCode() const;
+
+ bool isCompiled() const;
+ QString errors() const;
+
+ GLuint shaderId() const;
+
+private:
+ QGLShaderPrivate *d;
+
+ friend class QGLShaderProgram;
+
+ Q_DISABLE_COPY(QGLShader);
+};
+
+class QGLShaderProgramPrivate;
+
+class Q_OPENGL_EXPORT QGLShaderProgram : public QObject
+{
+ Q_OBJECT
+public:
+ explicit QGLShaderProgram(QObject *parent = 0);
+ explicit QGLShaderProgram(const QGLContext *context, QObject *parent = 0);
+ virtual ~QGLShaderProgram();
+
+ bool isValid() const;
+
+ bool addShader(QGLShader *shader);
+ void removeShader(QGLShader *shader);
+ QList<QGLShader *> shaders() const;
+
+ bool addShader(QGLShader::ShaderType type, const char *source);
+ bool addShader(QGLShader::ShaderType type, const QByteArray& source);
+ bool addShader(QGLShader::ShaderType type, const QString& source);
+
+ void removeAllShaders();
+
+ QByteArray programBinary(int *format) const;
+ bool setProgramBinary(int format, const QByteArray& binary);
+ static QList<int> programBinaryFormats();
+
+ virtual bool link();
+ bool isLinked() const;
+ QString errors() const;
+
+ bool enable();
+ void disable();
+
+ GLuint programId() const;
+
+ void bindAttributeLocation(const char *name, int location);
+ void bindAttributeLocation(const QByteArray& name, int location);
+ void bindAttributeLocation(const QString& name, int location);
+
+ int attributeLocation(const char *name) const;
+ int attributeLocation(const QByteArray& name) const;
+ int attributeLocation(const QString& name) const;
+
+ void setAttributeValue(int location, GLfloat value);
+ void setAttributeValue(int location, GLfloat x, GLfloat y);
+ void setAttributeValue(int location, GLfloat x, GLfloat y, GLfloat z);
+ void setAttributeValue(int location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+ void setAttributeValue(int location, const QVector2D& value);
+ void setAttributeValue(int location, const QVector3D& value);
+ void setAttributeValue(int location, const QVector4D& value);
+ void setAttributeValue(int location, const QColor& value);
+ void setAttributeValue(int location, const GLfloat *values, int columns, int rows);
+
+ void setAttributeValue(const char *name, GLfloat value);
+ void setAttributeValue(const char *name, GLfloat x, GLfloat y);
+ void setAttributeValue(const char *name, GLfloat x, GLfloat y, GLfloat z);
+ void setAttributeValue(const char *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+ void setAttributeValue(const char *name, const QVector2D& value);
+ void setAttributeValue(const char *name, const QVector3D& value);
+ void setAttributeValue(const char *name, const QVector4D& value);
+ void setAttributeValue(const char *name, const QColor& value);
+ void setAttributeValue(const char *name, const GLfloat *values, int columns, int rows);
+
+ void setAttributeArray
+ (int location, const GLfloat *values, int size, int stride = 0);
+ void setAttributeArray
+ (int location, const QVector2D *values, int stride = 0);
+ void setAttributeArray
+ (int location, const QVector3D *values, int stride = 0);
+ void setAttributeArray
+ (int location, const QVector4D *values, int stride = 0);
+ void setAttributeArray
+ (const char *name, const GLfloat *values, int size, int stride = 0);
+ void setAttributeArray
+ (const char *name, const QVector2D *values, int stride = 0);
+ void setAttributeArray
+ (const char *name, const QVector3D *values, int stride = 0);
+ void setAttributeArray
+ (const char *name, const QVector4D *values, int stride = 0);
+ void disableAttributeArray(int location);
+ void disableAttributeArray(const char *name);
+
+ int uniformLocation(const char *name) const;
+ int uniformLocation(const QByteArray& name) const;
+ int uniformLocation(const QString& name) const;
+
+ void setUniformValue(int location, GLfloat value);
+ void setUniformValue(int location, GLint value);
+ void setUniformValue(int location, GLfloat x, GLfloat y);
+ void setUniformValue(int location, GLfloat x, GLfloat y, GLfloat z);
+ void setUniformValue(int location, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+ void setUniformValue(int location, const QVector2D& value);
+ void setUniformValue(int location, const QVector3D& value);
+ void setUniformValue(int location, const QVector4D& value);
+ void setUniformValue(int location, const QColor& color);
+ void setUniformValue(int location, const QMatrix2x2& value);
+ void setUniformValue(int location, const QMatrix2x3& value);
+ void setUniformValue(int location, const QMatrix2x4& value);
+ void setUniformValue(int location, const QMatrix3x2& value);
+ void setUniformValue(int location, const QMatrix3x3& value);
+ void setUniformValue(int location, const QMatrix3x4& value);
+ void setUniformValue(int location, const QMatrix4x2& value);
+ void setUniformValue(int location, const QMatrix4x3& value);
+ void setUniformValue(int location, const QMatrix4x4& value);
+ void setUniformValue(int location, const GLfloat value[4][4]);
+ void setUniformValue(int location, const QTransform& value);
+
+ void setUniformValue(const char *name, GLfloat value);
+ void setUniformValue(const char *name, GLint value);
+ void setUniformValue(const char *name, GLfloat x, GLfloat y);
+ void setUniformValue(const char *name, GLfloat x, GLfloat y, GLfloat z);
+ void setUniformValue(const char *name, GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+ void setUniformValue(const char *name, const QVector2D& value);
+ void setUniformValue(const char *name, const QVector3D& value);
+ void setUniformValue(const char *name, const QVector4D& value);
+ void setUniformValue(const char *name, const QColor& color);
+ void setUniformValue(const char *name, const QMatrix2x2& value);
+ void setUniformValue(const char *name, const QMatrix2x3& value);
+ void setUniformValue(const char *name, const QMatrix2x4& value);
+ void setUniformValue(const char *name, const QMatrix3x2& value);
+ void setUniformValue(const char *name, const QMatrix3x3& value);
+ void setUniformValue(const char *name, const QMatrix3x4& value);
+ void setUniformValue(const char *name, const QMatrix4x2& value);
+ void setUniformValue(const char *name, const QMatrix4x3& value);
+ void setUniformValue(const char *name, const QMatrix4x4& value);
+ void setUniformValue(const char *name, const GLfloat value[4][4]);
+ void setUniformValue(const char *name, const QTransform& value);
+
+ void setUniformValueArray(int location, const GLfloat *values, int count, int size);
+ void setUniformValueArray(int location, const GLint *values, int count);
+ void setUniformValueArray(int location, const QVector2D *values, int count);
+ void setUniformValueArray(int location, const QVector3D *values, int count);
+ void setUniformValueArray(int location, const QVector4D *values, int count);
+ void setUniformValueArray(int location, const QMatrix2x2 *values, int count);
+ void setUniformValueArray(int location, const QMatrix2x3 *values, int count);
+ void setUniformValueArray(int location, const QMatrix2x4 *values, int count);
+ void setUniformValueArray(int location, const QMatrix3x2 *values, int count);
+ void setUniformValueArray(int location, const QMatrix3x3 *values, int count);
+ void setUniformValueArray(int location, const QMatrix3x4 *values, int count);
+ void setUniformValueArray(int location, const QMatrix4x2 *values, int count);
+ void setUniformValueArray(int location, const QMatrix4x3 *values, int count);
+ void setUniformValueArray(int location, const QMatrix4x4 *values, int count);
+
+ void setUniformValueArray(const char *name, const GLfloat *values, int count, int size);
+ void setUniformValueArray(const char *name, const GLint *values, int count);
+ void setUniformValueArray(const char *name, const QVector2D *values, int count);
+ void setUniformValueArray(const char *name, const QVector3D *values, int count);
+ void setUniformValueArray(const char *name, const QVector4D *values, int count);
+ void setUniformValueArray(const char *name, const QMatrix2x2 *values, int count);
+ void setUniformValueArray(const char *name, const QMatrix2x3 *values, int count);
+ void setUniformValueArray(const char *name, const QMatrix2x4 *values, int count);
+ void setUniformValueArray(const char *name, const QMatrix3x2 *values, int count);
+ void setUniformValueArray(const char *name, const QMatrix3x3 *values, int count);
+ void setUniformValueArray(const char *name, const QMatrix3x4 *values, int count);
+ void setUniformValueArray(const char *name, const QMatrix4x2 *values, int count);
+ void setUniformValueArray(const char *name, const QMatrix4x3 *values, int count);
+ void setUniformValueArray(const char *name, const QMatrix4x4 *values, int count);
+
+ static bool hasShaderPrograms(const QGLContext *context = 0);
+
+private:
+ QGLShaderProgramPrivate *d;
+
+ Q_DISABLE_COPY(QGLShaderProgram);
+
+ bool init();
+};
+
+#endif
+
+QT_END_NAMESPACE
+
+QT_END_HEADER
+
+#endif