tor-browser

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

es3fFramebufferBlitTests.js (63513B)


      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 'use strict';
     21 goog.provide('functional.gles3.es3fFramebufferBlitTests');
     22 goog.require('framework.common.tcuImageCompare');
     23 goog.require('framework.common.tcuRGBA');
     24 goog.require('framework.common.tcuSurface');
     25 goog.require('framework.common.tcuTestCase');
     26 goog.require('framework.common.tcuTexture');
     27 goog.require('framework.common.tcuTextureUtil');
     28 goog.require('framework.delibs.debase.deMath');
     29 goog.require('framework.opengl.gluShaderUtil');
     30 goog.require('framework.opengl.gluTextureUtil');
     31 goog.require('framework.opengl.simplereference.sglrGLContext');
     32 goog.require('framework.opengl.simplereference.sglrReferenceContext');
     33 goog.require('framework.referencerenderer.rrUtil');
     34 goog.require('functional.gles3.es3fFboTestCase');
     35 goog.require('functional.gles3.es3fFboTestUtil');
     36 
     37 goog.scope(function() {
     38 
     39    var es3fFramebufferBlitTests = functional.gles3.es3fFramebufferBlitTests;
     40    var es3fFboTestCase = functional.gles3.es3fFboTestCase;
     41    var es3fFboTestUtil = functional.gles3.es3fFboTestUtil;
     42    var tcuTestCase = framework.common.tcuTestCase;
     43    var tcuSurface = framework.common.tcuSurface;
     44    var tcuRGBA = framework.common.tcuRGBA;
     45    var tcuImageCompare = framework.common.tcuImageCompare;
     46    var tcuTexture = framework.common.tcuTexture;
     47    var tcuTextureUtil = framework.common.tcuTextureUtil;
     48    var deMath = framework.delibs.debase.deMath;
     49    var gluTextureUtil = framework.opengl.gluTextureUtil;
     50    var gluShaderUtil = framework.opengl.gluShaderUtil;
     51    var rrUtil = framework.referencerenderer.rrUtil;
     52    var sglrReferenceContext = framework.opengl.simplereference.sglrReferenceContext;
     53    var sglrGLContext = framework.opengl.simplereference.sglrGLContext;
     54 
     55    var DE_ASSERT = function(x) {
     56        if (!x)
     57            throw new Error('Assert failed');
     58    };
     59 
     60    /** @type {WebGL2RenderingContext} */ var gl;
     61    /**
     62    * es3fFramebufferBlitTests.BlitRectCase class, inherits from FboTestCase
     63    * @constructor
     64    * @extends {es3fFboTestCase.FboTestCase}
     65    * @param {string} name
     66    * @param {string} desc
     67    * @param {number} filter deUint32
     68    * @param {Array<number>} srcSize
     69    * @param {Array<number>} srcRect
     70    * @param {Array<number>} dstSize
     71    * @param {Array<number>} dstRect
     72    * @param {number=} cellSize
     73    */
     74    es3fFramebufferBlitTests.BlitRectCase = function(name, desc, filter, srcSize, srcRect, dstSize, dstRect, cellSize) {
     75        es3fFboTestCase.FboTestCase.call(this, name, desc);
     76        /** @const {number} */ this.m_filter = filter;
     77        /** @const {Array<number>} */ this.m_srcSize = srcSize;
     78        /** @const {Array<number>} */ this.m_srcRect = srcRect;
     79        /** @const {Array<number>} */ this.m_dstSize = dstSize;
     80        /** @const {Array<number>} */ this.m_dstRect = dstRect;
     81        /** @const {number} */ this.m_cellSize = cellSize === undefined ? 8 : cellSize;
     82        /** @const {Array<number>} */ this.m_gridCellColorA = [0.2, 0.7, 0.1, 1.0];
     83        /** @const {Array<number>} */ this.m_gridCellColorB = [0.7, 0.1, 0.5, 0.8];
     84    };
     85 
     86    es3fFramebufferBlitTests.BlitRectCase.prototype = Object.create(es3fFboTestCase.FboTestCase.prototype);
     87    es3fFramebufferBlitTests.BlitRectCase.prototype.constructor = es3fFramebufferBlitTests.BlitRectCase;
     88 
     89    /**
     90    * @param {tcuSurface.Surface} dst
     91    */
     92    es3fFramebufferBlitTests.BlitRectCase.prototype.render = function(dst) {
     93        var ctx = this.getCurrentContext();
     94        /** @type {number} */ var colorFormat = gl.RGBA8;
     95 
     96        /** @type {es3fFboTestUtil.GradientShader} */
     97        var gradShader = new es3fFboTestUtil.GradientShader(
     98            gluShaderUtil.DataType.FLOAT_VEC4);
     99        /** @type {es3fFboTestUtil.Texture2DShader} */
    100        var texShader = new es3fFboTestUtil.Texture2DShader(
    101            [gluShaderUtil.DataType.SAMPLER_2D],
    102            gluShaderUtil.DataType.FLOAT_VEC4);
    103 
    104        var gradShaderID = ctx.createProgram(gradShader);
    105        var texShaderID = ctx.createProgram(texShader);
    106 
    107        var srcFbo;
    108        var dstFbo;
    109        var srcRbo;
    110        var dstRbo;
    111 
    112        // Setup shaders
    113        gradShader.setGradient(ctx, gradShaderID, [0.0, 0.0, 0.0, 0.0], [1.0, 1.0, 1.0, 1.0]);
    114        texShader.setUniforms(ctx, texShaderID);
    115 
    116        // Create framebuffers.
    117 
    118        /** @type {Array<number>} */ var size;
    119 
    120        // source framebuffers
    121        srcFbo = ctx.createFramebuffer();
    122        srcRbo = ctx.createRenderbuffer();
    123        size = this.m_srcSize;
    124 
    125        ctx.bindRenderbuffer(gl.RENDERBUFFER, srcRbo);
    126        ctx.renderbufferStorage(gl.RENDERBUFFER, colorFormat, size[0], size[1]);
    127        ctx.bindFramebuffer(gl.FRAMEBUFFER, srcFbo);
    128        ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, srcRbo);
    129        this.checkError();
    130        this.checkFramebufferStatus(gl.FRAMEBUFFER);
    131 
    132        // destination framebuffers
    133        dstFbo = ctx.createFramebuffer();
    134        dstRbo = ctx.createRenderbuffer();
    135        size = this.m_dstSize;
    136 
    137        ctx.bindRenderbuffer(gl.RENDERBUFFER, dstRbo);
    138        ctx.renderbufferStorage(gl.RENDERBUFFER, colorFormat, size[0], size[1]);
    139        ctx.bindFramebuffer(gl.FRAMEBUFFER, dstFbo);
    140        ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, dstRbo);
    141        this.checkError();
    142        this.checkFramebufferStatus(gl.FRAMEBUFFER);
    143 
    144        // Fill destination with gradient.
    145        ctx.bindFramebuffer(gl.FRAMEBUFFER, dstFbo);
    146        ctx.viewport(0, 0, this.m_dstSize[0], this.m_dstSize[1]);
    147 
    148        rrUtil.drawQuad(ctx, gradShaderID, [-1, -1, 0], [1, 1, 0]);
    149 
    150        // Fill source with grid pattern.
    151        /** @const {number} */ var format = gl.RGBA;
    152        /** @const {number} */ var dataType = gl.UNSIGNED_BYTE;
    153        /** @const {number} */ var texW = this.m_srcSize[0];
    154        /** @const {number} */ var texH = this.m_srcSize[1];
    155        var gridTex;
    156        /** @type {tcuTexture.TextureLevel} */ var data = new tcuTexture.TextureLevel(gluTextureUtil.mapGLTransferFormat(format, dataType), texW, texH, 1);
    157 
    158        tcuTextureUtil.fillWithGrid(data.getAccess(), this.m_cellSize, this.m_gridCellColorA, this.m_gridCellColorB);
    159 
    160        gridTex = ctx.createTexture();
    161        ctx.bindTexture(gl.TEXTURE_2D, gridTex);
    162        ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    163        ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
    164        ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
    165        ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
    166        ctx.texImage2D(gl.TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr());
    167 
    168        ctx.bindFramebuffer(gl.FRAMEBUFFER, srcFbo);
    169        ctx.viewport(0, 0, this.m_srcSize[0], this.m_srcSize[1]);
    170 
    171        rrUtil.drawQuad(ctx, texShaderID, [-1, -1, 0], [1, 1, 0]);
    172 
    173        // Perform copy.
    174        ctx.bindFramebuffer(gl.READ_FRAMEBUFFER, srcFbo);
    175        ctx.bindFramebuffer(gl.DRAW_FRAMEBUFFER, dstFbo);
    176        ctx.blitFramebuffer(this.m_srcRect[0], this.m_srcRect[1], this.m_srcRect[2], this.m_srcRect[3],
    177                           this.m_dstRect[0], this.m_dstRect[1], this.m_dstRect[2], this.m_dstRect[3],
    178                           gl.COLOR_BUFFER_BIT, this.m_filter);
    179 
    180        // Read back results.
    181        ctx.bindFramebuffer(gl.READ_FRAMEBUFFER, dstFbo);
    182 
    183        this.readPixelsUsingFormat(dst, 0, 0, this.m_dstSize[0], this.m_dstSize[1],
    184                                          gluTextureUtil.mapGLInternalFormat(colorFormat),
    185                                          [1.0, 1.0, 1.0, 1.0],
    186                                          [0.0, 0.0, 0.0, 0.0]);
    187    };
    188 
    189    /**
    190    * @param {tcuSurface.Surface} reference
    191    * @param {tcuSurface.Surface} result
    192    * @return {boolean}
    193    */
    194    es3fFramebufferBlitTests.BlitRectCase.prototype.compare = function(reference, result) {
    195        // Use pixel-threshold compare for rect cases since 1px off will mean failure.
    196        var threshold = [7, 7, 7, 7];
    197        return tcuImageCompare.pixelThresholdCompare('Result', 'Image comparison result', reference, result, threshold);
    198    };
    199 
    200    /**
    201    * es3fFramebufferBlitTests.BlitNearestFilterConsistencyCase class
    202    * @constructor
    203    * @extends {es3fFramebufferBlitTests.BlitRectCase}
    204    * @param {string} name
    205    * @param {string} desc
    206    * @param {Array<number>} srcSize
    207    * @param {Array<number>} srcRect
    208    * @param {Array<number>} dstSize
    209    * @param {Array<number>} dstRect
    210    */
    211    es3fFramebufferBlitTests.BlitNearestFilterConsistencyCase = function(name, desc, srcSize, srcRect, dstSize, dstRect) {
    212        es3fFramebufferBlitTests.BlitRectCase.call(this, name, desc, gl.NEAREST, srcSize, srcRect, dstSize, dstRect, 1);
    213    };
    214 
    215    es3fFramebufferBlitTests.BlitNearestFilterConsistencyCase.prototype = Object.create(es3fFramebufferBlitTests.BlitRectCase.prototype);
    216    es3fFramebufferBlitTests.BlitNearestFilterConsistencyCase.prototype.constructor = es3fFramebufferBlitTests.BlitNearestFilterConsistencyCase;
    217 
    218    /**
    219    * @param {tcuSurface.Surface} reference
    220    * @param {tcuSurface.Surface} result
    221    * @return {boolean}
    222    */
    223    es3fFramebufferBlitTests.BlitNearestFilterConsistencyCase.prototype.compare = function(reference, result) {
    224        assertMsgOptions(result.getWidth() == reference.getWidth() && result.getHeight() == reference.getHeight(),
    225            'Reference and result images have different dimensions', false, true);
    226 
    227        // Image origin must be visible (for baseColor)
    228        DE_ASSERT(Math.min(this.m_dstRect[0], this.m_dstRect[2]) >= 0);
    229        DE_ASSERT(Math.min(this.m_dstRect[1], this.m_dstRect[3]) >= 0);
    230        /** @const {tcuRGBA.RGBA} */ var cellColorA = tcuRGBA.newRGBAFromVec(this.m_gridCellColorA);
    231        /** @const {tcuRGBA.RGBA} */ var cellColorB = tcuRGBA.newRGBAFromVec(this.m_gridCellColorB);
    232        // TODO: implement
    233        // const tcu::RGBA threshold = this.m_context.getRenderTarget().getPixelFormat().getColorThreshold() + tcu::RGBA(7,7,7,7);
    234        /** @type {tcuRGBA.RGBA} */ var threshold = tcuRGBA.newRGBAComponents(7, 7, 7, 7);
    235        /** @const {Array<number>} */  //IVec4.xyzw
    236        var destinationArea = [
    237            deMath.clamp(Math.min(this.m_dstRect[0], this.m_dstRect[2]), 0, result.getWidth()),
    238            deMath.clamp(Math.min(this.m_dstRect[1], this.m_dstRect[3]), 0, result.getHeight()),
    239            deMath.clamp(Math.max(this.m_dstRect[0], this.m_dstRect[2]), 0, result.getWidth()),
    240            deMath.clamp(Math.max(this.m_dstRect[1], this.m_dstRect[3]), 0, result.getHeight())];
    241 
    242        /** @const {tcuRGBA.RGBA} */ var baseColor = new tcuRGBA.RGBA(result.getPixel(destinationArea[0], destinationArea[1]));
    243 
    244        /** @const {boolean} */ var signConfig = tcuRGBA.compareThreshold(baseColor, cellColorA, threshold);
    245 
    246        /** @type {boolean} */ var error = false;
    247        /** @type {tcuSurface.Surface} */ var errorMask = new tcuSurface.Surface(result.getWidth(), result.getHeight());
    248        /** @type {Array<boolean>} */ var horisontalSign = [];
    249        /** @type {Array<boolean>} */ var verticalSign = [];
    250 
    251        errorMask.getAccess().clear([0.0, 1.0, 0.0, 1.0]);
    252 
    253        // Checking only area in our destination rect
    254 
    255        // m_testCtx.getLog()
    256        //     << tcu::TestLog::Message
    257        //     << 'Verifying consistency of NEAREST filtering. Verifying rect ' << m_dstRect << '.\n'
    258        //     << 'Rounding direction of the NEAREST filter at the horisontal texel edge (x = n + 0.5) should not depend on the y-coordinate.\n'
    259        //     << 'Rounding direction of the NEAREST filter at the vertical texel edge (y = n + 0.5) should not depend on the x-coordinate.\n'
    260        //     << 'Blitting a grid (with uniform sized cells) should result in a grid (with non-uniform sized cells).'
    261        //     << tcu::TestLog::EndMessage;
    262 
    263        // Verify that destination only contains valid colors
    264 
    265        /** @type {tcuRGBA.RGBA} */ var color;
    266 
    267        for (var dy = 0; dy < destinationArea[3] - destinationArea[1]; ++dy) {
    268            for (var dx = 0; dx < destinationArea[2] - destinationArea[0]; ++dx) {
    269                color = new tcuRGBA.RGBA(result.getPixel(destinationArea[0] + dx, destinationArea[1] + dy));
    270 
    271                /** @const {boolean} */
    272                var isValidColor =
    273                            tcuRGBA.compareThreshold(color, cellColorA, threshold) ||
    274                            tcuRGBA.compareThreshold(color, cellColorB, threshold);
    275 
    276                if (!isValidColor) {
    277                    errorMask.setPixel(destinationArea[0] + dx, destinationArea[1] + dy, tcuRGBA.RGBA.red.toVec());
    278                    error = true;
    279                }
    280            }
    281        }
    282 
    283        if (error) {
    284            // m_testCtx.getLog()
    285            //     << tcu::TestLog::Message
    286            //     << 'Image verification failed, destination rect contains unexpected values. '
    287            //     << 'Expected either ' << cellColorA << ' or ' << cellColorB << '.'
    288            //     << tcu::TestLog::EndMessage
    289            //     << tcu::TestLog::ImageSet('Result', 'Image verification result')
    290            //     << tcu::TestLog::Image('Result', 'Result', result)
    291            //     << tcu::TestLog::Image('ErrorMask', 'Error mask', errorMask)
    292            //     << tcu::TestLog::EndImageSet;
    293            return false;
    294        }
    295 
    296        // Detect result edges by reading the first row and first column of the blitted area.
    297        // Blitting a grid should result in a grid-like image. ('sign changes' should be consistent)
    298 
    299        for (var dx = 0; dx < destinationArea[2] - destinationArea[0]; ++dx) {
    300            color = new tcuRGBA.RGBA(result.getPixel(destinationArea[0] + dx, destinationArea[1]));
    301            if (tcuRGBA.compareThreshold(color, cellColorA, threshold))
    302                horisontalSign[dx] = true;
    303            else if (tcuRGBA.compareThreshold(color, cellColorB, threshold))
    304                horisontalSign[dx] = false;
    305            else
    306                DE_ASSERT(false);
    307        }
    308        for (var dy = 0; dy < destinationArea[3] - destinationArea[1]; ++dy) {
    309            color = new tcuRGBA.RGBA(result.getPixel(destinationArea[0], destinationArea[1] + dy));
    310 
    311            if (tcuRGBA.compareThreshold(color, cellColorA, threshold))
    312                verticalSign[dy] = true;
    313            else if (tcuRGBA.compareThreshold(color, cellColorB, threshold))
    314                verticalSign[dy] = false;
    315            else
    316                DE_ASSERT(false);
    317        }
    318 
    319        // Verify grid-like image
    320 
    321        for (var dy = 0; dy < destinationArea[3] - destinationArea[1]; ++dy) {
    322            for (var dx = 0; dx < destinationArea[2] - destinationArea[0]; ++dx) {
    323                color = new tcuRGBA.RGBA(result.getPixel(destinationArea[0] + dx, destinationArea[1] + dy));
    324                /** @const {boolean} */ var resultSign = tcuRGBA.compareThreshold(cellColorA, color, threshold);
    325                /** @const {boolean} */ var correctSign = (horisontalSign[dx] == verticalSign[dy]) == signConfig;
    326 
    327                if (resultSign != correctSign) {
    328                    errorMask.setPixel(destinationArea[0] + dx, destinationArea[1] + dy, tcuRGBA.RGBA.red.toVec());
    329                    error = true;
    330                }
    331            }
    332        }
    333        // Report result
    334 
    335        // if (error)
    336        // {
    337        //     m_testCtx.getLog()
    338        //         << tcu::TestLog::Message
    339        //         << 'Image verification failed, nearest filter is not consistent.'
    340        //         << tcu::TestLog::EndMessage
    341        //         << tcu::TestLog::ImageSet('Result', 'Image verification result')
    342        //         << tcu::TestLog::Image('Result', 'Result', result)
    343        //         << tcu::TestLog::Image('ErrorMask', 'Error mask', errorMask)
    344        //         << tcu::TestLog::EndImageSet;
    345        // }
    346        // else
    347        // {
    348        //     m_testCtx.getLog()
    349        //         << tcu::TestLog::Message
    350        //         << 'Image verification passed.'
    351        //         << tcu::TestLog::EndMessage
    352        //         << tcu::TestLog::ImageSet('Result', 'Image verification result')
    353        //         << tcu::TestLog::Image('Result', 'Result', result)
    354        //         << tcu::TestLog::EndImageSet;
    355        // }
    356 
    357        return !error;
    358    };
    359 
    360    /**
    361    * es3fFramebufferBlitTests.FramebufferBlitTests class, inherits from TestCase
    362    * @constructor
    363    * @extends {tcuTestCase.DeqpTest}
    364    */
    365    es3fFramebufferBlitTests.FramebufferBlitTests = function() {
    366        tcuTestCase.DeqpTest.call(this, 'blit', 'Framebuffer blit tests');
    367    };
    368 
    369    es3fFramebufferBlitTests.FramebufferBlitTests.prototype = Object.create(tcuTestCase.DeqpTest.prototype);
    370    es3fFramebufferBlitTests.FramebufferBlitTests.prototype.constructor = es3fFramebufferBlitTests.FramebufferBlitTests;
    371 
    372    es3fFramebufferBlitTests.FramebufferBlitTests.prototype.init = function() {
    373        /** @const {Array<number>} */ var colorFormats = [
    374            // RGBA formats
    375            gl.RGBA32I,
    376            gl.RGBA32UI,
    377            gl.RGBA16I,
    378            gl.RGBA16UI,
    379            gl.RGBA8,
    380            gl.RGBA8I,
    381            gl.RGBA8UI,
    382            gl.SRGB8_ALPHA8,
    383            gl.RGB10_A2,
    384            gl.RGB10_A2UI,
    385            gl.RGBA4,
    386            gl.RGB5_A1,
    387 
    388            // RGB formats
    389            gl.RGB8,
    390            gl.RGB565,
    391 
    392            // RG formats
    393            gl.RG32I,
    394            gl.RG32UI,
    395            gl.RG16I,
    396            gl.RG16UI,
    397            gl.RG8,
    398            gl.RG8I,
    399            gl.RG8UI,
    400 
    401            // R formats
    402            gl.R32I,
    403            gl.R32UI,
    404            gl.R16I,
    405            gl.R16UI,
    406            gl.R8,
    407            gl.R8I,
    408            gl.R8UI,
    409 
    410            // gl.EXT_color_buffer_float
    411            gl.RGBA32F,
    412            gl.RGBA16F,
    413            gl.R11F_G11F_B10F,
    414            gl.RG32F,
    415            gl.RG16F,
    416            gl.R32F,
    417            gl.R16F
    418        ];
    419 
    420        /** @const {Array<number>} */ var depthStencilFormats = [
    421            gl.DEPTH_COMPONENT32F,
    422            gl.DEPTH_COMPONENT24,
    423            gl.DEPTH_COMPONENT16,
    424            gl.DEPTH32F_STENCIL8,
    425            gl.DEPTH24_STENCIL8,
    426            gl.STENCIL_INDEX8
    427        ];
    428 
    429        // .rect
    430        /** @constructor
    431         * @param {string} name
    432         * @param {Array<number>} srcRect
    433         * @param {Array<number>} dstRect
    434         */
    435        var CopyRect = function(name, srcRect, dstRect) {
    436            /** @const {string} */ this.name = name;
    437            /** @type {Array<number>} */ this.srcRect = srcRect;
    438            /** @type {Array<number>} */ this.dstRect = dstRect;
    439        };
    440 
    441        /** @const {Array<CopyRect>} */ var copyRects = [
    442            new CopyRect('basic', [10, 20, 65, 100], [45, 5, 100, 85]),
    443            new CopyRect('scale', [10, 20, 65, 100], [25, 30, 125, 94]),
    444            new CopyRect('out_of_bounds', [-10, -15, 100, 63], [50, 30, 136, 144])
    445        ];
    446 
    447        /** @const {Array<CopyRect>} */ var filterConsistencyRects = [
    448 
    449            new CopyRect('mag', [20, 10, 74, 88], [10, 10, 91, 101]),
    450            new CopyRect('min', [10, 20, 78, 100], [20, 20, 71, 80]),
    451            new CopyRect('out_of_bounds_mag', [21, 10, 73, 82], [11, 43, 141, 151]),
    452            new CopyRect('out_of_bounds_min', [11, 21, 77, 97], [80, 82, 135, 139])
    453        ];
    454 
    455        /** @constructor
    456         * @param {?string} name
    457         * @param {Array<number>} srcSwizzle
    458         * @param {Array<number>} dstSwizzle
    459         */
    460        var Swizzle = function(name, srcSwizzle, dstSwizzle) {
    461            /** @const {?string} */ this.name = name;
    462            /** @type {Array<number>} */ this.srcSwizzle = srcSwizzle;
    463            /** @type {Array<number>} */ this.dstSwizzle = dstSwizzle;
    464        };
    465 
    466        /** @const {Array<Swizzle>} */ var swizzles = [
    467            new Swizzle(null, [0, 1, 2, 3], [0, 1, 2, 3]),
    468            new Swizzle('reverse_src_x', [2, 1, 0, 3], [0, 1, 2, 3]),
    469            new Swizzle('reverse_src_y', [0, 3, 2, 1], [0, 1, 2, 3]),
    470            new Swizzle('reverse_dst_x', [0, 1, 2, 3], [2, 1, 0, 3]),
    471            new Swizzle('reverse_dst_y', [0, 1, 2, 3], [0, 3, 2, 1]),
    472            new Swizzle('reverse_src_dst_x', [2, 1, 0, 3], [2, 1, 0, 3]),
    473            new Swizzle('reverse_src_dst_y', [0, 3, 2, 1], [0, 3, 2, 1])
    474        ];
    475 
    476        /** @const {Array<number>} */ var srcSize = [127, 119];
    477        /** @const {Array<number>} */ var dstSize = [132, 128];
    478 
    479        // Blit rectangle tests.
    480        for (var rectNdx = 0; rectNdx < copyRects.length; rectNdx++) {
    481            /** @type {tcuTestCase.DeqpTest} */ var rectGroup = tcuTestCase.newTest('rect', 'Blit rectangle tests');
    482            this.addChild(rectGroup);
    483 
    484            for (var swzNdx = 0; swzNdx < swizzles.length; swzNdx++) {
    485                /** @type {string} */ var name = copyRects[rectNdx].name + (swizzles[swzNdx].name ? ('_' + swizzles[swzNdx].name) : '');
    486                /** @type {Array<number>} */ var srcSwz = swizzles[swzNdx].srcSwizzle;
    487                /** @type {Array<number>} */ var dstSwz = swizzles[swzNdx].dstSwizzle;
    488                /** @type {Array<number>} */ var srcRect = deMath.swizzle(copyRects[rectNdx].srcRect, srcSwz);
    489                /** @type {Array<number>} */ var dstRect = deMath.swizzle(copyRects[rectNdx].dstRect, dstSwz);
    490 
    491                rectGroup.addChild(new es3fFramebufferBlitTests.BlitRectCase((name + '_nearest'), '', gl.NEAREST, srcSize, srcRect, dstSize, dstRect));
    492                rectGroup.addChild(new es3fFramebufferBlitTests.BlitRectCase((name + '_linear'), '', gl.LINEAR, srcSize, srcRect, dstSize, dstRect));
    493            }
    494        }
    495 
    496        // Nearest filter tests
    497        for (var rectNdx = 0; rectNdx < filterConsistencyRects.length; rectNdx++) {
    498            /** @type {tcuTestCase.DeqpTest} */ var rectGroup = tcuTestCase.newTest('rect', 'Blit rectangle tests');
    499            this.addChild(rectGroup);
    500            for (var swzNdx = 0; swzNdx < swizzles.length; swzNdx++) {
    501                var name = 'nearest_consistency_' + filterConsistencyRects[rectNdx].name + (swizzles[swzNdx].name ? ('_' + swizzles[swzNdx].name) : '');
    502                var srcSwz = swizzles[swzNdx].srcSwizzle;
    503                var dstSwz = swizzles[swzNdx].dstSwizzle;
    504                var srcRect = deMath.swizzle(filterConsistencyRects[rectNdx].srcRect, srcSwz);
    505                var dstRect = deMath.swizzle(filterConsistencyRects[rectNdx].dstRect, dstSwz);
    506 
    507                rectGroup.addChild(new es3fFramebufferBlitTests.BlitNearestFilterConsistencyCase(name, 'Test consistency of the nearest filter', srcSize, srcRect, dstSize, dstRect));
    508            }
    509        }
    510 
    511        // .conversion
    512        for (var srcFmtNdx = 0; srcFmtNdx < colorFormats.length; srcFmtNdx++) {
    513            /** @type {tcuTestCase.DeqpTest} */ var conversionGroup = tcuTestCase.newTest('conversion', 'Color conversion tests');
    514            this.addChild(conversionGroup);
    515            for (var dstFmtNdx = 0; dstFmtNdx < colorFormats.length; dstFmtNdx++) {
    516                /** @type {number} */ var srcFormat = colorFormats[srcFmtNdx];
    517                /** @type {tcuTexture.TextureFormat} */ var srcTexFmt = gluTextureUtil.mapGLInternalFormat(srcFormat);
    518                /** @type {tcuTexture.TextureChannelClass} */ var srcType = tcuTexture.getTextureChannelClass(srcTexFmt.type);
    519                /** @type {number} */ var dstFormat = colorFormats[dstFmtNdx];
    520                /** @type {tcuTexture.TextureFormat} */ var dstTexFmt = gluTextureUtil.mapGLInternalFormat(dstFormat);
    521                /** @type {tcuTexture.TextureChannelClass} */ var dstType = tcuTexture.getTextureChannelClass(dstTexFmt.type);
    522 
    523                if (((srcType == tcuTexture.TextureChannelClass.FLOATING_POINT || srcType == tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT) !=
    524                     (dstType == tcuTexture.TextureChannelClass.FLOATING_POINT || dstType == tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT)) ||
    525                    ((srcType == tcuTexture.TextureChannelClass.SIGNED_INTEGER) != (dstType == tcuTexture.TextureChannelClass.SIGNED_INTEGER)) ||
    526                    ((srcType == tcuTexture.TextureChannelClass.UNSIGNED_INTEGER) != (dstType == tcuTexture.TextureChannelClass.UNSIGNED_INTEGER)))
    527                    continue; // Conversion not supported.
    528 
    529                var name = es3fFboTestUtil.getFormatName(srcFormat) + '_to_' + es3fFboTestUtil.getFormatName(dstFormat);
    530 
    531                conversionGroup.addChild(new es3fFramebufferBlitTests.BlitColorConversionCase(name, '', srcFormat, dstFormat, [127, 113]));
    532            }
    533        }
    534 
    535        // .depth_stencil
    536        /** @type {tcuTestCase.DeqpTest} */ var depthStencilGroup = tcuTestCase.newTest('depth_stencil', 'Depth and stencil blits');
    537        this.addChild(depthStencilGroup);
    538 
    539        for (var fmtNdx = 0; fmtNdx < depthStencilFormats.length; fmtNdx++) {
    540            /** @type {number} */ var format = depthStencilFormats[fmtNdx];
    541            /** @type {tcuTexture.TextureFormat} */ var texFmt = gluTextureUtil.mapGLInternalFormat(format);
    542            /** @type {string} */ var fmtName = es3fFboTestUtil.getFormatName(format);
    543            /** @type {boolean} */ var depth = texFmt.order == tcuTexture.ChannelOrder.D || texFmt.order == tcuTexture.ChannelOrder.DS;
    544            /** @type {boolean} */ var stencil = texFmt.order == tcuTexture.ChannelOrder.S || texFmt.order == tcuTexture.ChannelOrder.DS;
    545            /** @type {number} */ var buffers = (depth ? gl.DEPTH_BUFFER_BIT : 0) | (stencil ? gl.STENCIL_BUFFER_BIT : 0);
    546 
    547            depthStencilGroup.addChild(new es3fFramebufferBlitTests.BlitDepthStencilCase((fmtName + '_basic'), '', format, buffers, [128, 128], [0, 0, 128, 128], buffers, [128, 128], [0, 0, 128, 128], buffers));
    548            depthStencilGroup.addChild(new es3fFramebufferBlitTests.BlitDepthStencilCase((fmtName + '_scale'), '', format, buffers, [127, 119], [10, 30, 100, 70], buffers, [111, 130], [20, 5, 80, 130], buffers));
    549 
    550            if (depth && stencil) {
    551                depthStencilGroup.addChild(new es3fFramebufferBlitTests.BlitDepthStencilCase((fmtName + '_depth_only'), '', format, buffers, [128, 128], [0, 0, 128, 128], buffers, [128, 128], [0, 0, 128, 128], gl.DEPTH_BUFFER_BIT));
    552                depthStencilGroup.addChild(new es3fFramebufferBlitTests.BlitDepthStencilCase((fmtName + '_stencil_only'), '', format, buffers, [128, 128], [0, 0, 128, 128], buffers, [128, 128], [0, 0, 128, 128], gl.STENCIL_BUFFER_BIT));
    553            }
    554        }
    555 
    556        // .default_framebuffer
    557        /**
    558         * @constructor
    559         * @param {string} name
    560         * @param {es3fFramebufferBlitTests.BlitArea} area
    561         */
    562        var Area = function(name, area) {
    563            /** @type {string} name */ this.name = name;
    564            /** @type {es3fFramebufferBlitTests.BlitArea} area */ this.area = area;
    565        };
    566 
    567        /** @type {Array<Area>} */ var areas = [
    568            new Area('scale', es3fFramebufferBlitTests.BlitArea.AREA_SCALE),
    569            new Area('out_of_bounds', es3fFramebufferBlitTests.BlitArea.AREA_OUT_OF_BOUNDS)
    570        ];
    571 
    572        var numDefaultFbSubGroups = 7;
    573        /** @type {Array<tcuTestCase.DeqpTest>} */ var defaultFbGroup = [];
    574        for (var ii = 0; ii < numDefaultFbSubGroups; ++ii) {
    575            defaultFbGroup[ii] = tcuTestCase.newTest('default_framebuffer', 'Blits with default framebuffer');
    576            this.addChild(defaultFbGroup[ii]);
    577        }
    578        for (var fmtNdx = 0; fmtNdx < colorFormats.length; fmtNdx++) {
    579            var format = colorFormats[fmtNdx];
    580            var texFmt = gluTextureUtil.mapGLInternalFormat(format);
    581            var fmtClass = tcuTexture.getTextureChannelClass(texFmt.type);
    582            var filter = gluTextureUtil.isGLInternalColorFormatFilterable(format) ? gl.LINEAR : gl.NEAREST;
    583            var filterable = gluTextureUtil.isGLInternalColorFormatFilterable(format);
    584 
    585            if (fmtClass != tcuTexture.TextureChannelClass.FLOATING_POINT &&
    586                fmtClass != tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT &&
    587                fmtClass != tcuTexture.TextureChannelClass.SIGNED_FIXED_POINT)
    588                continue; // Conversion not supported.
    589 
    590            defaultFbGroup[fmtNdx % numDefaultFbSubGroups].addChild(new es3fFramebufferBlitTests.BlitDefaultFramebufferCase(es3fFboTestUtil.getFormatName(format), '', format, filter));
    591 
    592            for (var areaNdx = 0; areaNdx < areas.length; areaNdx++) {
    593                var name = areas[areaNdx].name;
    594                var addLinear = filterable;
    595                var addNearest = !addLinear || (areas[areaNdx].area != es3fFramebufferBlitTests.BlitArea.AREA_OUT_OF_BOUNDS); // No need to check out-of-bounds with different filtering
    596 
    597                if (addNearest) {
    598 
    599                    defaultFbGroup[fmtNdx % numDefaultFbSubGroups].addChild(new es3fFramebufferBlitTests.DefaultFramebufferBlitCase((es3fFboTestUtil.getFormatName(format) + '_nearest_' + name + '_blit_from_default'), '', format, gl.NEAREST, es3fFramebufferBlitTests.BlitDirection.BLIT_DEFAULT_TO_TARGET, areas[areaNdx].area));
    600                    defaultFbGroup[fmtNdx % numDefaultFbSubGroups].addChild(new es3fFramebufferBlitTests.DefaultFramebufferBlitCase((es3fFboTestUtil.getFormatName(format) + '_nearest_' + name + '_blit_to_default'), '', format, gl.NEAREST, es3fFramebufferBlitTests.BlitDirection.BLIT_TO_DEFAULT_FROM_TARGET, areas[areaNdx].area));
    601                }
    602 
    603                if (addLinear) {
    604                    defaultFbGroup[fmtNdx % numDefaultFbSubGroups].addChild(new es3fFramebufferBlitTests.DefaultFramebufferBlitCase((es3fFboTestUtil.getFormatName(format) + '_linear_' + name + '_blit_from_default'), '', format, gl.LINEAR, es3fFramebufferBlitTests.BlitDirection.BLIT_DEFAULT_TO_TARGET, areas[areaNdx].area));
    605                    defaultFbGroup[fmtNdx % numDefaultFbSubGroups].addChild(new es3fFramebufferBlitTests.DefaultFramebufferBlitCase((es3fFboTestUtil.getFormatName(format) + '_linear_' + name + '_blit_to_default'), '', format, gl.LINEAR, es3fFramebufferBlitTests.BlitDirection.BLIT_TO_DEFAULT_FROM_TARGET, areas[areaNdx].area));
    606                }
    607            }
    608        }
    609    };
    610 
    611    /**
    612     * @param {?tcuTexture.ChannelOrder} order
    613     * @return {Array<boolean>}
    614     */
    615    es3fFramebufferBlitTests.getChannelMask = function(order) {
    616        switch (order) {
    617            case tcuTexture.ChannelOrder.R: return [true, false, false, false];
    618            case tcuTexture.ChannelOrder.RG: return [true, true, false, false];
    619            case tcuTexture.ChannelOrder.RGB: return [true, true, true, false];
    620            case tcuTexture.ChannelOrder.RGBA: return [true, true, true, true];
    621            case tcuTexture.ChannelOrder.sRGB: return [true, true, true, false];
    622            case tcuTexture.ChannelOrder.sRGBA: return [true, true, true, true];
    623            default:
    624                DE_ASSERT(false);
    625                return [false, false, false, false];
    626        }
    627    };
    628 
    629    /**
    630     * es3fFramebufferBlitTests.BlitColorConversionCase class, inherits from FboTestCase
    631     * @constructor
    632     * @extends {es3fFboTestCase.FboTestCase}
    633     * @param {string} name
    634     * @param {string} desc
    635     * @param {number} srcFormat
    636     * @param {number} dstFormat
    637     * @param {Array<number>} size
    638     */
    639    es3fFramebufferBlitTests.BlitColorConversionCase = function(name, desc, srcFormat, dstFormat, size) {
    640        es3fFboTestCase.FboTestCase.call(this, name, desc);
    641        /** @type {number} */ this.m_srcFormat = srcFormat;
    642        /** @type {number} */ this.m_dstFormat = dstFormat;
    643        /** @type {Array<number>} */ this.m_size = size;
    644    };
    645 
    646    es3fFramebufferBlitTests.BlitColorConversionCase.prototype = Object.create(es3fFboTestCase.FboTestCase.prototype);
    647    es3fFramebufferBlitTests.BlitColorConversionCase.prototype.constructor = es3fFramebufferBlitTests.BlitColorConversionCase;
    648 
    649    es3fFramebufferBlitTests.BlitColorConversionCase.prototype.preCheck = function() {
    650        this.checkFormatSupport(this.m_srcFormat);
    651        this.checkFormatSupport(this.m_dstFormat);
    652        return true; // No exception thrown
    653    };
    654 
    655    /**
    656     * @param {tcuSurface.Surface} dst
    657     */
    658    es3fFramebufferBlitTests.BlitColorConversionCase.prototype.render = function(dst) {
    659        var ctx = this.getCurrentContext();
    660        /** @type {tcuTexture.TextureFormat} */ var srcFormat = gluTextureUtil.mapGLInternalFormat(this.m_srcFormat);
    661        /** @type {tcuTexture.TextureFormat} */ var dstFormat = gluTextureUtil.mapGLInternalFormat(this.m_dstFormat);
    662 
    663        /** @type {gluShaderUtil.DataType} */ var srcOutputType = es3fFboTestUtil.getFragmentOutputType(srcFormat);
    664        /** @type {gluShaderUtil.DataType} */ var dstOutputType = es3fFboTestUtil.getFragmentOutputType(dstFormat);
    665 
    666        // Compute ranges \note Doesn't handle case where src or dest is not subset of the another!
    667        /** @type {tcuTextureUtil.TextureFormatInfo} */ var srcFmtRangeInfo = tcuTextureUtil.getTextureFormatInfo(srcFormat);
    668        /** @type {tcuTextureUtil.TextureFormatInfo} */ var dstFmtRangeInfo = tcuTextureUtil.getTextureFormatInfo(dstFormat);
    669 
    670        /** @type {Array<boolean>} */ var copyMask = deMath.logicalAndBool(es3fFramebufferBlitTests.getChannelMask(srcFormat.order), es3fFramebufferBlitTests.getChannelMask(dstFormat.order));
    671        /** @type {Array<boolean>} */ var srcIsGreater = deMath.greaterThan(deMath.subtract(srcFmtRangeInfo.valueMax, srcFmtRangeInfo.valueMin), deMath.subtract(dstFmtRangeInfo.valueMax, dstFmtRangeInfo.valueMin));
    672 
    673        /** @type {tcuTextureUtil.TextureFormatInfo} */ var srcRangeInfo = new tcuTextureUtil.TextureFormatInfo(
    674                                                     tcuTextureUtil.select(dstFmtRangeInfo.valueMin, srcFmtRangeInfo.valueMin, deMath.logicalAndBool(copyMask, srcIsGreater)),
    675                                                     tcuTextureUtil.select(dstFmtRangeInfo.valueMax, srcFmtRangeInfo.valueMax, deMath.logicalAndBool(copyMask, srcIsGreater)),
    676                                                     tcuTextureUtil.select(dstFmtRangeInfo.lookupScale, srcFmtRangeInfo.lookupScale, deMath.logicalAndBool(copyMask, srcIsGreater)),
    677                                                     tcuTextureUtil.select(dstFmtRangeInfo.lookupBias, srcFmtRangeInfo.lookupBias, deMath.logicalAndBool(copyMask, srcIsGreater)));
    678        /** @type {tcuTextureUtil.TextureFormatInfo} */ var dstRangeInfo = new tcuTextureUtil.TextureFormatInfo(
    679                                                     tcuTextureUtil.select(dstFmtRangeInfo.valueMin, srcFmtRangeInfo.valueMin, deMath.logicalOrBool(deMath.logicalNotBool(copyMask), srcIsGreater)),
    680                                                     tcuTextureUtil.select(dstFmtRangeInfo.valueMax, srcFmtRangeInfo.valueMax, deMath.logicalOrBool(deMath.logicalNotBool(copyMask), srcIsGreater)),
    681                                                     tcuTextureUtil.select(dstFmtRangeInfo.lookupScale, srcFmtRangeInfo.lookupScale, deMath.logicalOrBool(deMath.logicalNotBool(copyMask), srcIsGreater)),
    682                                                     tcuTextureUtil.select(dstFmtRangeInfo.lookupBias, srcFmtRangeInfo.lookupBias, deMath.logicalOrBool(deMath.logicalNotBool(copyMask), srcIsGreater)));
    683 
    684        // Shaders.
    685        /** @type {es3fFboTestUtil.GradientShader} */
    686        var gradientToSrcShader = new es3fFboTestUtil.GradientShader(srcOutputType);
    687        /** @type {es3fFboTestUtil.GradientShader} */
    688        var gradientToDstShader = new es3fFboTestUtil.GradientShader(dstOutputType);
    689 
    690        var gradShaderSrcID = ctx.createProgram(gradientToSrcShader);
    691        var gradShaderDstID = ctx.createProgram(gradientToDstShader);
    692 
    693        var srcFbo;
    694        var dstFbo;
    695        var srcRbo;
    696        var dstRbo;
    697 
    698        // Create framebuffers.
    699        // Source framebuffers
    700        srcFbo = ctx.createFramebuffer();
    701        srcRbo = ctx.createRenderbuffer();
    702 
    703        ctx.bindRenderbuffer(gl.RENDERBUFFER, srcRbo);
    704        ctx.renderbufferStorage(gl.RENDERBUFFER, this.m_srcFormat, this.m_size[0], this.m_size[1]);
    705 
    706        ctx.bindFramebuffer(gl.FRAMEBUFFER, srcFbo);
    707        ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, srcRbo);
    708        this.checkError();
    709        this.checkFramebufferStatus(gl.FRAMEBUFFER);
    710 
    711        // Destination framebuffers
    712        dstFbo = ctx.createFramebuffer();
    713        dstRbo = ctx.createRenderbuffer();
    714 
    715        ctx.bindRenderbuffer(gl.RENDERBUFFER, dstRbo);
    716        ctx.renderbufferStorage(gl.RENDERBUFFER, this.m_dstFormat, this.m_size[0], this.m_size[1]);
    717 
    718        ctx.bindFramebuffer(gl.FRAMEBUFFER, dstFbo);
    719        ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, dstRbo);
    720        this.checkError();
    721        this.checkFramebufferStatus(gl.FRAMEBUFFER);
    722 
    723        ctx.viewport(0, 0, this.m_size[0], this.m_size[1]);
    724 
    725        // Render gradients.
    726        for (var ndx = 0; ndx < 2; ndx++) {
    727            ctx.bindFramebuffer(gl.FRAMEBUFFER, ndx ? dstFbo : srcFbo);
    728            if (ndx) {
    729                gradientToDstShader.setGradient(ctx, gradShaderDstID, dstRangeInfo.valueMax, dstRangeInfo.valueMin);
    730                rrUtil.drawQuad(ctx, gradShaderDstID, [-1, -1, 0], [1, 1, 0]);
    731            } else {
    732                gradientToSrcShader.setGradient(ctx, gradShaderSrcID, srcRangeInfo.valueMin, srcRangeInfo.valueMax);
    733                rrUtil.drawQuad(ctx, gradShaderSrcID, [-1, -1, 0], [1, 1, 0]);
    734            }
    735        }
    736 
    737        // Execute copy.
    738        ctx.bindFramebuffer(gl.READ_FRAMEBUFFER, srcFbo);
    739        ctx.bindFramebuffer(gl.DRAW_FRAMEBUFFER, dstFbo);
    740        ctx.blitFramebuffer(0, 0, this.m_size[0], this.m_size[1], 0, 0, this.m_size[0], this.m_size[1], gl.COLOR_BUFFER_BIT, gl.NEAREST);
    741        this.checkError();
    742 
    743        // Read results.
    744        ctx.bindFramebuffer(gl.READ_FRAMEBUFFER, dstFbo);
    745        this.readPixelsUsingFormat(dst, 0, 0, this.m_size[0], this.m_size[1], dstFormat, dstRangeInfo.lookupScale, dstRangeInfo.lookupBias);
    746 
    747    };
    748 
    749    /**
    750     * @param {tcuSurface.Surface} reference
    751     * @param {tcuSurface.Surface} result
    752     */
    753    es3fFramebufferBlitTests.BlitColorConversionCase.prototype.compare = function(reference, result) {
    754        /** @const {tcuTexture.TextureFormat} */ var srcFormat = gluTextureUtil.mapGLInternalFormat(this.m_srcFormat);
    755        /** @const {tcuTexture.TextureFormat} */ var dstFormat = gluTextureUtil.mapGLInternalFormat(this.m_dstFormat);
    756        /** @const {boolean} */ var srcIsSRGB = (srcFormat.order == tcuTexture.ChannelOrder.sRGBA);
    757        /** @const {boolean} */ var dstIsSRGB = (dstFormat.order == tcuTexture.ChannelOrder.sRGBA);
    758        /** @type {tcuRGBA.RGBA} */ var threshold = new tcuRGBA.RGBA();
    759 
    760        if (dstIsSRGB)
    761            threshold = es3fFboTestUtil.getToSRGBConversionThreshold(srcFormat, dstFormat);
    762        else {
    763            /** @type {tcuRGBA.RGBA} */ var srcMaxDiff = es3fFboTestUtil.getThresholdFromTextureFormat(srcFormat);
    764            /** @type {tcuRGBA.RGBA} */ var dstMaxDiff = es3fFboTestUtil.getThresholdFromTextureFormat(dstFormat);
    765            if (srcIsSRGB)
    766                srcMaxDiff = tcuRGBA.multiply(srcMaxDiff, 2);
    767 
    768            threshold = tcuRGBA.max(srcMaxDiff, dstMaxDiff);
    769        }
    770 
    771        // m_testCtx.getLog() << tcu::TestLog::Message << 'threshold = ' << threshold << tcu::TestLog::EndMessage;
    772        return tcuImageCompare.pixelThresholdCompare('Result', 'Image comparison result', reference, result, threshold.toIVec());
    773    };
    774 
    775    /**
    776     * @constructor
    777     * @extends {es3fFboTestCase.FboTestCase}
    778     * @param {string} name
    779     * @param {string} desc
    780     * @param {number} format deUint32
    781     * @param {number} srcBuffers deUint32
    782     * @param {Array<number>} srcSize IVec2
    783     * @param {Array<number>} srcRect IVec4
    784     * @param {number} dstBuffers deUint32
    785     * @param {Array<number>} dstSize IVec2
    786     * @param {Array<number>} dstRect IVec4
    787     * @param {number} copyBuffers deUint32
    788     */
    789    es3fFramebufferBlitTests.BlitDepthStencilCase = function(name, desc, format, srcBuffers, srcSize, srcRect, dstBuffers, dstSize, dstRect, copyBuffers) {
    790        es3fFboTestCase.FboTestCase.call(this, name, desc);
    791        /** @type {number} */ this.m_format = format;
    792        /** @type {number} */ this.m_srcBuffers = srcBuffers;
    793        /** @type {Array<number>} */ this.m_srcSize = srcSize;
    794        /** @type {Array<number>} */ this.m_srcRect = srcRect;
    795        /** @type {number} */ this.m_dstBuffers = dstBuffers;
    796        /** @type {Array<number>} */ this.m_dstSize = dstSize;
    797        /** @type {Array<number>} */ this.m_dstRect = dstRect;
    798        /** @type {number} */ this.m_copyBuffers = copyBuffers;
    799    };
    800 
    801    es3fFramebufferBlitTests.BlitDepthStencilCase.prototype = Object.create(es3fFboTestCase.FboTestCase.prototype);
    802    es3fFramebufferBlitTests.BlitDepthStencilCase.prototype.constructor = es3fFramebufferBlitTests.BlitDepthStencilCase;
    803 
    804    /**
    805     * @protected
    806     */
    807    es3fFramebufferBlitTests.BlitDepthStencilCase.prototype.preCheck = function() {
    808        this.checkFormatSupport(this.m_format);
    809        return true; // No exception thrown
    810    };
    811 
    812    /**
    813     * @protected
    814     * @param {tcuSurface.Surface} dst
    815     */
    816    es3fFramebufferBlitTests.BlitDepthStencilCase.prototype.render = function(dst) {
    817        var ctx = this.getCurrentContext();
    818        /** @const {number} */ var colorFormat = gl.RGBA8;
    819        var gradShader = new es3fFboTestUtil.GradientShader(gluShaderUtil.DataType.FLOAT_VEC4);
    820        var texShader = new es3fFboTestUtil.Texture2DShader(
    821            [gluShaderUtil.DataType.SAMPLER_2D] ,
    822            gluShaderUtil.DataType.FLOAT_VEC4);
    823        var flatShader = new es3fFboTestUtil.FlatColorShader(gluShaderUtil.DataType.FLOAT_VEC4);
    824 
    825        var flatShaderID = ctx.createProgram(flatShader);
    826        var texShaderID = ctx.createProgram(texShader);
    827        var gradShaderID = ctx.createProgram(gradShader);
    828 
    829        var srcFbo;
    830        var dstFbo;
    831        var srcColorRbo;
    832        var dstColorRbo;
    833        var srcDepthStencilRbo;
    834        var dstDepthStencilRbo;
    835 
    836        // setup shaders
    837        gradShader.setGradient(ctx, gradShaderID, [0.0, 0.0, 0.0, 0.0], [1.0, 1.0, 1.0, 1.0]);
    838        texShader.setUniforms(ctx, texShaderID);
    839 
    840        // Create framebuffers
    841        // Source framebuffers
    842        srcFbo = ctx.createFramebuffer();
    843        srcColorRbo = ctx.createRenderbuffer();
    844        srcDepthStencilRbo = ctx.createRenderbuffer();
    845 
    846        ctx.bindRenderbuffer(gl.RENDERBUFFER, srcColorRbo);
    847        ctx.renderbufferStorage(gl.RENDERBUFFER, colorFormat, this.m_srcSize[0], this.m_srcSize[1]);
    848 
    849        ctx.bindRenderbuffer(gl.RENDERBUFFER, srcDepthStencilRbo);
    850        ctx.renderbufferStorage(gl.RENDERBUFFER, this.m_format, this.m_srcSize[0], this.m_srcSize[1]);
    851 
    852        ctx.bindFramebuffer(gl.FRAMEBUFFER, srcFbo);
    853        ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, srcColorRbo);
    854 
    855        if (this.m_srcBuffers & gl.DEPTH_BUFFER_BIT)
    856            ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, srcDepthStencilRbo);
    857        if (this.m_srcBuffers & gl.STENCIL_BUFFER_BIT)
    858            ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, srcDepthStencilRbo);
    859 
    860        this.checkError();
    861        this.checkFramebufferStatus(gl.FRAMEBUFFER);
    862 
    863        // Clear depth to 1 and stencil to 0.
    864        ctx.clearBufferfi(gl.DEPTH_STENCIL, 0, 1.0, 0);
    865 
    866        // Destination framebuffers
    867        dstFbo = ctx.createFramebuffer();
    868        dstColorRbo = ctx.createRenderbuffer();
    869        dstDepthStencilRbo = ctx.createRenderbuffer();
    870 
    871        ctx.bindRenderbuffer(gl.RENDERBUFFER, dstColorRbo);
    872        ctx.renderbufferStorage(gl.RENDERBUFFER, colorFormat, this.m_dstSize[0], this.m_dstSize[1]);
    873 
    874        ctx.bindRenderbuffer(gl.RENDERBUFFER, dstDepthStencilRbo);
    875        ctx.renderbufferStorage(gl.RENDERBUFFER, this.m_format, this.m_dstSize[0], this.m_dstSize[1]);
    876 
    877        ctx.bindFramebuffer(gl.FRAMEBUFFER, dstFbo);
    878        ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, dstColorRbo);
    879 
    880        if (this.m_dstBuffers & gl.DEPTH_BUFFER_BIT)
    881            ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, dstDepthStencilRbo);
    882        if (this.m_dstBuffers & gl.STENCIL_BUFFER_BIT)
    883            ctx.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.STENCIL_ATTACHMENT, gl.RENDERBUFFER, dstDepthStencilRbo);
    884 
    885        this.checkError();
    886        this.checkFramebufferStatus(gl.FRAMEBUFFER);
    887 
    888        // Clear depth to 1 and stencil to 0.
    889        ctx.clearBufferfi(gl.DEPTH_STENCIL, 0, 1.0, 0);
    890 
    891        // Fill source with gradient, depth = [-1..1], stencil = 7
    892        ctx.bindFramebuffer(gl.FRAMEBUFFER, srcFbo);
    893        ctx.viewport(0, 0, this.m_srcSize[0], this.m_srcSize[1]);
    894        ctx.enable(gl.DEPTH_TEST);
    895        ctx.enable(gl.STENCIL_TEST);
    896        ctx.stencilOp(gl.KEEP, gl.KEEP, gl.REPLACE);
    897        ctx.stencilFunc(gl.ALWAYS, 7, 0xff);
    898 
    899        rrUtil.drawQuad(ctx, gradShaderID, [-1, -1, -1], [1, 1, 1]);
    900 
    901        // Fill destination with grid pattern, depth = 0 and stencil = 1
    902        /** @const {number} */ var format = gl.RGBA;
    903        /** @const {number} */ var dataType = gl.UNSIGNED_BYTE;
    904        /** @const {number} */ var texW = this.m_srcSize[0];
    905        /** @const {number} */ var texH = this.m_srcSize[1];
    906        /** @type {WebGLTexture|sglrReferenceContext.TextureContainer} */ var gridTex = null;
    907        /** @type {tcuTexture.TextureLevel} */ var data = new tcuTexture.TextureLevel(gluTextureUtil.mapGLTransferFormat(format, dataType), texW, texH, 1);
    908 
    909        tcuTextureUtil.fillWithGrid(data.getAccess(), 8, [0.2, 0.7, 0.1, 1.0], [0.7, 0.1, 0.5, 0.8]);
    910 
    911        gridTex = ctx.createTexture();
    912        ctx.bindTexture(gl.TEXTURE_2D, gridTex);
    913        ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
    914        ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
    915        ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
    916        ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
    917        ctx.texImage2D(gl.TEXTURE_2D, 0, format, texW, texH, 0, format, dataType, data.getAccess().getDataPtr());
    918 
    919        ctx.bindFramebuffer(gl.FRAMEBUFFER, dstFbo);
    920        ctx.viewport(0, 0, this.m_dstSize[0], this.m_dstSize[1]);
    921        ctx.stencilFunc(gl.ALWAYS, 1, 0xff);
    922 
    923        rrUtil.drawQuad(ctx, texShaderID, [-1, -1, 0], [1, 1, 0]);
    924 
    925        // Perform copy.
    926        ctx.bindFramebuffer(gl.READ_FRAMEBUFFER, srcFbo);
    927        ctx.bindFramebuffer(gl.DRAW_FRAMEBUFFER, dstFbo);
    928        ctx.blitFramebuffer(this.m_srcRect[0], this.m_srcRect[1], this.m_srcRect[2], this.m_srcRect[3], this.m_dstRect[0], this.m_dstRect[1], this.m_dstRect[2], this.m_dstRect[3], this.m_copyBuffers, gl.NEAREST);
    929 
    930        // Render blue color where depth < 0, decrement on depth failure.
    931        ctx.bindFramebuffer(gl.FRAMEBUFFER, dstFbo);
    932        ctx.viewport(0, 0, this.m_dstSize[0], this.m_dstSize[1]);
    933        ctx.stencilOp(gl.KEEP, gl.DECR, gl.KEEP);
    934        ctx.stencilFunc(gl.ALWAYS, 0, 0xff);
    935 
    936        flatShader.setColor(this.getCurrentContext(), flatShaderID, [0.0, 0.0, 1.0, 1.0]);
    937 
    938        rrUtil.drawQuad(ctx, flatShaderID, [-1, -1, 0], [1, 1, 0]);
    939 
    940        if (this.m_dstBuffers & gl.STENCIL_BUFFER_BIT) {
    941            // Render green color where stencil == 6.
    942            ctx.disable(gl.DEPTH_TEST);
    943            ctx.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP);
    944            ctx.stencilFunc(gl.EQUAL, 6, 0xff);
    945 
    946            flatShader.setColor(this.getCurrentContext(), flatShaderID, [0.0, 1.0, 0.0, 1.0]);
    947 
    948            rrUtil.drawQuad(ctx, flatShaderID, [-1, -1, 0], [1, 1, 0]);
    949 
    950        }
    951        this.readPixelsUsingFormat(dst, 0, 0, this.m_dstSize[0], this.m_dstSize[1], gluTextureUtil.mapGLInternalFormat(colorFormat), [1.0, 1.0, 1.0, 1.0], [0.0, 0.0, 0.0, 0.0]);
    952 
    953    };
    954 
    955    /**
    956     * @constructor
    957     * @extends {es3fFboTestCase.FboTestCase}
    958     * @param {string} name
    959     * @param {string} desc
    960     * @param {number} format
    961     * @param {number} filter
    962     */
    963    es3fFramebufferBlitTests.BlitDefaultFramebufferCase = function(name, desc, format, filter) {
    964        es3fFboTestCase.FboTestCase.call(this, name, desc);
    965        /** @const {number} */ this.m_format = format;
    966        /** @const {number} */ this.m_filter = filter;
    967    };
    968 
    969    es3fFramebufferBlitTests.BlitDefaultFramebufferCase.prototype = Object.create(es3fFboTestCase.FboTestCase.prototype);
    970    es3fFramebufferBlitTests.BlitDefaultFramebufferCase.prototype.constructor = es3fFramebufferBlitTests.BlitDefaultFramebufferCase;
    971 
    972    /**
    973     * @protected
    974     */
    975    es3fFramebufferBlitTests.BlitDefaultFramebufferCase.prototype.preCheck = function() {
    976        this.checkFormatSupport(this.m_format);
    977        return true; // No exception thrown
    978    };
    979 
    980    /**
    981     * @protected
    982     * @param {tcuSurface.Surface} dst
    983     */
    984    es3fFramebufferBlitTests.BlitDefaultFramebufferCase.prototype.render = function(dst) {
    985        var ctx = this.getCurrentContext();
    986        /** @type {tcuTexture.TextureFormat} */ var colorFormat = gluTextureUtil.mapGLInternalFormat(this.m_format);
    987        /** @type {gluTextureUtil.TransferFormat} */ var transferFmt = gluTextureUtil.getTransferFormat(colorFormat);
    988 
    989        /** @type {es3fFboTestUtil.GradientShader} */ var gradShader = new es3fFboTestUtil.GradientShader(gluShaderUtil.DataType.FLOAT_VEC4);
    990        /** @type {es3fFboTestUtil.Texture2DShader} */ var texShader = new es3fFboTestUtil.Texture2DShader([gluTextureUtil.getSampler2DType(colorFormat)], gluShaderUtil.DataType.FLOAT_VEC4);
    991 
    992        var gradShaderID = ctx.createProgram(gradShader);
    993        var texShaderID = ctx.createProgram(texShader);
    994        var fbo;
    995        var tex;
    996        /** @const {number} */ var texW = 128;
    997        /** @const {number} */ var texH = 128;
    998 
    999        // Setup shaders
   1000        gradShader.setGradient(ctx, gradShaderID, [0.0, 0.0, 0.0, 0.0], [1.0, 1.0, 1.0, 1.0]);
   1001        texShader.setUniforms(ctx, texShaderID);
   1002 
   1003        // FBO
   1004        fbo = ctx.createFramebuffer();
   1005        tex = ctx.createTexture();
   1006 
   1007        ctx.bindTexture(gl.TEXTURE_2D, tex);
   1008        ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
   1009        ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
   1010        ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, this.m_filter);
   1011        ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, this.m_filter);
   1012        ctx.texImage2D(gl.TEXTURE_2D, 0, this.m_format, texW, texH, 0, transferFmt.format, transferFmt.dataType, null);
   1013 
   1014        ctx.bindFramebuffer(gl.FRAMEBUFFER, fbo);
   1015        ctx.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, tex, 0);
   1016        this.checkError();
   1017        this.checkFramebufferStatus(gl.FRAMEBUFFER);
   1018 
   1019        // Render gradient to screen.
   1020        ctx.bindFramebuffer(gl.FRAMEBUFFER, null);
   1021 
   1022        rrUtil.drawQuad(ctx, gradShaderID, [-1, -1, 0], [1, 1, 0]);
   1023 
   1024        // Blit gradient from screen to fbo.
   1025        ctx.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fbo);
   1026        ctx.blitFramebuffer(0, 0, ctx.getWidth(), ctx.getHeight(), 0, 0, texW, texH, gl.COLOR_BUFFER_BIT, this.m_filter);
   1027 
   1028        // Fill left half of viewport with quad that uses texture.
   1029        ctx.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
   1030        ctx.clearBufferfv(gl.COLOR, 0, [1.0, 0.0, 0.0, 1.0]);
   1031 
   1032        rrUtil.drawQuad(ctx, texShaderID, [-1, -1, 0], [1, 1, 0]);
   1033 
   1034        // Blit fbo to right half.
   1035        ctx.bindFramebuffer(gl.READ_FRAMEBUFFER, fbo);
   1036        ctx.blitFramebuffer(0, 0, texW, texH, Math.floor(ctx.getWidth() / 2), 0, ctx.getWidth(), ctx.getHeight(), gl.COLOR_BUFFER_BIT, this.m_filter);
   1037 
   1038        ctx.bindFramebuffer(gl.READ_FRAMEBUFFER, null);
   1039        this.readPixels(dst, 0, 0, ctx.getWidth(), ctx.getHeight());
   1040 
   1041    };
   1042 
   1043    /**
   1044     * @protected
   1045     * @param {tcuSurface.Surface} reference
   1046     * @param {tcuSurface.Surface} result
   1047     */
   1048    es3fFramebufferBlitTests.BlitDefaultFramebufferCase.prototype.compare = function(reference, result) {
   1049        /** @const {tcuRGBA.RGBA} */
   1050        var threshold = tcuRGBA.max(es3fFboTestUtil.getFormatThreshold(this.m_format), tcuRGBA.newRGBAComponents(12, 12, 12, 12));
   1051 
   1052        //m_testCtx.getLog() << TestLog::Message << 'Comparing images, threshold: ' << threshold << TestLog::EndMessage;
   1053 
   1054        return tcuImageCompare.bilinearCompare('Result', 'Image comparison result', reference.getAccess(), result.getAccess(), threshold);
   1055    };
   1056 
   1057    /** @enum */
   1058    es3fFramebufferBlitTests.BlitDirection = {
   1059        BLIT_DEFAULT_TO_TARGET: 0,
   1060        BLIT_TO_DEFAULT_FROM_TARGET: 1
   1061    };
   1062 
   1063    /** @enum */
   1064    es3fFramebufferBlitTests.BlitArea = {
   1065        AREA_SCALE: 0,
   1066        AREA_OUT_OF_BOUNDS: 1
   1067    };
   1068 
   1069    /**
   1070     * @constructor
   1071     * @extends {es3fFramebufferBlitTests.BlitDefaultFramebufferCase}
   1072     * @param {string} name
   1073     * @param {string} desc
   1074     * @param {number} format
   1075     * @param {number} filter
   1076     * @param {es3fFramebufferBlitTests.BlitDirection} dir
   1077     * @param {es3fFramebufferBlitTests.BlitArea} area
   1078     */
   1079    es3fFramebufferBlitTests.DefaultFramebufferBlitCase = function(name, desc, format, filter, dir, area) {
   1080        es3fFramebufferBlitTests.BlitDefaultFramebufferCase.call(this, name, desc, format, filter);
   1081        /** @const {es3fFramebufferBlitTests.BlitDirection} */ this.m_blitDir = dir;
   1082        /** @const {es3fFramebufferBlitTests.BlitArea} */ this.m_blitArea = area;
   1083        /** @type {Array<number>} */ this.m_srcRect = [-1, -1, -1, -1];
   1084        /** @type {Array<number>} */ this.m_dstRect = [-1, -1, -1, -1];
   1085        /** @type {Array<number>} */ this.m_interestingArea = [-1, -1, -1, -1];
   1086    };
   1087 
   1088    es3fFramebufferBlitTests.DefaultFramebufferBlitCase.prototype = Object.create(es3fFramebufferBlitTests.BlitDefaultFramebufferCase.prototype);
   1089    es3fFramebufferBlitTests.DefaultFramebufferBlitCase.prototype.constructor = es3fFramebufferBlitTests.DefaultFramebufferBlitCase;
   1090 
   1091    es3fFramebufferBlitTests.DefaultFramebufferBlitCase.prototype.init = function() {
   1092        // requirements
   1093        /** @const {number} */ var minViewportSize = 128;
   1094        if (gl.drawingBufferWidth < minViewportSize ||
   1095            gl.drawingBufferHeight < minViewportSize)
   1096            throw new Error('Viewport size ' + minViewportSize + 'x' + minViewportSize + ' required');
   1097 
   1098        // prevent viewport randoming
   1099        this.m_viewportWidth = gl.drawingBufferWidth;
   1100        this.m_viewportHeight = gl.drawingBufferHeight;
   1101 
   1102        // set proper areas
   1103        if (this.m_blitArea == es3fFramebufferBlitTests.BlitArea.AREA_SCALE) {
   1104            this.m_srcRect = [10, 20, 65, 100];
   1105            this.m_dstRect = [25, 30, 125, 94];
   1106            this.m_interestingArea = [0, 0, 128, 128];
   1107        } else if (this.m_blitArea == es3fFramebufferBlitTests.BlitArea.AREA_OUT_OF_BOUNDS) {
   1108            /** @const {Array<number>} */
   1109            var ubound = (this.m_blitDir == es3fFramebufferBlitTests.BlitDirection.BLIT_DEFAULT_TO_TARGET) ?
   1110                         ([128, 128]) :
   1111                         ([gl.drawingBufferWidth, gl.drawingBufferHeight]);
   1112 
   1113            this.m_srcRect = [-10, -15, 100, 63];
   1114            this.m_dstRect = deMath.add(deMath.swizzle(ubound, [0, 1, 0, 1]), [-75, -99, 8, 16]);
   1115            this.m_interestingArea = [ubound[0] - 128, ubound[1] - 128, ubound[0], ubound[1]];
   1116        }
   1117    };
   1118 
   1119    /**
   1120     * @param {tcuSurface.Surface} dst
   1121     */
   1122    es3fFramebufferBlitTests.DefaultFramebufferBlitCase.prototype.render = function(dst) {
   1123        /** @type {es3fFboTestCase.Context} */
   1124        var ctx = this.getCurrentContext();
   1125        // TOOD: implement
   1126        /** @type {tcuTexture.TextureFormat} */ var colorFormat = gluTextureUtil.mapGLInternalFormat(this.m_format);
   1127        /** @type {gluTextureUtil.TransferFormat} */ var transferFmt = gluTextureUtil.getTransferFormat(colorFormat);
   1128        /** @const {tcuTexture.TextureChannelClass} */
   1129        var targetClass = (this.m_blitDir == es3fFramebufferBlitTests.BlitDirection.BLIT_DEFAULT_TO_TARGET) ?
   1130            (tcuTexture.getTextureChannelClass(colorFormat.type)) :
   1131            (tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT);
   1132 
   1133        var fbo;
   1134        var fboTex;
   1135        /** @const {number} */ var fboTexW = 128;
   1136        /** @const {number} */ var fboTexH = 128;
   1137        /** @const {number} */ var sourceWidth = (this.m_blitDir == es3fFramebufferBlitTests.BlitDirection.BLIT_DEFAULT_TO_TARGET) ? (ctx.getWidth()) : (fboTexW);
   1138        /** @const {number} */ var sourceHeight = (this.m_blitDir == es3fFramebufferBlitTests.BlitDirection.BLIT_DEFAULT_TO_TARGET) ? (ctx.getHeight()) : (fboTexH);
   1139        /** @const {number} */ var gridRenderWidth = Math.min(256, sourceWidth);
   1140        /** @const {number} */ var gridRenderHeight = Math.min(256, sourceHeight);
   1141 
   1142        var targetFbo;
   1143        var sourceFbo;
   1144 
   1145        // FBO
   1146        fbo = ctx.createFramebuffer();
   1147        fboTex = ctx.createTexture();
   1148 
   1149        ctx.bindTexture(gl.TEXTURE_2D, fboTex);
   1150        ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
   1151        ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
   1152        ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, this.m_filter);
   1153        ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, this.m_filter);
   1154        ctx.texImage2D(gl.TEXTURE_2D, 0, this.m_format, fboTexW, fboTexH, 0, transferFmt.format, transferFmt.dataType, null);
   1155 
   1156        ctx.bindFramebuffer(gl.FRAMEBUFFER, fbo);
   1157        ctx.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, fboTex, 0);
   1158        this.checkError();
   1159        this.checkFramebufferStatus(gl.FRAMEBUFFER);
   1160 
   1161        targetFbo = (this.m_blitDir == es3fFramebufferBlitTests.BlitDirection.BLIT_DEFAULT_TO_TARGET) ? (fbo) : (null);
   1162        sourceFbo = (this.m_blitDir == es3fFramebufferBlitTests.BlitDirection.BLIT_DEFAULT_TO_TARGET) ? (null) : (fbo);
   1163 
   1164        // Render grid to source framebuffer
   1165        /** @type {es3fFboTestUtil.Texture2DShader} */
   1166        var texShader = new es3fFboTestUtil.Texture2DShader(
   1167            [gluShaderUtil.DataType.SAMPLER_2D],
   1168            gluShaderUtil.DataType.FLOAT_VEC4);
   1169        var texShaderID = this.getCurrentContext().createProgram(texShader);
   1170        /** @const {number} */ var internalFormat = gl.RGBA8;
   1171        /** @const {number} */ var format = gl.RGBA;
   1172        /** @const {number} */ var dataType = gl.UNSIGNED_BYTE;
   1173        /** @const {number} */ var gridTexW = 128;
   1174        /** @const {number} */ var gridTexH = 128;
   1175        /** @type {WebGLTexture|framework.opengl.simplereference.sglrReferenceContext.TextureContainer|null} */
   1176        var gridTex = null;
   1177        /** @type {tcuTexture.TextureLevel} */ var data = new tcuTexture.TextureLevel(gluTextureUtil.mapGLTransferFormat(format, dataType), gridTexW, gridTexH, 1);
   1178 
   1179        tcuTextureUtil.fillWithGrid(data.getAccess(), 9, [0.9, 0.5, 0.1, 0.9], [0.2, 0.8, 0.2, 0.7]);
   1180 
   1181        gridTex = ctx.createTexture();
   1182        ctx.bindTexture(gl.TEXTURE_2D, gridTex);
   1183        ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE);
   1184        ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE);
   1185        ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.NEAREST);
   1186        ctx.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.NEAREST);
   1187        ctx.texImage2D(gl.TEXTURE_2D, 0, internalFormat, gridTexW, gridTexH, 0, format, dataType, data.getAccess().getDataPtr());
   1188 
   1189        ctx.bindFramebuffer(gl.FRAMEBUFFER, sourceFbo);
   1190        ctx.viewport(0, 0, gridRenderWidth, gridRenderHeight);
   1191        ctx.clearBufferfv(gl.COLOR, 0, [1.0, 0.0, 0.0, 1.0]);
   1192 
   1193        texShader.setUniforms(this.getCurrentContext(), texShaderID);
   1194 
   1195        rrUtil.drawQuad(ctx, texShaderID, [-1, -1, 0], [1, 1, 0]);
   1196 
   1197        ctx.useProgram(null);
   1198 
   1199        // Blit source framebuffer to destination
   1200 
   1201        ctx.bindFramebuffer(gl.READ_FRAMEBUFFER, sourceFbo);
   1202        ctx.bindFramebuffer(gl.DRAW_FRAMEBUFFER, targetFbo);
   1203        this.checkError();
   1204 
   1205        if (targetClass == tcuTexture.TextureChannelClass.SIGNED_FIXED_POINT ||
   1206            targetClass == tcuTexture.TextureChannelClass.UNSIGNED_FIXED_POINT ||
   1207            targetClass == tcuTexture.TextureChannelClass.FLOATING_POINT)
   1208            ctx.clearBufferfv(gl.COLOR, 0, [1.0, 1.0, 0.0, 1.0]);
   1209        else if (targetClass == tcuTexture.TextureChannelClass.SIGNED_INTEGER)
   1210            ctx.clearBufferiv(gl.COLOR, 0, [0, 0, 0, 0]);
   1211        else if (targetClass == tcuTexture.TextureChannelClass.UNSIGNED_INTEGER)
   1212            ctx.clearBufferuiv(gl.COLOR, 0, [0, 0, 0, 0]);
   1213        else
   1214            DE_ASSERT(false);
   1215 
   1216        ctx.blitFramebuffer(this.m_srcRect[0], this.m_srcRect[1], this.m_srcRect[2], this.m_srcRect[3], this.m_dstRect[0], this.m_dstRect[1], this.m_dstRect[2], this.m_dstRect[3], gl.COLOR_BUFFER_BIT, this.m_filter);
   1217        this.checkError();
   1218 
   1219        // Read target
   1220 
   1221        ctx.bindFramebuffer(gl.FRAMEBUFFER, targetFbo);
   1222 
   1223        if (this.m_blitDir == es3fFramebufferBlitTests.BlitDirection.BLIT_TO_DEFAULT_FROM_TARGET)
   1224            this.readPixels(dst, this.m_interestingArea[0], this.m_interestingArea[1], this.m_interestingArea[2] - this.m_interestingArea[0], this.m_interestingArea[3] - this.m_interestingArea[1]);
   1225        else
   1226            this.readPixelsUsingFormat(dst, this.m_interestingArea[0], this.m_interestingArea[1], this.m_interestingArea[2] - this.m_interestingArea[0], this.m_interestingArea[3] - this.m_interestingArea[1], colorFormat, [1.0, 1.0, 1.0, 1.0], [0.0, 0.0, 0.0, 0.0]);
   1227 
   1228        this.checkError();
   1229    };
   1230 
   1231    es3fFramebufferBlitTests.run = function(context, range) {
   1232        gl = context;
   1233        //Set up root Test
   1234        var state = tcuTestCase.runner;
   1235 
   1236        var test = new es3fFramebufferBlitTests.FramebufferBlitTests();
   1237        var testName = test.fullName();
   1238        var testDescription = test.getDescription() || '';
   1239 
   1240        state.testName = testName;
   1241        state.setRoot(test);
   1242        //Set up name and description of this test series.
   1243        setCurrentTestName(testName);
   1244        description(testDescription);
   1245 
   1246        try {
   1247            //Create test cases
   1248            test.init();
   1249            if (range)
   1250                state.setRange(range);
   1251            //Run test cases
   1252            tcuTestCase.runTestCases();
   1253        }
   1254        catch (err) {
   1255            bufferedLogToConsole(err);
   1256            testFailedOptions('Failed to es3fFramebufferBlitTests.run tests', false);
   1257            tcuTestCase.runner.terminate();
   1258        }
   1259    };
   1260 
   1261 });