﻿<!--
Copyright (c) 2019 The Khronos Group Inc.
Use of this source code is governed by an MIT-style license that can be
found in the LICENSE.txt file.
-->

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>WebGL EXT_blend_minmax Conformance Tests</title>
<link rel="stylesheet" href="../../resources/js-test-style.css"/>
<script src="../../js/js-test-pre.js"></script>
<script src="../../js/webgl-test-utils.js"></script>
</head>
<body>
<div id="description"></div>
<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
<div id="console"></div>
<!-- Shaders to test output -->
<script id="outputVertexShader" type="x-shader/x-vertex">
attribute vec4 vPosition;
void main() {
    gl_Position = vPosition;
}
</script>
<script id="outputFragmentShader" type="x-shader/x-fragment">
precision mediump float;
uniform vec4 uColor;
void main() {
    gl_FragColor = uColor;
}
</script>

<script>
"use strict";
description("This test verifies the functionality of the EXT_blend_minmax extension, if it is available.");

debug("");

var wtu = WebGLTestUtils;
var canvas = document.getElementById("canvas");
var gl = wtu.create3DContext(canvas);
var ext = null;

// Use the constant directly when we don't have the extension
var MIN_EXT = 0x8007;
var MAX_EXT = 0x8008;

if (!gl) {
    testFailed("WebGL context does not exist");
} else {
    testPassed("WebGL context exists");

    runBlendTestDisabled();

    // Query the extension and store globally so shouldBe can access it
    ext = wtu.getExtensionWithKnownPrefixes(gl, "EXT_blend_minmax");
    if (!ext) {
        testPassed("No EXT_blend_minmax support -- this is legal");

        runSupportedTest(false);
    } else {
        debug("");
        testPassed("Successfully enabled EXT_blend_minmax extension");

        runSupportedTest(true);

        runBlendTestEnabled();
        runOutputTests();
        runUniqueObjectTest();
    }
}

function runSupportedTest(extensionEnabled) {
    var supported = gl.getSupportedExtensions();
    if (supported.indexOf("EXT_blend_minmax") >= 0) {
        if (extensionEnabled) {
            testPassed("EXT_blend_minmax listed as supported and getExtension succeeded");
        } else {
            testFailed("EXT_blend_minmax listed as supported but getExtension failed");
        }
    } else {
        if (extensionEnabled) {
            testFailed("EXT_blend_minmax not listed as supported but getExtension succeeded");
        } else {
            testPassed("EXT_blend_minmax not listed as supported and getExtension failed -- this is legal");
        }
    }
}

function runBlendTestDisabled() {
    debug("");
    debug("Testing blending enums with extension disabled");

    // Set the blend equation to a known-good enum first
    gl.blendEquation(gl.FUNC_ADD);

    wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.blendEquation(MIN_EXT)");
    shouldBe("gl.getParameter(gl.BLEND_EQUATION)", "gl.FUNC_ADD");

    wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.blendEquation(MAX_EXT)");
    shouldBe("gl.getParameter(gl.BLEND_EQUATION)", "gl.FUNC_ADD");

    wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.blendEquationSeparate(MIN_EXT, gl.FUNC_ADD)");
    shouldBe("gl.getParameter(gl.BLEND_EQUATION_RGB)", "gl.FUNC_ADD");

    wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.blendEquationSeparate(gl.FUNC_ADD, MIN_EXT)");
    shouldBe("gl.getParameter(gl.BLEND_EQUATION_ALPHA)", "gl.FUNC_ADD");

    wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.blendEquationSeparate(MAX_EXT, gl.FUNC_ADD)");
    shouldBe("gl.getParameter(gl.BLEND_EQUATION_RGB)", "gl.FUNC_ADD");

    wtu.shouldGenerateGLError(gl, gl.INVALID_ENUM, "gl.blendEquationSeparate(gl.FUNC_ADD, MAX_EXT)");
    shouldBe("gl.getParameter(gl.BLEND_EQUATION_ALPHA)", "gl.FUNC_ADD");
}

