| /*------------------------------------------------------------------------- |
| * drawElements Quality Program OpenGL ES Utilities |
| * ------------------------------------------------ |
| * |
| * Copyright 2014 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| * |
| */ |
| 'use strict'; |
| goog.provide('functional.gles3.es3fLifetimeTests'); |
| goog.require('framework.common.tcuSurface'); |
| goog.require('framework.common.tcuTestCase'); |
| goog.require('framework.delibs.debase.deRandom'); |
| goog.require('framework.opengl.gluShaderProgram'); |
| goog.require('modules.shared.glsLifetimeTests'); |
| goog.require('modules.shared.glsTextureTestUtil'); |
| |
| goog.scope(function() { |
| var es3fLifetimeTests = functional.gles3.es3fLifetimeTests; |
| var glsLifetimeTests = modules.shared.glsLifetimeTests; |
| var gluShaderProgram = framework.opengl.gluShaderProgram; |
| var deRandom = framework.delibs.debase.deRandom; |
| var tcuSurface = framework.common.tcuSurface; |
| var glsTextureTestUtil = modules.shared.glsTextureTestUtil; |
| var tcuTestCase = framework.common.tcuTestCase; |
| |
| /** @const */ var VIEWPORT_SIZE = 128; |
| /** @const */ var NUM_COMPONENTS = 4; |
| /** @const */ var NUM_VERTICES = 3; |
| |
| /** @type {WebGL2RenderingContext} */ var gl; |
| |
| var setParentClass = function(child, parent) { |
| child.prototype = Object.create(parent.prototype); |
| child.prototype.constructor = child; |
| }; |
| |
| /** |
| * @constructor |
| * @extends {gluShaderProgram.ShaderProgram} |
| */ |
| es3fLifetimeTests.ScaleProgram = function() { |
| gluShaderProgram.ShaderProgram.call(this, gl, this.getSources()); |
| assertMsgOptions(this.isOk(), 'Program creation failed', false, true); |
| this.m_scaleLoc = gl.getUniformLocation(this.getProgram(), 'scale'); |
| this.m_posLoc = gl.getAttribLocation(this.getProgram(), 'pos'); |
| }; |
| |
| setParentClass(es3fLifetimeTests.ScaleProgram, gluShaderProgram.ShaderProgram); |
| |
| /** |
| * @param {WebGLVertexArrayObject} vao |
| * @param {number} scale |
| * @param {boolean} tf |
| * @param {tcuSurface.Surface} dst |
| */ |
| es3fLifetimeTests.ScaleProgram.prototype.draw = function(vao, scale, tf, dst) { |
| es3fLifetimeTests.ScaleProgram.seed = es3fLifetimeTests.ScaleProgram.seed || 0; |
| ++es3fLifetimeTests.ScaleProgram.seed; |
| |
| var viewport = new glsTextureTestUtil.RandomViewport(document.getElementById('canvas'), VIEWPORT_SIZE, VIEWPORT_SIZE, es3fLifetimeTests.ScaleProgram.seed); |
| gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height); |
| gl.clearColor(0, 0, 0, 1); |
| gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); |
| |
| gl.bindVertexArray(vao); |
| gl.enableVertexAttribArray(this.m_posLoc); |
| gl.useProgram(this.getProgram()); |
| |
| gl.uniform1f(this.m_scaleLoc, scale); |
| |
| if (tf) |
| gl.beginTransformFeedback(gl.TRIANGLES); |
| gl.drawArrays(gl.TRIANGLES, 0, 3); |
| if (tf) |
| gl.endTransformFeedback(); |
| |
| if (dst) |
| glsLifetimeTests.readRectangle(viewport, dst); |
| |
| gl.bindVertexArray(null); |
| |
| }; |
| |
| /** |
| * @param {WebGLBuffer} buffer |
| * @param {WebGLVertexArrayObject} vao |
| */ |
| es3fLifetimeTests.ScaleProgram.prototype.setPos = function(buffer, vao) { |
| gl.bindBuffer(gl.ARRAY_BUFFER, buffer); |
| gl.bindVertexArray(vao); |
| gl.vertexAttribPointer(this.m_posLoc, NUM_COMPONENTS, gl.FLOAT, false, 0, 0); |
| gl.bindVertexArray(null); |
| gl.bindBuffer(gl.ARRAY_BUFFER, null); |
| }; |
| |
| /** |
| * @private |
| */ |
| es3fLifetimeTests.ScaleProgram.prototype.getSources = function() { |
| /** @const */ var s_vertexShaderSrc = |
| '#version 100\n' + |
| 'attribute vec4 pos;\n' + |
| 'uniform float scale;\n' + |
| 'void main ()\n' + |
| '{\n' + |
| ' gl_Position = vec4(scale * pos.xy, pos.zw);\n' + |
| '}'; |
| |
| /** @const */ var s_fragmentShaderSrc = |
| '#version 100\n' + |
| 'void main ()\n' + |
| '{\n' + |
| ' gl_FragColor = vec4(1.0, 0.0, 1.0, 1.0);\n' + |
| '}'; |
| var sources = new gluShaderProgram.ProgramSources(); |
| sources.add(new gluShaderProgram.VertexSource(s_vertexShaderSrc)); |
| sources.add(new gluShaderProgram.FragmentSource(s_fragmentShaderSrc)); |
| sources.add(new gluShaderProgram.TransformFeedbackMode(gl.INTERLEAVED_ATTRIBS)); |
| sources.add(new gluShaderProgram.TransformFeedbackVarying('gl_Position')); |
| return sources; |
| }; |
| |
| /** |
| * @constructor |
| * @extends {glsLifetimeTests.SimpleBinder} |
| */ |
| es3fLifetimeTests.VertexArrayBinder = function() { |
| glsLifetimeTests.SimpleBinder.call(this, null, gl.NONE, gl.VERTEX_ARRAY_BINDING); |
| }; |
| |
| setParentClass(es3fLifetimeTests.VertexArrayBinder, glsLifetimeTests.SimpleBinder); |
| |
| es3fLifetimeTests.VertexArrayBinder.prototype.bind = function(obj) { |
| var vao = /** @type {WebGLVertexArrayObject} */ (obj); |
| gl.bindVertexArray(vao); |
| }; |
| |
| /** |
| * @constructor |
| * @extends {glsLifetimeTests.Binder} |
| */ |
| es3fLifetimeTests.SamplerBinder = function() { |
| glsLifetimeTests.Binder.call(this); |
| }; |
| |
| setParentClass(es3fLifetimeTests.SamplerBinder, glsLifetimeTests.Binder); |
| |
| es3fLifetimeTests.SamplerBinder.prototype.bind = function(obj) { |
| var sampler = /** @type {WebGLSampler} */ (obj); |
| gl.bindSampler(0, sampler); |
| }; |
| es3fLifetimeTests.SamplerBinder.prototype.getBinding = function() { return /** @type {WebGLSampler} */ (gl.getParameter(gl.SAMPLER_BINDING)); }; |
| |
| /** |
| * @constructor |
| * @extends {glsLifetimeTests.Binder} |
| */ |
| es3fLifetimeTests.QueryBinder = function() { |
| glsLifetimeTests.Binder.call(this); |
| }; |
| |
| setParentClass(es3fLifetimeTests.QueryBinder, glsLifetimeTests.Binder); |
| |
| es3fLifetimeTests.QueryBinder.prototype.bind = function(obj) { |
| var query = /** @type {WebGLQuery} */ (obj); |
| if (query) |
| gl.beginQuery(gl.ANY_SAMPLES_PASSED, query); |
| else |
| gl.endQuery(gl.ANY_SAMPLES_PASSED); |
| }; |
| |
| es3fLifetimeTests.QueryBinder.prototype.getBinding = function() { return null; }; |
| |
| /** |
| * @constructor |
| * @extends {glsLifetimeTests.Attacher} |
| * @param {glsLifetimeTests.Type} elementType |
| * @param {glsLifetimeTests.Type} varrType |
| * @param {es3fLifetimeTests.ScaleProgram} program |
| */ |
| es3fLifetimeTests.BufferVAOAttacher = function(elementType, varrType, program) { |
| glsLifetimeTests.Attacher.call(this, elementType, varrType); |
| this.m_program = program; |
| }; |
| |
| setParentClass(es3fLifetimeTests.BufferVAOAttacher, glsLifetimeTests.Attacher); |
| |
| /** |
| * @return {es3fLifetimeTests.ScaleProgram} |
| */ |
| es3fLifetimeTests.BufferVAOAttacher.prototype.getProgram = function() { return this.m_program; }; |
| |
| /** |
| * @param {number} seed |
| * @param {number} usage |
| * @param {WebGLBuffer} buffer |
| */ |
| es3fLifetimeTests.initBuffer = function(seed, usage, buffer) { |
| /** @const */ var s_varrData = [ |
| -1.0, 0.0, 0.0, 1.0, |
| 1.0, 1.0, 0.0, 1.0, |
| 0.0, -1.0, 0.0, 1.0 |
| ]; |
| gl.bindBuffer(gl.ARRAY_BUFFER, buffer); |
| if (seed == 0) |
| gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(s_varrData), usage); |
| else { |
| var rnd = new deRandom.Random(seed); |
| var data = []; |
| |
| for (var ndx = 0; ndx < NUM_VERTICES; ndx++) { |
| data.push(2 * (rnd.getFloat() - 0.5)); |
| data.push(2 * (rnd.getFloat() - 0.5)); |
| data.push(0); |
| data.push(1); |
| } |
| gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(data), usage); |
| } |
| gl.bindBuffer(gl.ARRAY_BUFFER, null); |
| }; |
| |
| es3fLifetimeTests.BufferVAOAttacher.prototype.initAttachment = function(seed, obj) { |
| var buffer = /** @type {WebGLBuffer} */ (obj); |
| es3fLifetimeTests.initBuffer(seed, gl.STATIC_DRAW, buffer); |
| bufferedLogToConsole('Initialized buffer ' + buffer + ' from seed ' + seed); |
| }; |
| |
| es3fLifetimeTests.BufferVAOAttacher.prototype.attach = function(element, target) { |
| var buffer = /** @type {WebGLBuffer} */ (element); |
| var vao = /** @type {WebGLVertexArrayObject} */ (target); |
| |
| this.m_program.setPos(buffer, vao); |
| bufferedLogToConsole('Set the `pos` attribute in VAO ' + vao + ' to buffer ' + buffer); |
| }; |
| |
| es3fLifetimeTests.BufferVAOAttacher.prototype.detach = function(element, target) { |
| var vao = /** @type {WebGLVertexArrayObject} */ (target); |
| this.attach(null, vao); |
| }; |
| |
| es3fLifetimeTests.BufferVAOAttacher.prototype.getAttachment = function(target) { |
| var vao = /** @type {WebGLVertexArrayObject} */ (target); |
| gl.bindVertexArray(vao); |
| var name = gl.getVertexAttrib(this.m_posLoc, gl.VERTEX_ATTRIB_ARRAY_BUFFER_BINDING); |
| gl.bindVertexArray(null); |
| return name; |
| }; |
| |
| /** |
| * @constructor |
| * @extends {glsLifetimeTests.InputAttacher} |
| * @param {es3fLifetimeTests.BufferVAOAttacher} attacher |
| */ |
| es3fLifetimeTests.BufferVAOInputAttacher = function(attacher) { |
| glsLifetimeTests.InputAttacher.call(this, attacher); |
| this.m_program = attacher.getProgram(); |
| }; |
| |
| setParentClass(es3fLifetimeTests.BufferVAOInputAttacher, glsLifetimeTests.InputAttacher); |
| |
| es3fLifetimeTests.BufferVAOInputAttacher.prototype.drawContainer = function(obj, dst) { |
| var vao = /** @type {WebGLVertexArrayObject} */ (obj); |
| this.m_program.draw(vao, 1.0, false, dst); |
| bufferedLogToConsole('Drew an output image with VAO ' + vao); |
| }; |
| |
| /** |
| * @constructor |
| * @extends {glsLifetimeTests.Attacher} |
| * @param {glsLifetimeTests.Type} elementType |
| * @param {glsLifetimeTests.Type} tfType |
| */ |
| es3fLifetimeTests.BufferTfAttacher = function(elementType, tfType) { |
| glsLifetimeTests.Attacher.call(this, elementType, tfType); |
| }; |
| |
| setParentClass(es3fLifetimeTests.BufferTfAttacher, glsLifetimeTests.Attacher); |
| |
| es3fLifetimeTests.BufferTfAttacher.prototype.initAttachment = function(seed, obj) { |
| var buffer = /** @type {WebGLBuffer} */ (obj); |
| es3fLifetimeTests.initBuffer(seed, gl.DYNAMIC_READ, buffer); |
| bufferedLogToConsole('Initialized buffer ' + buffer + ' from seed ' + seed); |
| }; |
| |
| es3fLifetimeTests.BufferTfAttacher.prototype.attach = function(element, target) { |
| var buffer = /** @type {WebGLBuffer} */ (element); |
| var tf = /** @type {WebGLTransformFeedback} */ (target); |
| gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf); |
| gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, buffer); |
| gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null); |
| }; |
| |
| es3fLifetimeTests.BufferTfAttacher.prototype.detach = function(element, target) { |
| var buffer = /** @type {WebGLBuffer} */ (element); |
| var tf = /** @type {WebGLTransformFeedback} */ (target); |
| gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf); |
| gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, null); |
| gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null); |
| |
| }; |
| |
| es3fLifetimeTests.BufferTfAttacher.prototype.getAttachment = function(target) { |
| var tf = /** @type {WebGLTransformFeedback} */ (target); |
| gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf); |
| var name = gl.getIndexedParameter(gl.TRANSFORM_FEEDBACK_BUFFER_BINDING, 0); |
| gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null); |
| return name; |
| }; |
| |
| /** |
| * @constructor |
| * @extends {glsLifetimeTests.OutputAttacher} |
| */ |
| es3fLifetimeTests.BufferTfOutputAttacher = function(attacher, program) { |
| glsLifetimeTests.OutputAttacher.call(this, attacher); |
| this.m_program = program; |
| }; |
| |
| setParentClass(es3fLifetimeTests.BufferTfOutputAttacher, glsLifetimeTests.OutputAttacher); |
| |
| es3fLifetimeTests.BufferTfOutputAttacher.prototype.setupContainer = function(seed, obj) { |
| var tf = /** @type {WebGLTransformFeedback} */ (obj); |
| var posBuf = gl.createBuffer(); |
| var vao = gl.createVertexArray(); |
| |
| es3fLifetimeTests.initBuffer(seed, gl.STATIC_DRAW, posBuf); |
| this.m_program.setPos(posBuf, vao); |
| |
| gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf); |
| this.m_program.draw(vao, -1.0, true, null); |
| bufferedLogToConsole('Drew an image with seed ' + seed + ' with transform feedback to ' + tf); |
| gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, null); |
| gl.deleteVertexArray(vao); |
| gl.deleteBuffer(posBuf); |
| }; |
| |
| es3fLifetimeTests.BufferTfOutputAttacher.prototype.drawAttachment = function(buffer, dst) { |
| var vao = gl.createVertexArray(); |
| |
| this.m_program.setPos(buffer, vao); |
| this.m_program.draw(vao, 1.0, false, dst); |
| bufferedLogToConsole('Drew output image with vertices from buffer ' + buffer); |
| gl.deleteVertexArray(vao); |
| }; |
| |
| /** |
| * @constructor |
| * @extends {glsLifetimeTests.ES2Types} |
| */ |
| es3fLifetimeTests.ES3Types = function() { |
| glsLifetimeTests.ES2Types.call(this); |
| this.m_program = new es3fLifetimeTests.ScaleProgram(); |
| this.m_queryBind = new es3fLifetimeTests.QueryBinder(); |
| this.m_queryType = new glsLifetimeTests.SimpleType('query', gl.createQuery, gl.deleteQuery, gl.isQuery, this.m_queryBind); |
| this.m_tfBind = new glsLifetimeTests.SimpleBinder(gl.bindTransformFeedback, gl.TRANSFORM_FEEDBACK, |
| gl.TRANSFORM_FEEDBACK_BINDING); |
| this.m_tfType = new glsLifetimeTests.SimpleType('transform_feedback', gl.createTransformFeedback, gl.deleteTransformFeedback, gl.isTransformFeedback, this.m_tfBind); |
| this.m_varrBind = new es3fLifetimeTests.VertexArrayBinder(); |
| this.m_varrType = new glsLifetimeTests.SimpleType('vertex_array', gl.createVertexArray, gl.deleteVertexArray, gl.isVertexArray, this.m_varrBind); |
| this.m_samplerBind = new es3fLifetimeTests.SamplerBinder(); |
| this.m_samplerType = new glsLifetimeTests.SimpleType('sampler', gl.createSampler, gl.deleteSampler, gl.isSampler, this.m_samplerBind, true); |
| this.m_bufVarrAtt = new es3fLifetimeTests.BufferVAOAttacher(this.m_bufferType, this.m_varrType, this.m_program); |
| this.m_bufVarrInAtt = new es3fLifetimeTests.BufferVAOInputAttacher(this.m_bufVarrAtt); |
| this.m_bufTfAtt = new es3fLifetimeTests.BufferTfAttacher(this.m_bufferType, this.m_tfType); |
| this.m_bufTfOutAtt = new es3fLifetimeTests.BufferTfOutputAttacher(this.m_bufTfAtt, this.m_program); |
| |
| this.m_types.push(this.m_queryType, this.m_tfType, this.m_varrType, this.m_samplerType); |
| this.m_attachers.push(this.m_bufVarrAtt, this.m_bufTfAtt); |
| this.m_inAttachers.push(this.m_bufVarrInAtt); |
| this.m_outAttachers.push(this.m_bufTfOutAtt); |
| }; |
| |
| setParentClass(es3fLifetimeTests.ES3Types, glsLifetimeTests.ES2Types); |
| |
| /** |
| * @constructor |
| * @extends {tcuTestCase.DeqpTest} |
| */ |
| es3fLifetimeTests.TfDeleteActiveTest = function(name, description) { |
| tcuTestCase.DeqpTest.call(this, name, description); |
| }; |
| |
| setParentClass(es3fLifetimeTests.TfDeleteActiveTest, tcuTestCase.DeqpTest); |
| |
| es3fLifetimeTests.TfDeleteActiveTest.prototype.iterate = function() { |
| /** @const */ var s_xfbVertexSource = |
| '#version 300 es\n' + |
| 'void main ()\n' + |
| '{\n' + |
| ' gl_Position = vec4(float(gl_VertexID) / 2.0, float(gl_VertexID % 2) / 2.0, 0.0, 1.0);\n' + |
| '}\n'; |
| |
| /** @const */ var s_xfbFragmentSource = |
| '#version 300 es\n' + |
| 'layout(location=0) out mediump vec4 dEQP_FragColor;\n' + |
| 'void main (void)\n' + |
| '{\n' + |
| ' dEQP_FragColor = vec4(1.0, 1.0, 0.0, 1.0);\n' + |
| '}\n'; |
| var buf = gl.createBuffer(); |
| |
| var sources = new gluShaderProgram.ProgramSources(); |
| sources.add(new gluShaderProgram.VertexSource(s_xfbVertexSource)); |
| sources.add(new gluShaderProgram.FragmentSource(s_xfbFragmentSource)); |
| sources.add(new gluShaderProgram.TransformFeedbackMode(gl.SEPARATE_ATTRIBS)); |
| sources.add(new gluShaderProgram.TransformFeedbackVarying('gl_Position')); |
| var program = new gluShaderProgram.ShaderProgram(gl, sources); |
| if (!program.isOk()) { |
| bufferedLogToConsole(program.getProgramInfo().infoLog); |
| testFailedOptions('failed to build program', true); |
| } |
| gl.useProgram(program.getProgram()); |
| |
| var tf = gl.createTransformFeedback(); |
| gl.bindTransformFeedback(gl.TRANSFORM_FEEDBACK, tf); |
| gl.bindBufferBase(gl.TRANSFORM_FEEDBACK_BUFFER, 0, buf); |
| gl.bufferData(gl.TRANSFORM_FEEDBACK_BUFFER, 48, gl.STATIC_DRAW); |
| |
| gl.beginTransformFeedback(gl.TRIANGLES); |
| var errCode = gl.NONE; |
| gl.deleteTransformFeedback(tf); |
| errCode = gl.getError(); |
| assertMsgOptions(errCode == gl.INVALID_OPERATION, |
| 'Deleting active transform feedback must produce INVALID_OPERATION', false, true); |
| gl.endTransformFeedback(); |
| gl.deleteTransformFeedback(tf); |
| testPassed(); |
| return tcuTestCase.IterateResult.STOP; |
| }; |
| |
| es3fLifetimeTests.genTestCases = function() { |
| var state = tcuTestCase.runner; |
| state.setRoot(tcuTestCase.newTest('lifetime', 'Top level')); |
| |
| var types = new es3fLifetimeTests.ES3Types(); |
| glsLifetimeTests.addTestCases(state.testCases, types); |
| /* TODO: Add TfDeleteActiveTest test */ |
| var deleteActiveGroup = tcuTestCase.newTest('delete_active', 'Delete active object'); |
| state.testCases.addChild(deleteActiveGroup); |
| deleteActiveGroup.addChild( |
| new es3fLifetimeTests.TfDeleteActiveTest('transform_feedback', 'Transform Feedback')); |
| }; |
| |
| /** |
| * Create and execute the test cases |
| */ |
| es3fLifetimeTests.run = function(context) { |
| gl = context; |
| try { |
| es3fLifetimeTests.genTestCases(); |
| tcuTestCase.runner.runCallback(tcuTestCase.runTestCases); |
| } catch (err) { |
| bufferedLogToConsole(err); |
| tcuTestCase.runner.terminate(); |
| } |
| |
| }; |
| |
| }); |