diff --git a/tests/auto/qmltest/canvas3d/tst_render_checkresult.js b/tests/auto/qmltest/canvas3d/tst_render_checkresult.js new file mode 100644 index 0000000000000000000000000000000000000000..c2d52af08d7815be69ac135f749dc9e75f1a3d3c --- /dev/null +++ b/tests/auto/qmltest/canvas3d/tst_render_checkresult.js @@ -0,0 +1,256 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtCanvas3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/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$ +** +****************************************************************************/ + +Qt.include("../../../../3rdparty/gl-matrix.js") + +var gl; + +var mvMatrix = mat4.create(); +var pMatrix = mat4.create(); + +var colorBuffer; +var texture = null; + +var pMatrixUniform; +var mvMatrixUniform; + +var vertexPositionAttribute; +var textureCoordAttribute; +var vertexColorAttribute; + +var colorFlagUniform; + +function initGL(canvas) { + gl = canvas.getContext(""); + gl.pixelStorei(gl.UNPACK_FLIP_Y_WEBGL, true); + var pixelRatio = canvas.devicePixelRatio; + gl.viewport(0, 0, pixelRatio * canvas.width, pixelRatio * canvas.height); + gl.clearColor(1.0, 0.0, 0.0, 1.0); + + initShaders(); + initBuffers(); + + mat4.perspective(pMatrix, degToRad(45), canvas.width / canvas.height, 0.1, 500.0); + gl.uniformMatrix4fv(pMatrixUniform, false, pMatrix); + mat4.identity(mvMatrix); + mat4.translate(mvMatrix, mvMatrix, [0, 0, -5]); + gl.uniformMatrix4fv(mvMatrixUniform, false, mvMatrix); + + gl.uniform1i(colorFlagUniform, 1); +} + +function renderGL() { + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0); +} + +function renderGL(x, y) { + gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); + gl.drawElements(gl.TRIANGLES, 6, gl.UNSIGNED_SHORT, 0); + return checkPixel(x, y); +} + +function checkPixel(x, y) { + var pixels = new Uint8Array(4); + gl.readPixels(x, y, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, pixels); + return pixels; +} + +function setTexture(canvas, image) { + if (image) { + gl.uniform1i(colorFlagUniform, 0); + var texImage = TextureImageFactory.newTexImage(); + texImage.src = image; + texImage.imageLoaded.connect(function() { + canvas.textureLoaded = true + texture = gl.createTexture(); + gl.bindTexture(gl.TEXTURE_2D, texture); + gl.texImage2D(gl.TEXTURE_2D, + 0, + gl.RGBA, + gl.RGBA, + gl.UNSIGNED_BYTE, + texImage); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST); + gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST); + }); + texImage.imageLoadingFailed.connect(function() { + console.log("Texture load FAILED, "+texImage.errorString); + }); + } else { + gl.uniform1i(colorFlagUniform, 1); + // TODO: Take into use once QTBUG-44834 is fixed +// if (texture) +// gl.deleteTexture(texture); + // TODO: Remove once QTBUG-44834 is fixed + if (texture) + delete texture; + texture = null; + gl.bindTexture(gl.TEXTURE_2D, 0); + } +} + +function setColor(r, g, b, a) { + gl.bindTexture(gl.TEXTURE_2D, 0); + gl.uniform1i(colorFlagUniform, 1); + + gl.bindBuffer(gl.ARRAY_BUFFER, colorBuffer); + var colors = [r / 255.0, g / 255.0, b / 255.0, a / 255.0]; + var generatedColors = []; + for (var i = 0; i < 4; i++) + generatedColors = generatedColors.concat(colors); + gl.bufferData(gl.ARRAY_BUFFER, + new Float32Array(generatedColors), + gl.STATIC_DRAW); + gl.enableVertexAttribArray(vertexColorAttribute); + gl.vertexAttribPointer(vertexColorAttribute, 4, gl.FLOAT, false, 0, 0); +} + +function initBuffers() +{ + var vertexBuffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer); + gl.bufferData(gl.ARRAY_BUFFER, + new Float32Array([-1.0, -1.0, 1.0, + 1.0, -1.0, 1.0, + 1.0, 1.0, 1.0, + -1.0, 1.0, 1.0]), + gl.STATIC_DRAW); + gl.enableVertexAttribArray(vertexPositionAttribute); + gl.vertexAttribPointer(vertexPositionAttribute, 3, gl.FLOAT, false, 0, 0); + + colorBuffer = gl.createBuffer(); + setColor(0.0, 0.0, 255.0, 255.0); + + var uvBuffer = gl.createBuffer(); + gl.bindBuffer(gl.ARRAY_BUFFER, uvBuffer); + gl.bufferData(gl.ARRAY_BUFFER, + new Float32Array([1.0, 0.0, + 0.0, 0.0, + 0.0, 1.0, + 1.0, 1.0]), + gl.STATIC_DRAW); + gl.enableVertexAttribArray(textureCoordAttribute); + gl.vertexAttribPointer(textureCoordAttribute, 2, gl.FLOAT, false, 0, 0); + + var indexBuffer = gl.createBuffer(); + gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, indexBuffer); + gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, + new Uint16Array([0, 1, 2, + 0, 2, 3]), + gl.STATIC_DRAW); +} + +function initShaders() +{ + var vertexShader = getShader( + gl, + "attribute highp vec3 aVertexPosition; \ + attribute mediump vec4 aVertexColor; \ + attribute highp vec2 aTextureCoord; \ + uniform mat4 uMVMatrix; \ + uniform mat4 uPMatrix; \ + varying mediump vec4 vColor; \ + varying highp vec2 vTextureCoord; \ + void main(void) { \ + gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition, 1.0); \ + vColor = aVertexColor; \ + vTextureCoord = aTextureCoord; \ + }", + gl.VERTEX_SHADER); + var fragmentShader = getShader( + gl, + "varying mediump vec4 vColor; \ + varying highp vec2 vTextureCoord; \ + uniform sampler2D uSampler; \ + uniform bool justColor; \ + void main(void) { \ + if (justColor) \ + gl_FragColor = vColor; \ + else \ + gl_FragColor = texture2D(uSampler, vec2(vTextureCoord.s, vTextureCoord.t)); \ + }", + gl.FRAGMENT_SHADER); + + var shaderProgram = gl.createProgram(); + gl.attachShader(shaderProgram, vertexShader); + gl.attachShader(shaderProgram, fragmentShader); + gl.linkProgram(shaderProgram); + gl.deleteShader(vertexShader); + gl.deleteShader(fragmentShader); + + if (!gl.getProgramParameter(shaderProgram, gl.LINK_STATUS)) { + console.log("Could not initialize shaders"); + console.log(gl.getProgramInfoLog(shaderProgram)); + } + + gl.useProgram(shaderProgram); + + vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition"); + gl.enableVertexAttribArray(vertexPositionAttribute); + vertexColorAttribute = gl.getAttribLocation(shaderProgram, "aVertexColor"); + gl.enableVertexAttribArray(vertexColorAttribute); + textureCoordAttribute = gl.getAttribLocation(shaderProgram, "aTextureCoord"); + gl.enableVertexAttribArray(textureCoordAttribute); + + pMatrixUniform = gl.getUniformLocation(shaderProgram, "uPMatrix"); + mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix"); + + var textureSamplerUniform = gl.getUniformLocation(shaderProgram, "uSampler") + gl.activeTexture(gl.TEXTURE0); + gl.bindTexture(gl.TEXTURE_2D, texture); + gl.uniform1i(textureSamplerUniform, 0); + + colorFlagUniform = gl.getUniformLocation(shaderProgram, "justColor") +} + +function getShader(gl, str, type) { + var shader = gl.createShader(type); + gl.shaderSource(shader, str); + gl.compileShader(shader); + + if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { + console.log("JS:Shader compile failed"); + console.log(gl.getShaderInfoLog(shader)); + return null; + } + + return shader; +} + +function degToRad(degrees) { + return degrees * Math.PI / 180; +} diff --git a/tests/auto/qmltest/canvas3d/tst_render_checkresult.png b/tests/auto/qmltest/canvas3d/tst_render_checkresult.png new file mode 100644 index 0000000000000000000000000000000000000000..df71b45cecd613c13d829b54cd76da1deb122024 Binary files /dev/null and b/tests/auto/qmltest/canvas3d/tst_render_checkresult.png differ diff --git a/tests/auto/qmltest/canvas3d/tst_render_checkresult.qml b/tests/auto/qmltest/canvas3d/tst_render_checkresult.qml new file mode 100644 index 0000000000000000000000000000000000000000..7638a11eae003df32bec506cf13323c6451e4ad4 --- /dev/null +++ b/tests/auto/qmltest/canvas3d/tst_render_checkresult.qml @@ -0,0 +1,158 @@ +/**************************************************************************** +** +** Copyright (C) 2015 The Qt Company Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the QtCanvas3D module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** 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 The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/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$ +** +****************************************************************************/ + +import QtQuick 2.2 +import QtCanvas3D 1.0 +import QtTest 1.0 + +import "tst_render_checkresult.js" as Content + +Item { + id: top + height: 300 + width: 300 + + property bool checkResult: false + property int xpos: 0 + property int ypos: 0 + property var pixels + property int red: -1 + property int green: -1 + property int blue: -1 + property int alpha: -1 + property bool renderOk: false + + Canvas3D { + id: render_check_result + property bool textureLoaded: false + anchors.fill: parent + onInitGL: Content.initGL(this) + onRenderGL: { + if (checkResult) { + pixels = Content.renderGL(xpos, ypos) + red = pixels[0] + green = pixels[1] + blue = pixels[2] + alpha = pixels[3] + delete pixels + } else { + Content.renderGL() + red = -1 + green = -1 + blue = -1 + alpha = -1 + } + renderOk = true + } + } + + TestCase { + name: "Canvas3D_render_checkresult" + when: windowShown + + function test_render_1_checkresult() { + // Check color in the center of the blue square + xpos = 150 + ypos = 150 + checkResult = true + renderOk = false + waitForRendering(render_check_result) + tryCompare(top, "renderOk", true) + tryCompare(top, "red", 0x00) + tryCompare(top, "green", 0x00) + tryCompare(top, "blue", 0xff) + tryCompare(top, "alpha", 0xff) + checkResult = false + + waitForRendering(render_check_result) + + // Check color in the corner of the screen, which is cleared with red + xpos = 0 + ypos = 0 + checkResult = true + renderOk = false + waitForRendering(render_check_result) + tryCompare(top, "renderOk", true) + tryCompare(top, "red", 0xff) + tryCompare(top, "green", 0x00) + tryCompare(top, "blue", 0x00) + tryCompare(top, "alpha", 0xff) + checkResult = false + + waitForRendering(render_check_result) + } + + function test_render_2_checkresult() { + // Set a solid color texture, and check that the color matches in the center + waitForRendering(render_check_result) + Content.setTexture(render_check_result, "tst_render_checkresult.png") + xpos = 150 + ypos = 150 + checkResult = true + renderOk = false + waitForRendering(render_check_result) + tryCompare(top, "renderOk", true) + tryCompare(render_check_result, "textureLoaded", true, 10000) + tryCompare(top, "red", 0xff) + tryCompare(top, "green", 0x99) + tryCompare(top, "blue", 0x22) + tryCompare(top, "alpha", 0xff) + checkResult = false + Content.setTexture() + + waitForRendering(render_check_result) + } + + function test_render_3_checkresult() { + // Set a partially transparent color, and check it + waitForRendering(render_check_result) + Content.setColor(0x22, 0x99, 0xff, 0x80) + xpos = 150 + ypos = 150 + checkResult = true + renderOk = false + waitForRendering(render_check_result) + tryCompare(top, "renderOk", true) + tryCompare(top, "red", 0x22) + tryCompare(top, "green", 0x99) + tryCompare(top, "blue", 0xff) + tryCompare(top, "alpha", 0x80) + checkResult = false + + waitForRendering(render_check_result) + } + } +} diff --git a/tests/auto/qmltest/qmltest.pro b/tests/auto/qmltest/qmltest.pro index 43098a63eb6afb778bf579d0702ca38a1eb23c5d..b33e5c8c56537636b409201233f6937c235a4149 100644 --- a/tests/auto/qmltest/qmltest.pro +++ b/tests/auto/qmltest/qmltest.pro @@ -7,5 +7,5 @@ CONFIG += console SOURCES += tst_qmltest.cpp -OTHER_FILES += canvas3d/tst_*.qml canvas3d/tst_*.js +OTHER_FILES += canvas3d/tst_*.qml canvas3d/*.js canvas3d/*.png DEFINES += QUICK_TEST_SOURCE_DIR=\"\\\"$$PWD/canvas3d\\\"\"