function runBlendTestEnabled() {
    debug("");
    debug("Testing blending enums with extension enabled");

    shouldBe("ext.MIN_EXT", "0x8007");
    shouldBe("ext.MAX_EXT", "0x8008");

    wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.blendEquation(ext.MIN_EXT)");
    shouldBe("gl.getParameter(gl.BLEND_EQUATION)", "ext.MIN_EXT");

    wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.blendEquation(ext.MAX_EXT)");
    shouldBe("gl.getParameter(gl.BLEND_EQUATION)", "ext.MAX_EXT");

    wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.blendEquationSeparate(ext.MIN_EXT, gl.FUNC_ADD)");
    shouldBe("gl.getParameter(gl.BLEND_EQUATION_RGB)", "ext.MIN_EXT");
    shouldBe("gl.getParameter(gl.BLEND_EQUATION_ALPHA)", "gl.FUNC_ADD");

    wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.blendEquationSeparate(gl.FUNC_ADD, ext.MIN_EXT)");
    shouldBe("gl.getParameter(gl.BLEND_EQUATION_RGB)", "gl.FUNC_ADD");
    shouldBe("gl.getParameter(gl.BLEND_EQUATION_ALPHA)", "ext.MIN_EXT");

    wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.blendEquationSeparate(ext.MAX_EXT, gl.FUNC_ADD)");
    shouldBe("gl.getParameter(gl.BLEND_EQUATION_RGB)", "ext.MAX_EXT");
    shouldBe("gl.getParameter(gl.BLEND_EQUATION_ALPHA)", "gl.FUNC_ADD");

    wtu.shouldGenerateGLError(gl, gl.NO_ERROR, "gl.blendEquationSeparate(gl.FUNC_ADD, ext.MAX_EXT)");
    shouldBe("gl.getParameter(gl.BLEND_EQUATION_RGB)", "gl.FUNC_ADD");
    shouldBe("gl.getParameter(gl.BLEND_EQUATION_ALPHA)", "ext.MAX_EXT");
}

function runOutputTests() {
    var e = 2; // Amount of variance to allow in result pixels - may need to be tweaked higher

    debug("");
    debug("Testing various draws for valid blending behavior");

    canvas.width = 50; canvas.height = 50;
    gl.viewport(0, 0, canvas.width, canvas.height);
    gl.enable(gl.BLEND);
    gl.blendFunc(gl.ONE, gl.ONE);

    var program = wtu.setupProgram(gl, ["outputVertexShader", "outputFragmentShader"], ['vPosition'], [0]);
    var quadParameters = wtu.setupUnitQuad(gl, 0, 1);
    var colorUniform = gl.getUniformLocation(program, "uColor");


    // Draw 1
    gl.blendEquation(ext.MIN_EXT);

    gl.clearColor(0.2, 0.4, 0.6, 0.8);
    gl.clear(gl.COLOR_BUFFER_BIT);

    gl.uniform4f(colorUniform, 0.8, 0.6, 0.4, 0.2);
    wtu.drawUnitQuad(gl);

    wtu.checkCanvasRect(gl, 0, 0, canvas.width, canvas.height, [51, 102, 102, 51]);

    // Draw 2:
    gl.blendEquation(ext.MAX_EXT);

    gl.clearColor(0.2, 0.4, 0.6, 0.8);
    gl.clear(gl.COLOR_BUFFER_BIT);

    gl.uniform4f(colorUniform, 0.8, 0.6, 0.4, 0.2);
    wtu.drawUnitQuad(gl);

    wtu.checkCanvasRect(gl, 0, 0, canvas.width, canvas.height, [204, 153, 153, 204]);

    // Draw 3
    gl.blendEquationSeparate(ext.MIN_EXT, ext.MAX_EXT);

    gl.clearColor(0.2, 0.4, 0.6, 0.8);
    gl.clear(gl.COLOR_BUFFER_BIT);

    gl.uniform4f(colorUniform, 0.8, 0.6, 0.4, 0.2);
    wtu.drawUnitQuad(gl);

    wtu.checkCanvasRect(gl, 0, 0, canvas.width, canvas.height, [51, 102, 102, 204]);

    // Draw 4
    gl.blendEquationSeparate(ext.MAX_EXT, ext.MIN_EXT);

    gl.clearColor(0.2, 0.4, 0.6, 0.8);
    gl.clear(gl.COLOR_BUFFER_BIT);

    gl.uniform4f(colorUniform, 0.8, 0.6, 0.4, 0.2);
    wtu.drawUnitQuad(gl);

    wtu.checkCanvasRect(gl, 0, 0, canvas.width, canvas.height, [204, 153, 153, 51]);
}

function runUniqueObjectTest()
{
    debug("");
    debug("Testing that getExtension() returns the same object each time");
    ext = null;
    gl.getExtension("EXT_blend_minmax").myProperty = 2;
    webglHarnessCollectGarbage();
    shouldBe('gl.getExtension("EXT_blend_minmax").myProperty', '2');
}

debug("");
var successfullyParsed = true;
</script>
<script src="../../js/js-test-post.js"></script>

</body>
</html>
