From 68861d8eb2a0645da491c724bdcc545dcbdd41d8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Pasi=20Ker=C3=A4nen?= <pasi.keranen@digia.com>
Date: Tue, 12 May 2015 10:56:30 +0300
Subject: [PATCH] Fixes getUniform() method return values and types.
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

getUniform() method now returns correct types according
to the WebGL specification. Also number of returned values
was fixed.

Change-Id: I71d82ce09af462ddc420e1fd8be1cd5d96a4122d
Reviewed-by: Tomi Korpipää <tomi.korpipaa@theqtcompany.com>
Reviewed-by: Pasi Keränen <pasi.keranen@digia.com>
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@theqtcompany.com>
---
 src/imports/qtcanvas3d/context3d.cpp | 249 ++++++++++++++-------------
 src/imports/qtcanvas3d/context3d_p.h |   2 +-
 2 files changed, 132 insertions(+), 119 deletions(-)

diff --git a/src/imports/qtcanvas3d/context3d.cpp b/src/imports/qtcanvas3d/context3d.cpp
index 0b15a55..425c6ad 100644
--- a/src/imports/qtcanvas3d/context3d.cpp
+++ b/src/imports/qtcanvas3d/context3d.cpp
@@ -5895,35 +5895,35 @@ QJSValue CanvasContext::getVertexAttrib(uint index, glEnums pname)
  * The type returned is dependent on the uniform type, as shown in the table:
  * \table
  * \header
- *   \li Data Type
+ *   \li Uniform Type
  *   \li Returned Type
  * \row
  *   \li boolean
- *   \li sequence<boolean> (with 1 element)
+ *   \li boolean
  * \row
  *   \li int
- *   \li sequence<int> (with 1 element)
+ *   \li int
  * \row
  *   \li float
- *   \li sequence<float> (with 1 element)
+ *   \li float
  * \row
  *   \li vec2
- *   \li sequence<float> (with 2 elements)
+ *   \li Float32Array (with 2 elements)
  * \row
  *   \li vec3
- *   \li sequence<float> (with 3 elements)
+ *   \li Float32Array (with 3 elements)
  * \row
  *   \li vec4
- *   \li sequence<float> (with 4 elements)
+ *   \li Float32Array (with 4 elements)
  * \row
  *   \li ivec2
- *   \li sequence<int> (with 2 elements)
+ *   \li Int32Array (with 2 elements)
  * \row
  *   \li ivec3
- *   \li sequence<int> (with 3 elements)
+ *   \li Int32Array (with 3 elements)
  * \row
  *   \li ivec4
- *   \li sequence<int> (with 4 elements)
+ *   \li Int32Array (with 4 elements)
  * \row
  *   \li bvec2
  *   \li sequence<boolean> (with 2 elements)
@@ -5935,25 +5935,25 @@ QJSValue CanvasContext::getVertexAttrib(uint index, glEnums pname)
  *   \li sequence<boolean> (with 4 elements)
  * \row
  *   \li mat2
- *   \li sequence<float> (with 4 elements)
+ *   \li Float32Array (with 4 elements)
  * \row
  *   \li mat3
- *   \li sequence<float> (with 9 elements)
+ *   \li Float32Array (with 9 elements)
  * \row
  *   \li mat4
- *   \li sequence<float> (with 16 elements)
+ *   \li Float32Array (with 16 elements)
  * \row
  *   \li sampler2D
- *   \li sequence<int> (with 1 element)
+ *   \li int
  * \row
  *   \li samplerCube
- *   \li sequence<int> (with 1 element)
+ *   \li int
  *  \endtable
  */
 /*!
  * \internal
  */
