tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

es3fFboRenderTest.js (85605B)


      1 /*-------------------------------------------------------------------------
      2 * drawElements Quality Program OpenGL ES Utilities
      3 * ------------------------------------------------
      4 *
      5 * Copyright 2014 The Android Open Source Project
      6 *
      7 * Licensed under the Apache License, Version 2.0 (the "License");
      8 * you may not use this file except in compliance with the License.
      9 * You may obtain a copy of the License at
     10 *
     11 *      http://www.apache.org/licenses/LICENSE-2.0
     12 *
     13 * Unless required by applicable law or agreed to in writing, software
     14 * distributed under the License is distributed on an "AS IS" BASIS,
     15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     16 * See the License for the specific language governing permissions and
     17 * limitations under the License.
     18 *
     19 */
     20 
     21 'use strict';
     22 goog.provide('functional.gles3.es3fFboRenderTest');
     23 goog.require('framework.common.tcuImageCompare');
     24 goog.require('framework.common.tcuLogImage');
     25 goog.require('framework.common.tcuPixelFormat');
     26 goog.require('framework.common.tcuRGBA');
     27 goog.require('framework.common.tcuSurface');
     28 goog.require('framework.common.tcuTestCase');
     29 goog.require('framework.common.tcuTexture');
     30 goog.require('framework.common.tcuTextureUtil');
     31 goog.require('framework.delibs.debase.deMath');
     32 goog.require('framework.delibs.debase.deRandom');
     33 goog.require('framework.delibs.debase.deString');
     34 goog.require('framework.delibs.debase.deUtil');
     35 goog.require('framework.opengl.gluShaderUtil');
     36 goog.require('framework.opengl.gluTextureUtil');
     37 goog.require('framework.opengl.simplereference.sglrGLContext');
     38 goog.require('framework.opengl.simplereference.sglrReferenceContext');
     39 goog.require('framework.referencerenderer.rrUtil');
     40 goog.require('functional.gles3.es3fFboTestUtil');
     41 
     42 goog.scope(function() {
     43 
     44    var es3fFboRenderTest = functional.gles3.es3fFboRenderTest;
     45    var es3fFboTestUtil = functional.gles3.es3fFboTestUtil;
     46    var gluShaderUtil = framework.opengl.gluShaderUtil;
     47    var gluTextureUtil = framework.opengl.gluTextureUtil;
     48    var tcuImageCompare = framework.common.tcuImageCompare;
     49    var tcuLogImage = framework.common.tcuLogImage;
     50    var tcuPixelFormat = framework.common.tcuPixelFormat;
     51    var tcuRGBA = framework.common.tcuRGBA;
     52    var tcuTestCase = framework.common.tcuTestCase;
     53    var tcuSurface = framework.common.tcuSurface;
     54    var tcuTexture = framework.common.tcuTexture;
     55    var tcuTextureUtil = framework.common.tcuTextureUtil;
     56    var deMath = framework.delibs.debase.deMath;
     57    var deRandom = framework.delibs.debase.deRandom;
     58    var deString = framework.delibs.debase.deString;
     59    var deUtil = framework.delibs.debase.deUtil;
     60    var sglrGLContext = framework.opengl.simplereference.sglrGLContext;
     61    var sglrReferenceContext =
     62        framework.opengl.simplereference.sglrReferenceContext;
     63    var rrUtil = framework.referencerenderer.rrUtil;
     64 
     65    /** @type {WebGL2RenderingContext} */ var gl;
     66 
     67    /**
     68     * @constructor
     69     * @param {number=} buffers_
     70     * @param {number=} colorType_
     71     * @param {number=} colorFormat_
     72     * @param {number=} depthStencilType_
     73     * @param {number=} depthStencilFormat_
     74     * @param {number=} width_
     75     * @param {number=} height_
     76     * @param {number=} samples_
     77     */
     78    es3fFboRenderTest.FboConfig = function(
     79        buffers_, colorType_, colorFormat_, depthStencilType_,
     80        depthStencilFormat_, width_, height_, samples_
     81    ) {
     82        // Buffer bit mask (gl.COLOR_BUFFER_BIT|gl.DEPTH_BUFFER_BIT|...)
     83        this.buffers = buffers_ ? buffers_ : 0;
     84        // gl.TEXTURE_2D, gl.TEXTURE_CUBE_MAP, gl.RENDERBUFFER
     85        this.colorType = colorType_ ? colorType_ : gl.NONE;
     86        // Internal format for color buffer texture or renderbuffer
     87        this.colorFormat = colorFormat_ ? colorFormat_ : gl.NONE;
     88        this.depthStencilType = depthStencilType_?
     89            depthStencilType_ : gl.NONE;
     90        this.depthStencilFormat = depthStencilFormat_ ?
     91            depthStencilFormat_ : gl.NONE;
     92        this.width = width_ ? width_ : 0;
     93        this.height = height_ ? height_ : 0;
     94        this.samples = samples_? samples_ : 0;
     95    };
     96 
     97    /**
     98     * @param {number} type
     99     * @return {string}
    100     */
    101     es3fFboRenderTest.getTypeName = function(type) {
    102        switch (type) {
    103            case gl.TEXTURE_2D: return 'tex2d';
    104            case gl.RENDERBUFFER: return 'rbo';
    105            default:
    106                testFailed('Unknown type');
    107        }
    108        return 'Should not get to this point';
    109    };
    110 
    111    /**
    112     * @return {string}
    113     */
    114    es3fFboRenderTest.FboConfig.prototype.getName = function() {
    115        var name = '';
    116 
    117        assertMsgOptions((this.buffers & gl.COLOR_BUFFER_BIT) != 0,
    118            'Color buffer is not specified', false, true);
    119 
    120        name += es3fFboRenderTest.getTypeName(this.colorType) + '_' +
    121                es3fFboTestUtil.getFormatName(this.colorFormat);
    122 
    123        if (this.buffers & gl.DEPTH_BUFFER_BIT)
    124            name += '_depth';
    125        if (this.buffers & gl.STENCIL_BUFFER_BIT)
    126            name += '_stencil';
    127 
    128        if (this.buffers & (gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT))
    129            name += '_' + es3fFboRenderTest.getTypeName(this.depthStencilType) +
    130                   '_' + es3fFboTestUtil.getFormatName(this.depthStencilFormat);
    131 
    132        return name;
    133    };
    134 
    135    /**
    136     * @param {number} format
    137     * @return {Array<string>}
    138     */
    139    es3fFboRenderTest.getEnablingExtensions = function(format) {
    140        /** @type {Array<string>} */ var out = [];
    141 
    142        switch (format) {
    143            case gl.RGB16F:
    144                assertMsgOptions(false, "Not part of the tested formats", false, true);
    145                break;
    146 
    147            case gl.RGBA16F:
    148            case gl.RG16F:
    149            case gl.R16F:
    150            case gl.RGBA32F:
    151            case gl.RGB32F:
    152            case gl.R11F_G11F_B10F:
    153            case gl.RG32F:
    154            case gl.R32F:
    155                out.push('EXT_color_buffer_float');
    156 
    157            default:
    158                break;
    159        }
    160 
    161        return out;
    162    };
    163 
    164    /**
    165     * @param {?sglrGLContext.GLContext|sglrReferenceContext.ReferenceContext}
    166     * context
    167     * @param {string} name
    168     * @return {*}
    169     */
    170    es3fFboRenderTest.isExtensionSupported = function(context, name) {
    171        return context.getExtension(name);
    172    };
    173 
    174    /**
    175     * @param {?sglrGLContext.GLContext|sglrReferenceContext.ReferenceContext}
    176     * context
    177     * @param {Array<string>} requiredExts
    178     * @return {boolean}
    179     */
    180    es3fFboRenderTest.isAnyExtensionSupported = function(
    181        context, requiredExts) {
    182 
    183        if (!requiredExts || requiredExts.length == 0)
    184            return true;
    185 
    186        for (var extNdx = 0; extNdx < requiredExts.length; extNdx++) {
    187            var extension = requiredExts[extNdx];
    188 
    189            if (es3fFboRenderTest.isExtensionSupported(context, extension))
    190                return true;
    191        }
    192 
    193        return false;
    194    };
    195 
    196    /**
    197     * @param {Array} list
    198     * @param {string} sep
    199     * @return {string}
    200     */
    201    es3fFboRenderTest.join = function(list, sep) {
    202        var out = '';
    203 
    204        for (var elemNdx = 0; elemNdx < list.length; elemNdx++) {
    205            if (elemNdx != 0)
    206                out += sep;
    207            out += list[elemNdx];
    208        }
    209 
    210        return out;
    211    };
    212 
    213    /**
    214     * @param {?sglrGLContext.GLContext|sglrReferenceContext.ReferenceContext}
    215     * context
    216     * @param {number} sizedFormat
    217     */
    218    es3fFboRenderTest.checkColorFormatSupport = function(context, sizedFormat) {
    219        /** @type {Array<string>} */ var requiredExts =
    220            es3fFboRenderTest.getEnablingExtensions(sizedFormat);
    221 
    222        if (!es3fFboRenderTest.isAnyExtensionSupported(context, requiredExts)) {
    223            var errMsg = 'Format not supported, requires ' + (
    224                (requiredExts.length == 1) ? requiredExts[0] :
    225                ' one of the following: ' +
    226                requiredExts.join(', ')
    227            );
    228            checkMessage(false, errMsg);
    229 
    230            throw new TestFailedException(errMsg);
    231        }
    232    };
    233 
    234    /**
    235     * @constructor
    236     * @param {?sglrGLContext.GLContext|sglrReferenceContext.ReferenceContext}
    237     * context
    238     * @param {es3fFboRenderTest.FboConfig} config
    239     * @param {number} width
    240     * @param {number} height
    241     * @param {sglrReferenceContext.AnyFramebuffer=} fbo
    242     * @param {sglrReferenceContext.AnyRenderbuffer=} colorBufferName
    243     * @param {sglrReferenceContext.AnyRenderbuffer=} depthStencilBufferName
    244     */
    245    es3fFboRenderTest.Framebuffer = function(
    246        context, config, width, height, fbo,
    247        colorBufferName, depthStencilBufferName) {
    248 
    249        this.m_config = config;
    250        this.m_context = context;
    251        this.m_framebuffer = fbo ? fbo : null;
    252        this.m_colorBuffer = colorBufferName ? colorBufferName : null;
    253        this.m_depthStencilBuffer = depthStencilBufferName ?
    254            depthStencilBufferName : null;
    255 
    256        // Verify that color format is supported
    257        es3fFboRenderTest.checkColorFormatSupport(context, config.colorFormat);
    258 
    259        if (!this.m_framebuffer)
    260            this.m_framebuffer = context.createFramebuffer();
    261        context.bindFramebuffer(gl.FRAMEBUFFER, this.m_framebuffer);
    262 
    263        if (this.m_config.buffers & (gl.COLOR_BUFFER_BIT)) {
    264            switch (this.m_config.colorType) {
    265                case gl.TEXTURE_2D:
    266                    this.m_colorBuffer = this.createTex2D(
    267                        /** @type {WebGLTexture} */ (colorBufferName),
    268                        this.m_config.colorFormat, width, height
    269                    );
    270 
    271                    context.framebufferTexture2D(
    272                        gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
    273                        gl.TEXTURE_2D, this.m_colorBuffer, 0
    274                    );
    275 
    276                    break;
    277 
    278                case gl.RENDERBUFFER:
    279                    this.m_colorBuffer = this.createRbo(
    280                        /** @type {WebGLRenderbuffer} */ (colorBufferName),
    281                        this.m_config.colorFormat, width, height
    282                    );
    283 
    284                    context.framebufferRenderbuffer(
    285                        gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
    286                        gl.RENDERBUFFER, this.m_colorBuffer
    287                    );
    288 
    289                    break;
    290 
    291                default:
    292                    testFailed('Unsupported type');
    293            }
    294        }
    295 
    296        if (this.m_config.buffers &
    297            (gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT)) {
    298 
    299            switch (this.m_config.depthStencilType) {
    300                case gl.TEXTURE_2D:
    301                    this.m_depthStencilBuffer = this.createTex2D(
    302                        /** @type {WebGLTexture} */
    303                        (depthStencilBufferName),
    304                        this.m_config.depthStencilFormat, width, height
    305                    );
    306                    break;
    307                case gl.RENDERBUFFER:
    308                    this.m_depthStencilBuffer = this.createRbo(
    309                        /** @type {WebGLRenderbuffer} */
    310                        (depthStencilBufferName),
    311                        this.m_config.depthStencilFormat, width, height
    312                    );
    313                    break;
    314 
    315                default:
    316                    testFailed('Unsupported type');
    317            }
    318        }
    319 
    320        for (var ndx = 0; ndx < 2; ndx++) {
    321            var bit = ndx ? gl.STENCIL_BUFFER_BIT : gl.DEPTH_BUFFER_BIT;
    322            var point = ndx ? gl.STENCIL_ATTACHMENT : gl.DEPTH_ATTACHMENT;
    323 
    324            if ((this.m_config.buffers & bit) == 0)
    325                continue; /* Not used. */
    326 
    327            switch (this.m_config.depthStencilType) {
    328                case gl.TEXTURE_2D:
    329                    context.framebufferTexture2D(
    330                        gl.FRAMEBUFFER, point, gl.TEXTURE_2D,
    331                        this.m_depthStencilBuffer, 0
    332                    );
    333                    break;
    334                case gl.RENDERBUFFER:
    335                    context.framebufferRenderbuffer(
    336                        gl.FRAMEBUFFER, point,
    337                        gl.RENDERBUFFER, this.m_depthStencilBuffer
    338                    );
    339                    break;
    340                default:
    341                    throw new Error('Invalid depth stencil type');
    342            }
    343        }
    344 
    345        context.bindFramebuffer(gl.FRAMEBUFFER, null);
    346    };
    347 
    348    /**
    349     * @return {es3fFboRenderTest.FboConfig}
    350     */
    351    es3fFboRenderTest.Framebuffer.prototype.getConfig = function() {
    352        return this.m_config;
    353    };
    354 
    355    /**
    356     * @return {?sglrReferenceContext.AnyFramebuffer}
    357     */
    358    es3fFboRenderTest.Framebuffer.prototype.getFramebuffer = function() {
    359        return this.m_framebuffer;
    360    };
    361 
    362    /**
    363     * @return {?sglrReferenceContext.AnyRenderbuffer}
    364     */
    365    es3fFboRenderTest.Framebuffer.prototype.getColorBuffer = function() {
    366        return this.m_colorBuffer;
    367    };
    368 
    369    /**
    370     * @return {?sglrReferenceContext.AnyRenderbuffer}
    371     */
    372    es3fFboRenderTest.Framebuffer.prototype.getDepthStencilBuffer = function() {
    373        return this.m_depthStencilBuffer;
    374    };
    375 
    376    /**
    377     * deinit
    378     */
    379    es3fFboRenderTest.Framebuffer.prototype.deinit = function() {
    380        this.m_context.deleteFramebuffer(
    381            /** @type {WebGLFramebuffer} */ (this.m_framebuffer)
    382        );
    383        this.destroyBuffer(this.m_colorBuffer, this.m_config.colorType);
    384        this.destroyBuffer(
    385            this.m_depthStencilBuffer, this.m_config.depthStencilType
    386        );
    387    };
    388 
    389    /**
    390     * checkCompleteness
    391     */
    392    es3fFboRenderTest.Framebuffer.prototype.checkCompleteness = function() {
    393        this.m_context.bindFramebuffer(gl.FRAMEBUFFER, this.m_framebuffer);
    394        var status = this.m_context.checkFramebufferStatus(gl.FRAMEBUFFER);
    395        this.m_context.bindFramebuffer(gl.FRAMEBUFFER, null);
    396        if (status != gl.FRAMEBUFFER_COMPLETE)
    397            throw new es3fFboTestUtil.FboIncompleteException(status);
    398    };
    399 
    400    /**
    401     * @param {?WebGLTexture|sglrReferenceContext.TextureContainer} name
    402     * @param {number} format
    403     * @param {number} width
    404     * @param {number} height
    405     * @return {?WebGLTexture|sglrReferenceContext.TextureContainer}
    406     */
    407    es3fFboRenderTest.Framebuffer.prototype.createTex2D = function(
    408        name, format, width, height) {
    409 
    410        if (!name)
    411            name = this.m_context.createTexture();
    412 
    413        this.m_context.bindTexture(gl.TEXTURE_2D, name);
    414        this.m_context.texImage2DDelegate(
    415            gl.TEXTURE_2D, 0, format, width, height
    416        );
    417 
    418        if (!deMath.deIsPowerOfTwo32(width) ||
    419            !deMath.deIsPowerOfTwo32(height)) {
    420 
    421            // Set wrap mode to clamp for NPOT FBOs
    422            this.m_context.texParameteri(
    423                gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE
    424            );
    425            this.m_context.texParameteri(
    426                gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE
    427            );
    428        }
    429 
    430        this.m_context.texParameteri(
    431            gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST
    432        );
    433        this.m_context.texParameteri(
    434            gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST
    435        );
    436 
    437        return name;
    438    };
    439 
    440    /**
    441     * @param {?WebGLRenderbuffer|sglrReferenceContext.Renderbuffer} name
    442     * @param {number} format
    443     * @param {number} width
    444     * @param {number} height
    445     * @return {?WebGLRenderbuffer|sglrReferenceContext.Renderbuffer}
    446     */
    447    es3fFboRenderTest.Framebuffer.prototype.createRbo = function(
    448        name, format, width, height) {
    449 
    450        if (!name)
    451            name = this.m_context.createRenderbuffer();
    452 
    453        this.m_context.bindRenderbuffer(gl.RENDERBUFFER, name);
    454        this.m_context.renderbufferStorage(
    455            gl.RENDERBUFFER, format, width, height
    456        );
    457 
    458        return name;
    459    };
    460 
    461    /**
    462     * @param {?sglrReferenceContext.AnyRenderbuffer} name
    463     * @param {number} type
    464     */
    465    es3fFboRenderTest.Framebuffer.prototype.destroyBuffer = function(
    466        name, type) {
    467 
    468        if (type == gl.TEXTURE_2D || type == gl.TEXTURE_CUBE_MAP)
    469            this.m_context.deleteTexture(/** @type {?WebGLTexture} */ (name));
    470        else if (type == gl.RENDERBUFFER)
    471            this.m_context.deleteRenderbuffer(
    472                /** @type {?WebGLRenderbuffer} */ (name)
    473            );
    474        else
    475            assertMsgOptions(
    476                type == gl.NONE, 'Invalid buffer type', false, true
    477            );
    478    };
    479 
    480    /**
    481     * @param {?sglrGLContext.GLContext|sglrReferenceContext.ReferenceContext}
    482     * context
    483     * @param {WebGLTexture|sglrReferenceContext.TextureContainer} name
    484     * @param {number} format
    485     * @param {number} dataType
    486     * @param {number} width
    487     * @param {number} height
    488     */
    489    es3fFboRenderTest.createMetaballsTex2D = function(
    490        context, name, format, dataType, width, height) {
    491 
    492        /** @type {tcuTexture.TextureFormat} */ var texFormat =
    493            gluTextureUtil.mapGLTransferFormat(format, dataType);
    494        /** @type {tcuTexture.TextureLevel} */ var level =
    495            new tcuTexture.TextureLevel(texFormat, width, height);
    496 
    497        tcuTextureUtil.fillWithMetaballs(
    498            level.getAccess(), 5, /*name ^*/ width ^ height
    499        );
    500 
    501        context.bindTexture(gl.TEXTURE_2D, name);
    502        context.texImage2D(
    503            gl.TEXTURE_2D, 0, format, width, height, 0, format,
    504            dataType, level.getAccess().getDataPtr()
    505        );
    506        context.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
    507    };
    508 
    509    /**
    510     * @param {?sglrGLContext.GLContext|sglrReferenceContext.ReferenceContext}
    511     * context
    512     * @param {WebGLTexture|sglrReferenceContext.TextureContainer} name
    513     * @param {number} format
    514     * @param {number} dataType
    515     * @param {number} width
    516     * @param {number} height
    517     */
    518    es3fFboRenderTest.createQuadsTex2D = function(
    519        context, name, format, dataType, width, height) {
    520 
    521        /** @type {tcuTexture.TextureFormat} */
    522        var texFormat = gluTextureUtil.mapGLTransferFormat(format, dataType);
    523        /** @type {tcuTexture.TextureLevel} */
    524        var level = new tcuTexture.TextureLevel(texFormat, width, height);
    525 
    526        tcuTextureUtil.fillWithRGBAQuads(level.getAccess());
    527 
    528        context.bindTexture(gl.TEXTURE_2D, name);
    529        context.texImage2D(
    530            gl.TEXTURE_2D, 0, format, width, height, 0,
    531            format, dataType, level.getAccess().getDataPtr()
    532        );
    533        context.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR);
    534    };
    535 
    536    /**
    537     * @constructor
    538     * @extends {tcuTestCase.DeqpTest}
    539     * @param {string} name
    540     * @param {string} description
    541     * @param {es3fFboRenderTest.FboConfig} config
    542     */
    543    es3fFboRenderTest.FboRenderCase = function(name, description, config) {
    544        tcuTestCase.DeqpTest.call(this, name, description);
    545        this.m_config = config;
    546    };
    547 
    548    es3fFboRenderTest.FboRenderCase.prototype =
    549        Object.create(tcuTestCase.DeqpTest.prototype);
    550 
    551    es3fFboRenderTest.FboRenderCase.prototype.constructor =
    552        es3fFboRenderTest.FboRenderCase;
    553 
    554    /**
    555     * Must be overridden
    556     * @param {?sglrGLContext.GLContext|sglrReferenceContext.ReferenceContext}
    557     *      fboContext
    558     * @param {tcuSurface.Surface} dst
    559     */
    560    es3fFboRenderTest.FboRenderCase.prototype.render = function(
    561        fboContext, dst) {
    562            throw new Error('Must override');
    563    };
    564 
    565    /**
    566     * @return {tcuTestCase.IterateResult}
    567     */
    568    es3fFboRenderTest.FboRenderCase.prototype.iterate = function() {
    569        var clearColor = [0.125, 0.25, 0.5, 1.0];
    570        /** @type {?string} */ var failReason = "";
    571 
    572        // Position & size for context
    573        var rnd = new deRandom.deRandom();
    574        deRandom.deRandom_init(rnd, deString.deStringHash(this.fullName()));
    575 
    576        var width = Math.min(gl.canvas.width, 128);
    577        var height = Math.min(gl.canvas.height, 128);
    578        var xMax = gl.canvas.width - width + 1;
    579        var yMax = gl.canvas.height - height + 1;
    580        var x = Math.abs(deRandom.deRandom_getInt(rnd)) % xMax;
    581        var y = Math.abs(deRandom.deRandom_getInt(rnd)) % yMax;
    582 
    583        /** @type {tcuSurface.Surface} */
    584        var gles3Frame = new tcuSurface.Surface(width, height);
    585        /** @type {tcuSurface.Surface} */
    586        var refFrame = new tcuSurface.Surface(width, height);
    587 
    588        /** @type {number} */ var gles3Error = 0;
    589        /** @type {number} */ var refError = 0;
    590 
    591        // Render using GLES3
    592        /**
    593         * @type {sglrGLContext.GLContext|
    594         * sglrReferenceContext.ReferenceContext}
    595         */
    596        var context;
    597 
    598        try {
    599            context = new sglrGLContext.GLContext(gl, [x, y, width, height]);
    600 
    601            context.clearColor(
    602                clearColor[0], clearColor[1], clearColor[2], clearColor[3]
    603            );
    604 
    605            context.clear(
    606                gl.COLOR_BUFFER_BIT |
    607                gl.DEPTH_BUFFER_BIT |
    608                gl.STENCIL_BUFFER_BIT
    609            );
    610 
    611            this.render(context, gles3Frame); // Call actual render func
    612            gles3Error = context.getError();
    613        }
    614        catch (e) {
    615            if (e instanceof es3fFboTestUtil.FboIncompleteException) {
    616                e.message = WebGLTestUtils.glEnumToString(gl, e.getReason());
    617                if(e.getReason() == gl.FRAMEBUFFER_UNSUPPORTED) {
    618                    // Mark test case as unsupported
    619                    bufferedLogToConsole(e + ': ' + e.message);
    620                    testFailed('Not supported');
    621                    return tcuTestCase.IterateResult.STOP;
    622                }
    623            }
    624 
    625            // Propagate error
    626            throw e;
    627        }
    628 
    629        // Render reference image
    630 
    631        /** @type {sglrReferenceContext.ReferenceContextBuffers} */
    632        var buffers = new sglrReferenceContext.ReferenceContextBuffers(
    633            new tcuPixelFormat.PixelFormat(
    634                8, 8, 8,
    635                gl.getParameter(gl.ALPHA_BITS) ? 8 : 0
    636            ),
    637            /** @type {number} */ (gl.getParameter(gl.DEPTH_BITS)),
    638            /** @type {number} */ (gl.getParameter(gl.STENCIL_BITS)),
    639            width,
    640            height
    641        );
    642        context = new sglrReferenceContext.ReferenceContext(
    643            new sglrReferenceContext.ReferenceContextLimits(gl),
    644            buffers.getColorbuffer(),
    645            buffers.getDepthbuffer(),
    646            buffers.getStencilbuffer()
    647        );
    648 
    649        context.clearColor(
    650            clearColor[0], clearColor[1], clearColor[2], clearColor[3]
    651        );
    652 
    653        context.clear(
    654            gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT
    655        );
    656 
    657        this.render(context, refFrame);
    658        refError = context.getError();
    659 
    660        // Compare error codes
    661        var errorCodesOk = (gles3Error == refError);
    662 
    663        if (!errorCodesOk) {
    664            bufferedLogToConsole (
    665                'Error code mismatch: got ' +
    666                WebGLTestUtils.glEnumToString(gl, gles3Error) + ', expected ' +
    667                WebGLTestUtils.glEnumToString(gl, refError)
    668            );
    669            failReason = 'Got unexpected error';
    670        }
    671 
    672        // Compare images
    673        var imagesOk = this.compare(refFrame, gles3Frame);
    674 
    675        if (!imagesOk && !failReason)
    676            failReason = 'Image comparison failed';
    677 
    678        // Store test result
    679        var isOk = errorCodesOk && imagesOk;
    680        assertMsgOptions(isOk, failReason, true, true);
    681 
    682        return tcuTestCase.IterateResult.STOP;
    683    };
    684 
    685    /**
    686     * @param {tcuSurface.Surface} reference
    687     * @param {tcuSurface.Surface} result
    688     * @return {boolean}
    689     */
    690    es3fFboRenderTest.FboRenderCase.prototype.compare = function(
    691        reference, result) {
    692 
    693        var threshold = new tcuRGBA.RGBA(
    694            /* TODO: tcu::max(getFormatThreshold(this.m_config.colorFormat),*/
    695            [12, 12, 12, 12]
    696        );
    697 
    698        return tcuImageCompare.bilinearCompare(
    699            'ComparisonResult', 'Image comparison result',
    700            reference.getAccess(), result.getAccess(),
    701            threshold, tcuImageCompare.CompareLogMode.RESULT
    702        );
    703    };
    704 
    705    /**
    706     * deinit
    707     */
    708    es3fFboRenderTest.FboRenderCase.prototype.deinit = function() {
    709        gl.clearColor(0.0, 0.0, 0.0, 0.0);
    710        gl.clearDepth(1.0);
    711        gl.clearStencil(0);
    712 
    713        gl.disable(gl.STENCIL_TEST);
    714        gl.disable(gl.DEPTH_TEST);
    715        gl.disable(gl.BLEND);
    716 
    717        gl.bindFramebuffer(gl.FRAMEBUFFER, null);
    718        gl.bindRenderbuffer(gl.RENDERBUFFER, null);
    719    };
    720 
    721    // FboCases
    722 
    723    /**
    724     * @constructor
    725     * @extends {es3fFboRenderTest.FboRenderCase}
    726     * @param {es3fFboRenderTest.FboConfig} config
    727     */
    728    es3fFboRenderTest.StencilClearsTest = function(config) {
    729        es3fFboRenderTest.FboRenderCase.call(
    730            this, config.getName(), 'Stencil clears', config
    731        );
    732    };
    733 
    734    es3fFboRenderTest.StencilClearsTest.prototype =
    735        Object.create(es3fFboRenderTest.FboRenderCase.prototype);
    736 
    737    es3fFboRenderTest.StencilClearsTest.prototype.constructor =
    738        es3fFboRenderTest.StencilClearsTest;
    739 
    740    /**
    741     * @param {?sglrGLContext.GLContext|sglrReferenceContext.ReferenceContext}
    742     * context
    743     * @param {tcuSurface.Surface} dst
    744     */
    745    es3fFboRenderTest.StencilClearsTest.prototype.render = function(
    746        context, dst) {
    747 
    748        /** @type {tcuTexture.TextureFormat} */
    749        var colorFormat = gluTextureUtil.mapGLInternalFormat(
    750            this.m_config.colorFormat
    751        );
    752 
    753        /** @type {gluShaderUtil.DataType} */
    754        var fboSamplerType = /** @type {gluShaderUtil.DataType} */ (
    755            gluTextureUtil.getSampler2DType(colorFormat)
    756        );
    757 
    758        /** @type {gluShaderUtil.DataType} */
    759        var fboOutputType = es3fFboTestUtil.getFragmentOutputType(colorFormat);
    760 
    761        /** @type {tcuTextureUtil.TextureFormatInfo} */
    762        var fboRangeInfo = tcuTextureUtil.getTextureFormatInfo(colorFormat);
    763 
    764        var fboOutScale = deMath.subtract(
    765            fboRangeInfo.valueMax, fboRangeInfo.valueMin
    766        );
    767 
    768        var fboOutBias = fboRangeInfo.valueMin;
    769 
    770        /** @type {es3fFboTestUtil.Texture2DShader} */
    771        var texToFboShader = new es3fFboTestUtil.Texture2DShader(
    772            [gluShaderUtil.DataType.SAMPLER_2D], fboOutputType
    773        );
    774 
    775        /** @type {es3fFboTestUtil.Texture2DShader} */
    776        var texFromFboShader = new es3fFboTestUtil.Texture2DShader(
    777            [fboSamplerType], gluShaderUtil.DataType.FLOAT_VEC4);
    778 
    779        /** @type {number} */ var texToFboShaderID =
    780            context.createProgram(texToFboShader);
    781 
    782        /** @type {number} */ var texFromFboShaderID =
    783            context.createProgram(texFromFboShader);
    784 
    785        /** @type {?WebGLTexture|sglrReferenceContext.TextureContainer} */
    786        var metaballsTex = context.createTexture();
    787 
    788        /** @type {?WebGLTexture|sglrReferenceContext.TextureContainer} */
    789        var quadsTex = context.createTexture();
    790 
    791        /** @type {number} */ var width = 128;
    792        /** @type {number} */ var height = 128;
    793 
    794        texToFboShader.setOutScaleBias(fboOutScale, fboOutBias);
    795        texFromFboShader.setTexScaleBias(
    796            0, fboRangeInfo.lookupScale, fboRangeInfo.lookupBias
    797        );
    798 
    799        es3fFboRenderTest.createQuadsTex2D(
    800            context, quadsTex, gl.RGBA, gl.UNSIGNED_BYTE, width, height
    801        );
    802 
    803        es3fFboRenderTest.createMetaballsTex2D(
    804            context, metaballsTex, gl.RGBA, gl.UNSIGNED_BYTE, width, height
    805        );
    806 
    807        /** @type {es3fFboRenderTest.Framebuffer} */
    808        var fbo = new es3fFboRenderTest.Framebuffer(
    809            context, this.m_config, width, height
    810        );
    811        fbo.checkCompleteness();
    812 
    813        // Bind framebuffer and clear
    814        context.bindFramebuffer(gl.FRAMEBUFFER, fbo.getFramebuffer());
    815        context.viewport(0, 0, width, height);
    816        context.clearColor(0.0, 0.0, 0.0, 1.0);
    817        context.clear(
    818            gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT
    819        );
    820 
    821        // Do stencil clears
    822        context.enable(gl.SCISSOR_TEST);
    823        context.scissor(10, 16, 32, 120);
    824        context.clearStencil(1);
    825        context.clear(gl.STENCIL_BUFFER_BIT);
    826        context.scissor(16, 32, 100, 64);
    827        context.clearStencil(2);
    828        context.clear(gl.STENCIL_BUFFER_BIT);
    829        context.disable(gl.SCISSOR_TEST);
    830 
    831        // Draw 2 textures with stecil tests
    832        context.enable(gl.STENCIL_TEST);
    833 
    834        context.bindTexture(gl.TEXTURE_2D, quadsTex);
    835        context.stencilFunc(gl.EQUAL, 1, 0xff);
    836 
    837        texToFboShader.setUniforms(context, texToFboShaderID);
    838        rrUtil.drawQuad(
    839            context, texToFboShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]
    840        );
    841 
    842        context.bindTexture(gl.TEXTURE_2D, metaballsTex);
    843        context.stencilFunc(gl.EQUAL, 2, 0xff);
    844 
    845        texToFboShader.setUniforms(context, texToFboShaderID);
    846        rrUtil.drawQuad(
    847            context, texToFboShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]
    848        );
    849 
    850        context.disable(gl.STENCIL_TEST);
    851 
    852        if (fbo.getConfig().colorType == gl.TEXTURE_2D) {
    853            context.bindFramebuffer(gl.FRAMEBUFFER, null);
    854            context.bindTexture(gl.TEXTURE_2D, fbo.getColorBuffer());
    855            context.viewport(0, 0, context.getWidth(), context.getHeight());
    856 
    857            texFromFboShader.setUniforms(context, texFromFboShaderID);
    858            rrUtil.drawQuad(
    859                context, texFromFboShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]
    860            );
    861 
    862            dst.readViewport(
    863                context, [0, 0, context.getWidth(), context.getHeight()]
    864            );
    865        } else
    866            es3fFboTestUtil.readPixels(
    867                context, dst, 0, 0, width, height, colorFormat,
    868                fboRangeInfo.lookupScale, fboRangeInfo.lookupBias
    869            );
    870    };
    871 
    872    /**
    873     * @constructor
    874     * @extends {es3fFboRenderTest.FboRenderCase}
    875     * @param {es3fFboRenderTest.FboConfig} config
    876     */
    877    es3fFboRenderTest.SharedColorbufferTest = function(config) {
    878        es3fFboRenderTest.FboRenderCase.call(
    879            this, config.getName(), 'Shared colorbuffer', config
    880        );
    881    };
    882 
    883    es3fFboRenderTest.SharedColorbufferTest.prototype =
    884        Object.create(es3fFboRenderTest.FboRenderCase.prototype);
    885 
    886    es3fFboRenderTest.SharedColorbufferTest.prototype.constructor =
    887        es3fFboRenderTest.SharedColorbufferTest;
    888 
    889    /**
    890     * @param {?sglrGLContext.GLContext|sglrReferenceContext.ReferenceContext}
    891     * context
    892     * @param {tcuSurface.Surface} dst
    893     */
    894    es3fFboRenderTest.SharedColorbufferTest.prototype.render = function(
    895        context, dst) {
    896 
    897        /** @type {es3fFboTestUtil.Texture2DShader} */
    898        var texShader = new es3fFboTestUtil.Texture2DShader(
    899            [gluShaderUtil.DataType.SAMPLER_2D],
    900            gluShaderUtil.DataType.FLOAT_VEC4
    901        );
    902 
    903        /** @type {es3fFboTestUtil.FlatColorShader} */
    904        var flatShader = new es3fFboTestUtil.FlatColorShader(
    905            gluShaderUtil.DataType.FLOAT_VEC4
    906        );
    907 
    908        /** @type {number} */
    909        var texShaderID = context.createProgram(texShader);
    910        /** @type {number} */
    911        var flatShaderID = context.createProgram(flatShader);
    912 
    913        /** @type {number} */ var width = 128;
    914        /** @type {number} */ var height = 128;
    915 
    916        /** @type {?WebGLTexture|sglrReferenceContext.TextureContainer} */
    917        var quadsTex = context.createTexture();
    918 
    919        /** @type {?WebGLTexture|sglrReferenceContext.TextureContainer} */
    920        var metaballsTex = context.createTexture();
    921 
    922        /** @type {boolean} */ var stencil =
    923            (this.m_config.buffers & gl.STENCIL_BUFFER_BIT) != 0;
    924 
    925        context.disable(gl.DITHER);
    926 
    927        // Textures
    928        es3fFboRenderTest.createQuadsTex2D(
    929            context, quadsTex, gl.RGB, gl.UNSIGNED_BYTE, 64, 64
    930        );
    931        es3fFboRenderTest.createMetaballsTex2D(
    932            context, metaballsTex, gl.RGBA, gl.UNSIGNED_BYTE, 64, 64
    933        );
    934 
    935        context.viewport(0, 0, width, height);
    936 
    937        // Fbo A
    938        /** @type {es3fFboRenderTest.Framebuffer} */
    939        var fboA = new es3fFboRenderTest.Framebuffer(
    940                context, this.m_config, width, height
    941        );
    942        fboA.checkCompleteness();
    943 
    944        // Fbo B - don't create colorbuffer
    945 
    946        /** @type {es3fFboRenderTest.FboConfig} */
    947        var cfg = /** @type {es3fFboRenderTest.FboConfig} */
    948            (deUtil.clone(this.m_config));
    949 
    950        cfg.buffers = deMath.binaryOp(
    951            cfg.buffers,
    952            deMath.binaryNot(gl.COLOR_BUFFER_BIT),
    953            deMath.BinaryOp.AND
    954        );
    955        cfg.colorType = gl.NONE;
    956        cfg.colorFormat = gl.NONE;
    957 
    958        /** @type {es3fFboRenderTest.Framebuffer} */
    959        var fboB = new es3fFboRenderTest.Framebuffer(
    960            context, cfg, width, height
    961        );
    962 
    963        // Attach color buffer from fbo A
    964        context.bindFramebuffer(gl.FRAMEBUFFER, fboB.getFramebuffer());
    965        switch (this.m_config.colorType) {
    966            case gl.TEXTURE_2D:
    967                context.framebufferTexture2D(
    968                    gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
    969                    gl.TEXTURE_2D, fboA.getColorBuffer(), 0
    970                );
    971                break;
    972 
    973            case gl.RENDERBUFFER:
    974                context.framebufferRenderbuffer(
    975                    gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
    976                    gl.RENDERBUFFER, fboA.getColorBuffer()
    977                );
    978                break;
    979 
    980            default:
    981                throw new Error('Invalid color type');
    982        }
    983 
    984        // Clear depth and stencil in fbo B
    985        context.clear(gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
    986 
    987        // Render quads to fbo 1, with depth 0.0
    988        context.bindFramebuffer(gl.FRAMEBUFFER, fboA.getFramebuffer());
    989        context.bindTexture(gl.TEXTURE_2D, quadsTex);
    990        context.clearColor(0.0, 0.0, 0.0, 1.0);
    991        context.clear(
    992            gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT
    993        );
    994 
    995        if (stencil) {
    996            // Stencil to 1 in fbo A
    997            context.clearStencil(1);
    998            context.clear(gl.STENCIL_BUFFER_BIT);
    999        }
   1000 
   1001        texShader.setUniforms(context, texShaderID);
   1002 
   1003        context.enable(gl.DEPTH_TEST);
   1004        rrUtil.drawQuad(
   1005            context, texShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]
   1006        );
   1007        context.disable(gl.DEPTH_TEST);
   1008 
   1009        // Blend metaballs to fbo 2
   1010        context.bindFramebuffer(gl.FRAMEBUFFER, fboB.getFramebuffer());
   1011        context.bindTexture(gl.TEXTURE_2D, metaballsTex);
   1012        context.enable(gl.BLEND);
   1013        context.blendFuncSeparate(
   1014            gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ZERO, gl.ONE
   1015        );
   1016        rrUtil.drawQuad(
   1017            context, texShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]
   1018        );
   1019 
   1020        // Render small quad that is only visible if depth buffer
   1021        // is not shared with fbo A - or there is no depth bits
   1022        context.bindTexture(gl.TEXTURE_2D, quadsTex);
   1023        context.enable(gl.DEPTH_TEST);
   1024        rrUtil.drawQuad(context, texShaderID, [0.5, 0.5, 0.5], [1.0, 1.0, 0.5]);
   1025        context.disable(gl.DEPTH_TEST);
   1026 
   1027        if (stencil) {
   1028            flatShader.setColor(context, flatShaderID, [0.0, 1.0, 0.0, 1.0]);
   1029 
   1030            // Clear subset of stencil buffer to 1
   1031            context.enable(gl.SCISSOR_TEST);
   1032            context.scissor(10, 10, 12, 25);
   1033            context.clearStencil(1);
   1034            context.clear(gl.STENCIL_BUFFER_BIT);
   1035            context.disable(gl.SCISSOR_TEST);
   1036 
   1037            // Render quad with stencil mask == 1
   1038            context.enable(gl.STENCIL_TEST);
   1039            context.stencilFunc(gl.EQUAL, 1, 0xff);
   1040            rrUtil.drawQuad(
   1041                context, flatShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]
   1042            );
   1043            context.disable(gl.STENCIL_TEST);
   1044        }
   1045 
   1046        // Get results
   1047        if (fboA.getConfig().colorType == gl.TEXTURE_2D) {
   1048            texShader.setUniforms(context, texShaderID);
   1049 
   1050            context.bindFramebuffer(gl.FRAMEBUFFER, null);
   1051            context.bindTexture(gl.TEXTURE_2D, fboA.getColorBuffer());
   1052            context.viewport(0, 0, context.getWidth(), context.getHeight());
   1053            rrUtil.drawQuad(
   1054                context, texShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]
   1055            );
   1056            dst.readViewport(
   1057                context, [0, 0, context.getWidth(), context.getHeight()]
   1058            );
   1059        } else
   1060            es3fFboTestUtil.readPixels(
   1061                context, dst, 0, 0, width, height,
   1062                gluTextureUtil.mapGLInternalFormat(
   1063                    fboA.getConfig().colorFormat
   1064                ), [1.0, 1.0, 1.0, 1.0], [0.0, 0.0, 0.0, 0.0]
   1065            );
   1066    };
   1067 
   1068    /**
   1069     * @constructor
   1070     * @extends {es3fFboRenderTest.FboRenderCase}
   1071     * @param {es3fFboRenderTest.FboConfig} config
   1072     */
   1073    es3fFboRenderTest.SharedColorbufferClearsTest = function(config) {
   1074        es3fFboRenderTest.FboRenderCase.call(
   1075            this, config.getName(), 'Shared colorbuffer clears', config
   1076        );
   1077    };
   1078 
   1079    es3fFboRenderTest.SharedColorbufferClearsTest.prototype =
   1080        Object.create(es3fFboRenderTest.FboRenderCase.prototype);
   1081 
   1082    es3fFboRenderTest.SharedColorbufferClearsTest.prototype.constructor =
   1083        es3fFboRenderTest.SharedColorbufferClearsTest;
   1084 
   1085    /**
   1086     * @param {?sglrGLContext.GLContext|sglrReferenceContext.ReferenceContext}
   1087     * context
   1088     * @param {tcuSurface.Surface} dst
   1089     */
   1090    es3fFboRenderTest.SharedColorbufferClearsTest.prototype.render = function(
   1091        context, dst) {
   1092 
   1093        /** @type {tcuTexture.TextureFormat} */
   1094        var colorFormat = gluTextureUtil.mapGLInternalFormat(
   1095            this.m_config.colorFormat
   1096        );
   1097 
   1098        /** @type {gluShaderUtil.DataType} */
   1099        var fboSamplerType = gluTextureUtil.getSampler2DType(colorFormat);
   1100 
   1101        var width = 128;
   1102        var height = 128;
   1103        var colorbuffer = this.m_config.colorType == gl.TEXTURE_2D?
   1104            context.createTexture() :
   1105            context.createRenderbuffer();
   1106 
   1107        // Check for format support.
   1108        es3fFboRenderTest.checkColorFormatSupport(
   1109            context, this.m_config.colorFormat
   1110        );
   1111 
   1112        // Single colorbuffer
   1113        if (this.m_config.colorType == gl.TEXTURE_2D) {
   1114            context.bindTexture(gl.TEXTURE_2D, colorbuffer);
   1115            context.texImage2DDelegate(
   1116                gl.TEXTURE_2D, 0, this.m_config.colorFormat, width, height
   1117            );
   1118            context.texParameteri(
   1119                gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST
   1120            );
   1121            context.texParameteri(
   1122                gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST
   1123            );
   1124        } else {
   1125            assertMsgOptions(
   1126                this.m_config.colorType == gl.RENDERBUFFER,
   1127                'Not a render buffer type', false, true
   1128            );
   1129            context.bindRenderbuffer(gl.RENDERBUFFER, colorbuffer);
   1130            context.renderbufferStorage(
   1131                gl.RENDERBUFFER, this.m_config.colorFormat, width, height
   1132            );
   1133        }
   1134 
   1135        // Multiple framebuffers sharing the colorbuffer
   1136        var fbo = [
   1137            context.createFramebuffer(),
   1138            context.createFramebuffer(),
   1139            context.createFramebuffer()
   1140        ];
   1141 
   1142        for (var fboi = 0; fboi < fbo.length; fboi++) {
   1143            context.bindFramebuffer(gl.FRAMEBUFFER, fbo[fboi]);
   1144 
   1145            if (this.m_config.colorType == gl.TEXTURE_2D)
   1146                context.framebufferTexture2D(
   1147                    gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
   1148                    gl.TEXTURE_2D, colorbuffer, 0
   1149                );
   1150            else
   1151                context.framebufferRenderbuffer(
   1152                    gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0,
   1153                    gl.RENDERBUFFER, colorbuffer
   1154                );
   1155        }
   1156 
   1157        context.bindFramebuffer(gl.FRAMEBUFFER, fbo[0]);
   1158 
   1159        // Check completeness
   1160 
   1161        var status = context.checkFramebufferStatus(gl.FRAMEBUFFER);
   1162        if (status != gl.FRAMEBUFFER_COMPLETE)
   1163            throw new es3fFboTestUtil.FboIncompleteException(status);
   1164 
   1165        // Render to them
   1166        context.viewport(0, 0, width, height);
   1167        context.clearColor(0.0, 0.0, 1.0, 1.0);
   1168        context.clear(gl.COLOR_BUFFER_BIT);
   1169 
   1170        context.enable(gl.SCISSOR_TEST);
   1171 
   1172        context.bindFramebuffer(gl.FRAMEBUFFER, fbo[1]);
   1173        context.clearColor(0.6, 0.0, 0.0, 1.0);
   1174        context.scissor(10, 10, 64, 64);
   1175        context.clear(gl.COLOR_BUFFER_BIT);
   1176        context.clearColor(0.0, 0.6, 0.0, 1.0);
   1177        context.scissor(60, 60, 40, 20);
   1178        context.clear(gl.COLOR_BUFFER_BIT);
   1179 
   1180        context.bindFramebuffer(gl.FRAMEBUFFER, fbo[2]);
   1181        context.clearColor(0.0, 0.0, 0.6, 1.0);
   1182        context.scissor(20, 20, 100, 10);
   1183        context.clear(gl.COLOR_BUFFER_BIT);
   1184 
   1185        context.bindFramebuffer(gl.FRAMEBUFFER, fbo[0]);
   1186        context.clearColor(0.6, 0.0, 0.6, 1.0);
   1187        context.scissor(20, 20, 5, 100);
   1188        context.clear(gl.COLOR_BUFFER_BIT);
   1189 
   1190        context.disable(gl.SCISSOR_TEST);
   1191 
   1192        if (this.m_config.colorType == gl.TEXTURE_2D) {
   1193            /** @type {es3fFboTestUtil.Texture2DShader} */
   1194            var shader = new es3fFboTestUtil.Texture2DShader(
   1195                [fboSamplerType], gluShaderUtil.DataType.FLOAT_VEC4
   1196            );
   1197            var shaderID = context.createProgram(shader);
   1198 
   1199            shader.setUniforms(context, shaderID);
   1200 
   1201            context.bindFramebuffer(gl.FRAMEBUFFER, null);
   1202            context.viewport(0, 0, context.getWidth(), context.getHeight());
   1203            rrUtil.drawQuad(
   1204                context, shaderID, [-0.9, -0.9, 0.0], [0.9, 0.9, 0.0]
   1205            );
   1206            dst.readViewport(
   1207                context, [0, 0, context.getWidth(), context.getHeight()]
   1208            );
   1209        } else
   1210            es3fFboTestUtil.readPixels(
   1211                context, dst, 0, 0, width, height, colorFormat,
   1212                [1.0, 1.0, 1.0, 1.0], [0.0, 0.0, 0.0, 0.0]
   1213            );
   1214 
   1215        //delete FBOs
   1216        for (fboi = 0; fboi < fbo.length; fboi++)
   1217            context.deleteFramebuffer(fbo[fboi]);
   1218 
   1219        //delete Texture/Renderbuffer
   1220        if (this.m_config.colorType == gl.TEXTURE_2D)
   1221            context.deleteTexture(colorbuffer);
   1222        else
   1223            context.deleteRenderbuffer(colorbuffer);
   1224    };
   1225 
   1226    /**
   1227     * @constructor
   1228     * @extends {es3fFboRenderTest.FboRenderCase}
   1229     * @param {es3fFboRenderTest.FboConfig} config
   1230     */
   1231    es3fFboRenderTest.SharedDepthStencilTest = function(config) {
   1232        es3fFboRenderTest.FboRenderCase.call(
   1233            this, config.getName(), 'Shared depth/stencilbuffer', config
   1234        );
   1235    };
   1236 
   1237    es3fFboRenderTest.SharedDepthStencilTest.prototype =
   1238        Object.create(es3fFboRenderTest.FboRenderCase.prototype);
   1239 
   1240    es3fFboRenderTest.SharedDepthStencilTest.prototype.constructor =
   1241        es3fFboRenderTest.SharedDepthStencilTest;
   1242 
   1243    /**
   1244     * @param {es3fFboRenderTest.FboConfig} config
   1245     * @return {boolean}
   1246     */
   1247    es3fFboRenderTest.SharedDepthStencilTest.prototype.isConfigSupported =
   1248    function(config) {
   1249        return deMath.binaryOp(
   1250            config.buffers,
   1251            deMath.binaryOp(
   1252                gl.DEPTH_BUFFER_BIT, gl.STENCIL_BUFFER_BIT, deMath.BinaryOp.OR
   1253            ), deMath.BinaryOp.AND
   1254        ) != 0;
   1255    };
   1256 
   1257    /**
   1258     * @param {?sglrGLContext.GLContext|sglrReferenceContext.ReferenceContext}
   1259     * context
   1260     * @param {tcuSurface.Surface} dst
   1261     */
   1262    es3fFboRenderTest.SharedDepthStencilTest.prototype.render = function(
   1263        context, dst) {
   1264 
   1265        /** @type {es3fFboTestUtil.Texture2DShader} */
   1266        var texShader = new es3fFboTestUtil.Texture2DShader(
   1267            [gluShaderUtil.DataType.SAMPLER_2D],
   1268            gluShaderUtil.DataType.FLOAT_VEC4
   1269        );
   1270 
   1271        /** @type {es3fFboTestUtil.FlatColorShader} */
   1272        var flatShader = new es3fFboTestUtil.FlatColorShader(
   1273            gluShaderUtil.DataType.FLOAT_VEC4
   1274        );
   1275 
   1276        var texShaderID = context.createProgram(texShader);
   1277        var flatShaderID = context.createProgram(flatShader);
   1278        var width = 128;
   1279        var height = 128;
   1280        // bool depth = (this.m_config.buffers & gl.DEPTH_BUFFER_BIT) != 0;
   1281        /**@type {boolean} */ var stencil =
   1282            (this.m_config.buffers & gl.STENCIL_BUFFER_BIT) != 0;
   1283 
   1284        // Textures
   1285        var metaballsTex = context.createTexture();
   1286        var quadsTex = context.createTexture();
   1287        es3fFboRenderTest.createMetaballsTex2D(
   1288            context, metaballsTex, gl.RGB, gl.UNSIGNED_BYTE, 64, 64
   1289        );
   1290        es3fFboRenderTest.createQuadsTex2D(
   1291            context, quadsTex, gl.RGB, gl.UNSIGNED_BYTE, 64, 64
   1292        );
   1293 
   1294        context.viewport(0, 0, width, height);
   1295 
   1296        // Fbo A
   1297        /** @type {es3fFboRenderTest.Framebuffer} */
   1298        var fboA = new es3fFboRenderTest.Framebuffer(
   1299            context, this.m_config, width, height
   1300        );
   1301 
   1302        fboA.checkCompleteness();
   1303 
   1304        // Fbo B
   1305        /** @type {es3fFboRenderTest.FboConfig} */
   1306        var cfg = /** @type {es3fFboRenderTest.FboConfig} */
   1307            (deUtil.clone(this.m_config));
   1308 
   1309        cfg.buffers = deMath.binaryOp(
   1310            cfg.buffers,
   1311            deMath.binaryNot(gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT),
   1312            deMath.BinaryOp.AND
   1313        );
   1314        cfg.depthStencilType = gl.NONE;
   1315        cfg.depthStencilFormat = gl.NONE;
   1316 
   1317        /** @type {es3fFboRenderTest.Framebuffer} */
   1318        var fboB = new es3fFboRenderTest.Framebuffer(
   1319            context, cfg, width, height
   1320        );
   1321 
   1322        // Bind depth/stencil buffers from fbo A to fbo B
   1323        context.bindFramebuffer(gl.FRAMEBUFFER, fboB.getFramebuffer());
   1324        for (var ndx = 0; ndx < 2; ndx++) {
   1325            var bit = ndx ? gl.STENCIL_BUFFER_BIT : gl.DEPTH_BUFFER_BIT;
   1326            var point = ndx ? gl.STENCIL_ATTACHMENT : gl.DEPTH_ATTACHMENT;
   1327 
   1328            if (
   1329                deMath.binaryOp(
   1330                    this.m_config.buffers, bit, deMath.BinaryOp.AND
   1331                ) == 0
   1332            )
   1333                continue;
   1334 
   1335            switch (this.m_config.depthStencilType) {
   1336                case gl.TEXTURE_2D:
   1337                    context.framebufferTexture2D(
   1338                        gl.FRAMEBUFFER, point, gl.TEXTURE_2D,
   1339                        fboA.getDepthStencilBuffer(), 0
   1340                    );
   1341                    break;
   1342                case gl.RENDERBUFFER:
   1343                    context.framebufferRenderbuffer(
   1344                        gl.FRAMEBUFFER, point, gl.RENDERBUFFER,
   1345                        fboA.getDepthStencilBuffer()
   1346                    );
   1347                    break;
   1348                default:
   1349                    testFailed('Not implemented');
   1350            }
   1351        }
   1352 
   1353        // Setup uniforms
   1354        texShader.setUniforms(context, texShaderID);
   1355 
   1356        // Clear color to red and stencil to 1 in fbo B.
   1357        context.clearColor(1.0, 0.0, 0.0, 1.0);
   1358        context.clearStencil(1);
   1359        context.clear(
   1360            gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT
   1361        );
   1362 
   1363        context.enable(gl.DEPTH_TEST);
   1364 
   1365        // Render quad to fbo A
   1366        context.bindFramebuffer(gl.FRAMEBUFFER, fboA.getFramebuffer());
   1367        context.bindTexture(gl.TEXTURE_2D, quadsTex);
   1368        rrUtil.drawQuad(
   1369            context, texShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]
   1370        );
   1371 
   1372        if (stencil) {
   1373            // Clear subset of stencil buffer to 0 in fbo A
   1374            context.enable(gl.SCISSOR_TEST);
   1375            context.scissor(10, 10, 12, 25);
   1376            context.clearStencil(0);
   1377            context.clear(gl.STENCIL_BUFFER_BIT);
   1378            context.disable(gl.SCISSOR_TEST);
   1379        }
   1380 
   1381        // Render metaballs to fbo B
   1382        context.bindFramebuffer(gl.FRAMEBUFFER, fboB.getFramebuffer());
   1383        context.bindTexture(gl.TEXTURE_2D, metaballsTex);
   1384        rrUtil.drawQuad(
   1385            context, texShaderID, [-1.0, -1.0, -1.0], [1.0, 1.0, 1.0]
   1386        );
   1387 
   1388        context.disable(gl.DEPTH_TEST);
   1389 
   1390        if (stencil) {
   1391            // Render quad with stencil mask == 0
   1392            context.enable(gl.STENCIL_TEST);
   1393            context.stencilFunc(gl.EQUAL, 0, 0xff);
   1394            context.useProgram(flatShaderID);
   1395            flatShader.setColor(context, flatShaderID, [0.0, 1.0, 0.0, 1.0]);
   1396            rrUtil.drawQuad(
   1397                context, flatShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]
   1398            );
   1399            context.disable(gl.STENCIL_TEST);
   1400        }
   1401 
   1402        if (this.m_config.colorType == gl.TEXTURE_2D) {
   1403            // Render both to screen
   1404            context.bindFramebuffer(gl.FRAMEBUFFER, null);
   1405            context.viewport(0, 0, context.getWidth(), context.getHeight());
   1406            context.bindTexture(gl.TEXTURE_2D, fboA.getColorBuffer());
   1407            rrUtil.drawQuad(
   1408                context, texShaderID, [-1.0, -1.0, 0.0], [0.0, 1.0, 0.0]
   1409            );
   1410            context.bindTexture(gl.TEXTURE_2D, fboB.getColorBuffer());
   1411            rrUtil.drawQuad(
   1412                context, texShaderID, [0.0, -1.0, 0.0], [1.0, 1.0, 0.0]
   1413            );
   1414 
   1415            dst.readViewport(
   1416                context, [0, 0, context.getWidth(), context.getHeight()]
   1417            );
   1418        } else {
   1419            // Read results from fbo B
   1420            es3fFboTestUtil.readPixels(
   1421                context, dst, 0, 0, width, height,
   1422                gluTextureUtil.mapGLInternalFormat(this.m_config.colorFormat),
   1423                [1.0, 1.0, 1.0, 1.0], [0.0, 0.0, 0.0, 0.0]
   1424            );
   1425        }
   1426    };
   1427 
   1428    /**
   1429     * @constructor
   1430     * @extends {es3fFboRenderTest.FboRenderCase}
   1431     * @param {es3fFboRenderTest.FboConfig} config
   1432     */
   1433    es3fFboRenderTest.ResizeTest = function(config) {
   1434        es3fFboRenderTest.FboRenderCase.call(
   1435            this, config.getName(), 'Resize framebuffer', config
   1436        );
   1437    };
   1438 
   1439    es3fFboRenderTest.ResizeTest.prototype =
   1440        Object.create(es3fFboRenderTest.FboRenderCase.prototype);
   1441 
   1442    es3fFboRenderTest.ResizeTest.prototype.constructor =
   1443        es3fFboRenderTest.ResizeTest;
   1444 
   1445    /**
   1446     * @param {?sglrGLContext.GLContext|sglrReferenceContext.ReferenceContext}
   1447     * context
   1448     * @param {tcuSurface.Surface} dst
   1449     */
   1450    es3fFboRenderTest.ResizeTest.prototype.render = function(context, dst) {
   1451        /** @type {tcuTexture.TextureFormat} */
   1452        var colorFormat = gluTextureUtil.mapGLInternalFormat(
   1453            this.m_config.colorFormat
   1454        );
   1455        /** @type {gluShaderUtil.DataType} */
   1456        var fboSamplerType = gluTextureUtil.getSampler2DType(colorFormat);
   1457        /** @type {gluShaderUtil.DataType} */
   1458        var fboOutputType = es3fFboTestUtil.getFragmentOutputType(colorFormat);
   1459        /** @type {tcuTextureUtil.TextureFormatInfo} */
   1460        var fboRangeInfo = tcuTextureUtil.getTextureFormatInfo(colorFormat);
   1461        var fboOutScale = deMath.subtract(
   1462            fboRangeInfo.valueMax, fboRangeInfo.valueMin
   1463        );
   1464        var fboOutBias = fboRangeInfo.valueMin;
   1465 
   1466        /** @type {es3fFboTestUtil.Texture2DShader} */
   1467        var texToFboShader = new es3fFboTestUtil.Texture2DShader(
   1468            [gluShaderUtil.DataType.SAMPLER_2D], fboOutputType
   1469        );
   1470 
   1471        /** @type {es3fFboTestUtil.Texture2DShader} */
   1472        var texFromFboShader = new es3fFboTestUtil.Texture2DShader(
   1473            [fboSamplerType], gluShaderUtil.DataType.FLOAT_VEC4
   1474        );
   1475 
   1476        /** @type {es3fFboTestUtil.FlatColorShader} */
   1477        var flatShader = new es3fFboTestUtil.FlatColorShader(fboOutputType);
   1478        /** @type {WebGLProgram} */
   1479        var texToFboShaderID = context.createProgram(texToFboShader);
   1480        /** @type {WebGLProgram} */
   1481        var texFromFboShaderID = context.createProgram(texFromFboShader);
   1482        /** @type {WebGLProgram} */
   1483        var flatShaderID = context.createProgram(flatShader);
   1484 
   1485        var quadsTex = context.createTexture();
   1486        var metaballsTex = context.createTexture();
   1487 
   1488        var depth = deMath.binaryOp(
   1489            this.m_config.buffers, gl.DEPTH_BUFFER_BIT, deMath.BinaryOp.AND
   1490        ) != 0;
   1491        var stencil = deMath.binaryOp(
   1492            this.m_config.buffers, gl.STENCIL_BUFFER_BIT, deMath.BinaryOp.AND
   1493        ) != 0;
   1494 
   1495        var initialWidth = 128;
   1496        var initialHeight = 128;
   1497        var newWidth = 64;
   1498        var newHeight = 32;
   1499 
   1500        texToFboShader.setOutScaleBias(fboOutScale, fboOutBias);
   1501        texFromFboShader.setTexScaleBias(
   1502            0, fboRangeInfo.lookupScale, fboRangeInfo.lookupBias
   1503        );
   1504 
   1505        es3fFboRenderTest.createQuadsTex2D(
   1506            context, quadsTex, gl.RGB, gl.UNSIGNED_BYTE, 64, 64
   1507        );
   1508        es3fFboRenderTest.createMetaballsTex2D(
   1509            context, metaballsTex, gl.RGB, gl.UNSIGNED_BYTE, 32, 32
   1510        );
   1511 
   1512        /** @type {es3fFboRenderTest.Framebuffer} */
   1513        var fbo = new es3fFboRenderTest.Framebuffer(
   1514            context, this.m_config, initialWidth, initialHeight
   1515        );
   1516        fbo.checkCompleteness();
   1517 
   1518        // Setup shaders
   1519        texToFboShader.setUniforms(context, texToFboShaderID);
   1520        texFromFboShader.setUniforms(context, texFromFboShaderID);
   1521        flatShader.setColor(
   1522            context, flatShaderID, deMath.add(
   1523                deMath.multiply([0.0, 1.0, 0.0, 1.0], fboOutScale), fboOutBias
   1524            )
   1525        );
   1526 
   1527        // Render quads
   1528        context.bindFramebuffer(gl.FRAMEBUFFER, fbo.getFramebuffer());
   1529        context.viewport(0, 0, initialWidth, initialHeight);
   1530        es3fFboTestUtil.clearColorBuffer(
   1531            context, colorFormat, [0.0, 0.0, 0.0, 1.0]
   1532        );
   1533        context.clear(gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
   1534        context.bindTexture(gl.TEXTURE_2D, quadsTex);
   1535        rrUtil.drawQuad(
   1536            context, texToFboShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]
   1537        );
   1538 
   1539        if (fbo.getConfig().colorType == gl.TEXTURE_2D) {
   1540            // Render fbo to screen
   1541            context.bindFramebuffer(gl.FRAMEBUFFER, null);
   1542            context.viewport(0, 0, context.getWidth(), context.getHeight());
   1543            context.bindTexture(gl.TEXTURE_2D, fbo.getColorBuffer());
   1544            rrUtil.drawQuad(
   1545                context, texFromFboShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]
   1546            );
   1547            // Restore binding
   1548            context.bindFramebuffer(gl.FRAMEBUFFER, fbo.getFramebuffer());
   1549        }
   1550 
   1551        // Resize buffers
   1552        switch (fbo.getConfig().colorType) {
   1553            case gl.TEXTURE_2D:
   1554                context.bindTexture(gl.TEXTURE_2D, fbo.getColorBuffer());
   1555                context.texImage2DDelegate(
   1556                    gl.TEXTURE_2D, 0, fbo.getConfig().colorFormat,
   1557                    newWidth, newHeight
   1558                );
   1559                break;
   1560 
   1561            case gl.RENDERBUFFER:
   1562                context.bindRenderbuffer(gl.RENDERBUFFER, fbo.getColorBuffer());
   1563                context.renderbufferStorage(
   1564                    gl.RENDERBUFFER, fbo.getConfig().colorFormat,
   1565                    newWidth, newHeight
   1566                );
   1567                break;
   1568 
   1569            default:
   1570                throw new Error('Color type unsupported');
   1571        }
   1572 
   1573        if (depth || stencil) {
   1574            switch (fbo.getConfig().depthStencilType) {
   1575                case gl.TEXTURE_2D:
   1576                    context.bindTexture(
   1577                        gl.TEXTURE_2D, fbo.getDepthStencilBuffer()
   1578                    );
   1579                    context.texImage2DDelegate(
   1580                        gl.TEXTURE_2D, 0, fbo.getConfig().depthStencilFormat,
   1581                        newWidth, newHeight
   1582                    );
   1583                    break;
   1584 
   1585                case gl.RENDERBUFFER:
   1586                    context.bindRenderbuffer(
   1587                        gl.RENDERBUFFER, fbo.getDepthStencilBuffer()
   1588                    );
   1589                    context.renderbufferStorage(
   1590                        gl.RENDERBUFFER, fbo.getConfig().depthStencilFormat,
   1591                        newWidth, newHeight
   1592                    );
   1593                    break;
   1594 
   1595                default:
   1596                    throw new Error('Depth / stencil type unsupported');
   1597            }
   1598        }
   1599 
   1600        // Render to resized fbo
   1601        context.viewport(0, 0, newWidth, newHeight);
   1602        es3fFboTestUtil.clearColorBuffer(
   1603            context, colorFormat, [1.0, 0.0, 0.0, 1.0]
   1604        );
   1605        context.clear(gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
   1606 
   1607        context.enable(gl.DEPTH_TEST);
   1608 
   1609        context.bindTexture(gl.TEXTURE_2D, metaballsTex);
   1610        rrUtil.drawQuad(
   1611            context, texToFboShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]
   1612        );
   1613 
   1614        context.bindTexture(gl.TEXTURE_2D, quadsTex);
   1615        rrUtil.drawQuad(
   1616            context, texToFboShaderID, [0.0, 0.0, -1.0], [1.0, 1.0, 1.0]
   1617        );
   1618 
   1619        context.disable(gl.DEPTH_TEST);
   1620 
   1621        if (stencil) {
   1622            context.enable(gl.SCISSOR_TEST);
   1623            context.clearStencil(1);
   1624            context.scissor(10, 10, 5, 15);
   1625            context.clear(gl.STENCIL_BUFFER_BIT);
   1626            context.disable(gl.SCISSOR_TEST);
   1627 
   1628            context.enable(gl.STENCIL_TEST);
   1629            context.stencilFunc(gl.EQUAL, 1, 0xff);
   1630            rrUtil.drawQuad(
   1631                context, flatShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]
   1632            );
   1633            context.disable(gl.STENCIL_TEST);
   1634        }
   1635 
   1636        if (this.m_config.colorType == gl.TEXTURE_2D) {
   1637            context.bindFramebuffer(gl.FRAMEBUFFER, null);
   1638            context.viewport(0, 0, context.getWidth(), context.getHeight());
   1639            context.bindTexture(gl.TEXTURE_2D, fbo.getColorBuffer());
   1640            rrUtil.drawQuad(
   1641                context, texFromFboShaderID, [-0.5, -0.5, 0.0], [0.5, 0.5, 0.0]
   1642            );
   1643            dst.readViewport(
   1644                context, [0, 0, context.getWidth(), context.getHeight()]
   1645            );
   1646        } else
   1647            es3fFboTestUtil.readPixels(
   1648                context, dst, 0, 0, newWidth, newHeight, colorFormat,
   1649                fboRangeInfo.lookupScale, fboRangeInfo.lookupBias
   1650            );
   1651    };
   1652 
   1653    /**
   1654     * @constructor
   1655     * @extends {es3fFboRenderTest.FboRenderCase}
   1656     * @param {es3fFboRenderTest.FboConfig} config
   1657     * @param {number} buffers
   1658     * @param {boolean} rebind
   1659     */
   1660    es3fFboRenderTest.RecreateBuffersTest = function(config, buffers, rebind) {
   1661        es3fFboRenderTest.FboRenderCase.call(
   1662            this, config.getName() +
   1663            (rebind ? '' : '_no_rebind'),
   1664            'Recreate buffers', config
   1665        );
   1666        this.m_buffers = buffers;
   1667        this.m_rebind = rebind;
   1668    };
   1669 
   1670    es3fFboRenderTest.RecreateBuffersTest.prototype =
   1671        Object.create(es3fFboRenderTest.FboRenderCase.prototype);
   1672 
   1673    es3fFboRenderTest.RecreateBuffersTest.prototype.construtor =
   1674        es3fFboRenderTest.RecreateBuffersTest;
   1675 
   1676    /**
   1677     * @param {?sglrGLContext.GLContext|sglrReferenceContext.ReferenceContext}
   1678     * ctx
   1679     * @param {tcuSurface.Surface} dst
   1680     */
   1681    es3fFboRenderTest.RecreateBuffersTest.prototype.render = function(
   1682        ctx, dst) {
   1683 
   1684        /** @type {tcuTexture.TextureFormat} */
   1685        var colorFormat = gluTextureUtil.mapGLInternalFormat(
   1686            this.m_config.colorFormat
   1687        );
   1688        /** @type {gluShaderUtil.DataType} */
   1689        var fboSamplerType = gluTextureUtil.getSampler2DType(colorFormat);
   1690        /** @type {gluShaderUtil.DataType} */
   1691        var fboOutputType = es3fFboTestUtil.getFragmentOutputType(colorFormat);
   1692        /** @type {tcuTextureUtil.TextureFormatInfo} */
   1693        var fboRangeInfo = tcuTextureUtil.getTextureFormatInfo(colorFormat);
   1694        var fboOutScale = deMath.subtract(
   1695            fboRangeInfo.valueMax, fboRangeInfo.valueMin
   1696        );
   1697        var fboOutBias = fboRangeInfo.valueMin;
   1698 
   1699        /** @type {es3fFboTestUtil.Texture2DShader} */
   1700        var texToFboShader = new es3fFboTestUtil.Texture2DShader(
   1701            [gluShaderUtil.DataType.SAMPLER_2D], fboOutputType
   1702        );
   1703        /** @type {es3fFboTestUtil.Texture2DShader} */
   1704        var texFromFboShader = new es3fFboTestUtil.Texture2DShader(
   1705            [fboSamplerType], gluShaderUtil.DataType.FLOAT_VEC4
   1706        );
   1707 
   1708        /** @type {es3fFboTestUtil.FlatColorShader} */
   1709        var flatShader = new es3fFboTestUtil.FlatColorShader(fboOutputType);
   1710        /** @type {number} */
   1711        var texToFboShaderID = ctx.createProgram(texToFboShader);
   1712        /** @type {number} */
   1713        var texFromFboShaderID = ctx.createProgram(texFromFboShader);
   1714        /** @type {number} */
   1715        var flatShaderID = ctx.createProgram(flatShader);
   1716 
   1717        var width = 128;
   1718        var height = 128;
   1719        var metaballsTex = ctx.createTexture();
   1720        var quadsTex = ctx.createTexture();
   1721        var stencil = deMath.binaryOp(
   1722            this.m_config.buffers, gl.STENCIL_BUFFER_BIT, deMath.BinaryOp.AND
   1723        ) != 0;
   1724 
   1725        es3fFboRenderTest.createQuadsTex2D(
   1726            ctx, quadsTex, gl.RGB, gl.UNSIGNED_BYTE, 64, 64
   1727        );
   1728        es3fFboRenderTest.createMetaballsTex2D(
   1729            ctx, metaballsTex, gl.RGB, gl.UNSIGNED_BYTE, 64, 64
   1730        );
   1731 
   1732        /** @type {es3fFboRenderTest.Framebuffer} */
   1733        var fbo = new es3fFboRenderTest.Framebuffer(
   1734            ctx, this.m_config, width, height
   1735        );
   1736        fbo.checkCompleteness();
   1737 
   1738        // Setup shaders
   1739        texToFboShader.setOutScaleBias(fboOutScale, fboOutBias);
   1740        texFromFboShader.setTexScaleBias(
   1741            0, fboRangeInfo.lookupScale, fboRangeInfo.lookupBias
   1742        );
   1743        texToFboShader.setUniforms(ctx, texToFboShaderID);
   1744        texFromFboShader.setUniforms(ctx, texFromFboShaderID);
   1745        flatShader.setColor(
   1746            ctx, flatShaderID, deMath.add(
   1747                deMath.multiply([0.0, 0.0, 1.0, 1.0], fboOutScale
   1748            ), fboOutBias)
   1749        );
   1750 
   1751        // Draw scene
   1752        ctx.bindFramebuffer(gl.FRAMEBUFFER, fbo.getFramebuffer());
   1753        ctx.viewport(0, 0, width, height);
   1754        es3fFboTestUtil.clearColorBuffer(
   1755            ctx, colorFormat, [1.0, 0.0, 0.0, 1.0]
   1756        );
   1757        ctx.clear(gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
   1758 
   1759        ctx.enable(gl.DEPTH_TEST);
   1760 
   1761        ctx.bindTexture(gl.TEXTURE_2D, quadsTex);
   1762        rrUtil.drawQuad(
   1763            ctx, texToFboShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]
   1764        );
   1765 
   1766        ctx.disable(gl.DEPTH_TEST);
   1767 
   1768        if (stencil) {
   1769            ctx.enable(gl.SCISSOR_TEST);
   1770            ctx.scissor(
   1771                Math.floor(width / 4), Math.floor(height / 4),
   1772                Math.floor(width / 2), Math.floor(height / 2)
   1773            );
   1774            ctx.clearStencil(1);
   1775            ctx.clear(gl.STENCIL_BUFFER_BIT);
   1776            ctx.disable(gl.SCISSOR_TEST);
   1777        }
   1778 
   1779        // Recreate buffers
   1780        if (!this.m_rebind)
   1781            ctx.bindFramebuffer(gl.FRAMEBUFFER, null);
   1782 
   1783        assertMsgOptions(
   1784            deMath.binaryOp(
   1785                this.m_buffers, deMath.binaryOp(
   1786                    gl.DEPTH_BUFFER_BIT,
   1787                    gl.STENCIL_BUFFER_BIT,
   1788                    deMath.BinaryOp.OR
   1789                ), deMath.BinaryOp.AND
   1790            ) == 0 || deMath.binaryOp(
   1791                this.m_buffers, deMath.binaryOp(
   1792                    gl.DEPTH_BUFFER_BIT,
   1793                    gl.STENCIL_BUFFER_BIT,
   1794                    deMath.BinaryOp.OR
   1795                ), deMath.BinaryOp.AND
   1796            ) == deMath.binaryOp(
   1797                    this.m_config.buffers, deMath.binaryOp(
   1798                        gl.DEPTH_BUFFER_BIT,
   1799                        gl.STENCIL_BUFFER_BIT,
   1800                        deMath.BinaryOp.OR
   1801                    ), deMath.BinaryOp.AND
   1802            ), 'Depth/stencil buffers are not disabled or not ' +
   1803            'equal to the config\'s depth/stencil buffer state',
   1804            false, true
   1805        );
   1806 
   1807        // Recreate.
   1808        for (var ndx = 0; ndx < 2; ndx++) {
   1809            var bit = ndx == 0 ? gl.COLOR_BUFFER_BIT :
   1810                (gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT);
   1811            var type = ndx == 0 ? fbo.getConfig().colorType :
   1812                fbo.getConfig().depthStencilType;
   1813            var format = ndx == 0 ? fbo.getConfig().colorFormat :
   1814                fbo.getConfig().depthStencilFormat;
   1815            var buf = ndx == 0 ? fbo.getColorBuffer() :
   1816                fbo.getDepthStencilBuffer();
   1817 
   1818            if (deMath.binaryOp(this.m_buffers, bit, deMath.BinaryOp.AND) == 0)
   1819                continue;
   1820 
   1821            switch (type) {
   1822                case gl.TEXTURE_2D:
   1823                    ctx.deleteTexture(/** @type {WebGLTexture} */ (buf));
   1824                    buf = ctx.createTexture();
   1825                    ctx.bindTexture(gl.TEXTURE_2D, buf);
   1826                    ctx.texImage2DDelegate(
   1827                        gl.TEXTURE_2D, 0, format, width, height
   1828                    );
   1829                    ctx.texParameteri(
   1830                        gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST
   1831                    );
   1832                    ctx.texParameteri(
   1833                        gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST
   1834                    );
   1835                    break;
   1836 
   1837                case gl.RENDERBUFFER:
   1838                    ctx.deleteRenderbuffer(
   1839                        /** @type {WebGLRenderbuffer} */ (buf)
   1840                    );
   1841                    buf = ctx.createRenderbuffer();
   1842                    ctx.bindRenderbuffer(gl.RENDERBUFFER, buf);
   1843                    ctx.renderbufferStorage(
   1844                        gl.RENDERBUFFER, format, width, height
   1845                    );
   1846                    break;
   1847 
   1848                default:
   1849                    throw new Error('Unsupported buffer type');
   1850            }
   1851 
   1852            if (ndx == 0) {
   1853                fbo.m_colorBuffer = buf;
   1854            } else {
   1855                fbo.m_depthStencilBuffer = buf;
   1856            }
   1857        }
   1858 
   1859        // Rebind.
   1860        if (this.m_rebind) {
   1861            for (var ndx = 0; ndx < 3; ndx++) {
   1862                var bit = ndx == 0 ? gl.COLOR_BUFFER_BIT :
   1863                    ndx == 1 ? gl.DEPTH_BUFFER_BIT :
   1864                    ndx == 2 ? gl.STENCIL_BUFFER_BIT : 0;
   1865                var point = ndx == 0 ? gl.COLOR_ATTACHMENT0 :
   1866                    ndx == 1 ? gl.DEPTH_ATTACHMENT :
   1867                    ndx == 2 ? gl.STENCIL_ATTACHMENT : 0;
   1868                var type = ndx == 0 ? fbo.getConfig().colorType :
   1869                    fbo.getConfig().depthStencilType;
   1870                var buf = ndx == 0 ? fbo.getColorBuffer() :
   1871                    fbo.getDepthStencilBuffer();
   1872 
   1873                if (deMath.binaryOp(
   1874                        this.m_buffers, bit, deMath.BinaryOp.AND) == 0)
   1875                    continue;
   1876 
   1877                switch (type) {
   1878                    case gl.TEXTURE_2D:
   1879                        ctx.framebufferTexture2D(
   1880                            gl.FRAMEBUFFER, point, gl.TEXTURE_2D, buf, 0
   1881                        );
   1882                        break;
   1883 
   1884                    case gl.RENDERBUFFER:
   1885                        ctx.framebufferRenderbuffer(
   1886                            gl.FRAMEBUFFER, point, gl.RENDERBUFFER, buf
   1887                        );
   1888                        break;
   1889 
   1890                    default:
   1891                        throw new Error('Invalid buffer type');
   1892                }
   1893            }
   1894        }
   1895 
   1896        if (!this.m_rebind)
   1897            ctx.bindFramebuffer(gl.FRAMEBUFFER, fbo.getFramebuffer());
   1898 
   1899        ctx.clearStencil(0);
   1900 
   1901        // \note Clear only buffers that were re-created
   1902        ctx.clear(
   1903            deMath.binaryOp(
   1904                this.m_buffers,
   1905                deMath.binaryOp(
   1906                    gl.DEPTH_BUFFER_BIT,
   1907                    gl.STENCIL_BUFFER_BIT,
   1908                    deMath.BinaryOp.OR
   1909                ), deMath.BinaryOp.AND
   1910            )
   1911        );
   1912 
   1913        if (deMath.binaryOp(
   1914            this.m_buffers, gl.COLOR_BUFFER_BIT, deMath.BinaryOp.AND)) {
   1915            // Clearing of integer buffers is undefined
   1916            // so do clearing by rendering flat color.
   1917            rrUtil.drawQuad(
   1918                ctx, flatShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]
   1919            );
   1920        }
   1921 
   1922        ctx.enable(gl.DEPTH_TEST);
   1923 
   1924        if (stencil) {
   1925            // \note Stencil test enabled only if we have stencil buffer
   1926            ctx.enable(gl.STENCIL_TEST);
   1927            ctx.stencilFunc(gl.EQUAL, 0, 0xff);
   1928        }
   1929        ctx.bindTexture(gl.TEXTURE_2D, metaballsTex);
   1930        rrUtil.drawQuad(
   1931            ctx, texToFboShaderID, [-1.0, -1.0, 1.0], [1.0, 1.0, -1.0]
   1932        );
   1933        if (stencil)
   1934            ctx.disable(gl.STENCIL_TEST);
   1935 
   1936        ctx.disable(gl.DEPTH_TEST);
   1937 
   1938        if (fbo.getConfig().colorType == gl.TEXTURE_2D) {
   1939            // Unbind fbo
   1940            ctx.bindFramebuffer(gl.FRAMEBUFFER, null);
   1941 
   1942            // Draw to screen
   1943            ctx.bindTexture(gl.TEXTURE_2D, fbo.getColorBuffer());
   1944            ctx.viewport(0, 0, ctx.getWidth(), ctx.getHeight());
   1945            rrUtil.drawQuad(
   1946                ctx, texFromFboShaderID, [-1.0, -1.0, 0.0], [1.0, 1.0, 0.0]
   1947            );
   1948 
   1949            // Read from screen
   1950            dst.readViewport(ctx, [0, 0, ctx.getWidth(), ctx.getHeight()]);
   1951        } else {
   1952            // Read from fbo
   1953            es3fFboTestUtil.readPixels(
   1954                ctx, dst, 0, 0, width, height, colorFormat,
   1955                fboRangeInfo.lookupScale, fboRangeInfo.lookupBias
   1956            );
   1957        }
   1958    };
   1959 
   1960    // FboGroups
   1961 
   1962    /**
   1963     * @constructor
   1964     * @extends {tcuTestCase.DeqpTest}
   1965     */
   1966    es3fFboRenderTest.FboRenderTestGroup = function() {
   1967        tcuTestCase.DeqpTest.call(this, 'render', 'Rendering Tests');
   1968    };
   1969 
   1970    es3fFboRenderTest.FboRenderTestGroup.prototype =
   1971        Object.create(tcuTestCase.DeqpTest.prototype);
   1972 
   1973    es3fFboRenderTest.FboRenderTestGroup.prototype.constructor =
   1974        es3fFboRenderTest.FboRenderTestGroup;
   1975 
   1976    /**
   1977     * @enum {number}
   1978     */
   1979    var FormatType = {
   1980        FLOAT: 0,
   1981        INT: 1,
   1982        UINT: 2
   1983    };
   1984 
   1985    // Required by specification.
   1986    /**
   1987     * @typedef {{format: number, type: FormatType}}
   1988     */
   1989    var ColorFormatStruct;
   1990 
   1991    /**
   1992     * @typedef {{format: number, depth: boolean, stencil: boolean}}
   1993     */
   1994    var DepthStencilFormatStruct;
   1995 
   1996    /**
   1997     * init
   1998     */
   1999    es3fFboRenderTest.FboRenderTestGroup.prototype.init = function() {
   2000        var objectTypes = [
   2001            gl.TEXTURE_2D,
   2002            gl.RENDERBUFFER
   2003        ];
   2004 
   2005        /** @type {Array<ColorFormatStruct>} */ var colorFormats = [{
   2006                format: gl.RGBA32F, type: FormatType.FLOAT
   2007            },{
   2008                format: gl.RGBA32I, type: FormatType.INT
   2009            },{
   2010                format: gl.RGBA32UI, type: FormatType.UINT
   2011            },{
   2012                format: gl.RGBA16F, type: FormatType.FLOAT
   2013            },{
   2014                format: gl.RGBA16I, type: FormatType.INT
   2015            },{
   2016                format: gl.RGBA16UI, type: FormatType.UINT
   2017            },/*{
   2018                // RGB16F isn't made color-renderable through WebGL's EXT_color_buffer_float
   2019                format: gl.RGB16F, type: FormatType.FLOAT
   2020            },*/{
   2021                format: gl.RGBA8I, type: FormatType.INT
   2022            },{
   2023                format: gl.RGBA8UI, type: FormatType.UINT
   2024            },{
   2025                format: gl.RGB10_A2UI, type: FormatType.UINT
   2026            },{
   2027                format: gl.R11F_G11F_B10F, type: FormatType.FLOAT
   2028            },{
   2029                format: gl.RG32F, type: FormatType.FLOAT
   2030            },{
   2031                format: gl.RG32I, type: FormatType.INT
   2032            },{
   2033                format: gl.RG32UI, type: FormatType.UINT
   2034            },{
   2035                format: gl.RG16F, type: FormatType.FLOAT
   2036            },{
   2037                format: gl.RG16I, type: FormatType.INT
   2038            },{
   2039                format: gl.RG16UI, type: FormatType.UINT
   2040            },{
   2041                format: gl.RG8, type: FormatType.FLOAT
   2042            },{
   2043                format: gl.RG8I, type: FormatType.INT
   2044            },{
   2045                format: gl.RG8UI, type: FormatType.UINT
   2046            },{
   2047                format: gl.R32F, type: FormatType.FLOAT
   2048            },{
   2049                format: gl.R32I, type: FormatType.INT
   2050            },{
   2051                format: gl.R32UI, type: FormatType.UINT
   2052            },{
   2053                format: gl.R16F, type: FormatType.FLOAT
   2054            },{
   2055                format: gl.R16I, type: FormatType.INT
   2056            },{
   2057                format: gl.R16UI, type: FormatType.UINT
   2058            },{
   2059                format: gl.R8, type: FormatType.FLOAT
   2060            },{
   2061                format: gl.R8I, type: FormatType.INT
   2062            },{
   2063                format: gl.R8UI, type: FormatType.UINT
   2064        }];
   2065 
   2066        /** @type {Array<DepthStencilFormatStruct>} */
   2067        var depthStencilFormats = [{
   2068                format: gl.DEPTH_COMPONENT32F, depth: true, stencil: false
   2069            },{
   2070                format: gl.DEPTH_COMPONENT24, depth: true, stencil: false
   2071            },{
   2072                format: gl.DEPTH_COMPONENT16, depth: true, stencil: false
   2073            },{
   2074                format: gl.DEPTH32F_STENCIL8, depth: true, stencil: true
   2075            },{
   2076                format: gl.DEPTH24_STENCIL8, depth: true, stencil: true
   2077            },{
   2078                format: gl.STENCIL_INDEX8, depth: false, stencil: true
   2079        }];
   2080 
   2081        /** @type {es3fFboRenderTest.FboConfig} */ var config;
   2082        var colorType;
   2083        var stencilType;
   2084        var colorFmt;
   2085        var depth;
   2086        var stencil;
   2087        var depthStencilType;
   2088        var depthStencilFormat;
   2089 
   2090        // .stencil_clear
   2091        /** @type {tcuTestCase.DeqpTest} */
   2092        var stencilClearGroup = new tcuTestCase.DeqpTest(
   2093            'stencil_clear', 'Stencil buffer clears'
   2094        );
   2095 
   2096        this.addChild(stencilClearGroup);
   2097 
   2098        for (var fmtNdx = 0; fmtNdx < depthStencilFormats.length; fmtNdx++) {
   2099            colorType = gl.TEXTURE_2D;
   2100            stencilType = gl.RENDERBUFFER;
   2101            colorFmt = gl.RGBA8;
   2102 
   2103            if (!depthStencilFormats[fmtNdx].stencil)
   2104                continue;
   2105 
   2106            config = new es3fFboRenderTest.FboConfig(
   2107                gl.COLOR_BUFFER_BIT | gl.STENCIL_BUFFER_BIT,
   2108                colorType, colorFmt, stencilType,
   2109                depthStencilFormats[fmtNdx].format
   2110            );
   2111            stencilClearGroup.addChild(
   2112                new es3fFboRenderTest.StencilClearsTest(config)
   2113            );
   2114        }
   2115 
   2116        // .shared_colorbuffer_clear
   2117        /** @type {tcuTestCase.DeqpTest} */
   2118        var sharedColorbufferClearGroup = new tcuTestCase.DeqpTest(
   2119            'shared_colorbuffer_clear', 'Shader colorbuffer clears'
   2120        );
   2121 
   2122        this.addChild(sharedColorbufferClearGroup);
   2123 
   2124        for (var colorFmtNdx = 0;
   2125            colorFmtNdx < colorFormats.length;
   2126            colorFmtNdx++) {
   2127 
   2128            // Clearing of integer buffers is undefined.
   2129            if (colorFormats[colorFmtNdx].type == FormatType.INT ||
   2130                colorFormats[colorFmtNdx].type == FormatType.UINT)
   2131                continue;
   2132 
   2133            for (var typeNdx = 0; typeNdx < objectTypes.length; typeNdx++) {
   2134                config = new es3fFboRenderTest.FboConfig(
   2135                    gl.COLOR_BUFFER_BIT, objectTypes[typeNdx],
   2136                    colorFormats[colorFmtNdx].format, gl.NONE, gl.NONE
   2137                );
   2138                sharedColorbufferClearGroup.addChild(
   2139                    new es3fFboRenderTest.SharedColorbufferClearsTest(config)
   2140                );
   2141            }
   2142        }
   2143 
   2144        // .shared_colorbuffer
   2145        /** @type {Array<tcuTestCase.DeqpTest>} */ var sharedColorbufferGroup = [];
   2146        var numSharedColorbufferGroups = 3;
   2147        for (var ii = 0; ii < numSharedColorbufferGroups; ++ii) {
   2148            sharedColorbufferGroup[ii] = new tcuTestCase.DeqpTest(
   2149                'shared_colorbuffer', 'Shared colorbuffer tests'
   2150            );
   2151            this.addChild(sharedColorbufferGroup[ii]);
   2152        }
   2153 
   2154        for (var colorFmtNdx = 0; colorFmtNdx < colorFormats.length; colorFmtNdx++) {
   2155 
   2156            depthStencilType = gl.RENDERBUFFER;
   2157            depthStencilFormat = gl.DEPTH24_STENCIL8;
   2158 
   2159            // Blending with integer buffers and fp32 targets is not supported.
   2160            if (colorFormats[colorFmtNdx].type == FormatType.INT ||
   2161                colorFormats[colorFmtNdx].type == FormatType.UINT ||
   2162                colorFormats[colorFmtNdx].format == gl.RGBA32F ||
   2163                colorFormats[colorFmtNdx].format == gl.RGB32F ||
   2164                colorFormats[colorFmtNdx].format == gl.RG32F ||
   2165                colorFormats[colorFmtNdx].format == gl.R32F)
   2166                continue;
   2167 
   2168            for (var typeNdx = 0; typeNdx < objectTypes.length; typeNdx++) {
   2169                /** @type {es3fFboRenderTest.FboConfig} */
   2170                var colorOnlyConfig = new es3fFboRenderTest.FboConfig(
   2171                    gl.COLOR_BUFFER_BIT, objectTypes[typeNdx],
   2172                    colorFormats[colorFmtNdx].format, gl.NONE, gl.NONE
   2173                );
   2174                /** @type {es3fFboRenderTest.FboConfig} */
   2175                var colorDepthConfig = new es3fFboRenderTest.FboConfig(
   2176                    gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT,
   2177                    objectTypes[typeNdx], colorFormats[colorFmtNdx].format,
   2178                    depthStencilType, depthStencilFormat
   2179                );
   2180                /** @type {es3fFboRenderTest.FboConfig} */
   2181                var colorDepthStencilConfig =
   2182                    new es3fFboRenderTest.FboConfig(
   2183                        gl.COLOR_BUFFER_BIT |
   2184                        gl.DEPTH_BUFFER_BIT |
   2185                        gl.STENCIL_BUFFER_BIT,
   2186                        objectTypes[typeNdx], colorFormats[colorFmtNdx].format,
   2187                        depthStencilType, depthStencilFormat
   2188                );
   2189 
   2190                sharedColorbufferGroup[0].addChild(
   2191                    new es3fFboRenderTest.SharedColorbufferTest(colorOnlyConfig)
   2192                );
   2193 
   2194                sharedColorbufferGroup[1].addChild(
   2195                    new es3fFboRenderTest.SharedColorbufferTest(
   2196                        colorDepthConfig
   2197                    )
   2198                );
   2199 
   2200                sharedColorbufferGroup[2].addChild(
   2201                    new es3fFboRenderTest.SharedColorbufferTest(
   2202                        colorDepthStencilConfig
   2203                    )
   2204                );
   2205            }
   2206        }
   2207 
   2208        // .shared_depth_stencil
   2209        /** @type {tcuTestCase.DeqpTest} */
   2210        var sharedDepthStencilGroup = new tcuTestCase.DeqpTest(
   2211            'shared_depth_stencil', 'Shared depth and stencil buffers'
   2212        );
   2213 
   2214        this.addChild(sharedDepthStencilGroup);
   2215 
   2216        for (var fmtNdx = 0; fmtNdx < depthStencilFormats.length; fmtNdx++) {
   2217            colorType = gl.TEXTURE_2D;
   2218            colorFmt = gl.RGBA8;
   2219            depth = depthStencilFormats[fmtNdx].depth;
   2220            stencil = depthStencilFormats[fmtNdx].stencil;
   2221 
   2222            if (!depth)
   2223                continue; // Not verified.
   2224 
   2225            // Depth and stencil: both rbo and textures
   2226            for (var typeNdx = 0; typeNdx < objectTypes.length; typeNdx++) {
   2227                config = new es3fFboRenderTest.FboConfig(
   2228                    gl.COLOR_BUFFER_BIT |
   2229                    (depth ? gl.DEPTH_BUFFER_BIT : 0) |
   2230                    (stencil ? gl.STENCIL_BUFFER_BIT : 0),
   2231                    colorType, colorFmt, objectTypes[typeNdx],
   2232                    depthStencilFormats[fmtNdx].format
   2233                );
   2234 
   2235                sharedDepthStencilGroup.addChild(
   2236                    new es3fFboRenderTest.SharedDepthStencilTest(config)
   2237                );
   2238            }
   2239        }
   2240 
   2241        // .resize
   2242        /** @type {Array<tcuTestCase.DeqpTest>} */ var resizeGroup = [];
   2243        var numResizeGroups = 4;
   2244        for (var ii = 0; ii < numResizeGroups; ++ii) {
   2245            resizeGroup[ii] = new tcuTestCase.DeqpTest('resize', 'FBO resize tests');
   2246            this.addChild(resizeGroup[ii]);
   2247        }
   2248 
   2249        for (var colorFmtNdx = 0; colorFmtNdx < colorFormats.length; colorFmtNdx++) {
   2250 
   2251            var colorFormat = colorFormats[colorFmtNdx].format;
   2252 
   2253            // Color-only.
   2254            for (var typeNdx = 0; typeNdx < objectTypes.length; typeNdx++) {
   2255                config = new es3fFboRenderTest.FboConfig(
   2256                    gl.COLOR_BUFFER_BIT, objectTypes[typeNdx],
   2257                    colorFormat, gl.NONE, gl.NONE
   2258                );
   2259                resizeGroup[colorFmtNdx % numResizeGroups].addChild(new es3fFboRenderTest.ResizeTest(config));
   2260            }
   2261 
   2262            // For selected color formats tests depth & stencil variants.
   2263            if (colorFormat == gl.RGBA8 || colorFormat == gl.RGBA16F) {
   2264                for (var depthStencilFmtNdx = 0; depthStencilFmtNdx < depthStencilFormats.length; depthStencilFmtNdx++) {
   2265 
   2266                    colorType = gl.TEXTURE_2D;
   2267                    depth = depthStencilFormats[depthStencilFmtNdx].depth;
   2268                    stencil = depthStencilFormats[depthStencilFmtNdx].stencil;
   2269 
   2270                    // Depth and stencil: both rbo and textures
   2271                    for (var typeNdx = 0; typeNdx < objectTypes.length; typeNdx++) {
   2272 
   2273                        if (!depth && objectTypes[typeNdx] != gl.RENDERBUFFER)
   2274                            continue; // Not supported.
   2275 
   2276                        config = new es3fFboRenderTest.FboConfig(
   2277                            gl.COLOR_BUFFER_BIT |
   2278                            (depth ? gl.DEPTH_BUFFER_BIT : 0) |
   2279                            (stencil ? gl.STENCIL_BUFFER_BIT : 0),
   2280                            colorType, colorFormat, objectTypes[typeNdx],
   2281                            depthStencilFormats[depthStencilFmtNdx].format
   2282                        );
   2283 
   2284                        resizeGroup[colorFmtNdx % numResizeGroups].addChild(
   2285                            new es3fFboRenderTest.ResizeTest(config)
   2286                        );
   2287                    }
   2288                }
   2289            }
   2290        }
   2291 
   2292        // .recreate_color
   2293        /** @type {Array<tcuTestCase.DeqpTest>} */ var recreateColorGroup = [];
   2294        var numRecreateColorGroups = 7;
   2295        for (var ii = 0; ii < numRecreateColorGroups; ++ii) {
   2296            recreateColorGroup[ii] = new tcuTestCase.DeqpTest('recreate_color', 'Recreate colorbuffer tests');
   2297            this.addChild(recreateColorGroup[ii]);
   2298        }
   2299 
   2300        for (var colorFmtNdx = 0; colorFmtNdx < colorFormats.length; colorFmtNdx++) {
   2301 
   2302            colorFormat = colorFormats[colorFmtNdx].format;
   2303            depthStencilFormat = gl.DEPTH24_STENCIL8;
   2304            depthStencilType = gl.RENDERBUFFER;
   2305 
   2306            // Color-only.
   2307            for (var typeNdx = 0; typeNdx < objectTypes.length; typeNdx++) {
   2308                config = new es3fFboRenderTest.FboConfig(
   2309                    gl.COLOR_BUFFER_BIT |
   2310                    gl.DEPTH_BUFFER_BIT |
   2311                    gl.STENCIL_BUFFER_BIT,
   2312                    objectTypes[typeNdx], colorFormat,
   2313                    depthStencilType, depthStencilFormat
   2314                );
   2315 
   2316                recreateColorGroup[colorFmtNdx % numRecreateColorGroups].addChild(
   2317                    new es3fFboRenderTest.RecreateBuffersTest(
   2318                        config, gl.COLOR_BUFFER_BIT, true /* rebind */
   2319                    )
   2320                );
   2321            }
   2322        }
   2323 
   2324        // .recreate_depth_stencil
   2325        /** @type {tcuTestCase.DeqpTest} */
   2326        var recreateDepthStencilGroup = new tcuTestCase.DeqpTest(
   2327            'recreate_depth_stencil', 'Recreate depth and stencil buffers'
   2328        );
   2329 
   2330        this.addChild(recreateDepthStencilGroup);
   2331 
   2332        for (var fmtNdx = 0; fmtNdx < depthStencilFormats.length; fmtNdx++) {
   2333            colorType = gl.TEXTURE_2D;
   2334            colorFmt = gl.RGBA8;
   2335            depth = depthStencilFormats[fmtNdx].depth;
   2336            stencil = depthStencilFormats[fmtNdx].stencil;
   2337 
   2338            // Depth and stencil: both rbo and textures
   2339            for (var typeNdx = 0; typeNdx < objectTypes.length; typeNdx++) {
   2340                if (!depth && objectTypes[typeNdx] != gl.RENDERBUFFER)
   2341                    continue;
   2342 
   2343                config = new es3fFboRenderTest.FboConfig(
   2344                    gl.COLOR_BUFFER_BIT |
   2345                    (depth ? gl.DEPTH_BUFFER_BIT : 0) |
   2346                    (stencil ? gl.STENCIL_BUFFER_BIT : 0),
   2347                    colorType, colorFmt, objectTypes[typeNdx],
   2348                    depthStencilFormats[fmtNdx].format
   2349                );
   2350 
   2351                recreateDepthStencilGroup.addChild(
   2352                    new es3fFboRenderTest.RecreateBuffersTest(
   2353                        config,
   2354                        (depth ? gl.DEPTH_BUFFER_BIT : 0) |
   2355                        (stencil ? gl.STENCIL_BUFFER_BIT : 0),
   2356                        true /* rebind */
   2357                    )
   2358                );
   2359            }
   2360        }
   2361    };
   2362 
   2363    /**
   2364     * Create and execute the test cases
   2365     * @param {WebGL2RenderingContext} context
   2366     */
   2367    es3fFboRenderTest.run = function(context, range) {
   2368        gl = context;
   2369        //Set up Test Root parameters
   2370        var state = tcuTestCase.runner;
   2371 
   2372        state.setRoot(new es3fFboRenderTest.FboRenderTestGroup());
   2373 
   2374        //Set up name and description of this test series.
   2375        setCurrentTestName(state.testCases.fullName());
   2376        description(state.testCases.getDescription());
   2377 
   2378        try {
   2379            if (range)
   2380                state.setRange(range);
   2381            //Run test cases
   2382            tcuTestCase.runTestCases();
   2383        }
   2384        catch (err) {
   2385            testFailedOptions('Failed to run tests', false);
   2386            tcuTestCase.runner.terminate();
   2387        }
   2388    };
   2389 });