/*------------------------------------------------------------------------- * 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.es3fFboRenderTest'); goog.require('framework.common.tcuImageCompare'); goog.require('framework.common.tcuLogImage'); goog.require('framework.common.tcuPixelFormat'); goog.require('framework.common.tcuRGBA'); goog.require('framework.common.tcuSurface'); goog.require('framework.common.tcuTestCase'); goog.require('framework.common.tcuTexture'); goog.require('framework.common.tcuTextureUtil'); goog.require('framework.delibs.debase.deMath'); goog.require('framework.delibs.debase.deRandom'); goog.require('framework.delibs.debase.deString'); goog.require('framework.delibs.debase.deUtil'); goog.require('framework.opengl.gluShaderUtil'); goog.require('framework.opengl.gluTextureUtil'); goog.require('framework.opengl.simplereference.sglrGLContext'); goog.require('framework.opengl.simplereference.sglrReferenceContext'); goog.require('framework.referencerenderer.rrUtil'); goog.require('functional.gles3.es3fFboTestUtil'); goog.scope(function() { var es3fFboRenderTest = functional.gles3.es3fFboRenderTest; var es3fFboTestUtil = functional.gles3.es3fFboTestUtil; var gluShaderUtil = framework.opengl.gluShaderUtil; var gluTextureUtil = framework.opengl.gluTextureUtil; var tcuImageCompare = framework.common.tcuImageCompare; var tcuLogImage = framework.common.tcuLogImage; var tcuPixelFormat = framework.common.tcuPixelFormat; var tcuRGBA = framework.common.tcuRGBA; var tcuTestCase = framework.common.tcuTestCase; var tcuSurface = framework.common.tcuSurface; var tcuTexture = framework.common.tcuTexture; var tcuTextureUtil = framework.common.tcuTextureUtil; var deMath = framework.delibs.debase.deMath; var deRandom = framework.delibs.debase.deRandom; var deString = framework.delibs.debase.deString; var deUtil = framework.delibs.debase.deUtil; var sglrGLContext = framework.opengl.simplereference.sglrGLContext; var sglrReferenceContext = framework.opengl.simplereference.sglrReferenceContext; var rrUtil = framework.referencerenderer.rrUtil; /** @type {WebGL2RenderingContext} */ var gl; /** * @constructor * @param {number=} buffers_ * @param {number=} colorType_ * @param {number=} colorFormat_ * @param {number=} depthStencilType_ * @param {number=} depthStencilFormat_ * @param {number=} width_ * @param {number=} height_ * @param {number=} samples_ */ es3fFboRenderTest.FboConfig = function( buffers_, colorType_, colorFormat_, depthStencilType_, depthStencilFormat_, width_, height_, samples_ ) { // Buffer bit mask (gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT|...) this.buffers = buffers_ ? buffers_ : 0; // gl.TEXTURE_2D, gl.TEXTURE_CUBE_MAP, gl.RENDERBUFFER this.colorType = colorType_ ? colorType_ : gl.NONE; // Internal format for color buffer texture or renderbuffer this.colorFormat = colorFormat_ ? colorFormat_ : gl.NONE; this.depthStencilType = depthStencilType_? depthStencilType_ : gl.NONE; this.depthStencilFormat = depthStencilFormat_ ? depthStencilFormat_ : gl.NONE; this.width = width_ ? width_ : 0; this.height = height_ ? height_ : 0; this.samples = samples_? samples_ : 0; }; /** * @param {number} type * @return {string} */ es3fFboRenderTest.getTypeName = function(type) { switch (type) { case gl.TEXTURE_2D: return 'tex2d'; case gl.RENDERBUFFER: return 'rbo'; default: testFailed('Unknown type'); } return 'Should not get to this point'; }; /** * @return {string} */ es3fFboRenderTest.FboConfig.prototype.getName = function() { var name = ''; assertMsgOptions((this.buffers & gl.COLOR_BUFFER_BIT) != 0, 'Color buffer is not specified', false, true); name += es3fFboRenderTest.getTypeName(this.colorType) + '_' + es3fFboTestUtil.getFormatName(this.colorFormat); if (this.buffers & gl.DEPTH_BUFFER_BIT) name += '_depth'; if (this.buffers & gl.STENCIL_BUFFER_BIT) name += '_stencil'; if (this.buffers & (gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT)) name += '_' + es3fFboRenderTest.getTypeName(this.depthStencilType) + '_' + es3fFboTestUtil.getFormatName(this.depthStencilFormat); return name; }; /** * @param {number} format * @return {Array} */ es3fFboRenderTest.getEnablingExtensions = function(format) { /** @type {Array} */ var out = []; switch (format) { case gl.RGB16F: assertMsgOptions(false, "Not part of the tested formats", false, true); break; case gl.RGBA16F: case gl.RG16F: case gl.R16F: case gl.RGBA32F: case gl.RGB32F: case gl.R11F_G11F_B10F: case gl.RG32F: case gl.R32F: out.push('EXT_color_buffer_float'); default: break; } return out; }; /** * @param {?sglrGLContext.GLContext|sglrReferenceContext.ReferenceContext} * context * @param {string} name * @return {*} */ es3fFboRenderTest.isExtensionSupported = function(context, name) { return context.getExtension(name); }; /** * @param {?sglrGLContext.GLContext|sglrReferenceContext.ReferenceContext} * context * @param {Array} requiredExts * @return {boolean} */ es3fFboRenderTest.isAnyExtensionSupported = function( context, requiredExts) { if (!requiredExts || requiredExts.length == 0) return true; for (var extNdx = 0; extNdx < requiredExts.length; extNdx++) { var extension = requiredExts[extNdx]; if (es3fFboRenderTest.isExtensionSupported(context, extension)) return true; } return false; }; /** * @param {Array} list * @param {string} sep * @return {string} */ es3fFboRenderTest.join = function(list, sep) { var out = ''; for (var elemNdx = 0; elemNdx < list.length; elemNdx++) { if (elemNdx != 0) out += sep; out += list[elemNdx]; } return out; }; /** * @param {?sglrGLContext.GLContext|sglrReferenceContext.ReferenceContext} * context * @param {number} sizedFormat */ es3fFboRenderTest.checkColorFormatSupport = function(context, sizedFormat) { /** @type {Array} */ var requiredExts = es3fFboRenderTest.getEnablingExtensions(sizedFormat); if (!es3fFboRenderTest.isAnyExtensionSupported(context, requiredExts)) { var errMsg = 'Format not supported, requires ' + ( (requiredExts.length == 1) ? requiredExts[0] : ' one of the following: ' + requiredExts.join(', ') ); checkMessage(false, errMsg); throw new TestFailedException(errMsg); } }; /** * @constructor * @param {?sglrGLContext.GLContext|sglrReferenceContext.ReferenceContext} * context * @param {es3fFboRenderTest.FboConfig} config * @param {number} width * @param {number} height * @param {sglrReferenceContext.AnyFramebuffer=} fbo * @param {sglrReferenceContext.AnyRenderbuffer=} colorBufferName * @param {sglrReferenceContext.AnyRenderbuffer=} depthStencilBufferName */ es3fFboRenderTest.Framebuffer = function( context, config, width, height, fbo, colorBufferName, depthStencilBufferName) { this.m_config = config; this.m_context = context; this.m_framebuffer = fbo ? fbo : null; this.m_colorBuffer = colorBufferName ? colorBufferName : null; this.m_depthStencilBuffer = depthStencilBufferName ? depthStencilBufferName : null; // Verify that color format is supported es3fFboRenderTest.checkColorFormatSupport(context, config.colorFormat); if (!this.m_framebuffer) this.m_framebuffer = context.createFramebuffer(); context.bindFramebuffer(gl.FRAMEBUFFER, this.m_framebuffer); if (this.m_config.buffers & (gl.COLOR_BUFFER_BIT)) { switch (this.m_config.colorType) { case gl.TEXTURE_2D: this.m_colorBuffer = this.createTex2D( /** @type {WebGLTexture} */ (colorBufferName), this.m_config.colorFormat, width, height ); context.framebufferTexture2D( gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, this.m_colorBuffer, 0 ); break; case gl.RENDERBUFFER: this.m_colorBuffer = this.createRbo( /** @type {WebGLRenderbuffer} */ (colorBufferName), this.m_config.colorFormat, width, height ); context.framebufferRenderbuffer( gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, this.m_colorBuffer ); break; default: testFailed('Unsupported type'); } } if (this.m_config.buffers & (gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT)) { switch (this.m_config.depthStencilType) { case gl.TEXTURE_2D: this.m_depthStencilBuffer = this.createTex2D( /** @type {WebGLTexture} */ (depthStencilBufferName), this.m_config.depthStencilFormat, width, height ); break; case gl.RENDERBUFFER: this.m_depthStencilBuffer = this.createRbo( /** @type {WebGLRenderbuffer} */ (depthStencilBufferName), this.m_config.depthStencilFormat, width, height ); break; default: testFailed('Unsupported type'); } } for (var ndx = 0; ndx < 2; ndx++) { var bit = ndx ? gl.STENCIL_BUFFER_BIT : gl.DEPTH_BUFFER_BIT; var point = ndx ? gl.STENCIL_ATTACHMENT : gl.DEPTH_ATTACHMENT; if ((this.m_config.buffers & bit) == 0) continue; /* Not used. */ switch (this.m_config.depthStencilType) { case gl.TEXTURE_2D: context.framebufferTexture2D( gl.FRAMEBUFFER, point, gl.TEXTURE_2D, this.m_depthStencilBuffer, 0 ); break; case gl.RENDERBUFFER: context.framebufferRenderbuffer( gl.FRAMEBUFFER, point, gl.RENDERBUFFER, this.m_depthStencilBuffer ); break; default: throw new Error('Invalid depth stencil type'); } } context.bindFramebuffer(gl.FRAMEBUFFER, null); }; /** * @return {es3fFboRenderTest.FboConfig} */ es3fFboRenderTest.Framebuffer.prototype.getConfig = function() { return this.m_config; }; /** * @return {?sglrReferenceContext.AnyFramebuffer} */ es3fFboRenderTest.Framebuffer.prototype.getFramebuffer = function() { return this.m_framebuffer; }; /** * @return {?sglrReferenceContext.AnyRenderbuffer} */ es3fFboRenderTest.Framebuffer.prototype.getColorBuffer = function() { return this.m_colorBuffer; }; /** * @return {?sglrReferenceContext.AnyRenderbuffer} */ es3fFboRenderTest.Framebuffer.prototype.getDepthStencilBuffer = function() { return this.m_depthStencilBuffer; }; /** * deinit */ es3fFboRenderTest.Framebuffer.prototype.deinit = function() { this.m_context.deleteFramebuffer( /** @type {WebGLFramebuffer} */ (this.m_framebuffer) ); this.destroyBuffer(this.m_colorBuffer, this.m_config.colorType); this.destroyBuffer( this.m_depthStencilBuffer, this.m_config.depthStencilType ); }; /** * checkCompleteness */ es3fFboRenderTest.Framebuffer.prototype.checkCompleteness = function() { this.m_context.bindFramebuffer(gl.FRAMEBUFFER, this.m_framebuffer); var status = this.m_context.checkFramebufferStatus(gl.FRAMEBUFFER); this.m_context.bindFramebuffer(gl.FRAMEBUFFER, null); if (status != gl.FRAMEBUFFER_COMPLETE) throw new es3fFboTestUtil.FboIncompleteException(status); }; /** * @param {?WebGLTexture|sglrReferenceContext.TextureContainer} name * @param {number} format * @param {number} width * @param {number} height * @return {?WebGLTexture|sglrReferenceContext.TextureContainer} */ es3fFboRenderTest.Framebuffer.prototype.createTex2D = function( name, format, width, height) { if (!name) name = this.m_context.createTexture(); this.m_context.bindTexture(gl.TEXTURE_2D, name); this.m_context.texImage2DDelegate( gl.TEXTURE_2D, 0, format, width, height ); if (!deMath.deIsPowerOfTwo32(width) || !deMath.deIsPowerOfTwo32(height)) { // Set wrap mode to clamp for NPOT FBOs this.m_context.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE ); this.m_context.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE ); } this.m_context.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST ); this.m_context.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST ); return name; }; /** * @param {?WebGLRenderbuffer|sglrReferenceContext.Renderbuffer} name * @param {number} format * @param {number} width * @param {number} height * @return {?WebGLRenderbuffer|sglrReferenceContext.Renderbuffer} */ es3fFboRenderTest.Framebuffer.prototype.createRbo = function( name, format, width, height) { if (!name) name = this.m_context.createRenderbuffer(); this.m_context.bindRenderbuffer(gl.RENDERBUFFER, name); this.m_context.renderbufferStorage( gl.RENDERBUFFER, format, width, height ); return name; }; /** * @param {?sglrReferenceContext.AnyRenderbuffer} name * @param {number} type */ es3fFboRenderTest.Framebuffer.prototype.destroyBuffer = function( name, type) { if (type == gl.TEXTURE_2D || type == gl.TEXTURE_CUBE_MAP) this.m_context.deleteTexture(/** @type {?WebGLTexture} */ (name)); else if (type == gl.RENDERBUFFER) this.m_context.deleteRenderbuffer( /** @type {?WebGLRenderbuffer} */ (name) ); else assertMsgOptions( type == gl.NONE, 'Invalid buffer type', false, true ); }; /** * @param {?sglrGLContext.GLContext|sglrReferenceContext.ReferenceContext} * context * @param {WebGLTexture|sglrReferenceContext.TextureContainer} name * @param {number} format * @param {number} dataType * @param {number} width * @param {number} height */ es3fFboRenderTest.createMetaballsTex2D = function( context, name, format, dataType, width, height) { /** @type {tcuTexture.TextureFormat} */ var texFormat = gluTextureUtil.mapGLTransferFormat(format, dataType); /** @type {tcuTexture.TextureLevel} */ var level = new tcuTexture.TextureLevel(texFormat, width, height); tcuTextureUtil.fillWithMetaballs( level.getAccess(), 5, /*name ^*/ width ^ height ); context.bindTexture(gl.TEXTURE_2D, name); context.texImage2D( gl.TEXTURE_2D, 0, format, width, height, 0, format, dataType, level.getAccess().getDataPtr() ); context.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); }; /** * @param {?sglrGLContext.GLContext|sglrReferenceContext.ReferenceContext} * context * @param {WebGLTexture|sglrReferenceContext.TextureContainer} name * @param {number} format * @param {number} dataType * @param {number} width * @param {number} height */ es3fFboRenderTest.createQuadsTex2D = function( context, name, format, dataType, width, height) { /** @type {tcuTexture.TextureFormat} */ var texFormat = gluTextureUtil.mapGLTransferFormat(format, dataType); /** @type {tcuTexture.TextureLevel} */ var level = new tcuTexture.TextureLevel(texFormat, width, height); tcuTextureUtil.fillWithRGBAQuads(level.getAccess()); context.bindTexture(gl.TEXTURE_2D, name); context.texImage2D( gl.TEXTURE_2D, 0, format, width, height, 0, format, dataType, level.getAccess().getDataPtr() ); context.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR); }; /** * @constructor * @extends {tcuTestCase.DeqpTest} * @param {string} name * @param {string} description * @param {es3fFboRenderTest.FboConfig} config */ es3fFboRenderTest.FboRenderCase = function(name, description, config) { tcuTestCase.DeqpTest.call(this, name, description); this.m_config = config; }; es3fFboRenderTest.FboRenderCase.prototype = Object.create(tcuTestCase.DeqpTest.prototype); es3fFboRenderTest.FboRenderCase.prototype.constructor = es3fFboRenderTest.FboRenderCase; /** * Must be overridden * @param {?sglrGLContext.GLContext|sglrReferenceContext.ReferenceContext} * fboContext * @param {tcuSurface.Surface} dst */ es3fFboRenderTest.FboRenderCase.prototype.render = function( fboContext, dst) { throw new Error('Must override'); }; /** * @return {tcuTestCase.IterateResult} */ es3fFboRenderTest.FboRenderCase.prototype.iterate = function() { var clearColor = [0.125, 0.25, 0.5, 1.0]; /** @type {?string} */ var failReason = ""; // Position & size for context var rnd = new deRandom.deRandom(); deRandom.deRandom_init(rnd, deString.deStringHash(this.fullName())); var width = Math.min(gl.canvas.width, 128); var height = Math.min(gl.canvas.height, 128); var xMax = gl.canvas.width - width + 1; var yMax = gl.canvas.height - height + 1; var x = Math.abs(deRandom.deRandom_getInt(rnd)) % xMax; var y = Math.abs(deRandom.deRandom_getInt(rnd)) % yMax; /** @type {tcuSurface.Surface} */ var gles3Frame = new tcuSurface.Surface(width, height); /** @type {tcuSurface.Surface} */ var refFrame = new tcuSurface.Surface(width, height); /** @type {number} */ var gles3Error = 0; /** @type {number} */ var refError = 0; // Render using GLES3 /** * @type {sglrGLContext.GLContext| * sglrReferenceContext.ReferenceContext} */ var context; try { context = new sglrGLContext.GLContext(gl, [x, y, width, height]); context.clearColor( clearColor[0], clearColor[1], clearColor[2], clearColor[3] ); context.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT ); this.render(context, gles3Frame); // Call actual render func gles3Error = context.getError(); } catch (e) { if (e instanceof es3fFboTestUtil.FboIncompleteException) { e.message = WebGLTestUtils.glEnumToString(gl, e.getReason()); if(e.getReason() == gl.FRAMEBUFFER_UNSUPPORTED) { // Mark test case as unsupported bufferedLogToConsole(e + ': ' + e.message); testFailed('Not supported'); return tcuTestCase.IterateResult.STOP; } } // Propagate error throw e; } // Render reference image /** @type {sglrReferenceContext.ReferenceContextBuffers} */ var buffers = new sglrReferenceContext.ReferenceContextBuffers( new tcuPixelFormat.PixelFormat( 8, 8, 8, gl.getParameter(gl.ALPHA_BITS) ? 8 : 0 ), /** @type {number} */ (gl.getParameter(gl.DEPTH_BITS)), /** @type {number} */ (gl.getParameter(gl.STENCIL_BITS)), width, height ); context = new sglrReferenceContext.ReferenceContext( new sglrReferenceContext.ReferenceContextLimits(gl), buffers.getColorbuffer(), buffers.getDepthbuffer(), buffers.getStencilbuffer() ); context.clearColor( clearColor[0], clearColor[1], clearColor[2], clearColor[3] ); context.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT ); this.render(context, refFrame); refError = context.getError(); // Compare error codes var errorCodesOk = (gles3Error == refError); if (!errorCodesOk) { bufferedLogToConsole ( 'Error code mismatch: got ' + WebGLTestUtils.glEnumToString(gl, gles3Error) + ', expected ' + WebGLTestUtils.glEnumToString(gl, refError) ); failReason = 'Got unexpected error'; } // Compare images var imagesOk = this.compare(refFrame, gles3Frame); if (!imagesOk && !failReason) failReason = 'Image comparison failed'; // Store test result var isOk = errorCodesOk && imagesOk; assertMsgOptions(isOk, failReason, true, true); return tcuTestCase.IterateResult.STOP; }; /** * @param {tcuSurface.Surface} reference * @param {tcuSurface.Surface} result * @return {boolean} */ es3fFboRenderTest.FboRenderCase.prototype.compare = function( reference, result) { var threshold = new tcuRGBA.RGBA( /* TODO: tcu::max(getFormatThreshold(this.m_config.colorFormat),*/ [12, 12, 12, 12] ); return tcuImageCompare.bilinearCompare( 'ComparisonResult', 'Image comparison result', reference.getAccess(), result.getAccess(), threshold, tcuImageCompare.CompareLogMode.RESULT ); }; /** * deinit */ es3fFboRenderTest.FboRenderCase.prototype.deinit = function() { gl.clearColor(0.0, 0.0, 0.0, 0.0); gl.clearDepth(1.0); gl.clearStencil(0); gl.disable(gl.STENCIL_TEST); gl.disable(gl.DEPTH_TEST); gl.disable(gl.BLEND); gl.bindFramebuffer(gl.FRAMEBUFFER, null); gl.bindRenderbuffer(gl.RENDERBUFFER, null); }; // FboCases /** * @constructor * @extends {es3fFboRenderTest.FboRenderCase} * @param {es3fFboRenderTest.FboConfig} config */ es3fFboRenderTest.StencilClearsTest = function(config) { es3fFboRenderTest.FboRenderCase.call( this, config.getName(), 'Stencil clears', config ); }; es3fFboRenderTest.StencilClearsTest.prototype = Object.create(es3fFboRenderTest.FboRenderCase.prototype); es3fFboRenderTest.StencilClearsTest.prototype.constructor = es3fFboRenderTest.StencilClearsTest; /** * @param {?sglrGLContext.GLContext|sglrReferenceContext.ReferenceContext} * context * @param {tcuSurface.Surface} dst */ es3fFboRenderTest.StencilClearsTest.prototype.render = function( context, dst) { /** @type {tcuTexture.TextureFormat} */ var colorFormat = gluTextureUtil.mapGLInternalFormat( this.m_config.colorFormat ); /** @type {gluShaderUtil.DataType} */ var fboSamplerType = /** @type {gluShaderUtil.DataType} */ ( gluTextureUtil.getSampler2DType(colorFormat) ); /** @type {gluShaderUtil.DataType} */ var fboOutputType = es3fFboTestUtil.getFragmentOutputType(colorFormat); /** @type {tcuTextureUtil.TextureFormatInfo} */ var fboRangeInfo = tcuTextureUtil.getTextureFormatInfo(colorFormat); var fboOutScale = deMath.subtract( fboRangeInfo.valueMax, fboRangeInfo.valueMin ); var fboOutBias = fboRangeInfo.valueMin; /** @type {es3fFboTestUtil.Texture2DShader} */ var texToFboShader = new es3fFboTestUtil.Texture2DShader( [gluShaderUtil.DataType.SAMPLER_2D], fboOutputType ); /** @type {es3fFboTestUtil.Texture2DShader} */ var texFromFboShader = new es3fFboTestUtil.Texture2DShader( [fboSamplerType], gluShaderUtil.DataType.FLOAT_VEC4); /** @type {number} */ var texToFboShaderID = context.createProgram(texToFboShader); /** @type {number} */ var texFromFboShaderID = context.createProgram(texFromFboShader); /** @type {?WebGLTexture|sglrReferenceContext.TextureContainer} */ var metaballsTex = context.createTexture(); /** @type {?WebGLTexture|sglrReferenceContext.TextureContainer} */ var quadsTex = context.createTexture(); /** @type {number} */ var width = 128; /** @type {number} */ var height = 128; texToFboShader.setOutScaleBias(fboOutScale, fboOutBias); texFromFboShader.setTexScaleBias( 0, fboRangeInfo.lookupScale, fboRangeInfo.lookupBias ); es3fFboRenderTest.createQuadsTex2D( context, quadsTex, gl.RGBA, gl.UNSIGNED_BYTE, width, height ); es3fFboRenderTest.createMetaballsTex2D( context, metaballsTex, gl.RGBA, gl.UNSIGNED_BYTE, width, height ); /** @type {es3fFboRenderTest.Framebuffer} */ var fbo = new es3fFboRenderTest.Framebuffer( context, this.m_config, width, height ); fbo.checkCompleteness(); // Bind framebuffer and clear context.bindFramebuffer(gl.FRAMEBUFFER, fbo.getFramebuffer()); context.viewport(0, 0, width, height); context.clearColor(0.0, 0.0, 0.0, 1.0); context.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT ); // Do stencil clears context.enable(gl.SCISSOR_TEST); context.scissor(10, 16, 32, 120); context.clearStencil(1); context.clear(gl.STENCIL_BUFFER_BIT); context.scissor(16, 32, 100, 64); context.clearStencil(2); context.clear(gl.STENCIL_BUFFER_BIT); context.disable(gl.SCISSOR_TEST); // Draw 2 textures with stecil tests context.enable(gl.STENCIL_TEST); context.bindTexture(gl.TEXTURE_2D, quadsTex); context.stencilFunc(gl.EQUAL, 1, 0xff); texToFboShader.setUniforms(context, texToFboShaderID); rrUtil.drawQuad( context, texToFboShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0] ); context.bindTexture(gl.TEXTURE_2D, metaballsTex); context.stencilFunc(gl.EQUAL, 2, 0xff); texToFboShader.setUniforms(context, texToFboShaderID); rrUtil.drawQuad( context, texToFboShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0] ); context.disable(gl.STENCIL_TEST); if (fbo.getConfig().colorType == gl.TEXTURE_2D) { context.bindFramebuffer(gl.FRAMEBUFFER, null); context.bindTexture(gl.TEXTURE_2D, fbo.getColorBuffer()); context.viewport(0, 0, context.getWidth(), context.getHeight()); texFromFboShader.setUniforms(context, texFromFboShaderID); rrUtil.drawQuad( context, texFromFboShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0] ); dst.readViewport( context, [0, 0, context.getWidth(), context.getHeight()] ); } else es3fFboTestUtil.readPixels( context, dst, 0, 0, width, height, colorFormat, fboRangeInfo.lookupScale, fboRangeInfo.lookupBias ); }; /** * @constructor * @extends {es3fFboRenderTest.FboRenderCase} * @param {es3fFboRenderTest.FboConfig} config */ es3fFboRenderTest.SharedColorbufferTest = function(config) { es3fFboRenderTest.FboRenderCase.call( this, config.getName(), 'Shared colorbuffer', config ); }; es3fFboRenderTest.SharedColorbufferTest.prototype = Object.create(es3fFboRenderTest.FboRenderCase.prototype); es3fFboRenderTest.SharedColorbufferTest.prototype.constructor = es3fFboRenderTest.SharedColorbufferTest; /** * @param {?sglrGLContext.GLContext|sglrReferenceContext.ReferenceContext} * context * @param {tcuSurface.Surface} dst */ es3fFboRenderTest.SharedColorbufferTest.prototype.render = function( context, dst) { /** @type {es3fFboTestUtil.Texture2DShader} */ var texShader = new es3fFboTestUtil.Texture2DShader( [gluShaderUtil.DataType.SAMPLER_2D], gluShaderUtil.DataType.FLOAT_VEC4 ); /** @type {es3fFboTestUtil.FlatColorShader} */ var flatShader = new es3fFboTestUtil.FlatColorShader( gluShaderUtil.DataType.FLOAT_VEC4 ); /** @type {number} */ var texShaderID = context.createProgram(texShader); /** @type {number} */ var flatShaderID = context.createProgram(flatShader); /** @type {number} */ var width = 128; /** @type {number} */ var height = 128; /** @type {?WebGLTexture|sglrReferenceContext.TextureContainer} */ var quadsTex = context.createTexture(); /** @type {?WebGLTexture|sglrReferenceContext.TextureContainer} */ var metaballsTex = context.createTexture(); /** @type {boolean} */ var stencil = (this.m_config.buffers & gl.STENCIL_BUFFER_BIT) != 0; context.disable(gl.DITHER); // Textures es3fFboRenderTest.createQuadsTex2D( context, quadsTex, gl.RGB, gl.UNSIGNED_BYTE, 64, 64 ); es3fFboRenderTest.createMetaballsTex2D( context, metaballsTex, gl.RGBA, gl.UNSIGNED_BYTE, 64, 64 ); context.viewport(0, 0, width, height); // Fbo A /** @type {es3fFboRenderTest.Framebuffer} */ var fboA = new es3fFboRenderTest.Framebuffer( context, this.m_config, width, height ); fboA.checkCompleteness(); // Fbo B - don't create colorbuffer /** @type {es3fFboRenderTest.FboConfig} */ var cfg = /** @type {es3fFboRenderTest.FboConfig} */ (deUtil.clone(this.m_config)); cfg.buffers = deMath.binaryOp( cfg.buffers, deMath.binaryNot(gl.COLOR_BUFFER_BIT), deMath.BinaryOp.AND ); cfg.colorType = gl.NONE; cfg.colorFormat = gl.NONE; /** @type {es3fFboRenderTest.Framebuffer} */ var fboB = new es3fFboRenderTest.Framebuffer( context, cfg, width, height ); // Attach color buffer from fbo A context.bindFramebuffer(gl.FRAMEBUFFER, fboB.getFramebuffer()); switch (this.m_config.colorType) { case gl.TEXTURE_2D: context.framebufferTexture2D( gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, fboA.getColorBuffer(), 0 ); break; case gl.RENDERBUFFER: context.framebufferRenderbuffer( gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, fboA.getColorBuffer() ); break; default: throw new Error('Invalid color type'); } // Clear depth and stencil in fbo B context.clear(gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT); // Render quads to fbo 1, with depth 0.0 context.bindFramebuffer(gl.FRAMEBUFFER, fboA.getFramebuffer()); context.bindTexture(gl.TEXTURE_2D, quadsTex); context.clearColor(0.0, 0.0, 0.0, 1.0); context.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT ); if (stencil) { // Stencil to 1 in fbo A context.clearStencil(1); context.clear(gl.STENCIL_BUFFER_BIT); } texShader.setUniforms(context, texShaderID); context.enable(gl.DEPTH_TEST); rrUtil.drawQuad( context, texShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0] ); context.disable(gl.DEPTH_TEST); // Blend metaballs to fbo 2 context.bindFramebuffer(gl.FRAMEBUFFER, fboB.getFramebuffer()); context.bindTexture(gl.TEXTURE_2D, metaballsTex); context.enable(gl.BLEND); context.blendFuncSeparate( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ZERO, gl.ONE ); rrUtil.drawQuad( context, texShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0] ); // Render small quad that is only visible if depth buffer // is not shared with fbo A - or there is no depth bits context.bindTexture(gl.TEXTURE_2D, quadsTex); context.enable(gl.DEPTH_TEST); rrUtil.drawQuad(context, texShaderID, [0.5, 0.5, 0.5], [1.0, 1.0, 0.5]); context.disable(gl.DEPTH_TEST); if (stencil) { flatShader.setColor(context, flatShaderID, [0.0, 1.0, 0.0, 1.0]); // Clear subset of stencil buffer to 1 context.enable(gl.SCISSOR_TEST); context.scissor(10, 10, 12, 25); context.clearStencil(1); context.clear(gl.STENCIL_BUFFER_BIT); context.disable(gl.SCISSOR_TEST); // Render quad with stencil mask == 1 context.enable(gl.STENCIL_TEST); context.stencilFunc(gl.EQUAL, 1, 0xff); rrUtil.drawQuad( context, flatShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0] ); context.disable(gl.STENCIL_TEST); } // Get results if (fboA.getConfig().colorType == gl.TEXTURE_2D) { texShader.setUniforms(context, texShaderID); context.bindFramebuffer(gl.FRAMEBUFFER, null); context.bindTexture(gl.TEXTURE_2D, fboA.getColorBuffer()); context.viewport(0, 0, context.getWidth(), context.getHeight()); rrUtil.drawQuad( context, texShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0] ); dst.readViewport( context, [0, 0, context.getWidth(), context.getHeight()] ); } else es3fFboTestUtil.readPixels( context, dst, 0, 0, width, height, gluTextureUtil.mapGLInternalFormat( fboA.getConfig().colorFormat ), [1.0, 1.0, 1.0, 1.0], [0.0, 0.0, 0.0, 0.0] ); }; /** * @constructor * @extends {es3fFboRenderTest.FboRenderCase} * @param {es3fFboRenderTest.FboConfig} config */ es3fFboRenderTest.SharedColorbufferClearsTest = function(config) { es3fFboRenderTest.FboRenderCase.call( this, config.getName(), 'Shared colorbuffer clears', config ); }; es3fFboRenderTest.SharedColorbufferClearsTest.prototype = Object.create(es3fFboRenderTest.FboRenderCase.prototype); es3fFboRenderTest.SharedColorbufferClearsTest.prototype.constructor = es3fFboRenderTest.SharedColorbufferClearsTest; /** * @param {?sglrGLContext.GLContext|sglrReferenceContext.ReferenceContext} * context * @param {tcuSurface.Surface} dst */ es3fFboRenderTest.SharedColorbufferClearsTest.prototype.render = function( context, dst) { /** @type {tcuTexture.TextureFormat} */ var colorFormat = gluTextureUtil.mapGLInternalFormat( this.m_config.colorFormat ); /** @type {gluShaderUtil.DataType} */ var fboSamplerType = gluTextureUtil.getSampler2DType(colorFormat); var width = 128; var height = 128; var colorbuffer = this.m_config.colorType == gl.TEXTURE_2D? context.createTexture() : context.createRenderbuffer(); // Check for format support. es3fFboRenderTest.checkColorFormatSupport( context, this.m_config.colorFormat ); // Single colorbuffer if (this.m_config.colorType == gl.TEXTURE_2D) { context.bindTexture(gl.TEXTURE_2D, colorbuffer); context.texImage2DDelegate( gl.TEXTURE_2D, 0, this.m_config.colorFormat, width, height ); context.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST ); context.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST ); } else { assertMsgOptions( this.m_config.colorType == gl.RENDERBUFFER, 'Not a render buffer type', false, true ); context.bindRenderbuffer(gl.RENDERBUFFER, colorbuffer); context.renderbufferStorage( gl.RENDERBUFFER, this.m_config.colorFormat, width, height ); } // Multiple framebuffers sharing the colorbuffer var fbo = [ context.createFramebuffer(), context.createFramebuffer(), context.createFramebuffer() ]; for (var fboi = 0; fboi < fbo.length; fboi++) { context.bindFramebuffer(gl.FRAMEBUFFER, fbo[fboi]); if (this.m_config.colorType == gl.TEXTURE_2D) context.framebufferTexture2D( gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, colorbuffer, 0 ); else context.framebufferRenderbuffer( gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorbuffer ); } context.bindFramebuffer(gl.FRAMEBUFFER, fbo[0]); // Check completeness var status = context.checkFramebufferStatus(gl.FRAMEBUFFER); if (status != gl.FRAMEBUFFER_COMPLETE) throw new es3fFboTestUtil.FboIncompleteException(status); // Render to them context.viewport(0, 0, width, height); context.clearColor(0.0, 0.0, 1.0, 1.0); context.clear(gl.COLOR_BUFFER_BIT); context.enable(gl.SCISSOR_TEST); context.bindFramebuffer(gl.FRAMEBUFFER, fbo[1]); context.clearColor(0.6, 0.0, 0.0, 1.0); context.scissor(10, 10, 64, 64); context.clear(gl.COLOR_BUFFER_BIT); context.clearColor(0.0, 0.6, 0.0, 1.0); context.scissor(60, 60, 40, 20); context.clear(gl.COLOR_BUFFER_BIT); context.bindFramebuffer(gl.FRAMEBUFFER, fbo[2]); context.clearColor(0.0, 0.0, 0.6, 1.0); context.scissor(20, 20, 100, 10); context.clear(gl.COLOR_BUFFER_BIT); context.bindFramebuffer(gl.FRAMEBUFFER, fbo[0]); context.clearColor(0.6, 0.0, 0.6, 1.0); context.scissor(20, 20, 5, 100); context.clear(gl.COLOR_BUFFER_BIT); context.disable(gl.SCISSOR_TEST); if (this.m_config.colorType == gl.TEXTURE_2D) { /** @type {es3fFboTestUtil.Texture2DShader} */ var shader = new es3fFboTestUtil.Texture2DShader( [fboSamplerType], gluShaderUtil.DataType.FLOAT_VEC4 ); var shaderID = context.createProgram(shader); shader.setUniforms(context, shaderID); context.bindFramebuffer(gl.FRAMEBUFFER, null); context.viewport(0, 0, context.getWidth(), context.getHeight()); rrUtil.drawQuad( context, shaderID, [-0.9, -0.9, 0.0], [0.9, 0.9, 0.0] ); dst.readViewport( context, [0, 0, context.getWidth(), context.getHeight()] ); } else es3fFboTestUtil.readPixels( context, dst, 0, 0, width, height, colorFormat, [1.0, 1.0, 1.0, 1.0], [0.0, 0.0, 0.0, 0.0] ); //delete FBOs for (fboi = 0; fboi < fbo.length; fboi++) context.deleteFramebuffer(fbo[fboi]); //delete Texture/Renderbuffer if (this.m_config.colorType == gl.TEXTURE_2D) context.deleteTexture(colorbuffer); else context.deleteRenderbuffer(colorbuffer); }; /** * @constructor * @extends {es3fFboRenderTest.FboRenderCase} * @param {es3fFboRenderTest.FboConfig} config */ es3fFboRenderTest.SharedDepthStencilTest = function(config) { es3fFboRenderTest.FboRenderCase.call( this, config.getName(), 'Shared depth/stencilbuffer', config ); }; es3fFboRenderTest.SharedDepthStencilTest.prototype = Object.create(es3fFboRenderTest.FboRenderCase.prototype); es3fFboRenderTest.SharedDepthStencilTest.prototype.constructor = es3fFboRenderTest.SharedDepthStencilTest; /** * @param {es3fFboRenderTest.FboConfig} config * @return {boolean} */ es3fFboRenderTest.SharedDepthStencilTest.prototype.isConfigSupported = function(config) { return deMath.binaryOp( config.buffers, deMath.binaryOp( gl.DEPTH_BUFFER_BIT, gl.STENCIL_BUFFER_BIT, deMath.BinaryOp.OR ), deMath.BinaryOp.AND ) != 0; }; /** * @param {?sglrGLContext.GLContext|sglrReferenceContext.ReferenceContext} * context * @param {tcuSurface.Surface} dst */ es3fFboRenderTest.SharedDepthStencilTest.prototype.render = function( context, dst) { /** @type {es3fFboTestUtil.Texture2DShader} */ var texShader = new es3fFboTestUtil.Texture2DShader( [gluShaderUtil.DataType.SAMPLER_2D], gluShaderUtil.DataType.FLOAT_VEC4 ); /** @type {es3fFboTestUtil.FlatColorShader} */ var flatShader = new es3fFboTestUtil.FlatColorShader( gluShaderUtil.DataType.FLOAT_VEC4 ); var texShaderID = context.createProgram(texShader); var flatShaderID = context.createProgram(flatShader); var width = 128; var height = 128; // bool depth = (this.m_config.buffers & gl.DEPTH_BUFFER_BIT) != 0; /**@type {boolean} */ var stencil = (this.m_config.buffers & gl.STENCIL_BUFFER_BIT) != 0; // Textures var metaballsTex = context.createTexture(); var quadsTex = context.createTexture(); es3fFboRenderTest.createMetaballsTex2D( context, metaballsTex, gl.RGB, gl.UNSIGNED_BYTE, 64, 64 ); es3fFboRenderTest.createQuadsTex2D( context, quadsTex, gl.RGB, gl.UNSIGNED_BYTE, 64, 64 ); context.viewport(0, 0, width, height); // Fbo A /** @type {es3fFboRenderTest.Framebuffer} */ var fboA = new es3fFboRenderTest.Framebuffer( context, this.m_config, width, height ); fboA.checkCompleteness(); // Fbo B /** @type {es3fFboRenderTest.FboConfig} */ var cfg = /** @type {es3fFboRenderTest.FboConfig} */ (deUtil.clone(this.m_config)); cfg.buffers = deMath.binaryOp( cfg.buffers, deMath.binaryNot(gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT), deMath.BinaryOp.AND ); cfg.depthStencilType = gl.NONE; cfg.depthStencilFormat = gl.NONE; /** @type {es3fFboRenderTest.Framebuffer} */ var fboB = new es3fFboRenderTest.Framebuffer( context, cfg, width, height ); // Bind depth/stencil buffers from fbo A to fbo B context.bindFramebuffer(gl.FRAMEBUFFER, fboB.getFramebuffer()); for (var ndx = 0; ndx < 2; ndx++) { var bit = ndx ? gl.STENCIL_BUFFER_BIT : gl.DEPTH_BUFFER_BIT; var point = ndx ? gl.STENCIL_ATTACHMENT : gl.DEPTH_ATTACHMENT; if ( deMath.binaryOp( this.m_config.buffers, bit, deMath.BinaryOp.AND ) == 0 ) continue; switch (this.m_config.depthStencilType) { case gl.TEXTURE_2D: context.framebufferTexture2D( gl.FRAMEBUFFER, point, gl.TEXTURE_2D, fboA.getDepthStencilBuffer(), 0 ); break; case gl.RENDERBUFFER: context.framebufferRenderbuffer( gl.FRAMEBUFFER, point, gl.RENDERBUFFER, fboA.getDepthStencilBuffer() ); break; default: testFailed('Not implemented'); } } // Setup uniforms texShader.setUniforms(context, texShaderID); // Clear color to red and stencil to 1 in fbo B. context.clearColor(1.0, 0.0, 0.0, 1.0); context.clearStencil(1); context.clear( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT ); context.enable(gl.DEPTH_TEST); // Render quad to fbo A context.bindFramebuffer(gl.FRAMEBUFFER, fboA.getFramebuffer()); context.bindTexture(gl.TEXTURE_2D, quadsTex); rrUtil.drawQuad( context, texShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0] ); if (stencil) { // Clear subset of stencil buffer to 0 in fbo A context.enable(gl.SCISSOR_TEST); context.scissor(10, 10, 12, 25); context.clearStencil(0); context.clear(gl.STENCIL_BUFFER_BIT); context.disable(gl.SCISSOR_TEST); } // Render metaballs to fbo B context.bindFramebuffer(gl.FRAMEBUFFER, fboB.getFramebuffer()); context.bindTexture(gl.TEXTURE_2D, metaballsTex); rrUtil.drawQuad( context, texShaderID, [-1.0, -1.0, -1.0], [1.0, 1.0, 1.0] ); context.disable(gl.DEPTH_TEST); if (stencil) { // Render quad with stencil mask == 0 context.enable(gl.STENCIL_TEST); context.stencilFunc(gl.EQUAL, 0, 0xff); context.useProgram(flatShaderID); flatShader.setColor(context, flatShaderID, [0.0, 1.0, 0.0, 1.0]); rrUtil.drawQuad( context, flatShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0] ); context.disable(gl.STENCIL_TEST); } if (this.m_config.colorType == gl.TEXTURE_2D) { // Render both to screen context.bindFramebuffer(gl.FRAMEBUFFER, null); context.viewport(0, 0, context.getWidth(), context.getHeight()); context.bindTexture(gl.TEXTURE_2D, fboA.getColorBuffer()); rrUtil.drawQuad( context, texShaderID, [-1.0, -1.0, 0.0], [0.0, 1.0, 0.0] ); context.bindTexture(gl.TEXTURE_2D, fboB.getColorBuffer()); rrUtil.drawQuad( context, texShaderID, [0.0, -1.0, 0.0], [1.0, 1.0, 0.0] ); dst.readViewport( context, [0, 0, context.getWidth(), context.getHeight()] ); } else { // Read results from fbo B es3fFboTestUtil.readPixels( context, dst, 0, 0, width, height, gluTextureUtil.mapGLInternalFormat(this.m_config.colorFormat), [1.0, 1.0, 1.0, 1.0], [0.0, 0.0, 0.0, 0.0] ); } }; /** * @constructor * @extends {es3fFboRenderTest.FboRenderCase} * @param {es3fFboRenderTest.FboConfig} config */ es3fFboRenderTest.ResizeTest = function(config) { es3fFboRenderTest.FboRenderCase.call( this, config.getName(), 'Resize framebuffer', config ); }; es3fFboRenderTest.ResizeTest.prototype = Object.create(es3fFboRenderTest.FboRenderCase.prototype); es3fFboRenderTest.ResizeTest.prototype.constructor = es3fFboRenderTest.ResizeTest; /** * @param {?sglrGLContext.GLContext|sglrReferenceContext.ReferenceContext} * context * @param {tcuSurface.Surface} dst */ es3fFboRenderTest.ResizeTest.prototype.render = function(context, dst) { /** @type {tcuTexture.TextureFormat} */ var colorFormat = gluTextureUtil.mapGLInternalFormat( this.m_config.colorFormat ); /** @type {gluShaderUtil.DataType} */ var fboSamplerType = gluTextureUtil.getSampler2DType(colorFormat); /** @type {gluShaderUtil.DataType} */ var fboOutputType = es3fFboTestUtil.getFragmentOutputType(colorFormat); /** @type {tcuTextureUtil.TextureFormatInfo} */ var fboRangeInfo = tcuTextureUtil.getTextureFormatInfo(colorFormat); var fboOutScale = deMath.subtract( fboRangeInfo.valueMax, fboRangeInfo.valueMin ); var fboOutBias = fboRangeInfo.valueMin; /** @type {es3fFboTestUtil.Texture2DShader} */ var texToFboShader = new es3fFboTestUtil.Texture2DShader( [gluShaderUtil.DataType.SAMPLER_2D], fboOutputType ); /** @type {es3fFboTestUtil.Texture2DShader} */ var texFromFboShader = new es3fFboTestUtil.Texture2DShader( [fboSamplerType], gluShaderUtil.DataType.FLOAT_VEC4 ); /** @type {es3fFboTestUtil.FlatColorShader} */ var flatShader = new es3fFboTestUtil.FlatColorShader(fboOutputType); /** @type {WebGLProgram} */ var texToFboShaderID = context.createProgram(texToFboShader); /** @type {WebGLProgram} */ var texFromFboShaderID = context.createProgram(texFromFboShader); /** @type {WebGLProgram} */ var flatShaderID = context.createProgram(flatShader); var quadsTex = context.createTexture(); var metaballsTex = context.createTexture(); var depth = deMath.binaryOp( this.m_config.buffers, gl.DEPTH_BUFFER_BIT, deMath.BinaryOp.AND ) != 0; var stencil = deMath.binaryOp( this.m_config.buffers, gl.STENCIL_BUFFER_BIT, deMath.BinaryOp.AND ) != 0; var initialWidth = 128; var initialHeight = 128; var newWidth = 64; var newHeight = 32; texToFboShader.setOutScaleBias(fboOutScale, fboOutBias); texFromFboShader.setTexScaleBias( 0, fboRangeInfo.lookupScale, fboRangeInfo.lookupBias ); es3fFboRenderTest.createQuadsTex2D( context, quadsTex, gl.RGB, gl.UNSIGNED_BYTE, 64, 64 ); es3fFboRenderTest.createMetaballsTex2D( context, metaballsTex, gl.RGB, gl.UNSIGNED_BYTE, 32, 32 ); /** @type {es3fFboRenderTest.Framebuffer} */ var fbo = new es3fFboRenderTest.Framebuffer( context, this.m_config, initialWidth, initialHeight ); fbo.checkCompleteness(); // Setup shaders texToFboShader.setUniforms(context, texToFboShaderID); texFromFboShader.setUniforms(context, texFromFboShaderID); flatShader.setColor( context, flatShaderID, deMath.add( deMath.multiply([0.0, 1.0, 0.0, 1.0], fboOutScale), fboOutBias ) ); // Render quads context.bindFramebuffer(gl.FRAMEBUFFER, fbo.getFramebuffer()); context.viewport(0, 0, initialWidth, initialHeight); es3fFboTestUtil.clearColorBuffer( context, colorFormat, [0.0, 0.0, 0.0, 1.0] ); context.clear(gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT); context.bindTexture(gl.TEXTURE_2D, quadsTex); rrUtil.drawQuad( context, texToFboShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0] ); if (fbo.getConfig().colorType == gl.TEXTURE_2D) { // Render fbo to screen context.bindFramebuffer(gl.FRAMEBUFFER, null); context.viewport(0, 0, context.getWidth(), context.getHeight()); context.bindTexture(gl.TEXTURE_2D, fbo.getColorBuffer()); rrUtil.drawQuad( context, texFromFboShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0] ); // Restore binding context.bindFramebuffer(gl.FRAMEBUFFER, fbo.getFramebuffer()); } // Resize buffers switch (fbo.getConfig().colorType) { case gl.TEXTURE_2D: context.bindTexture(gl.TEXTURE_2D, fbo.getColorBuffer()); context.texImage2DDelegate( gl.TEXTURE_2D, 0, fbo.getConfig().colorFormat, newWidth, newHeight ); break; case gl.RENDERBUFFER: context.bindRenderbuffer(gl.RENDERBUFFER, fbo.getColorBuffer()); context.renderbufferStorage( gl.RENDERBUFFER, fbo.getConfig().colorFormat, newWidth, newHeight ); break; default: throw new Error('Color type unsupported'); } if (depth || stencil) { switch (fbo.getConfig().depthStencilType) { case gl.TEXTURE_2D: context.bindTexture( gl.TEXTURE_2D, fbo.getDepthStencilBuffer() ); context.texImage2DDelegate( gl.TEXTURE_2D, 0, fbo.getConfig().depthStencilFormat, newWidth, newHeight ); break; case gl.RENDERBUFFER: context.bindRenderbuffer( gl.RENDERBUFFER, fbo.getDepthStencilBuffer() ); context.renderbufferStorage( gl.RENDERBUFFER, fbo.getConfig().depthStencilFormat, newWidth, newHeight ); break; default: throw new Error('Depth / stencil type unsupported'); } } // Render to resized fbo context.viewport(0, 0, newWidth, newHeight); es3fFboTestUtil.clearColorBuffer( context, colorFormat, [1.0, 0.0, 0.0, 1.0] ); context.clear(gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT); context.enable(gl.DEPTH_TEST); context.bindTexture(gl.TEXTURE_2D, metaballsTex); rrUtil.drawQuad( context, texToFboShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0] ); context.bindTexture(gl.TEXTURE_2D, quadsTex); rrUtil.drawQuad( context, texToFboShaderID, [0.0, 0.0, -1.0], [1.0, 1.0, 1.0] ); context.disable(gl.DEPTH_TEST); if (stencil) { context.enable(gl.SCISSOR_TEST); context.clearStencil(1); context.scissor(10, 10, 5, 15); context.clear(gl.STENCIL_BUFFER_BIT); context.disable(gl.SCISSOR_TEST); context.enable(gl.STENCIL_TEST); context.stencilFunc(gl.EQUAL, 1, 0xff); rrUtil.drawQuad( context, flatShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0] ); context.disable(gl.STENCIL_TEST); } if (this.m_config.colorType == gl.TEXTURE_2D) { context.bindFramebuffer(gl.FRAMEBUFFER, null); context.viewport(0, 0, context.getWidth(), context.getHeight()); context.bindTexture(gl.TEXTURE_2D, fbo.getColorBuffer()); rrUtil.drawQuad( context, texFromFboShaderID, [-0.5, -0.5, 0.0], [0.5, 0.5, 0.0] ); dst.readViewport( context, [0, 0, context.getWidth(), context.getHeight()] ); } else es3fFboTestUtil.readPixels( context, dst, 0, 0, newWidth, newHeight, colorFormat, fboRangeInfo.lookupScale, fboRangeInfo.lookupBias ); }; /** * @constructor * @extends {es3fFboRenderTest.FboRenderCase} * @param {es3fFboRenderTest.FboConfig} config * @param {number} buffers * @param {boolean} rebind */ es3fFboRenderTest.RecreateBuffersTest = function(config, buffers, rebind) { es3fFboRenderTest.FboRenderCase.call( this, config.getName() + (rebind ? '' : '_no_rebind'), 'Recreate buffers', config ); this.m_buffers = buffers; this.m_rebind = rebind; }; es3fFboRenderTest.RecreateBuffersTest.prototype = Object.create(es3fFboRenderTest.FboRenderCase.prototype); es3fFboRenderTest.RecreateBuffersTest.prototype.construtor = es3fFboRenderTest.RecreateBuffersTest; /** * @param {?sglrGLContext.GLContext|sglrReferenceContext.ReferenceContext} * ctx * @param {tcuSurface.Surface} dst */ es3fFboRenderTest.RecreateBuffersTest.prototype.render = function( ctx, dst) { /** @type {tcuTexture.TextureFormat} */ var colorFormat = gluTextureUtil.mapGLInternalFormat( this.m_config.colorFormat ); /** @type {gluShaderUtil.DataType} */ var fboSamplerType = gluTextureUtil.getSampler2DType(colorFormat); /** @type {gluShaderUtil.DataType} */ var fboOutputType = es3fFboTestUtil.getFragmentOutputType(colorFormat); /** @type {tcuTextureUtil.TextureFormatInfo} */ var fboRangeInfo = tcuTextureUtil.getTextureFormatInfo(colorFormat); var fboOutScale = deMath.subtract( fboRangeInfo.valueMax, fboRangeInfo.valueMin ); var fboOutBias = fboRangeInfo.valueMin; /** @type {es3fFboTestUtil.Texture2DShader} */ var texToFboShader = new es3fFboTestUtil.Texture2DShader( [gluShaderUtil.DataType.SAMPLER_2D], fboOutputType ); /** @type {es3fFboTestUtil.Texture2DShader} */ var texFromFboShader = new es3fFboTestUtil.Texture2DShader( [fboSamplerType], gluShaderUtil.DataType.FLOAT_VEC4 ); /** @type {es3fFboTestUtil.FlatColorShader} */ var flatShader = new es3fFboTestUtil.FlatColorShader(fboOutputType); /** @type {number} */ var texToFboShaderID = ctx.createProgram(texToFboShader); /** @type {number} */ var texFromFboShaderID = ctx.createProgram(texFromFboShader); /** @type {number} */ var flatShaderID = ctx.createProgram(flatShader); var width = 128; var height = 128; var metaballsTex = ctx.createTexture(); var quadsTex = ctx.createTexture(); var stencil = deMath.binaryOp( this.m_config.buffers, gl.STENCIL_BUFFER_BIT, deMath.BinaryOp.AND ) != 0; es3fFboRenderTest.createQuadsTex2D( ctx, quadsTex, gl.RGB, gl.UNSIGNED_BYTE, 64, 64 ); es3fFboRenderTest.createMetaballsTex2D( ctx, metaballsTex, gl.RGB, gl.UNSIGNED_BYTE, 64, 64 ); /** @type {es3fFboRenderTest.Framebuffer} */ var fbo = new es3fFboRenderTest.Framebuffer( ctx, this.m_config, width, height ); fbo.checkCompleteness(); // Setup shaders texToFboShader.setOutScaleBias(fboOutScale, fboOutBias); texFromFboShader.setTexScaleBias( 0, fboRangeInfo.lookupScale, fboRangeInfo.lookupBias ); texToFboShader.setUniforms(ctx, texToFboShaderID); texFromFboShader.setUniforms(ctx, texFromFboShaderID); flatShader.setColor( ctx, flatShaderID, deMath.add( deMath.multiply([0.0, 0.0, 1.0, 1.0], fboOutScale ), fboOutBias) ); // Draw scene ctx.bindFramebuffer(gl.FRAMEBUFFER, fbo.getFramebuffer()); ctx.viewport(0, 0, width, height); es3fFboTestUtil.clearColorBuffer( ctx, colorFormat, [1.0, 0.0, 0.0, 1.0] ); ctx.clear(gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT); ctx.enable(gl.DEPTH_TEST); ctx.bindTexture(gl.TEXTURE_2D, quadsTex); rrUtil.drawQuad( ctx, texToFboShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0] ); ctx.disable(gl.DEPTH_TEST); if (stencil) { ctx.enable(gl.SCISSOR_TEST); ctx.scissor( Math.floor(width / 4), Math.floor(height / 4), Math.floor(width / 2), Math.floor(height / 2) ); ctx.clearStencil(1); ctx.clear(gl.STENCIL_BUFFER_BIT); ctx.disable(gl.SCISSOR_TEST); } // Recreate buffers if (!this.m_rebind) ctx.bindFramebuffer(gl.FRAMEBUFFER, null); assertMsgOptions( deMath.binaryOp( this.m_buffers, deMath.binaryOp( gl.DEPTH_BUFFER_BIT, gl.STENCIL_BUFFER_BIT, deMath.BinaryOp.OR ), deMath.BinaryOp.AND ) == 0 || deMath.binaryOp( this.m_buffers, deMath.binaryOp( gl.DEPTH_BUFFER_BIT, gl.STENCIL_BUFFER_BIT, deMath.BinaryOp.OR ), deMath.BinaryOp.AND ) == deMath.binaryOp( this.m_config.buffers, deMath.binaryOp( gl.DEPTH_BUFFER_BIT, gl.STENCIL_BUFFER_BIT, deMath.BinaryOp.OR ), deMath.BinaryOp.AND ), 'Depth/stencil buffers are not disabled or not ' + 'equal to the config\'s depth/stencil buffer state', false, true ); // Recreate. for (var ndx = 0; ndx < 2; ndx++) { var bit = ndx == 0 ? gl.COLOR_BUFFER_BIT : (gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT); var type = ndx == 0 ? fbo.getConfig().colorType : fbo.getConfig().depthStencilType; var format = ndx == 0 ? fbo.getConfig().colorFormat : fbo.getConfig().depthStencilFormat; var buf = ndx == 0 ? fbo.getColorBuffer() : fbo.getDepthStencilBuffer(); if (deMath.binaryOp(this.m_buffers, bit, deMath.BinaryOp.AND) == 0) continue; switch (type) { case gl.TEXTURE_2D: ctx.deleteTexture(/** @type {WebGLTexture} */ (buf)); buf = ctx.createTexture(); ctx.bindTexture(gl.TEXTURE_2D, buf); ctx.texImage2DDelegate( gl.TEXTURE_2D, 0, format, width, height ); ctx.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST ); ctx.texParameteri( gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST ); break; case gl.RENDERBUFFER: ctx.deleteRenderbuffer( /** @type {WebGLRenderbuffer} */ (buf) ); buf = ctx.createRenderbuffer(); ctx.bindRenderbuffer(gl.RENDERBUFFER, buf); ctx.renderbufferStorage( gl.RENDERBUFFER, format, width, height ); break; default: throw new Error('Unsupported buffer type'); } if (ndx == 0) { fbo.m_colorBuffer = buf; } else { fbo.m_depthStencilBuffer = buf; } } // Rebind. if (this.m_rebind) { for (var ndx = 0; ndx < 3; ndx++) { var bit = ndx == 0 ? gl.COLOR_BUFFER_BIT : ndx == 1 ? gl.DEPTH_BUFFER_BIT : ndx == 2 ? gl.STENCIL_BUFFER_BIT : 0; var point = ndx == 0 ? gl.COLOR_ATTACHMENT0 : ndx == 1 ? gl.DEPTH_ATTACHMENT : ndx == 2 ? gl.STENCIL_ATTACHMENT : 0; var type = ndx == 0 ? fbo.getConfig().colorType : fbo.getConfig().depthStencilType; var buf = ndx == 0 ? fbo.getColorBuffer() : fbo.getDepthStencilBuffer(); if (deMath.binaryOp( this.m_buffers, bit, deMath.BinaryOp.AND) == 0) continue; switch (type) { case gl.TEXTURE_2D: ctx.framebufferTexture2D( gl.FRAMEBUFFER, point, gl.TEXTURE_2D, buf, 0 ); break; case gl.RENDERBUFFER: ctx.framebufferRenderbuffer( gl.FRAMEBUFFER, point, gl.RENDERBUFFER, buf ); break; default: throw new Error('Invalid buffer type'); } } } if (!this.m_rebind) ctx.bindFramebuffer(gl.FRAMEBUFFER, fbo.getFramebuffer()); ctx.clearStencil(0); // \note Clear only buffers that were re-created ctx.clear( deMath.binaryOp( this.m_buffers, deMath.binaryOp( gl.DEPTH_BUFFER_BIT, gl.STENCIL_BUFFER_BIT, deMath.BinaryOp.OR ), deMath.BinaryOp.AND ) ); if (deMath.binaryOp( this.m_buffers, gl.COLOR_BUFFER_BIT, deMath.BinaryOp.AND)) { // Clearing of integer buffers is undefined // so do clearing by rendering flat color. rrUtil.drawQuad( ctx, flatShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0] ); } ctx.enable(gl.DEPTH_TEST); if (stencil) { // \note Stencil test enabled only if we have stencil buffer ctx.enable(gl.STENCIL_TEST); ctx.stencilFunc(gl.EQUAL, 0, 0xff); } ctx.bindTexture(gl.TEXTURE_2D, metaballsTex); rrUtil.drawQuad( ctx, texToFboShaderID, [-1.0, -1.0, 1.0], [1.0, 1.0, -1.0] ); if (stencil) ctx.disable(gl.STENCIL_TEST); ctx.disable(gl.DEPTH_TEST); if (fbo.getConfig().colorType == gl.TEXTURE_2D) { // Unbind fbo ctx.bindFramebuffer(gl.FRAMEBUFFER, null); // Draw to screen ctx.bindTexture(gl.TEXTURE_2D, fbo.getColorBuffer()); ctx.viewport(0, 0, ctx.getWidth(), ctx.getHeight()); rrUtil.drawQuad( ctx, texFromFboShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0] ); // Read from screen dst.readViewport(ctx, [0, 0, ctx.getWidth(), ctx.getHeight()]); } else { // Read from fbo es3fFboTestUtil.readPixels( ctx, dst, 0, 0, width, height, colorFormat, fboRangeInfo.lookupScale, fboRangeInfo.lookupBias ); } }; // FboGroups /** * @constructor * @extends {tcuTestCase.DeqpTest} */ es3fFboRenderTest.FboRenderTestGroup = function() { tcuTestCase.DeqpTest.call(this, 'render', 'Rendering Tests'); }; es3fFboRenderTest.FboRenderTestGroup.prototype = Object.create(tcuTestCase.DeqpTest.prototype); es3fFboRenderTest.FboRenderTestGroup.prototype.constructor = es3fFboRenderTest.FboRenderTestGroup; /** * @enum {number} */ var FormatType = { FLOAT: 0, INT: 1, UINT: 2 }; // Required by specification. /** * @typedef {{format: number, type: FormatType}} */ var ColorFormatStruct; /** * @typedef {{format: number, depth: boolean, stencil: boolean}} */ var DepthStencilFormatStruct; /** * init */ es3fFboRenderTest.FboRenderTestGroup.prototype.init = function() { var objectTypes = [ gl.TEXTURE_2D, gl.RENDERBUFFER ]; /** @type {Array} */ var colorFormats = [{ format: gl.RGBA32F, type: FormatType.FLOAT },{ format: gl.RGBA32I, type: FormatType.INT },{ format: gl.RGBA32UI, type: FormatType.UINT },{ format: gl.RGBA16F, type: FormatType.FLOAT },{ format: gl.RGBA16I, type: FormatType.INT },{ format: gl.RGBA16UI, type: FormatType.UINT },/*{ // RGB16F isn't made color-renderable through WebGL's EXT_color_buffer_float format: gl.RGB16F, type: FormatType.FLOAT },*/{ format: gl.RGBA8I, type: FormatType.INT },{ format: gl.RGBA8UI, type: FormatType.UINT },{ format: gl.RGB10_A2UI, type: FormatType.UINT },{ format: gl.R11F_G11F_B10F, type: FormatType.FLOAT },{ format: gl.RG32F, type: FormatType.FLOAT },{ format: gl.RG32I, type: FormatType.INT },{ format: gl.RG32UI, type: FormatType.UINT },{ format: gl.RG16F, type: FormatType.FLOAT },{ format: gl.RG16I, type: FormatType.INT },{ format: gl.RG16UI, type: FormatType.UINT },{ format: gl.RG8, type: FormatType.FLOAT },{ format: gl.RG8I, type: FormatType.INT },{ format: gl.RG8UI, type: FormatType.UINT },{ format: gl.R32F, type: FormatType.FLOAT },{ format: gl.R32I, type: FormatType.INT },{ format: gl.R32UI, type: FormatType.UINT },{ format: gl.R16F, type: FormatType.FLOAT },{ format: gl.R16I, type: FormatType.INT },{ format: gl.R16UI, type: FormatType.UINT },{ format: gl.R8, type: FormatType.FLOAT },{ format: gl.R8I, type: FormatType.INT },{ format: gl.R8UI, type: FormatType.UINT }]; /** @type {Array} */ var depthStencilFormats = [{ format: gl.DEPTH_COMPONENT32F, depth: true, stencil: false },{ format: gl.DEPTH_COMPONENT24, depth: true, stencil: false },{ format: gl.DEPTH_COMPONENT16, depth: true, stencil: false },{ format: gl.DEPTH32F_STENCIL8, depth: true, stencil: true },{ format: gl.DEPTH24_STENCIL8, depth: true, stencil: true },{ format: gl.STENCIL_INDEX8, depth: false, stencil: true }]; /** @type {es3fFboRenderTest.FboConfig} */ var config; var colorType; var stencilType; var colorFmt; var depth; var stencil; var depthStencilType; var depthStencilFormat; // .stencil_clear /** @type {tcuTestCase.DeqpTest} */ var stencilClearGroup = new tcuTestCase.DeqpTest( 'stencil_clear', 'Stencil buffer clears' ); this.addChild(stencilClearGroup); for (var fmtNdx = 0; fmtNdx < depthStencilFormats.length; fmtNdx++) { colorType = gl.TEXTURE_2D; stencilType = gl.RENDERBUFFER; colorFmt = gl.RGBA8; if (!depthStencilFormats[fmtNdx].stencil) continue; config = new es3fFboRenderTest.FboConfig( gl.COLOR_BUFFER_BIT | gl.STENCIL_BUFFER_BIT, colorType, colorFmt, stencilType, depthStencilFormats[fmtNdx].format ); stencilClearGroup.addChild( new es3fFboRenderTest.StencilClearsTest(config) ); } // .shared_colorbuffer_clear /** @type {tcuTestCase.DeqpTest} */ var sharedColorbufferClearGroup = new tcuTestCase.DeqpTest( 'shared_colorbuffer_clear', 'Shader colorbuffer clears' ); this.addChild(sharedColorbufferClearGroup); for (var colorFmtNdx = 0; colorFmtNdx < colorFormats.length; colorFmtNdx++) { // Clearing of integer buffers is undefined. if (colorFormats[colorFmtNdx].type == FormatType.INT || colorFormats[colorFmtNdx].type == FormatType.UINT) continue; for (var typeNdx = 0; typeNdx < objectTypes.length; typeNdx++) { config = new es3fFboRenderTest.FboConfig( gl.COLOR_BUFFER_BIT, objectTypes[typeNdx], colorFormats[colorFmtNdx].format, gl.NONE, gl.NONE ); sharedColorbufferClearGroup.addChild( new es3fFboRenderTest.SharedColorbufferClearsTest(config) ); } } // .shared_colorbuffer /** @type {Array} */ var sharedColorbufferGroup = []; var numSharedColorbufferGroups = 3; for (var ii = 0; ii < numSharedColorbufferGroups; ++ii) { sharedColorbufferGroup[ii] = new tcuTestCase.DeqpTest( 'shared_colorbuffer', 'Shared colorbuffer tests' ); this.addChild(sharedColorbufferGroup[ii]); } for (var colorFmtNdx = 0; colorFmtNdx < colorFormats.length; colorFmtNdx++) { depthStencilType = gl.RENDERBUFFER; depthStencilFormat = gl.DEPTH24_STENCIL8; // Blending with integer buffers and fp32 targets is not supported. if (colorFormats[colorFmtNdx].type == FormatType.INT || colorFormats[colorFmtNdx].type == FormatType.UINT || colorFormats[colorFmtNdx].format == gl.RGBA32F || colorFormats[colorFmtNdx].format == gl.RGB32F || colorFormats[colorFmtNdx].format == gl.RG32F || colorFormats[colorFmtNdx].format == gl.R32F) continue; for (var typeNdx = 0; typeNdx < objectTypes.length; typeNdx++) { /** @type {es3fFboRenderTest.FboConfig} */ var colorOnlyConfig = new es3fFboRenderTest.FboConfig( gl.COLOR_BUFFER_BIT, objectTypes[typeNdx], colorFormats[colorFmtNdx].format, gl.NONE, gl.NONE ); /** @type {es3fFboRenderTest.FboConfig} */ var colorDepthConfig = new es3fFboRenderTest.FboConfig( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT, objectTypes[typeNdx], colorFormats[colorFmtNdx].format, depthStencilType, depthStencilFormat ); /** @type {es3fFboRenderTest.FboConfig} */ var colorDepthStencilConfig = new es3fFboRenderTest.FboConfig( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT, objectTypes[typeNdx], colorFormats[colorFmtNdx].format, depthStencilType, depthStencilFormat ); sharedColorbufferGroup[0].addChild( new es3fFboRenderTest.SharedColorbufferTest(colorOnlyConfig) ); sharedColorbufferGroup[1].addChild( new es3fFboRenderTest.SharedColorbufferTest( colorDepthConfig ) ); sharedColorbufferGroup[2].addChild( new es3fFboRenderTest.SharedColorbufferTest( colorDepthStencilConfig ) ); } } // .shared_depth_stencil /** @type {tcuTestCase.DeqpTest} */ var sharedDepthStencilGroup = new tcuTestCase.DeqpTest( 'shared_depth_stencil', 'Shared depth and stencil buffers' ); this.addChild(sharedDepthStencilGroup); for (var fmtNdx = 0; fmtNdx < depthStencilFormats.length; fmtNdx++) { colorType = gl.TEXTURE_2D; colorFmt = gl.RGBA8; depth = depthStencilFormats[fmtNdx].depth; stencil = depthStencilFormats[fmtNdx].stencil; if (!depth) continue; // Not verified. // Depth and stencil: both rbo and textures for (var typeNdx = 0; typeNdx < objectTypes.length; typeNdx++) { config = new es3fFboRenderTest.FboConfig( gl.COLOR_BUFFER_BIT | (depth ? gl.DEPTH_BUFFER_BIT : 0) | (stencil ? gl.STENCIL_BUFFER_BIT : 0), colorType, colorFmt, objectTypes[typeNdx], depthStencilFormats[fmtNdx].format ); sharedDepthStencilGroup.addChild( new es3fFboRenderTest.SharedDepthStencilTest(config) ); } } // .resize /** @type {Array} */ var resizeGroup = []; var numResizeGroups = 4; for (var ii = 0; ii < numResizeGroups; ++ii) { resizeGroup[ii] = new tcuTestCase.DeqpTest('resize', 'FBO resize tests'); this.addChild(resizeGroup[ii]); } for (var colorFmtNdx = 0; colorFmtNdx < colorFormats.length; colorFmtNdx++) { var colorFormat = colorFormats[colorFmtNdx].format; // Color-only. for (var typeNdx = 0; typeNdx < objectTypes.length; typeNdx++) { config = new es3fFboRenderTest.FboConfig( gl.COLOR_BUFFER_BIT, objectTypes[typeNdx], colorFormat, gl.NONE, gl.NONE ); resizeGroup[colorFmtNdx % numResizeGroups].addChild(new es3fFboRenderTest.ResizeTest(config)); } // For selected color formats tests depth & stencil variants. if (colorFormat == gl.RGBA8 || colorFormat == gl.RGBA16F) { for (var depthStencilFmtNdx = 0; depthStencilFmtNdx < depthStencilFormats.length; depthStencilFmtNdx++) { colorType = gl.TEXTURE_2D; depth = depthStencilFormats[depthStencilFmtNdx].depth; stencil = depthStencilFormats[depthStencilFmtNdx].stencil; // Depth and stencil: both rbo and textures for (var typeNdx = 0; typeNdx < objectTypes.length; typeNdx++) { if (!depth && objectTypes[typeNdx] != gl.RENDERBUFFER) continue; // Not supported. config = new es3fFboRenderTest.FboConfig( gl.COLOR_BUFFER_BIT | (depth ? gl.DEPTH_BUFFER_BIT : 0) | (stencil ? gl.STENCIL_BUFFER_BIT : 0), colorType, colorFormat, objectTypes[typeNdx], depthStencilFormats[depthStencilFmtNdx].format ); resizeGroup[colorFmtNdx % numResizeGroups].addChild( new es3fFboRenderTest.ResizeTest(config) ); } } } } // .recreate_color /** @type {Array} */ var recreateColorGroup = []; var numRecreateColorGroups = 7; for (var ii = 0; ii < numRecreateColorGroups; ++ii) { recreateColorGroup[ii] = new tcuTestCase.DeqpTest('recreate_color', 'Recreate colorbuffer tests'); this.addChild(recreateColorGroup[ii]); } for (var colorFmtNdx = 0; colorFmtNdx < colorFormats.length; colorFmtNdx++) { colorFormat = colorFormats[colorFmtNdx].format; depthStencilFormat = gl.DEPTH24_STENCIL8; depthStencilType = gl.RENDERBUFFER; // Color-only. for (var typeNdx = 0; typeNdx < objectTypes.length; typeNdx++) { config = new es3fFboRenderTest.FboConfig( gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT, objectTypes[typeNdx], colorFormat, depthStencilType, depthStencilFormat ); recreateColorGroup[colorFmtNdx % numRecreateColorGroups].addChild( new es3fFboRenderTest.RecreateBuffersTest( config, gl.COLOR_BUFFER_BIT, true /* rebind */ ) ); } } // .recreate_depth_stencil /** @type {tcuTestCase.DeqpTest} */ var recreateDepthStencilGroup = new tcuTestCase.DeqpTest( 'recreate_depth_stencil', 'Recreate depth and stencil buffers' ); this.addChild(recreateDepthStencilGroup); for (var fmtNdx = 0; fmtNdx < depthStencilFormats.length; fmtNdx++) { colorType = gl.TEXTURE_2D; colorFmt = gl.RGBA8; depth = depthStencilFormats[fmtNdx].depth; stencil = depthStencilFormats[fmtNdx].stencil; // Depth and stencil: both rbo and textures for (var typeNdx = 0; typeNdx < objectTypes.length; typeNdx++) { if (!depth && objectTypes[typeNdx] != gl.RENDERBUFFER) continue; config = new es3fFboRenderTest.FboConfig( gl.COLOR_BUFFER_BIT | (depth ? gl.DEPTH_BUFFER_BIT : 0) | (stencil ? gl.STENCIL_BUFFER_BIT : 0), colorType, colorFmt, objectTypes[typeNdx], depthStencilFormats[fmtNdx].format ); recreateDepthStencilGroup.addChild( new es3fFboRenderTest.RecreateBuffersTest( config, (depth ? gl.DEPTH_BUFFER_BIT : 0) | (stencil ? gl.STENCIL_BUFFER_BIT : 0), true /* rebind */ ) ); } } }; /** * Create and execute the test cases * @param {WebGL2RenderingContext} context */ es3fFboRenderTest.run = function(context, range) { gl = context; //Set up Test Root parameters var state = tcuTestCase.runner; state.setRoot(new es3fFboRenderTest.FboRenderTestGroup()); //Set up name and description of this test series. setCurrentTestName(state.testCases.fullName()); description(state.testCases.getDescription()); try { if (range) state.setRange(range); //Run test cases tcuTestCase.runTestCases(); } catch (err) { testFailedOptions('Failed to run tests', false); tcuTestCase.runner.terminate(); } }; });