-QVariant CanvasContext::getUniform(QJSValue program3D, QJSValue location3D)
+QJSValue CanvasContext::getUniform(QJSValue program3D, QJSValue location3D)
 {
     qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
                                          << "(program" << program3D.toString()
@@ -5967,125 +5967,138 @@ QVariant CanvasContext::getUniform(QJSValue program3D, QJSValue location3D)
         qCWarning(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
                                                << ":INVALID_OPERATION:No program was specified";
         m_error |= CANVAS_INVALID_OPERATION;
+        return QJSValue(QJSValue::UndefinedValue);
+
     } else  if (!location) {
         qCWarning(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__
                                                << ":INVALID_OPERATION:No location3D was specified";
         m_error |= CANVAS_INVALID_OPERATION;
-    } else {
-        if (!checkParent(program, __FUNCTION__) || !checkParent(location, __FUNCTION__))
-            return QVariant();
-        uint programId = program->id();
-        uint locationId = location->id();
-        CanvasActiveInfo *info = getActiveUniform(program3D, locationId);
-        int numValues = 4;
-
-        switch (info->type()) {
-        case SAMPLER_2D:
-            // Intentional flow through
-        case SAMPLER_CUBE:
-            // Intentional flow through
-        case INT: {
-            GLint value = 0;
-            glGetUniformiv(programId, locationId, &value);
-            logAllGLErrors(__FUNCTION__);
-            return QVariant::fromValue(value);
-        }
-        case INT_VEC2:
-            numValues--;
-            // Intentional flow through
-        case INT_VEC3:
-            numValues--;
-            // Intentional flow through
-        case INT_VEC4: {
-            numValues--;
-            GLint *value = new GLint[numValues];
-            glGetUniformiv(programId, locationId, value);
-            logAllGLErrors(__FUNCTION__);
+        return QJSValue(QJSValue::UndefinedValue);
+    }
 
-            QList<float> intList;
-            for (int i = 0; i < numValues; i++)
-                intList << value[i];
+    if (!checkParent(program, __FUNCTION__) || !checkParent(location, __FUNCTION__))
+        return QJSValue(QJSValue::UndefinedValue);
 
-            // TODO: Should return Int32Array
-            return QVariant::fromValue(intList);
-        }
-        case FLOAT: {
-            GLfloat value = 0;
-            glGetUniformfv(programId, locationId, &value);
-            logAllGLErrors(__FUNCTION__);
-            return QVariant::fromValue(value);
-        }
-        case FLOAT_VEC2:
-            numValues--;
-            // Intentional flow through
-        case FLOAT_VEC3:
-            numValues--;
-            // Intentional flow through
-        case FLOAT_VEC4: {
-            numValues--;
-            GLfloat *value = new GLfloat[numValues];
+    uint programId = program->id();
+    uint locationId = location->id();
+    CanvasActiveInfo *info = getActiveUniform(program3D, locationId);
 
-            glGetUniformfv(programId, locationId, value);
-            logAllGLErrors(__FUNCTION__);
+    int numValues = 4;
+    switch (info->type()) {
+    case SAMPLER_2D:
+        // Intentional flow through
+    case SAMPLER_CUBE:
+        // Intentional flow through
+    case INT: {
+        GLint value = 0;
+        glGetUniformiv(programId, locationId, &value);
+        logAllGLErrors(__FUNCTION__);
+        return QJSValue(value);
+    }
+    case FLOAT: {
+        GLfloat value = 0;
+        glGetUniformfv(programId, locationId, &value);
+        logAllGLErrors(__FUNCTION__);
+        return QJSValue(value);
+    }
+    case BOOL: {
+        GLint value = 0;
+        glGetUniformiv(programId, locationId, &value);
+        logAllGLErrors(__FUNCTION__);
+        return QJSValue(bool(value));
+    }
+    case INT_VEC2:
+        numValues--;
+        // Intentional flow through
+    case INT_VEC3:
+        numValues--;
+        // Intentional flow through
+    case INT_VEC4: {
+        QV4::Scope scope(m_v4engine);
+        QV4::Scoped<QV4::ArrayBuffer> buffer(scope,
+                                             m_v4engine->memoryManager->alloc<QV4::ArrayBuffer>(
+                                                 m_v4engine,
+                                                 sizeof(int) * numValues));
+        glGetUniformiv(programId, locationId, (int *) buffer->data());
+        logAllGLErrors(__FUNCTION__);
 
-            QList<float> floatList;
-            for (int i = 0; i < numValues; i++)
-                floatList << value[i];
+        QV4::ScopedFunctionObject constructor(scope,
+                                              m_v4engine->typedArrayCtors[
+                                              QV4::Heap::TypedArray::Int32Array]);
+        QV4::ScopedCallData callData(scope, 1);
+        callData->args[0] = buffer;
+        return QJSValue(m_v4engine, constructor->construct(callData));
+    }
+    case FLOAT_VEC2:
+        numValues--;
+        // Intentional flow through
+    case FLOAT_VEC3:
+        numValues--;
+        // Intentional flow through
+    case FLOAT_VEC4: {
+        QV4::Scope scope(m_v4engine);
+        QV4::Scoped<QV4::ArrayBuffer> buffer(scope,
+                                             m_v4engine->memoryManager->alloc<QV4::ArrayBuffer>(
+                                                 m_v4engine,
+                                                 sizeof(float) * numValues));
+        glGetUniformfv(programId, locationId, (float *) buffer->data());
+        logAllGLErrors(__FUNCTION__);
 
-            // TODO: Should return Float32Array
-            return QVariant::fromValue(floatList);
-        }
-        case BOOL: {
-            GLint value = 0;
-            glGetUniformiv(programId, locationId, &value);
-            logAllGLErrors(__FUNCTION__);
-            return QVariant::fromValue(bool(value));
-        }
-        case BOOL_VEC2:
-            numValues--;
-            // Intentional flow through
-        case BOOL_VEC3:
-            numValues--;
-            // Intentional flow through
-        case BOOL_VEC4: {
-            numValues--;
-            GLint *value = new GLint[numValues];
+        QV4::ScopedFunctionObject constructor(scope,
+                                              m_v4engine->typedArrayCtors[
+                                              QV4::Heap::TypedArray::Float32Array]);
+        QV4::ScopedCallData callData(scope, 1);
+        callData->args[0] = buffer;
+        return QJSValue(m_v4engine, constructor->construct(callData));
+    }
+    case BOOL_VEC2:
+        numValues--;
+        // Intentional flow through
+    case BOOL_VEC3:
+        numValues--;
+        // Intentional flow through
+    case BOOL_VEC4: {
+        GLint *value = new GLint[numValues];
+        QJSValue array = m_engine->newArray(numValues);
 
-            glGetUniformiv(programId, locationId, value);
-            logAllGLErrors(__FUNCTION__);
+        glGetUniformiv(programId, locationId, value);
+        logAllGLErrors(__FUNCTION__);
 
-            QList<bool> boolList;
-            for (int i = 0; i < numValues; i++)
-                boolList << value[i];
+        for (int i = 0; i < numValues; i++)
+            array.setProperty(i, bool(value[i]));
 
-            return QVariant::fromValue(boolList);
-        }
-        case FLOAT_MAT2:
-            numValues--;
-            // Intentional flow through
-        case FLOAT_MAT3:
-            numValues--;
-            // Intentional flow through
-        case FLOAT_MAT4: {
-            numValues = numValues * numValues;
-            GLfloat *value = new GLfloat[numValues];
+        return array;
+    }
+    case FLOAT_MAT2:
+        numValues--;
+        // Intentional flow through
+    case FLOAT_MAT3:
+        numValues--;
+        // Intentional flow through
+    case FLOAT_MAT4: {
+        numValues = numValues * numValues;
 
-            glGetUniformfv(programId, locationId, value);
-            logAllGLErrors(__FUNCTION__);
 
-            QList<float> floatList;
-            for (int i = 0; i < numValues; i++)
-                floatList << value[i];
+        QV4::Scope scope(m_v4engine);
+        QV4::Scoped<QV4::ArrayBuffer> buffer(scope,
+                                             m_v4engine->memoryManager->alloc<QV4::ArrayBuffer>(
+                                                 m_v4engine,
+                                                 sizeof(float) * numValues));
+        glGetUniformfv(programId, locationId, (float *) buffer->data());
+        logAllGLErrors(__FUNCTION__);
 
-            // TODO: Should return Float32Array
-            return QVariant::fromValue(floatList);
-        }
-        default:
-            break;
-        }
+        QV4::ScopedFunctionObject constructor(scope,
+                                              m_v4engine->typedArrayCtors[
+                                              QV4::Heap::TypedArray::Float32Array]);
+        QV4::ScopedCallData callData(scope, 1);
+        callData->args[0] = buffer;
+        return QJSValue(m_v4engine, constructor->construct(callData));
+    }
+    default:
+        break;
     }
 
-    return QVariant();
+    return QJSValue(QJSValue::UndefinedValue);
 }
 
 /*!
diff --git a/src/imports/qtcanvas3d/context3d_p.h b/src/imports/qtcanvas3d/context3d_p.h
index d34ca39..72c8750 100644
--- a/src/imports/qtcanvas3d/context3d_p.h
+++ b/src/imports/qtcanvas3d/context3d_p.h
@@ -1174,7 +1174,7 @@ public:
                                                       glEnums pname);
     Q_INVOKABLE int getRenderbufferParameter(glEnums target, glEnums pname);
     Q_INVOKABLE QVariant getTexParameter(glEnums target, glEnums pname);
-    Q_INVOKABLE QVariant getUniform(QJSValue program, QJSValue location);
+    Q_INVOKABLE QJSValue getUniform(QJSValue program, QJSValue location);
     Q_INVOKABLE uint getVertexAttribOffset(uint index, glEnums pname);
     Q_INVOKABLE QJSValue getVertexAttrib(uint index, glEnums pname);
 
-- 
GitLab