From c35dda8139ed1d59cf8b4a01a3bf22515a72a836 Mon Sep 17 00:00:00 2001 From: Miikka Heikkinen <miikka.heikkinen@theqtcompany.com> Date: Tue, 19 May 2015 17:32:27 +0300 Subject: [PATCH] Refactored typed array handling MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Reduced copy/paste by centralizing typed array data pointer resolving. It now also uses byte offset in typed arrays if they have it. Change-Id: I2d3d63ba0a8056884044ac73e47bf3821279be97 Task-number: QTBUG-45825 Reviewed-by: Pasi Keränen <pasi.keranen@digia.com> --- src/imports/qtcanvas3d/context3d.cpp | 409 +++++++++++++-------------- src/imports/qtcanvas3d/context3d_p.h | 10 +- 2 files changed, 207 insertions(+), 212 deletions(-) diff --git a/src/imports/qtcanvas3d/context3d.cpp b/src/imports/qtcanvas3d/context3d.cpp index abb2b8c..a78d2ec 100644 --- a/src/imports/qtcanvas3d/context3d.cpp +++ b/src/imports/qtcanvas3d/context3d.cpp @@ -55,7 +55,6 @@ #include <QtGui/QOpenGLShader> #include <QtOpenGLExtensions/QOpenGLExtensions> -#include <QtQml/private/qv4typedarray_p.h> #include <QtQml/private/qv4arraybuffer_p.h> #include <QtQml/private/qjsvalue_p.h> #include <QtCore/private/qbytedata_p.h> @@ -640,8 +639,23 @@ CanvasTexture *CanvasContext::getAsTexture3D(QJSValue anyObject) /*! * \qmlmethod void Context3D::compressedTexImage2D(glEnums target, int level, glEnums internalformat, int width, int height, int border, TypedArray pixels) - * Not supported, \c{Context3D.INVALID_OPERATION} is generated when called. - * \a target, \a level, \a internalformat, \a width, \a height, \a border and \a pixels are ignored. + * Specify a 2D compressed texture image. + * \a target specifies the target texture of the active texture unit. Must be one of: + * \c{Context3D.TEXTURE_2D}, + * \c{Context3D.TEXTURE_CUBE_MAP_POSITIVE_X}, \c{Context3D.TEXTURE_CUBE_MAP_NEGATIVE_X}, + * \c{Context3D.TEXTURE_CUBE_MAP_POSITIVE_Y}, \c{Context3D.TEXTURE_CUBE_MAP_NEGATIVE_Y}, + * \c{Context3D.TEXTURE_CUBE_MAP_POSITIVE_Z}, or \c{Context3D.TEXTURE_CUBE_MAP_NEGATIVE_Z}. + * \a level specifies the level of detail number. Level \c 0 is the base image level. Level \c n is + * the \c{n}th mipmap reduction image. + * \a internalformat specifies the internal format of the compressed texture. + * \a width specifies the width of the texture image. All implementations will support 2D texture + * images that are at least 64 texels wide and cube-mapped texture images that are at least 16 + * texels wide. + * \a height specifies the height of the texture image. All implementations will support 2D texture + * images that are at least 64 texels high and cube-mapped texture images that are at least 16 + * texels high. + * \a border must be \c{0}. + * \a pixels specifies the TypedArray containing the compressed image data. */ /*! * \internal @@ -663,19 +677,18 @@ void CanvasContext::compressedTexImage2D(glEnums target, int level, glEnums inte if (!isValidTextureBound(target, __FUNCTION__)) return; - QV4::Scope scope(m_v4engine); - QV4::Scoped<QV4::TypedArray> typedArray(scope, - QJSValuePrivate::convertedToValue(m_v4engine, pixels)); + int byteLen = 0; + uchar *srcData = getTypedArrayAsRawDataPtr(pixels, byteLen, QV4::Heap::TypedArray::UInt8Array); - if (typedArray) { + if (srcData) { // Driver implementation will handle checking of texture // properties for specific compression methods glCompressedTexImage2D(target, level, internalformat, width, height, border, - typedArray->byteLength(), - (GLvoid *) typedArray->arrayData()->data()); + byteLen, + (GLvoid *)srcData ); logAllGLErrors(__FUNCTION__); } else { qCWarning(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__ @@ -687,9 +700,22 @@ void CanvasContext::compressedTexImage2D(glEnums target, int level, glEnums inte /*! * \qmlmethod void Context3D::compressedTexSubImage2D(glEnums target, int level, int xoffset, int yoffset, int width, int height, glEnums format, TypedArray pixels) - * Not supported, \c{Context3D.INVALID_OPERATION} is generated when called. - * \a target, \a level, \a xoffset, \a yoffset, \a width, \a height, \a format and \a pixels are - * ignored. + * Specify a 2D compressed texture image. + * \a target specifies the target texture of the active texture unit. Must be one of: + * \c{Context3D.TEXTURE_2D}, + * \c{Context3D.TEXTURE_CUBE_MAP_POSITIVE_X}, \c{Context3D.TEXTURE_CUBE_MAP_NEGATIVE_X}, + * \c{Context3D.TEXTURE_CUBE_MAP_POSITIVE_Y}, \c{Context3D.TEXTURE_CUBE_MAP_NEGATIVE_Y}, + * \c{Context3D.TEXTURE_CUBE_MAP_POSITIVE_Z}, or \c{Context3D.TEXTURE_CUBE_MAP_NEGATIVE_Z}. + * \a level specifies the level of detail number. Level \c 0 is the base image level. Level \c n is + * the \c{n}th mipmap reduction image. + * \a xoffset Specifies a texel offset in the x direction within the texture array. + * \a yoffset Specifies a texel offset in the y direction within the texture array. + * \a width Width of the texture subimage. + * \a height Height of the texture subimage. + * \a pixels specifies the TypedArray containing the compressed image data. + * \a format Format of the texel data given in \a pixels, must match the value + * of \c internalFormat parameter given when the texture was created. + * \a pixels TypedArray containing the compressed image data. If pixels is \c null. */ /*! * \internal @@ -714,11 +740,10 @@ void CanvasContext::compressedTexSubImage2D(glEnums target, int level, if (!isValidTextureBound(target, __FUNCTION__)) return; - QV4::Scope scope(m_v4engine); - QV4::Scoped<QV4::TypedArray> typedArray(scope, - QJSValuePrivate::convertedToValue(m_v4engine, pixels)); + int byteLen = 0; + uchar *srcData = getTypedArrayAsRawDataPtr(pixels, byteLen, QV4::Heap::TypedArray::UInt8Array); - if (typedArray) { + if (srcData) { // Driver implementation will handle checking of texture // properties for specific compression methods glCompressedTexSubImage2D(target, @@ -726,8 +751,8 @@ void CanvasContext::compressedTexSubImage2D(glEnums target, int level, xoffset, yoffset, width, height, format, - typedArray->byteLength(), - (GLvoid *) typedArray->arrayData()->data()); + byteLen, + (GLvoid *)srcData); logAllGLErrors(__FUNCTION__); } else { qCWarning(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__ @@ -922,7 +947,7 @@ void CanvasContext::texImage2D(glEnums target, int level, glEnums internalformat } if (!srcData) - srcData = getAsUint8ArrayRawPtr(pixels); + srcData = getTypedArrayAsRawDataPtr(pixels, QV4::Heap::TypedArray::UInt8Array); if (!srcData) { qCWarning(canvas3drendering).nospace() << "Context3D::" @@ -943,7 +968,7 @@ void CanvasContext::texImage2D(glEnums target, int level, glEnums internalformat case UNSIGNED_SHORT_5_6_5: case UNSIGNED_SHORT_5_5_5_1: { if (!srcData) - srcData = getAsUint16ArrayRawPtr(pixels); + srcData = getTypedArrayAsRawDataPtr(pixels, QV4::Heap::TypedArray::UInt16Array); if (!srcData) { qCWarning(canvas3drendering).nospace() << "Context3D::" @@ -978,7 +1003,8 @@ void CanvasContext::texImage2D(glEnums target, int level, glEnums internalformat /*! * \internal */ -uchar *CanvasContext::getAsUint8ArrayRawPtr(QJSValue jsValue) +uchar *CanvasContext::getTypedArrayAsRawDataPtr(const QJSValue &jsValue, int &byteLength, + QV4::Heap::TypedArray::Type type) { QV4::Scope scope(m_v4engine); QV4::Scoped<QV4::TypedArray> typedArray(scope, @@ -987,28 +1013,48 @@ uchar *CanvasContext::getAsUint8ArrayRawPtr(QJSValue jsValue) if (!typedArray) return 0; - if (typedArray->arrayType() != QV4::Heap::TypedArray::UInt8Array) + QV4::Heap::TypedArray::Type arrayType = typedArray->arrayType(); + if (type < QV4::Heap::TypedArray::NTypes && arrayType != type) return 0; - return reinterpret_cast<unsigned char *>(typedArray->arrayData()->data()); + uchar *dataPtr = reinterpret_cast<uchar *>(typedArray->arrayData()->data()); + dataPtr += typedArray->d()->byteOffset; + byteLength = typedArray->byteLength(); + return dataPtr; } /*! * \internal */ -uchar *CanvasContext::getAsUint16ArrayRawPtr(QJSValue jsValue) +uchar *CanvasContext::getTypedArrayAsRawDataPtr(const QJSValue &jsValue, + QV4::Heap::TypedArray::Type type) { - QV4::Scope scope(m_v4engine); - QV4::Scoped<QV4::TypedArray> typedArray(scope, - QJSValuePrivate::convertedToValue(m_v4engine, jsValue)); + int dummy; + return getTypedArrayAsRawDataPtr(jsValue, dummy, type); +} - if (!typedArray) - return 0; +/*! + * \internal + */ +uchar *CanvasContext::getTypedArrayAsRawDataPtr(const QJSValue &jsValue, int &byteLength) +{ + return getTypedArrayAsRawDataPtr(jsValue, byteLength, QV4::Heap::TypedArray::NTypes); +} - if (typedArray->arrayType() != QV4::Heap::TypedArray::UInt16Array) +/*! + * \internal + */ +uchar *CanvasContext::getArrayBufferAsRawDataPtr(const QJSValue &jsValue, int &byteLength) +{ + QV4::Scope scope(m_v4engine); + QV4::Scoped<QV4::ArrayBuffer> arrayBuffer(scope, + QJSValuePrivate::convertedToValue(m_v4engine, jsValue)); + if (!arrayBuffer) return 0; - return reinterpret_cast<unsigned char *>(typedArray->arrayData()->data()); + uchar *dataPtr = reinterpret_cast<uchar *>(arrayBuffer->data()); + byteLength = arrayBuffer->byteLength(); + return dataPtr; } /*! @@ -1025,12 +1071,11 @@ uchar *CanvasContext::getAsUint16ArrayRawPtr(QJSValue jsValue) * \a width Width of the texture subimage. * \a height Height of the texture subimage. * \a format Format of the texel data given in \a pixels, must match the value - * of \a internalFormat. + * of \c internalFormat parameter given when the texture was created. * \a type Data type of the data given in \a pixels, must match the TypedArray type * of \a pixels. Must be \c{Context3D.UNSIGNED_BYTE}, \c{Context3D.UNSIGNED_SHORT_5_6_5}, * \c{Context3D.UNSIGNED_SHORT_4_4_4_4} or \c{Context3D.UNSIGNED_SHORT_5_5_5_1}. - * \a pixels TypedArray containing the image data. If pixels is \c null, a buffer of - * sufficient size initialized to 0 is passed. + * \a pixels TypedArray containing the image data. */ /*! * \internal @@ -1097,7 +1142,7 @@ void CanvasContext::texSubImage2D(glEnums target, int level, return; } - srcData = getAsUint8ArrayRawPtr(pixels); + srcData = getTypedArrayAsRawDataPtr(pixels, QV4::Heap::TypedArray::UInt8Array); if (!srcData) { qCWarning(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__ @@ -1115,7 +1160,7 @@ void CanvasContext::texSubImage2D(glEnums target, int level, case UNSIGNED_SHORT_4_4_4_4: case UNSIGNED_SHORT_5_6_5: case UNSIGNED_SHORT_5_5_5_1: { - srcData = getAsUint16ArrayRawPtr(pixels); + srcData = getTypedArrayAsRawDataPtr(pixels, QV4::Heap::TypedArray::UInt16Array); if (!srcData) { qCWarning(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__ @@ -2777,18 +2822,15 @@ void CanvasContext::uniform1iv(QJSValue location3D, QJSValue array) return; } + int arrayLen = 0; + uchar *uniformData = getTypedArrayAsRawDataPtr(array, arrayLen, + QV4::Heap::TypedArray::Int32Array); - QV4::Scope scope(m_v4engine); - QV4::Scoped<QV4::TypedArray> typedArray(scope, - QJSValuePrivate::convertedToValue(m_v4engine, array)); - if (!typedArray - || !locationObj - || typedArray->arrayType() != QV4::Heap::TypedArray::Int32Array) + if (!uniformData || !locationObj) return; - glUniform1iv(locationObj->id(), - typedArray->length(), - (int *)typedArray->arrayData()->data()); + arrayLen /= 4; // get value count + glUniform1iv(locationObj->id(), arrayLen, (int *)uniformData); logAllGLErrors(__FUNCTION__); } @@ -2839,17 +2881,15 @@ void CanvasContext::uniform1fv(QJSValue location3D, QJSValue array) return; } - QV4::Scope scope(m_v4engine); - QV4::Scoped<QV4::TypedArray> typedArray(scope, - QJSValuePrivate::convertedToValue(m_v4engine, array)); - if (!typedArray - || !locationObj - || typedArray->arrayType() != QV4::Heap::TypedArray::Float32Array) + int arrayLen = 0; + uchar *uniformData = getTypedArrayAsRawDataPtr(array, arrayLen, + QV4::Heap::TypedArray::Float32Array); + + if (!uniformData || !locationObj) return; - glUniform1fv(locationObj->id(), - typedArray->length(), - (float *)typedArray->arrayData()->data()); + arrayLen /= 4; // get value count + glUniform1fv(locationObj->id(), arrayLen, (float *)uniformData); logAllGLErrors(__FUNCTION__); } @@ -2901,17 +2941,16 @@ void CanvasContext::uniform2fv(QJSValue location3D, QJSValue array) return; } - QV4::Scope scope(m_v4engine); - QV4::Scoped<QV4::TypedArray> typedArray(scope, - QJSValuePrivate::convertedToValue(m_v4engine, array)); - if (!typedArray - || !locationObj - || typedArray->arrayType() != QV4::Heap::TypedArray::Float32Array) + int arrayLen = 0; + uchar *uniformData = getTypedArrayAsRawDataPtr(array, arrayLen, + QV4::Heap::TypedArray::Float32Array); + + if (!uniformData || !locationObj) return; - glUniform2fv(locationObj->id(), - typedArray->length() / 2, - (float *)typedArray->arrayData()->data()); + + arrayLen /= (4 * 2); // get value count + glUniform2fv(locationObj->id(), arrayLen, (float *)uniformData); logAllGLErrors(__FUNCTION__); } @@ -2963,18 +3002,15 @@ void CanvasContext::uniform2iv(QJSValue location3D, QJSValue array) return; } - QV4::Scope scope(m_v4engine); - QV4::Scoped<QV4::TypedArray> typedArray(scope, - QJSValuePrivate::convertedToValue(m_v4engine, array)); - if (!typedArray - || !locationObj - || typedArray->arrayType() != QV4::Heap::TypedArray::Int32Array) - return; + int arrayLen = 0; + uchar *uniformData = getTypedArrayAsRawDataPtr(array, arrayLen, + QV4::Heap::TypedArray::Int32Array); - glUniform2iv(locationObj->id(), - typedArray->length() / 2, - (int *)typedArray->arrayData()->data()); + if (!uniformData || !locationObj) + return; + arrayLen /= (4 * 2); // get value count + glUniform2iv(locationObj->id(), arrayLen, (int *)uniformData); logAllGLErrors(__FUNCTION__); } @@ -3026,18 +3062,15 @@ void CanvasContext::uniform3fv(QJSValue location3D, QJSValue array) return; } - QV4::Scope scope(m_v4engine); - QV4::Scoped<QV4::TypedArray> typedArray(scope, - QJSValuePrivate::convertedToValue(m_v4engine, array)); - if (!typedArray - || !locationObj - || typedArray->arrayType() != QV4::Heap::TypedArray::Float32Array) { + int arrayLen = 0; + uchar *uniformData = getTypedArrayAsRawDataPtr(array, arrayLen, + QV4::Heap::TypedArray::Float32Array); + + if (!uniformData || !locationObj) return; - } - glUniform3fv(locationObj->id(), - typedArray->length() / 3, - (float *) typedArray->arrayData()->data()); + arrayLen /= (4 * 3); // get value count + glUniform3fv(locationObj->id(), arrayLen, (float *)uniformData); logAllGLErrors(__FUNCTION__); } @@ -3088,18 +3121,15 @@ void CanvasContext::uniform3iv(QJSValue location3D, QJSValue array) return; } - QV4::Scope scope(m_v4engine); - QV4::Scoped<QV4::TypedArray> typedArray(scope, - QJSValuePrivate::convertedToValue(m_v4engine, array)); - if (!typedArray - || !locationObj - || typedArray->arrayType() != QV4::Heap::TypedArray::Int32Array) { + int arrayLen = 0; + uchar *uniformData = getTypedArrayAsRawDataPtr(array, arrayLen, + QV4::Heap::TypedArray::Int32Array); + + if (!uniformData || !locationObj) return; - } - glUniform3iv(locationObj->id(), - typedArray->length() / 3, - (int *)typedArray->arrayData()->data()); + arrayLen /= (4 * 3); // get value count + glUniform3iv(locationObj->id(), arrayLen, (int *)uniformData); logAllGLErrors(__FUNCTION__); } @@ -3151,17 +3181,15 @@ void CanvasContext::uniform4fv(QJSValue location3D, QJSValue array) return; } - QV4::Scope scope(m_v4engine); - QV4::Scoped<QV4::TypedArray> typedArray(scope, - QJSValuePrivate::convertedToValue(m_v4engine, array)); - if (!typedArray - || !locationObj - || typedArray->arrayType() != QV4::Heap::TypedArray::Float32Array) + int arrayLen = 0; + uchar *uniformData = getTypedArrayAsRawDataPtr(array, arrayLen, + QV4::Heap::TypedArray::Float32Array); + + if (!uniformData || !locationObj) return; - glUniform4fv(locationObj->id(), - typedArray->length() / 4, - (float *)typedArray->arrayData()->data()); + arrayLen /= (4 * 4); // get value count + glUniform4fv(locationObj->id(), arrayLen, (float *)uniformData); logAllGLErrors(__FUNCTION__); } @@ -3213,17 +3241,15 @@ void CanvasContext::uniform4iv(QJSValue location3D, QJSValue array) return; } - QV4::Scope scope(m_v4engine); - QV4::Scoped<QV4::TypedArray> typedArray(scope, - QJSValuePrivate::convertedToValue(m_v4engine, array)); - if (!typedArray - || !locationObj - || typedArray->arrayType() != QV4::Heap::TypedArray::Int32Array) + int arrayLen = 0; + uchar *uniformData = getTypedArrayAsRawDataPtr(array, arrayLen, + QV4::Heap::TypedArray::Int32Array); + + if (!uniformData || !locationObj) return; - glUniform4iv(locationObj->id(), - typedArray->length() / 4, - (int *)typedArray->arrayData()->data()); + arrayLen /= (4 * 4); // get value count + glUniform4iv(locationObj->id(), arrayLen, (int *)uniformData); logAllGLErrors(__FUNCTION__); } @@ -3404,14 +3430,12 @@ void CanvasContext::vertexAttrib1fv(unsigned int indx, QJSValue array) return; } - // Check if we have a Float32Array - QV4::Scope scope(m_v4engine); - QV4::Scoped<QV4::TypedArray> typedArray(scope, - QJSValuePrivate::convertedToValue(m_v4engine, array)); - if (!typedArray || typedArray->arrayType() != QV4::Heap::TypedArray::Float32Array) + uchar *attribData = getTypedArrayAsRawDataPtr(array, QV4::Heap::TypedArray::Float32Array); + + if (!attribData) return; - glVertexAttrib1fv(indx, (float *)typedArray->arrayData()->data()); + glVertexAttrib1fv(indx, (float *)attribData); logAllGLErrors(__FUNCTION__); } @@ -3455,14 +3479,12 @@ void CanvasContext::vertexAttrib2fv(unsigned int indx, QJSValue array) return; } - // Check if we have a Float32Array - QV4::Scope scope(m_v4engine); - QV4::Scoped<QV4::TypedArray> typedArray(scope, - QJSValuePrivate::convertedToValue(m_v4engine, array)); - if (!typedArray || typedArray->arrayType() != QV4::Heap::TypedArray::Float32Array) + uchar *attribData = getTypedArrayAsRawDataPtr(array, QV4::Heap::TypedArray::Float32Array); + + if (!attribData) return; - glVertexAttrib2fv(indx, (float *)typedArray->arrayData()->data()); + glVertexAttrib2fv(indx, (float *)attribData); logAllGLErrors(__FUNCTION__); } @@ -3507,14 +3529,12 @@ void CanvasContext::vertexAttrib3fv(unsigned int indx, QJSValue array) return; } - // Check if we have a Float32Array - QV4::Scope scope(m_v4engine); - QV4::Scoped<QV4::TypedArray> typedArray(scope, - QJSValuePrivate::convertedToValue(m_v4engine, array)); - if (!typedArray || typedArray->arrayType() != QV4::Heap::TypedArray::Float32Array) + uchar *attribData = getTypedArrayAsRawDataPtr(array, QV4::Heap::TypedArray::Float32Array); + + if (!attribData) return; - glVertexAttrib3fv(indx, (float *)typedArray->arrayData()->data()); + glVertexAttrib3fv(indx, (float *)attribData); logAllGLErrors(__FUNCTION__); } @@ -3560,14 +3580,12 @@ void CanvasContext::vertexAttrib4fv(unsigned int indx, QJSValue array) return; } - // Check if we have a Float32Array - QV4::Scope scope(m_v4engine); - QV4::Scoped<QV4::TypedArray> typedArray(scope, - QJSValuePrivate::convertedToValue(m_v4engine, array)); - if (!typedArray || typedArray->arrayType() != QV4::Heap::TypedArray::Float32Array) + uchar *attribData = getTypedArrayAsRawDataPtr(array, QV4::Heap::TypedArray::Float32Array); + + if (!attribData) return; - glVertexAttrib4fv(indx, (float *)typedArray->arrayData()->data()); + glVertexAttrib4fv(indx, (float *)attribData); logAllGLErrors(__FUNCTION__); } @@ -3803,23 +3821,20 @@ void CanvasContext::uniformMatrix2fv(QJSValue location3D, bool transpose, QJSVal return; } - // We should have a Float32Array - QV4::Scope scope(m_v4engine); - QV4::Scoped<QV4::TypedArray> typedArray(scope, - QJSValuePrivate::convertedToValue(m_v4engine, array)); - if (!m_currentProgram - || !typedArray - || !locationObj - || typedArray->arrayType() != QV4::Heap::TypedArray::Float32Array) + int arrayLen = 0; + uchar *uniformData = getTypedArrayAsRawDataPtr(array, arrayLen, + QV4::Heap::TypedArray::Float32Array); + + if (!m_currentProgram || !uniformData || !locationObj) return; + int uniformLocation = locationObj->id(); + int numMatrices = arrayLen / (4 * 4); + qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__ - << "numMatrices:" << (typedArray->length() / 4); + << "numMatrices:" << numMatrices; - int uniformLocation = locationObj->id(); - float *arrayData = (float *)typedArray->arrayData()->data(); - int numMatrices = typedArray->length() / 4; - glUniformMatrix2fv(uniformLocation, numMatrices, transpose, arrayData); + glUniformMatrix2fv(uniformLocation, numMatrices, transpose, (float *)uniformData); logAllGLErrors(__FUNCTION__); } @@ -3853,24 +3868,20 @@ void CanvasContext::uniformMatrix3fv(QJSValue location3D, bool transpose, QJSVal return; } - // We should have a Float32Array - QV4::Scope scope(m_v4engine); - QV4::Scoped<QV4::TypedArray> typedArray(scope, - QJSValuePrivate::convertedToValue(m_v4engine, array)); - if (!m_currentProgram - || !typedArray - || !locationObj - || typedArray->arrayType() != QV4::Heap::TypedArray::Float32Array) - return; + int arrayLen = 0; + uchar *uniformData = getTypedArrayAsRawDataPtr(array, arrayLen, + QV4::Heap::TypedArray::Float32Array); - qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__ - << "numMatrices:" << (typedArray->length() / 9); + if (!m_currentProgram || !uniformData || !locationObj) + return; int uniformLocation = locationObj->id(); - float *arrayData = (float *)typedArray->arrayData()->data(); - int numMatrices = typedArray->length() / 9; + int numMatrices = arrayLen / (4 * 9); - glUniformMatrix3fv(uniformLocation, numMatrices, transpose, arrayData); + qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__ + << "numMatrices:" << numMatrices; + + glUniformMatrix3fv(uniformLocation, numMatrices, transpose, (float *)uniformData); logAllGLErrors(__FUNCTION__); } @@ -3904,23 +3915,20 @@ void CanvasContext::uniformMatrix4fv(QJSValue location3D, bool transpose, QJSVal return; } - // We should have a Float32Array - QV4::Scope scope(m_v4engine); - QV4::Scoped<QV4::TypedArray> typedArray(scope, - QJSValuePrivate::convertedToValue(m_v4engine, array)); - if (!m_currentProgram - || !typedArray - || !locationObj - || typedArray->arrayType() != QV4::Heap::TypedArray::Float32Array) + int arrayLen = 0; + uchar *uniformData = getTypedArrayAsRawDataPtr(array, arrayLen, + QV4::Heap::TypedArray::Float32Array); + + if (!m_currentProgram || !uniformData || !locationObj) return; - qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__ - << "numMatrices:" << (typedArray->length() / 16); int uniformLocation = locationObj->id(); - float *arrayData = (float *)typedArray->arrayData()->data(); - int numMatrices = typedArray->length() / 16; + int numMatrices = arrayLen / (4 * 16); - glUniformMatrix4fv(uniformLocation, numMatrices, transpose, arrayData); + qCDebug(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__ + << "numMatrices:" << numMatrices; + + glUniformMatrix4fv(uniformLocation, numMatrices, transpose, (float *)uniformData); logAllGLErrors(__FUNCTION__); } @@ -4201,29 +4209,19 @@ void CanvasContext::bufferData(glEnums target, QJSValue data, glEnums usage) return; } + int arrayLen = 0; + uchar *srcData = getTypedArrayAsRawDataPtr(data, arrayLen); - QV4::Scope scope(m_v4engine); - QV4::Scoped<QV4::TypedArray> typedArray(scope, - QJSValuePrivate::convertedToValue(m_v4engine, data)); - QV4::Scoped<QV4::ArrayBuffer> arrayBuffer(scope, - QJSValuePrivate::convertedToValue(m_v4engine, data)); + if (!srcData) + srcData = getArrayBufferAsRawDataPtr(data, arrayLen); - if (typedArray) { - glBufferData(GLenum(target), - typedArray->byteLength(), - (GLvoid *) typedArray->arrayData()->data(), - GLenum(usage)); - logAllGLErrors(__FUNCTION__); - } else if (arrayBuffer) { - glBufferData(GLenum(target), - arrayBuffer->byteLength(), - (GLvoid *) arrayBuffer->data(), - GLenum(usage)); + if (srcData) { + glBufferData(GLenum(target), arrayLen, (GLvoid *)srcData, GLenum(usage)); logAllGLErrors(__FUNCTION__); } else { qCWarning(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__ << ":INVALID_VALUE:data must be either" - << "TypedArray or ArrayBuffer"; + << " TypedArray or ArrayBuffer"; m_error |= CANVAS_INVALID_VALUE; return; } @@ -4261,28 +4259,19 @@ void CanvasContext::bufferSubData(glEnums target, int offset, QJSValue data) return; } - QV4::Scope scope(m_v4engine); - QV4::Scoped<QV4::TypedArray> typedArray(scope, - QJSValuePrivate::convertedToValue(m_v4engine, data)); - QV4::Scoped<QV4::ArrayBuffer> arrayBuffer(scope, - QJSValuePrivate::convertedToValue(m_v4engine, data)); + int arrayLen = 0; + uchar *srcData = getTypedArrayAsRawDataPtr(data, arrayLen); - if (typedArray) { - glBufferSubData(GLenum(target), - offset, - typedArray->byteLength(), - (GLvoid *) typedArray->arrayData()->data()); - logAllGLErrors(__FUNCTION__); - } else if (arrayBuffer) { - glBufferSubData(GLenum(target), - offset, - arrayBuffer->byteLength(), - (GLvoid *) arrayBuffer->data()); + if (!srcData) + srcData = getArrayBufferAsRawDataPtr(data, arrayLen); + + if (srcData) { + glBufferSubData(GLenum(target), offset, arrayLen, (GLvoid *)srcData); logAllGLErrors(__FUNCTION__); } else { qCWarning(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__ << ":INVALID_VALUE:data must be either" - << "TypedArray or ArrayBuffer"; + << " TypedArray or ArrayBuffer"; m_error |= CANVAS_INVALID_VALUE; return; } @@ -5271,7 +5260,7 @@ void CanvasContext::readPixels(int x, int y, long width, long height, glEnums fo return; } - uchar *bufferPtr = getAsUint8ArrayRawPtr(pixels); + uchar *bufferPtr = getTypedArrayAsRawDataPtr(pixels, QV4::Heap::TypedArray::UInt8Array); if (!bufferPtr) { qCWarning(canvas3drendering).nospace() << "Context3D::" << __FUNCTION__ << ":INVALID_OPERATION:pixels must be Uint8Array."; diff --git a/src/imports/qtcanvas3d/context3d_p.h b/src/imports/qtcanvas3d/context3d_p.h index 60ffcfe..db96ae8 100644 --- a/src/imports/qtcanvas3d/context3d_p.h +++ b/src/imports/qtcanvas3d/context3d_p.h @@ -62,6 +62,7 @@ #include <QtQml> #include <QtQml/QJSEngine> #include <QtQml/private/qqmlengine_p.h> +#include <QtQml/private/qv4typedarray_p.h> #ifdef NO_ERROR // may de defined in winerror.h #undef NO_ERROR @@ -1184,8 +1185,13 @@ signals: void drawingBufferHeightChanged(); private: - uchar *getAsUint8ArrayRawPtr(QJSValue value); - uchar *getAsUint16ArrayRawPtr(QJSValue value); + uchar *getTypedArrayAsRawDataPtr(const QJSValue &jsValue, int &byteLength, + QV4::Heap::TypedArray::Type type); + uchar *getTypedArrayAsRawDataPtr(const QJSValue &jsValue, + QV4::Heap::TypedArray::Type type); + uchar *getTypedArrayAsRawDataPtr(const QJSValue &jsValue, int &byteLength); + uchar *getArrayBufferAsRawDataPtr(const QJSValue &jsValue, int &byteLength); + CanvasTexture *getAsTexture3D(QJSValue anyObject); CanvasTextureImage* getAsTextureImage(QJSValue image); CanvasFrameBuffer *getAsFramebuffer(QJSValue anyObject); -- GitLab