context-attributes-alpha-depth-stencil-antialias.html (9235B)
1 <!-- 2 Copyright (c) 2019 The Khronos Group Inc. 3 Use of this source code is governed by an MIT-style license that can be 4 found in the LICENSE.txt file. 5 --> 6 7 <!DOCTYPE html> 8 <html> 9 <head> 10 <meta charset="utf-8"> 11 <link rel="stylesheet" href="../../resources/js-test-style.css"/> 12 <script src="../../js/js-test-pre.js"></script> 13 <script src="../../js/webgl-test-utils.js"></script> 14 <script id="vshader" type="x-shader/x-vertex"> 15 attribute vec3 pos; 16 attribute vec4 colorIn; 17 varying vec4 color; 18 19 void main() 20 { 21 color = colorIn; 22 gl_Position = vec4(pos.xyz, 1.0); 23 } 24 </script> 25 26 <script id="fshader" type="x-shader/x-fragment"> 27 precision mediump float; 28 29 varying vec4 color; 30 31 void main() 32 { 33 gl_FragColor = color; 34 } 35 </script> 36 37 <script> 38 "use strict"; 39 40 // These four declarations need to be global for "shouldBe" to see them 41 var wtu = WebGLTestUtils; 42 var gl; 43 var contextAttribs = null; 44 var redChannels = [0, 0, 0]; 45 var correctColor = null; 46 var framebuffer; 47 var fbHasColor; 48 var fbHasDepth; 49 var fbHasStencil; 50 var contextVersion = wtu.getDefault3DContextVersion(); 51 52 function init() 53 { 54 description('Verify WebGLContextAttributes are working as specified, including alpha, depth, stencil, antialias, but not premultipliedAlpha'); 55 56 runTest(); 57 } 58 59 var vertices = new Float32Array([ 60 1.0, 1.0, 0.0, 61 -1.0, 1.0, 0.0, 62 -1.0, -1.0, 0.0, 63 1.0, 1.0, 0.0, 64 -1.0, -1.0, 0.0, 65 1.0, -1.0, 0.0]); 66 67 var colors = new Uint8Array([ 68 255, 0, 0, 255, 69 255, 0, 0, 255, 70 255, 0, 0, 255, 71 255, 0, 0, 255, 72 255, 0, 0, 255, 73 255, 0, 0, 255]); 74 75 76 function getWebGL(canvasWidth, canvasHeight, contextAttribs, clearColor, clearDepth, clearStencil) 77 { 78 var canvas = document.createElement("canvas"); 79 if (!canvas) 80 return null; 81 canvas.width = canvasWidth; 82 canvas.height = canvasHeight; 83 84 gl = wtu.create3DContext(canvas, contextAttribs, contextVersion); 85 if (!gl) 86 return null; 87 88 var program = wtu.setupProgram(gl, ["vshader", "fshader"], ["pos", "colorIn"]); 89 if (!program) 90 return null; 91 92 gl.enable(gl.DEPTH_TEST); 93 gl.enable(gl.STENCIL_TEST); 94 95 gl.clearColor(clearColor[0], clearColor[1], clearColor[2], clearColor[3]); 96 gl.clearDepth(clearDepth); 97 gl.clearStencil(clearStencil); 98 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT); 99 100 framebuffer = gl.createFramebuffer(); 101 gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer); 102 var texture = gl.createTexture(); 103 gl.bindTexture(gl.TEXTURE_2D, texture); 104 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.canvas.width, gl.canvas.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, null); 105 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0); 106 fbHasStencil = false; 107 fbHasDepth = false; 108 fbHasColor = gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE; 109 if (fbHasColor) { 110 var depthStencil = gl.createRenderbuffer(); 111 gl.bindRenderbuffer(gl.RENDERBUFFER, depthStencil); 112 gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, gl.canvas.width, gl.canvas.height); 113 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, depthStencil); 114 fbHasDepth = gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPLETE; 115 if (!fbHasDepth) { 116 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, null); 117 shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEBUFFER_COMPLETE'); 118 } else { 119 fbHasStencil = true; 120 } 121 } 122 gl.bindFramebuffer(gl.FRAMEBUFFER, null); 123 124 var colorOffset = vertices.byteLength; 125 var vbo = gl.createBuffer(); 126 gl.bindBuffer(gl.ARRAY_BUFFER, vbo); 127 gl.bufferData(gl.ARRAY_BUFFER, colorOffset + colors.byteLength, gl.STATIC_DRAW); 128 gl.bufferSubData(gl.ARRAY_BUFFER, 0, vertices); 129 gl.bufferSubData(gl.ARRAY_BUFFER, colorOffset, colors); 130 gl.vertexAttribPointer(0, 3, gl.FLOAT, false, 0, 0); 131 gl.enableVertexAttribArray(0); 132 gl.vertexAttribPointer(1, 4, gl.UNSIGNED_BYTE, true, 0, colorOffset); 133 gl.enableVertexAttribArray(1); 134 135 wtu.glErrorShouldBe(gl, gl.NO_ERROR, "should be no errors"); 136 return gl; 137 } 138 139 function draw(gl, verticesCount) 140 { 141 verticesCount = verticesCount || vertices.length / 3; 142 gl.drawArrays(gl.TRIANGLES, 0, verticesCount); 143 } 144 145 function checkDraw(hasAlpha, hasStencil, hasDepth, hasAntialias) 146 { 147 let red = [255, 0, 0, 255 ]; 148 let black = [0, 0, 0, hasAlpha ? 0 : 255 ]; 149 debug(`Testing that stencil ${ hasStencil ? 'affects': 'does not affect'} the rendering.`); 150 gl.stencilFunc(gl.NEVER, 1, 1); 151 gl.stencilOp(gl.KEEP, gl.KEEP, gl.KEEP); 152 draw(gl); 153 correctColor = hasStencil ? black : red; 154 wtu.checkCanvas(gl, correctColor) 155 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT); 156 wtu.checkCanvas(gl, black); 157 gl.stencilFunc(gl.ALWAYS, 1, 1); 158 159 debug(`Testing that depth ${ hasDepth ? 'affects': 'does not affect'} the rendering.`); 160 gl.depthFunc(gl.NEVER); 161 draw(gl); 162 correctColor = hasDepth ? black : red; 163 wtu.checkCanvas(gl, correctColor); 164 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT); 165 wtu.checkCanvas(gl, black); 166 gl.depthFunc(gl.ALWAYS); 167 168 debug(`Testing that rendering is ${hasAntialias ? 'antialiased' : 'aliased'}.`); 169 draw(gl, 3); 170 let N = 2; 171 let buf = new Uint8Array(N * N * 4); 172 gl.readPixels(0, 0, N, N, gl.RGBA, gl.UNSIGNED_BYTE, buf); 173 redChannels[0] = buf[4 * (N + 1)]; // (1, 1) 174 redChannels[1] = buf[4 * N * (N - 1)]; // left top 175 redChannels[2] = buf[4 * (N - 1)]; // right bottom 176 shouldBe("redChannels[1]", "255"); 177 shouldBe("redChannels[2]", "0"); 178 if (hasAntialias) { 179 shouldNotBe("redChannels[0]", "255"); 180 shouldNotBe("redChannels[0]", "0"); 181 } else { 182 shouldBeTrue("redChannels[0] == 255 || redChannels[0] == 0"); 183 } 184 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT); 185 wtu.checkCanvas(gl, black); 186 187 debug("Testing that rendering works."); 188 draw(gl); 189 wtu.checkCanvas(gl, red); 190 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT); 191 wtu.checkCanvas(gl, black); 192 } 193 194 function testDefault() 195 { 196 debug("Testing default attributes: { stencil:false }"); 197 shouldBeNonNull("gl = getWebGL(1, 1, null, [ 0, 0, 0, 0 ], 1, 0)"); 198 shouldBeFalse("gl.getContextAttributes().stencil"); 199 shouldBe("gl.getParameter(gl.STENCIL_BITS)", "0"); 200 } 201 202 function testAttributesAffectContext(alpha, stencil, depth, antialias) 203 { 204 shouldBeNonNull(`gl = getWebGL(2, 2, { depth: ${depth}, stencil: ${stencil}, antialias: ${antialias}, alpha: ${alpha} }, [ 0, 0, 0, 0 ], 1, 0)`); 205 shouldBeNonNull("contextAttribs = gl.getContextAttributes()"); 206 207 shouldBeGreaterThanOrEqual("gl.getParameter(gl.RED_BITS)", "8"); 208 shouldBeGreaterThanOrEqual("gl.getParameter(gl.GREEN_BITS)", "8"); 209 shouldBeGreaterThanOrEqual("gl.getParameter(gl.BLUE_BITS)", "8"); 210 211 shouldBe("contextAttribs.alpha", "" + alpha); 212 if (contextVersion < 2) { 213 if (!stencil) 214 shouldBeFalse("contextAttribs.stencil"); 215 else 216 stencil = contextAttribs.stencil; 217 if (!depth) 218 shouldBeFalse("contextAttribs.depth"); 219 else 220 depth = contextAttribs.depth; 221 if (!antialias) 222 shouldBeFalse("contextAttribs.antialias"); 223 else 224 antialias = contextAttribs.antialias; 225 } else { 226 shouldBe("contextAttribs.stencil", "" + stencil); 227 shouldBe("contextAttribs.depth", "" + depth); 228 shouldBe("contextAttribs.antialias", "" + antialias); 229 } 230 231 if (alpha) 232 shouldBeGreaterThanOrEqual("gl.getParameter(gl.ALPHA_BITS)", "8"); 233 else 234 shouldBe("gl.getParameter(gl.ALPHA_BITS)", "0"); 235 if (stencil) 236 shouldBeGreaterThanOrEqual("gl.getParameter(gl.STENCIL_BITS)", "8"); 237 else 238 shouldBe("gl.getParameter(gl.STENCIL_BITS)", "0"); 239 if (depth) 240 shouldBeGreaterThanOrEqual("gl.getParameter(gl.DEPTH_BITS)", "16"); 241 else 242 shouldBe("gl.getParameter(gl.DEPTH_BITS)", "0"); 243 244 var correctColor = alpha ? [0, 0, 0, 0] : [0, 0, 0, 255]; 245 wtu.checkCanvas(gl, correctColor); 246 247 debug("Testing default framebuffer."); 248 checkDraw(alpha, stencil, depth, antialias); 249 250 if (fbHasColor) { 251 debug("Testing bound framebuffer object."); 252 gl.bindFramebuffer(gl.FRAMEBUFFER, framebuffer); 253 gl.clearColor(0, 0, 0, 0); 254 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT | gl.STENCIL_BUFFER_BIT); 255 checkDraw(true, fbHasStencil, fbHasDepth, false); 256 gl.bindFramebuffer(gl.FRAMEBUFFER, null); 257 } 258 } 259 260 function runTest() 261 { 262 testDefault(); 263 let cases = [false, true]; 264 for (let alpha of cases) { 265 for (let stencil of cases) { 266 for (let depth of cases) { 267 for (let antialias of cases) { 268 testAttributesAffectContext(alpha, stencil, depth, antialias); 269 } 270 } 271 } 272 } 273 finishTest(); 274 } 275 </script> 276 </head> 277 <body onload="init()"> 278 <div id="description"></div> 279 <div id="console"></div> 280 </body> 281 </html>