<!--

/*
** Copyright (c) 2017 The Khronos Group Inc.
**
** Permission is hereby granted, free of charge, to any person obtaining a
** copy of this software and/or associated documentation files (the
** "Materials"), to deal in the Materials without restriction, including
** without limitation the rights to use, copy, modify, merge, publish,
** distribute, sublicense, and/or sell copies of the Materials, and to
** permit persons to whom the Materials are furnished to do so, subject to
** the following conditions:
**
** The above copyright notice and this permission notice shall be included
** in all copies or substantial portions of the Materials.
**
** THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
** EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
** MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
** IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
** CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
** TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
** MATERIALS OR THE USE OR OTHER DEALINGS IN THE MATERIALS.
*/

-->

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>WebGL Uniform Buffers 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>
<script id="vshader" type="x-shader/x-vertex">#version 300 es

in vec4 position;

uniform localInputs
{
    mat4 projectionModelViewMatrix;
};

void main ()
{
    gl_Position = projectionModelViewMatrix * position;
}
</script>
<script id="fshader" type="x-shader/x-fragment">#version 300 es

out lowp vec4 resultColor;

void main()
{
    resultColor = vec4(0,1,0,1);
}
</script>
</head>
<body>
<div id="description"></div>
<canvas id="canvas" style="width: 50px; height: 50px;"> </canvas>
<div id="console"></div>
<script>
// Adopted from the test case provided in crbug.com/735784
"use strict";
description("This tests UBO block lookups still work after detaching shaders");

debug("");

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

function runTest(gl) {
    var program = wtu.loadProgramFromScript(gl, "vshader", "fshader");
    if (!program) {
        testFailed("Loading program failed");
        return;
    }

    var shaders = gl.getAttachedShaders(program);
    if (!shaders || shaders.length != 2) {
        testFailed("getAttachedShaders failed");
        return;
    }
    gl.detachShader (program, shaders[0]);
    gl.detachShader (program, shaders[1]);

    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No GL error from set up");

    var index = gl.getUniformBlockIndex(program, "localInputs");
    wtu.glErrorShouldBe(gl, gl.NO_ERROR, "No GL error from getUniformBlockIndex");
    if (index == gl.INVALID_INDEX) {
        testFailed("getUniformBlockIndex returns INVALID_INDEX");
    } else {
        testPassed("getUniformBlockIndex returns valid index");
    }
}

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

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

</body>
</html>
