From 12bbbdb904d047209fd8b175b87924db037b21d8 Mon Sep 17 00:00:00 2001 From: Pasi Keranen <pasi.keranen@digia.com> Date: Wed, 12 Nov 2014 14:42:44 +0200 Subject: [PATCH] Fixed crash of jsonmodels example on OS X. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Added QTCANVAS3D_gl_state_dump extension for dumping the current GL state for debugging purposes and added example use to jsonmodels example. Fixed documentation issues and removed invalid comments related to render thread. Change-Id: Ib4a81370bf2673a5bfb412038148646638f723a9 Reviewed-by: Tomi Korpipää <tomi.korpipaa@digia.com> Reviewed-by: Pasi Keränen <pasi.keranen@digia.com> --- examples/canvas3d/jsonmodels/jsonmodels.js | 19 +- examples/canvas3d/jsonmodels/jsonmodels.qml | 1 + src/canvas3d.cpp | 1 - src/canvas3dcommon_p.h | 2 + src/canvasglstatedump.cpp | 423 ++++++++++++++++++++ src/canvasglstatedump_p.h | 91 +++++ src/context3d.cpp | 99 +++-- src/context3d_p.h | 7 +- src/contextattributes.cpp | 2 +- src/plugins.qmltypes | 40 +- src/qcanvas3d_plugin.cpp | 6 + src/qcanvas3d_plugin.h | 3 + src/src.pro | 6 +- src/texture3d.cpp | 6 +- src/texture3d_p.h | 4 +- 15 files changed, 656 insertions(+), 54 deletions(-) create mode 100644 src/canvasglstatedump.cpp create mode 100644 src/canvasglstatedump_p.h diff --git a/examples/canvas3d/jsonmodels/jsonmodels.js b/examples/canvas3d/jsonmodels/jsonmodels.js index 0e6c427..42a302c 100644 --- a/examples/canvas3d/jsonmodels/jsonmodels.js +++ b/examples/canvas3d/jsonmodels/jsonmodels.js @@ -74,6 +74,7 @@ var modelTwo = new Model(); var modelThree = new Model(); var modelFour = new Model(); var modelFive = new Model(); +var stateDumpExt; function initGL(canvas) { canvas3d = canvas @@ -82,6 +83,12 @@ function initGL(canvas) { gl = canvas.getContext("canvas3d", {depth:true, antialias:true}); log(" Received context: "+gl); + stateDumpExt = gl.getExtension("QTCANVAS3D_gl_state_dump"); + if (stateDumpExt) + log("QTCANVAS3D_gl_state_dump extension found"); + else + log("QTCANVAS3D_gl_state_dump extension NOT found"); + var contextConfig = gl.getContextAttributes(); log(" Depth: "+contextConfig.alpha); log(" Stencil: "+contextConfig.stencil); @@ -95,7 +102,7 @@ function initGL(canvas) { gl.enable(gl.DEPTH_TEST); gl.disable(gl.CULL_FACE); gl.enable(gl.BLEND); - gl.enable(gl.DEPTH_WRITE); + gl.enable(gl.DEPTH_TEST); gl.depthMask(true); gl.blendFunc(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA); @@ -181,6 +188,7 @@ function renderGL(canvas) { // Calculate the modelview matrix mat4.identity(mMatrix); mat4.translate(mMatrix, mMatrix, posOne); + // Calculate normal matrix before scaling, to keep lighting in order // Scale normal matrix with distance instead mat4.copy(nMatrix, mMatrix); @@ -188,6 +196,7 @@ function renderGL(canvas) { mat4.invert(nMatrix, nMatrix); mat4.transpose(nMatrix, nMatrix); gl.uniformMatrix4fva(nMatrixUniform, false, nMatrix); + // Scale the modelview matrix, and apply the matrix mat4.scale(mMatrix, mMatrix, [canvas.itemSize, canvas.itemSize, canvas.itemSize]); mat4.multiply(mvMatrix, vMatrix, mMatrix); @@ -195,6 +204,10 @@ function renderGL(canvas) { // Draw the model gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, modelOne.indexVBO); + + if (stateDumpExt) + log("GL STATE DUMP:\n"+stateDumpExt.getGLStateDump(stateDumpExt.DUMP_FULL)); + gl.drawElements(drawMode, modelOne.count, gl.UNSIGNED_SHORT, 0); // Calculate the modelview matrix @@ -559,8 +572,10 @@ function fillModel(modelData, model) { gl.bufferData(gl.ARRAY_BUFFER, Arrays.newFloat32Array(modelData.vertices), gl.STATIC_DRAW); - log(" "+model.normalsVBO.name); + if (stateDumpExt) + log("GL STATE DUMP:\n"+stateDumpExt.getGLStateDump(stateDumpExt.DUMP_VERTEX_ATTRIB_ARRAYS_BIT || stateDumpExt.DUMP_VERTEX_ATTRIB_ARRAYS_CONTENTS_BIT)); + gl.bindBuffer(gl.ARRAY_BUFFER, model.normalsVBO); gl.bufferData(gl.ARRAY_BUFFER, Arrays.newFloat32Array(modelData.normals), diff --git a/examples/canvas3d/jsonmodels/jsonmodels.qml b/examples/canvas3d/jsonmodels/jsonmodels.qml index cdba0db..b7cb536 100644 --- a/examples/canvas3d/jsonmodels/jsonmodels.qml +++ b/examples/canvas3d/jsonmodels/jsonmodels.qml @@ -24,6 +24,7 @@ Window { Layout.fillWidth: true Canvas3D { id: canvas3d + Layout.fillHeight: true Layout.fillWidth: true //! [1] diff --git a/src/canvas3d.cpp b/src/canvas3d.cpp index 5937bac..f03d122 100644 --- a/src/canvas3d.cpp +++ b/src/canvas3d.cpp @@ -678,7 +678,6 @@ void Canvas::renderNext() // Rebind default FBO QOpenGLFramebufferObject::bindDefault(); - m_glContext->doneCurrent(); // Notify the render node of new texture emit textureReady(m_displayFbo->texture(), m_initialisedSize, m_devicePixelRatio); diff --git a/src/canvas3dcommon_p.h b/src/canvas3dcommon_p.h index 76c85bf..4516de1 100644 --- a/src/canvas3dcommon_p.h +++ b/src/canvas3dcommon_p.h @@ -51,4 +51,6 @@ #define VERBOSE_ALL_TYPED_ARRAY_CALLS false +#define QT_CANVAS3D_GL_STATE_DUMP_EXT_NAME "QTCANVAS3D_gl_state_dump" + #endif // CANVAS3DCOMMON_P_H diff --git a/src/canvasglstatedump.cpp b/src/canvasglstatedump.cpp new file mode 100644 index 0000000..7f7c9aa --- /dev/null +++ b/src/canvasglstatedump.cpp @@ -0,0 +1,423 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtCanvas3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later 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 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "canvasglstatedump_p.h" +#include "enumtostringmap_p.h" + +#include <QDebug> +#include <QColor> + +#define BOOL_TO_STR(a) a ? "true" : "false" + +/*! + \qmltype GLStateDumpExt + \since QtCanvas3D 1.0 + \ingroup qtcanvas3d-qml-types + \brief Provides means to print current GL driver state info. + + An uncreatable QML type that provides an extension API that can be used dump current OpenGL + driver state as string that can be then e.g. printed on console log. You can get it by + calling \l{Context3D::getExtension}{Context3D.getExtension} with "QTCANVAS3D_gl_state_dump" + as parameter. + + Typical usage could be something like this: + \code + // Declare the variable to contain the extension + var stateDumpExt; + . + . + // After context has been created from Canvas3D get the extension + stateDumpExt = gl.getExtension("QTCANVAS3D_gl_state_dump"); + . + . + // When you want to print the current GL state with everything enabled + // Check that you indeed have a valid extension (for portability) then use it + if (stateDumpExt) + log("GL STATE DUMP:\n"+stateDumpExt.getGLStateDump(stateDumpExt.DUMP_FULL)); + \endcode + + \sa Context3D + */ +CanvasGLStateDump::CanvasGLStateDump(QOpenGLContext *context, QObject *parent) : + QObject(parent), + QOpenGLFunctions(context), + m_map(EnumToStringMap::newInstance()) +{ + m_isOpenGLES2 = context->isOpenGLES(); + glGetIntegerv(GL_MAX_VERTEX_ATTRIBS, &m_maxVertexAttribs); +} + +/*! + * \internal + */ +CanvasGLStateDump::~CanvasGLStateDump() +{ + EnumToStringMap::deleteInstance(); + m_map = 0; +} + +/*! + * \internal + */ +QString CanvasGLStateDump::getGLArrayObjectDump(int target, int arrayObject, int type) +{ + QString stateDumpStr; + glBindBuffer(target, arrayObject); + + GLint size; + glGetBufferParameteriv(target, GL_BUFFER_SIZE, &size); + + if (type == GL_FLOAT) { + stateDumpStr.append("ARRAY_BUFFER_TYPE......................FLOAT\n"); + + stateDumpStr.append("ARRAY_BUFFER_SIZE......................"); + stateDumpStr.append(QString::number(size)); + stateDumpStr.append("\n"); + + } else if (type == GL_UNSIGNED_SHORT) { + stateDumpStr.append("ARRAY_BUFFER_TYPE......................UNSIGNED_SHORT\n"); + + stateDumpStr.append("ARRAY_BUFFER_SIZE......................"); + stateDumpStr.append(QString::number(size)); + stateDumpStr.append("\n"); + } + + return stateDumpStr; +} + +/*! + * \qmlmethod string GLStateDumpExt::getGLStateDump(stateDumpEnums options) + * \return OpenGL driver state with given options as a human readable string that can be printed. + * Optional paremeter \a options may contain bitfields masked together from following options: + * \list + * \li \c{GLStateDumpExt.DUMP_BASIC_ONLY} Includes only very basic OpenGL state information. + * \li \c{GLStateDumpExt.DUMP_VERTEX_ATTRIB_ARRAYS_BIT} Includes all vertex attribute array + * information. + * \li \c{GLStateDumpExt.DUMP_VERTEX_ATTRIB_ARRAYS_BUFFERS_BIT} Includes size and type + * from all currently active vertex attribute arrays (including the currently bound element array) + * to verify that there are actual values in the array. + * \li \c{GLStateDumpExt.DUMP_FULL} Includes everything. + * \endlist + */ +QString CanvasGLStateDump::getGLStateDump(CanvasGLStateDump::stateDumpEnums options) +{ +#if !defined(QT_OPENGL_ES_2) + GLint drawFramebuffer; + GLint readFramebuffer; + GLboolean polygonOffsetLineEnabled; + GLboolean polygonOffsetPointEnabled; + GLint boundVertexArray; +#endif + + QString stateDumpStr; + GLint renderbuffer; + GLfloat clearColor[4]; + GLfloat clearDepth; + GLboolean isBlendingEnabled = glIsEnabled(GL_BLEND); + GLboolean isDepthTestEnabled = glIsEnabled(GL_DEPTH_TEST); + GLint depthFunc; + GLboolean isDepthWriteEnabled; + GLint currentProgram; + GLint *vertexAttribArrayEnabledStates = new GLint[m_maxVertexAttribs]; + GLint *vertexAttribArrayBoundBuffers = new GLint[m_maxVertexAttribs]; + GLint *vertexAttribArraySizes = new GLint[m_maxVertexAttribs]; + GLint *vertexAttribArrayTypes = new GLint[m_maxVertexAttribs]; + GLint *vertexAttribArrayNormalized = new GLint[m_maxVertexAttribs]; + GLint *vertexAttribArrayStrides = new GLint[m_maxVertexAttribs]; + GLint activeTexture; + GLint texBinding2D; + GLint arrayBufferBinding; + GLint frontFace; + GLboolean isCullFaceEnabled = glIsEnabled(GL_CULL_FACE); + GLint cullFaceMode; + GLint blendEquationRGB; + GLint blendEquationAlpha; + + GLint blendDestAlpha; + GLint blendDestRGB; + GLint blendSrcAlpha; + GLint blendSrcRGB; + GLint scissorBox[4]; + GLboolean isScissorTestEnabled = glIsEnabled(GL_SCISSOR_TEST); + GLint boundElementArrayBuffer; + GLboolean polygonOffsetFillEnabled; + GLfloat polygonOffsetFactor; + GLfloat polygonOffsetUnits; + +#if !defined(QT_OPENGL_ES_2) + if (!m_isOpenGLES2) { + glGetIntegerv(GL_DRAW_FRAMEBUFFER_BINDING, &drawFramebuffer); + glGetIntegerv(GL_READ_FRAMEBUFFER_BINDING, &readFramebuffer); + glGetBooleanv(GL_POLYGON_OFFSET_LINE, &polygonOffsetLineEnabled); + glGetBooleanv(GL_POLYGON_OFFSET_POINT, &polygonOffsetPointEnabled); + glGetIntegerv(GL_VERTEX_ARRAY_BINDING, &boundVertexArray); + } +#endif + + glGetBooleanv(GL_DEPTH_WRITEMASK, &isDepthWriteEnabled); + glGetIntegerv(GL_RENDERBUFFER_BINDING, &renderbuffer); + glGetFloatv(GL_COLOR_CLEAR_VALUE, clearColor); + glGetFloatv(GL_DEPTH_CLEAR_VALUE, &clearDepth); + glGetIntegerv(GL_DEPTH_FUNC, &depthFunc); + glGetBooleanv(GL_POLYGON_OFFSET_FILL, &polygonOffsetFillEnabled); + glGetFloatv(GL_POLYGON_OFFSET_FACTOR, &polygonOffsetFactor); + glGetFloatv(GL_POLYGON_OFFSET_UNITS, &polygonOffsetUnits); + + glGetIntegerv(GL_CURRENT_PROGRAM, ¤tProgram); + glGetIntegerv(GL_ACTIVE_TEXTURE, &activeTexture); + glGetIntegerv(GL_TEXTURE_BINDING_2D, &texBinding2D ); + glGetIntegerv(GL_FRONT_FACE, &frontFace); + glGetIntegerv(GL_CULL_FACE_MODE, &cullFaceMode); + glGetIntegerv(GL_BLEND_EQUATION_RGB, &blendEquationRGB); + glGetIntegerv(GL_BLEND_EQUATION_ALPHA, &blendEquationAlpha); + glGetIntegerv(GL_BLEND_DST_ALPHA, &blendDestAlpha); + glGetIntegerv(GL_BLEND_DST_RGB, &blendDestRGB); + glGetIntegerv(GL_BLEND_SRC_ALPHA, &blendSrcAlpha); + glGetIntegerv(GL_BLEND_SRC_RGB, &blendSrcRGB); + glGetIntegerv(GL_SCISSOR_BOX, scissorBox); + glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING, &boundElementArrayBuffer); + glGetIntegerv(GL_ARRAY_BUFFER_BINDING, &arrayBufferBinding); + + +#if !defined(QT_OPENGL_ES_2) + if (!m_isOpenGLES2) { + stateDumpStr.append("GL_DRAW_FRAMEBUFFER_BINDING....."); + stateDumpStr.append(QString::number(drawFramebuffer)); + stateDumpStr.append("\n"); + + stateDumpStr.append("GL_READ_FRAMEBUFFER_BINDING....."); + stateDumpStr.append(QString::number(readFramebuffer)); + stateDumpStr.append("\n"); + } +#endif + + stateDumpStr.append("GL_RENDERBUFFER_BINDING........."); + stateDumpStr.append(QString::number(renderbuffer)); + stateDumpStr.append("\n"); + + stateDumpStr.append("GL_SCISSOR_TEST................."); + stateDumpStr.append(BOOL_TO_STR(isScissorTestEnabled)); + stateDumpStr.append("\n"); + + stateDumpStr.append("GL_SCISSOR_BOX.................."); + stateDumpStr.append(QString::number(scissorBox[0])); + stateDumpStr.append(", "); + stateDumpStr.append(QString::number(scissorBox[1])); + stateDumpStr.append(", "); + stateDumpStr.append(QString::number(scissorBox[2])); + stateDumpStr.append(", "); + stateDumpStr.append(QString::number(scissorBox[3])); + stateDumpStr.append("\n"); + + stateDumpStr.append("GL_COLOR_CLEAR_VALUE............"); + stateDumpStr.append("r:"); + stateDumpStr.append(QString::number(clearColor[0])); + stateDumpStr.append(" g:"); + stateDumpStr.append(QString::number(clearColor[1])); + stateDumpStr.append(" b:"); + stateDumpStr.append(QString::number(clearColor[2])); + stateDumpStr.append(" a:"); + stateDumpStr.append(QString::number(clearColor[3])); + stateDumpStr.append("\n"); + + stateDumpStr.append("GL_DEPTH_CLEAR_VALUE............"); + stateDumpStr.append(QString::number(clearDepth)); + stateDumpStr.append("\n"); + + stateDumpStr.append("GL_BLEND........................"); + stateDumpStr.append(BOOL_TO_STR(isBlendingEnabled)); + stateDumpStr.append("\n"); + + stateDumpStr.append("GL_BLEND_EQUATION_RGB..........."); + stateDumpStr.append(m_map->lookUp(blendEquationRGB)); + stateDumpStr.append("\n"); + + stateDumpStr.append("GL_BLEND_EQUATION_ALPHA........."); + stateDumpStr.append(m_map->lookUp(blendEquationAlpha)); + stateDumpStr.append("\n"); + + stateDumpStr.append("GL_DEPTH_TEST..................."); + stateDumpStr.append(BOOL_TO_STR(isDepthTestEnabled)); + stateDumpStr.append("\n"); + + stateDumpStr.append("GL_DEPTH_FUNC..................."); + stateDumpStr.append(m_map->lookUp(depthFunc)); + stateDumpStr.append("\n"); + + stateDumpStr.append("GL_DEPTH_WRITEMASK.............."); + stateDumpStr.append(BOOL_TO_STR(isDepthWriteEnabled)); + stateDumpStr.append("\n"); + + stateDumpStr.append("GL_POLYGON_OFFSET_FILL.........."); + stateDumpStr.append(BOOL_TO_STR(polygonOffsetFillEnabled)); + stateDumpStr.append("\n"); + +#if !defined(QT_OPENGL_ES_2) + if (!m_isOpenGLES2) { + stateDumpStr.append("GL_POLYGON_OFFSET_LINE.........."); + stateDumpStr.append(BOOL_TO_STR(polygonOffsetLineEnabled)); + stateDumpStr.append("\n"); + + stateDumpStr.append("GL_POLYGON_OFFSET_POINT........."); + stateDumpStr.append(BOOL_TO_STR(polygonOffsetPointEnabled)); + stateDumpStr.append("\n"); + } +#endif + + stateDumpStr.append("GL_POLYGON_OFFSET_FACTOR........"); + stateDumpStr.append(QString::number(polygonOffsetFactor)); + stateDumpStr.append("\n"); + + stateDumpStr.append("GL_POLYGON_OFFSET_UNITS........."); + stateDumpStr.append(QString::number(polygonOffsetUnits)); + stateDumpStr.append("\n"); + + stateDumpStr.append("GL_CULL_FACE...................."); + stateDumpStr.append(BOOL_TO_STR(isCullFaceEnabled)); + stateDumpStr.append("\n"); + + stateDumpStr.append("GL_CULL_FACE_MODE..............."); + stateDumpStr.append(m_map->lookUp(cullFaceMode)); + stateDumpStr.append("\n"); + + stateDumpStr.append("GL_FRONT_FACE..................."); + stateDumpStr.append(m_map->lookUp(frontFace)); + stateDumpStr.append("\n"); + + stateDumpStr.append("GL_CURRENT_PROGRAM.............."); + stateDumpStr.append(QString::number(currentProgram)); + stateDumpStr.append("\n"); + + stateDumpStr.append("GL_ACTIVE_TEXTURE..............."); + stateDumpStr.append(m_map->lookUp(activeTexture)); + stateDumpStr.append("\n"); + + stateDumpStr.append("GL_TEXTURE_BINDING_2D..........."); + stateDumpStr.append(QString::number(texBinding2D)); + stateDumpStr.append("\n"); + + stateDumpStr.append("GL_ELEMENT_ARRAY_BUFFER_BINDING."); + stateDumpStr.append(QString::number(boundElementArrayBuffer)); + stateDumpStr.append("\n"); + + stateDumpStr.append("GL_ARRAY_BUFFER_BINDING........."); + stateDumpStr.append(QString::number(arrayBufferBinding)); + stateDumpStr.append("\n"); + +#if !defined(QT_OPENGL_ES_2) + if (!m_isOpenGLES2) { + stateDumpStr.append("GL_VERTEX_ARRAY_BINDING........."); + stateDumpStr.append(QString::number(boundVertexArray)); + stateDumpStr.append("\n"); + } +#endif + + if (options && DUMP_VERTEX_ATTRIB_ARRAYS_BIT) { + for (int i = 0; i < m_maxVertexAttribs;i++) { + glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_ENABLED, &vertexAttribArrayEnabledStates[i]); + glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING, &vertexAttribArrayBoundBuffers[i]); + glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_SIZE, &vertexAttribArraySizes[i]); + glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_TYPE, &vertexAttribArrayTypes[i]); + glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_NORMALIZED, &vertexAttribArrayNormalized[i]); + glGetVertexAttribiv(i, GL_VERTEX_ATTRIB_ARRAY_STRIDE, &vertexAttribArrayStrides[i]); + } + + + for (int i = 0; i < m_maxVertexAttribs;i++) { + stateDumpStr.append("GL_VERTEX_ATTRIB_ARRAY_"); + stateDumpStr.append(QString::number(i)); + stateDumpStr.append("\n"); + + stateDumpStr.append("GL_VERTEX_ATTRIB_ARRAY_ENABLED........."); + stateDumpStr.append(BOOL_TO_STR(vertexAttribArrayEnabledStates[i])); + stateDumpStr.append("\n"); + + stateDumpStr.append("GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING.."); + stateDumpStr.append(QString::number(vertexAttribArrayBoundBuffers[i])); + stateDumpStr.append("\n"); + + stateDumpStr.append("GL_VERTEX_ATTRIB_ARRAY_SIZE............"); + stateDumpStr.append(QString::number(vertexAttribArraySizes[i])); + stateDumpStr.append("\n"); + + stateDumpStr.append("GL_VERTEX_ATTRIB_ARRAY_TYPE............"); + stateDumpStr.append(m_map->lookUp(vertexAttribArrayTypes[i])); + stateDumpStr.append("\n"); + + stateDumpStr.append("GL_VERTEX_ATTRIB_ARRAY_NORMALIZED......"); + stateDumpStr.append(QString::number(vertexAttribArrayNormalized[i])); + stateDumpStr.append("\n"); + + stateDumpStr.append("GL_VERTEX_ATTRIB_ARRAY_STRIDE.........."); + stateDumpStr.append(QString::number(vertexAttribArrayStrides[i])); + stateDumpStr.append("\n"); + } + } + + if (options && DUMP_VERTEX_ATTRIB_ARRAYS_BUFFERS_BIT) { + if (boundElementArrayBuffer != 0) { + stateDumpStr.append("GL_ELEMENT_ARRAY_BUFFER................"); + stateDumpStr.append(QString::number(boundElementArrayBuffer)); + stateDumpStr.append("\n"); + + stateDumpStr.append(getGLArrayObjectDump(GL_ELEMENT_ARRAY_BUFFER, + boundElementArrayBuffer, + GL_UNSIGNED_SHORT)); + } + + for (int i = 0; i < m_maxVertexAttribs;i++) { + if (vertexAttribArrayEnabledStates[i]) { + stateDumpStr.append("GL_ARRAY_BUFFER........................"); + stateDumpStr.append(QString::number(vertexAttribArrayBoundBuffers[i])); + stateDumpStr.append("\n"); + + stateDumpStr.append(getGLArrayObjectDump(GL_ARRAY_BUFFER, + vertexAttribArrayBoundBuffers[i], + vertexAttribArrayTypes[i])); + } + } + } + + + delete[] vertexAttribArrayEnabledStates; + delete[] vertexAttribArrayBoundBuffers; + delete[] vertexAttribArraySizes; + delete[] vertexAttribArrayTypes; + delete[] vertexAttribArrayNormalized; + delete[] vertexAttribArrayStrides; + + return stateDumpStr; +} diff --git a/src/canvasglstatedump_p.h b/src/canvasglstatedump_p.h new file mode 100644 index 0000000..70110a7 --- /dev/null +++ b/src/canvasglstatedump_p.h @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). +** Contact: http://www.qt-project.org/legal +** +** This file is part of the QtCanvas3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later 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 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the QtCanvas3D API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. + +#ifndef CANVASGLSTATEDUMP_P_H +#define CANVASGLSTATEDUMP_P_H + +#include "canvas3dcommon_p.h" + +#include <QObject> +#include <QtGui/QOpenGLFunctions> + +#define DUMP_ENUM_AS_PROPERTY(A,B,C) Q_PROPERTY(A::B C READ C ## _read); inline A::B C ## _read() { return A::C; } + +class EnumToStringMap; + +class CanvasGLStateDump : public QObject, protected QOpenGLFunctions +{ + Q_OBJECT + + Q_ENUMS(stateDumpEnums) + +public: + enum stateDumpEnums { + DUMP_BASIC_ONLY = 0x00, + DUMP_VERTEX_ATTRIB_ARRAYS_BIT = 0x01, + DUMP_VERTEX_ATTRIB_ARRAYS_BUFFERS_BIT = 0x02, + DUMP_FULL = 0x03 + }; + + DUMP_ENUM_AS_PROPERTY(CanvasGLStateDump,stateDumpEnums,DUMP_BASIC_ONLY) + DUMP_ENUM_AS_PROPERTY(CanvasGLStateDump,stateDumpEnums,DUMP_VERTEX_ATTRIB_ARRAYS_BIT) + DUMP_ENUM_AS_PROPERTY(CanvasGLStateDump,stateDumpEnums,DUMP_VERTEX_ATTRIB_ARRAYS_BUFFERS_BIT) + DUMP_ENUM_AS_PROPERTY(CanvasGLStateDump,stateDumpEnums,DUMP_FULL) + + CanvasGLStateDump(QOpenGLContext *context, QObject *parent = 0); + ~CanvasGLStateDump(); + + Q_INVOKABLE QString getGLStateDump(stateDumpEnums options = DUMP_BASIC_ONLY); + + QString getGLArrayObjectDump(int target, int arrayObject, int type); + +private: + GLint m_maxVertexAttribs; + EnumToStringMap *m_map; + bool m_isOpenGLES2; +}; + +#endif // CANVASGLSTATEDUMP_P_H diff --git a/src/context3d.cpp b/src/context3d.cpp index 71dd317..2018656 100644 --- a/src/context3d.cpp +++ b/src/context3d.cpp @@ -34,6 +34,7 @@ ** ****************************************************************************/ +#include "canvasglstatedump_p.h" #include "activeinfo3d_p.h" #include "canvas3d_p.h" #include "context3d_p.h" @@ -75,7 +76,6 @@ * \sa Canvas3D */ -// Owned by the SG Render Thread! CanvasContext::CanvasContext(QOpenGLContext *context, QSurface *surface, int width, int height, bool isES2, QObject *parent) : CanvasAbstractObject(parent), @@ -96,7 +96,8 @@ CanvasContext::CanvasContext(QOpenGLContext *context, QSurface *surface, m_map(EnumToStringMap::newInstance()), m_canvas(0), m_maxVertexAttribs(0), - m_isOpenGLES2(isES2) + m_isOpenGLES2(isES2), + m_stateDumpExt(0) { int value = 0; glGetIntegerv(MAX_VERTEX_ATTRIBS, &value); @@ -322,40 +323,6 @@ CanvasShaderPrecisionFormat *CanvasContext::getShaderPrecisionFormat(glEnums sha return format; } -/*! - * \qmlmethod list<variant> Context3D::getSupportedExtensions() - * Returns an array of the extension strings supported by this implementation - */ -/*! - * \internal - */ -QVariantList CanvasContext::getSupportedExtensions() -{ - if (m_logAllCalls) qDebug() << Q_FUNC_INFO; - - // No extensions supported at the moment - return QVariantList(); -} - -/*! - * \qmlmethod variant Context3D::getExtension(string name) - * Returns an object if given \a name matches a supported extension. - * Otherwise returns \c{null}. The returned object may contain constants and/or functions provided - * by the extension, but at minimum a unique object is returned. - * \a name is the case-insensitive name of the extension to be returned. - */ -/*! - * \internal - */ -QVariant CanvasContext::getExtension(const QString &name) -{ - if (m_logAllCalls) qDebug() << "Context3D::" << __FUNCTION__ - << "(name:" << name - << ")"; - - return QVariant(); -} - /*! * \qmlmethod bool Context3D::isContextLost() * Always returns false. @@ -4014,8 +3981,20 @@ void CanvasContext::useProgram(CanvasProgram *program) */ void CanvasContext::clear(glEnums flags) { - if (m_logAllCalls) qDebug() << "Context3D::" << __FUNCTION__ - << "(flags:" << glEnumToString(flags) << ")"; + if (m_logAllCalls) { + QString flagStr; + if (flags && COLOR_BUFFER_BIT != 0) + flagStr.append(" COLOR_BUFFER_BIT "); + + if (flags && DEPTH_BUFFER_BIT != 0) + flagStr.append(" DEPTH_BUFFER_BIT "); + + if (flags && STENCIL_BUFFER_BIT != 0) + flagStr.append(" STENCIL_BUFFER_BIT "); + + qDebug() << "Context3D::" << __FUNCTION__ << "(flags:" << flagStr << ")"; + } + glClear(flags); } @@ -5052,3 +5031,47 @@ QVariant CanvasContext::getUniform(CanvasProgram *program, CanvasUniformLocation return QVariant(); } + +/*! + * \qmlmethod list<variant> Context3D::getSupportedExtensions() + * Returns an array of the extension strings supported by this implementation + */ +/*! + * \internal + */ +QVariantList CanvasContext::getSupportedExtensions() +{ + if (m_logAllCalls) qDebug() << Q_FUNC_INFO; + + // No extensions supported at the moment + QVariantList list; + list.append(QVariant::fromValue(QStringLiteral(QT_CANVAS3D_GL_STATE_DUMP_EXT_NAME))); + return list; +} + +/*! + * \qmlmethod variant Context3D::getExtension(string name) + * \return object if given \a name matches a supported extension. + * Otherwise returns \c{null}. The returned object may contain constants and/or functions provided + * by the extension, but at minimum a unique object is returned. + * Case-insensitive \a name of the extension to be returned. + */ +/*! + * \internal + */ +QVariant CanvasContext::getExtension(const QString &name) +{ + if (m_logAllCalls) qDebug() << "Context3D::" << __FUNCTION__ + << "(name:" << name + << ")"; + + QString upperCaseName = name.toUpper(); + + if (upperCaseName == QStringLiteral(QT_CANVAS3D_GL_STATE_DUMP_EXT_NAME).toUpper()) { + if (!m_stateDumpExt) + m_stateDumpExt = new CanvasGLStateDump(m_context, this); + return QVariant::fromValue(m_stateDumpExt); + } + + return QVariant(QVariant::Int); +} diff --git a/src/context3d_p.h b/src/context3d_p.h index a18207b..411dc3d 100644 --- a/src/context3d_p.h +++ b/src/context3d_p.h @@ -50,6 +50,7 @@ #include "canvas3dcommon_p.h" #include "contextattributes_p.h" #include "abstractobject3d_p.h" +#include "canvasglstatedump_p.h" #include <QtGui/QOpenGLFunctions> #include <QString> @@ -95,9 +96,6 @@ class QT_CANVAS3D_EXPORT CanvasContext : public CanvasAbstractObject, protected Q_PROPERTY(uint drawingBufferWidth READ drawingBufferWidth NOTIFY drawingBufferWidthChanged) Q_PROPERTY(uint drawingBufferHeight READ drawingBufferHeight NOTIFY drawingBufferHeightChanged) - Q_PROPERTY(bool logAllCalls READ logAllCalls WRITE setLogAllCalls NOTIFY logAllCallsChanged) - Q_PROPERTY(bool logAllErrors READ logAllErrors WRITE setLogAllErrors NOTIFY logAllErrorsChanged) - public: enum glEnums { /* ClearBufferMask */ @@ -1232,6 +1230,9 @@ private: uint m_maxVertexAttribs; float **m_vertexAttribPointers; bool m_isOpenGLES2; + + // EXTENSIONS + CanvasGLStateDump *m_stateDumpExt; }; #endif // CONTEXT3D_P_H diff --git a/src/contextattributes.cpp b/src/contextattributes.cpp index a6a11e0..e2f4ffa 100644 --- a/src/contextattributes.cpp +++ b/src/contextattributes.cpp @@ -46,7 +46,7 @@ * \brief Attribute set for Context3D * * ContextAttributes is an attribute set that can be given as parameter on first call to - * Canvas3D object's \l{Canvas3D::getContext()}{getContext(string type, ContextAttributes options)} + * Canvas3D object's \l{Canvas3D::getContext}{getContext(string type, ContextAttributes options)} * method call. It can also be requested from the Context3D later on to verify what exact * attributes are in fact enabled/disabled in the created context. * diff --git a/src/plugins.qmltypes b/src/plugins.qmltypes index d93efa6..e96591e 100644 --- a/src/plugins.qmltypes +++ b/src/plugins.qmltypes @@ -462,8 +462,6 @@ Module { Property { name: "canvas"; type: "Canvas"; isReadonly: true; isPointer: true } Property { name: "drawingBufferWidth"; type: "uint"; isReadonly: true } Property { name: "drawingBufferHeight"; type: "uint"; isReadonly: true } - Property { name: "logAllCalls"; type: "bool" } - Property { name: "logAllErrors"; type: "bool" } Property { name: "DEPTH_BUFFER_BIT"; type: "CanvasContext::glEnums"; isReadonly: true } Property { name: "STENCIL_BUFFER_BIT"; type: "CanvasContext::glEnums"; isReadonly: true } Property { name: "COLOR_BUFFER_BIT"; type: "CanvasContext::glEnums"; isReadonly: true } @@ -1837,6 +1835,44 @@ Module { isCreatable: false exportMetaObjectRevisions: [0] } + Component { + name: "CanvasGLStateDump" + prototype: "QObject" + exports: ["QtCanvas3D/GLStateDumpExt 1.0"] + isCreatable: false + exportMetaObjectRevisions: [0] + Enum { + name: "stateDumpEnums" + values: { + "DUMP_BASIC_ONLY_BIT": 0, + "DUMP_VERTEX_ATTRIB_ARRAYS_BIT": 1, + "DUMP_VERTEX_ATTRIB_ARRAYS_CONTENTS_BIT": 2, + "DUMP_FULL": 3 + } + } + Property { + name: "DUMP_BASIC_ONLY_BIT" + type: "CanvasGLStateDump::stateDumpEnums" + isReadonly: true + } + Property { + name: "DUMP_VERTEX_ATTRIB_ARRAYS_BIT" + type: "CanvasGLStateDump::stateDumpEnums" + isReadonly: true + } + Property { + name: "DUMP_VERTEX_ATTRIB_ARRAYS_CONTENTS_BIT" + type: "CanvasGLStateDump::stateDumpEnums" + isReadonly: true + } + Property { name: "DUMP_FULL"; type: "CanvasGLStateDump::stateDumpEnums"; isReadonly: true } + Method { + name: "getGLStateDump" + type: "string" + Parameter { name: "options"; type: "stateDumpEnums" } + } + Method { name: "getGLStateDump"; type: "string" } + } Component { name: "CanvasInt16Array" prototype: "CanvasTypedArray" diff --git a/src/qcanvas3d_plugin.cpp b/src/qcanvas3d_plugin.cpp index 703af02..56d79b1 100644 --- a/src/qcanvas3d_plugin.cpp +++ b/src/qcanvas3d_plugin.cpp @@ -148,6 +148,12 @@ void QtCanvas3DPlugin::registerTypes(const char *uri) 1, 0, "UniformLocation", QLatin1String("Trying to create uncreatable: UniformLocation, use Context3D.getUniformLocation() instead.")); + + // EXTENSIONS + qmlRegisterUncreatableType<CanvasGLStateDump>(uri, + 1, 0, + "GLStateDumpExt", + QLatin1String("Trying to create uncreatable: GLStateDumpExt, use Context3D.getExtension(\"" QT_CANVAS3D_GL_STATE_DUMP_EXT_NAME "\") instead.")); } diff --git a/src/qcanvas3d_plugin.h b/src/qcanvas3d_plugin.h index 3cd0e9e..2bda1e7 100644 --- a/src/qcanvas3d_plugin.h +++ b/src/qcanvas3d_plugin.h @@ -63,6 +63,7 @@ #include "renderbuffer3d_p.h" #include "shaderprecisionformat_p.h" #include "activeinfo3d_p.h" +#include "canvasglstatedump_p.h" #include <QQmlExtensionPlugin> @@ -96,6 +97,8 @@ QML_DECLARE_TYPE(CanvasFrameBuffer) QML_DECLARE_TYPE(CanvasRenderBuffer) QML_DECLARE_TYPE(CanvasShaderPrecisionFormat) QML_DECLARE_TYPE(CanvasActiveInfo) +QML_DECLARE_TYPE(CanvasGLStateDump) + class QtCanvas3DPlugin : public QQmlExtensionPlugin { Q_OBJECT diff --git a/src/src.pro b/src/src.pro index 5231741..1f842d5 100644 --- a/src/src.pro +++ b/src/src.pro @@ -45,7 +45,8 @@ SOURCES += qcanvas3d_plugin.cpp \ teximage3d.cpp \ texture3d.cpp \ uniformlocation.cpp \ - activeinfo3d.cpp + activeinfo3d.cpp \ + canvasglstatedump.cpp HEADERS += qcanvas3d_plugin.h \ arraybuffer_p.h \ @@ -79,7 +80,8 @@ HEADERS += qcanvas3d_plugin.h \ teximage3d_p.h \ texture3d_p.h \ uniformlocation_p.h \ - activeinfo3d_p.h + activeinfo3d_p.h \ + canvasglstatedump_p.h OTHER_FILES = qmldir \ doc/* \ diff --git a/src/texture3d.cpp b/src/texture3d.cpp index 1a482db..69db079 100644 --- a/src/texture3d.cpp +++ b/src/texture3d.cpp @@ -81,7 +81,7 @@ void CanvasTexture::bind(CanvasContext::glEnums target) /*! * \internal */ -GLuint CanvasTexture::textureId() +GLuint CanvasTexture::textureId() const { if (!m_isAlive) return 0; @@ -92,7 +92,7 @@ GLuint CanvasTexture::textureId() /*! * \internal */ -bool CanvasTexture::isAlive() +bool CanvasTexture::isAlive() const { return bool(m_textureId); } @@ -113,7 +113,7 @@ void CanvasTexture::del() QDebug operator<<(QDebug dbg, const CanvasTexture *texture) { if (texture) - dbg.nospace() << "Texture3D("<< ((void*) texture) << ", name:" << texture->name() << ")"; + dbg.nospace() << "Texture3D("<< ((void*) texture) << ", name:" << texture->name() << ", id:" << texture->textureId() << ")"; else dbg.nospace() << "Texture3D("<< ((void*) texture) <<")"; return dbg.maybeSpace(); diff --git a/src/texture3d_p.h b/src/texture3d_p.h index 6c821b1..f328685 100644 --- a/src/texture3d_p.h +++ b/src/texture3d_p.h @@ -64,8 +64,8 @@ public: void bind(CanvasContext::glEnums target); void del(); - bool isAlive(); - GLuint textureId(); + bool isAlive() const; + GLuint textureId() const; friend QDebug operator<< (QDebug d, const CanvasTexture *texture); -- GitLab