summaryrefslogtreecommitdiffstats
path: root/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFboRenderTest.js
diff options
context:
space:
mode:
Diffstat (limited to 'dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFboRenderTest.js')
-rw-r--r--dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFboRenderTest.js2389
1 files changed, 2389 insertions, 0 deletions
diff --git a/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFboRenderTest.js b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFboRenderTest.js
new file mode 100644
index 0000000000..78229de447
--- /dev/null
+++ b/dom/canvas/test/webgl-conf/checkout/deqp/functional/gles3/es3fFboRenderTest.js
@@ -0,0 +1,2389 @@
+/*-------------------------------------------------------------------------
+ * 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<string>}
+ */
+ es3fFboRenderTest.getEnablingExtensions = function(format) {
+ /** @type {Array<string>} */ 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<string>} 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<string>} */ 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<ColorFormatStruct>} */ 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<DepthStencilFormatStruct>} */
+ 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<tcuTestCase.DeqpTest>} */ 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<tcuTestCase.DeqpTest>} */ 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<tcuTestCase.DeqpTest>} */ 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();
+ }
+ };
+});