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.
10 <meta charset=
"utf-8">
11 <title>WebGL Big FBO Test
</title>
12 <link rel=
"stylesheet" href=
"../resources/js-test-style.css"/>
13 <script src=
"../../devtools/src/debug/webgl-debug.js"></script>
14 <script src=
"../js/js-test-pre.js"></script>
15 <script src=
"../js/webgl-test-utils.js"></script>
18 <canvas id=
"canvas" width=
"256" height=
"256"> </canvas>
19 <div id=
"description"></div>
20 <div id=
"console"></div>
21 <script id=
"vshader" type=
"x-shader/x-vertex">
22 attribute vec4 vPosition;
23 attribute vec2 texCoord0;
24 varying vec2 texCoord;
27 gl_Position = vec4(vPosition.xyz,
1.0);
32 <script id=
"fshader" type=
"x-shader/x-fragment">
33 precision mediump float;
34 uniform sampler2D tex;
35 varying vec2 texCoord;
38 gl_FragColor = texture2D(tex, texCoord);
47 debug("Tests the performance of using lots of large FBOs");
51 "After clicking OK your machine may become unresponsive or crash.")) {
58 function checkFBOStatus(gl
) {
59 var err
= gl
.getError();
60 if (err
!= gl
.NO_ERROR
) {
61 if (err
!= gl
.OUT_OF_MEMORY
)
62 testFailed("gl.getError returned " + err
);
64 testPassed("OUT-OF-MEMORY");
67 var status
= gl
.checkFramebufferStatus(gl
.FRAMEBUFFER
);
68 if (status
!= gl
.FRAMEBUFFER_COMPLETE
) {
69 testFailed("gl.checkFramebufferStatus() returned " + WebGLTestUtils
.glEnumToString(gl
, status
));
75 function setupFBO(gl
, size
) {
76 var tex
= gl
.createTexture();
77 gl
.bindTexture(gl
.TEXTURE_2D
, tex
);
78 gl
.texParameteri(gl
.TEXTURE_2D
, gl
.TEXTURE_MIN_FILTER
, gl
.NEAREST
);
79 gl
.texParameteri(gl
.TEXTURE_2D
, gl
.TEXTURE_MAG_FILTER
, gl
.NEAREST
);
80 gl
.texParameteri(gl
.TEXTURE_2D
, gl
.TEXTURE_WRAP_S
, gl
.CLAMP_TO_EDGE
);
81 gl
.texParameteri(gl
.TEXTURE_2D
, gl
.TEXTURE_WRAP_T
, gl
.CLAMP_TO_EDGE
);
83 var fb
= gl
.createFramebuffer();
84 gl
.bindFramebuffer(gl
.FRAMEBUFFER
, fb
);
85 gl
.framebufferTexture2D(gl
.FRAMEBUFFER
, gl
.COLOR_ATTACHMENT0
, gl
.TEXTURE_2D
, tex
, 0);
87 gl
.texImage2D(gl
.TEXTURE_2D
,
89 gl
.RGBA
, // internalFormat
94 gl
.UNSIGNED_BYTE
, // type
96 if (!checkFBOStatus(gl
))
99 return { fb
: fb
, tex
: tex
};
102 function checkPixels(gl
) {
108 var buf
= new Uint8Array(width
* height
* 4);
109 gl
.readPixels(0, 0, width
, height
, gl
.RGBA
, gl
.UNSIGNED_BYTE
, buf
);
110 for (var yy
= 0; yy
< height
; ++yy
) {
111 for (var xx
= 0; xx
< width
; ++xx
) {
112 var offset
= (yy
* width
+ xx
) * 4;
113 if (Math
.abs(buf
[offset
] - 255) > thresh
||
114 Math
.abs(buf
[offset
+ 1] - 0) > thresh
||
115 Math
.abs(buf
[offset
+ 2] - 0) > thresh
) {
116 testFailed("drawing results incorrect");
124 function handleContextLost() {
125 debug("context lost");
130 debug("Checking for out of memory handling.");
132 var canvas
= document
.getElementById("canvas");
133 canvas
.addEventListener('webglcontextlost', handleContextLost
);
134 var wtu
= WebGLTestUtils
;
135 var gl
= wtu
.create3DContext("canvas");
136 var prog
= wtu
.setupProgram(gl
, ["vshader", "fshader"], ["vPosition", "texCoord0"]);
138 WebGLDebugUtils
.init(gl
);
140 gl
.disable(gl
.DEPTH_TEST
);
141 gl
.disable(gl
.BLEND
);
143 var vertexObject
= gl
.createBuffer();
144 gl
.bindBuffer(gl
.ARRAY_BUFFER
, vertexObject
);
145 gl
.bufferData(gl
.ARRAY_BUFFER
, new Float32Array([
146 -1,1,0, 1,1,0, -1,-1,0,
147 -1,-1,0, 1,1,0, 1,-1,0
149 gl
.enableVertexAttribArray(0);
150 gl
.vertexAttribPointer(0, 3, gl
.FLOAT
, false, 0, 0);
152 var vertexObject
= gl
.createBuffer();
153 gl
.bindBuffer(gl
.ARRAY_BUFFER
, vertexObject
);
154 gl
.bufferData(gl
.ARRAY_BUFFER
, new Float32Array([ 0,0, 1,0, 0,1,
157 gl
.enableVertexAttribArray(1);
158 gl
.vertexAttribPointer(1, 2, gl
.FLOAT
, false, 0, 0);
160 var texLoc
= gl
.getUniformLocation(prog
, "tex");
161 gl
.uniform1i(texLoc
, 0);
163 gl
.clearColor(0, 0, 0, 1);
164 gl
.clear(gl
.COLOR_BUFFER_BIT
);
166 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "setup should succeed");
168 var size
= gl
.getParameter(gl
.MAX_RENDERBUFFER_SIZE
);
169 debug("max render buffer size: " + size
+
170 ", size used: " + (size
/ 2));
177 function allocateNextFBO() {
178 if (numFBOs
>= maxFBOs
) {
182 if (!allocateFBO()) {
187 setTimeout(allocateNextFBO
, 100);
190 function allocateFBO() {
192 debug("trying to create fbo #" + (numFBOs
+ 1));
193 var t
= setupFBO(gl
, 2);
201 debug("allocating fbo color buffer of size " + size
+ " x " + size
);
202 gl
.texImage2D(gl
.TEXTURE_2D
,
204 gl
.RGBA
, // internalFormat
209 gl
.UNSIGNED_BYTE
, // type
211 if (!checkFBOStatus(gl
)) {
214 g_textures
.push(tex
);
215 debug("succeeded in creating fbo");
217 debug("clearing the fbo with red color");
218 gl
.bindFramebuffer(gl
.FRAMEBUFFER
, fb
);
219 gl
.clearColor(1, 0, 0, 1);
220 gl
.clear(gl
.COLOR_BUFFER_BIT
);
222 debug("deleting fbo, but the now red texture should be untouched");
223 gl
.bindFramebuffer(gl
.FRAMEBUFFER
, null);
224 gl
.deleteFramebuffer(fb
);
226 debug("drawing to the canvas using the red texture");
227 gl
.clearColor(0, 0, 0, 1);
228 gl
.clear(gl
.COLOR_BUFFER_BIT
);
229 gl
.drawArrays(gl
.TRIANGLES
, 0, 6);
230 if (!checkPixels(gl
)) {
234 debug("succeeded in drawing");
235 wtu
.glErrorShouldBe(gl
, gl
.NO_ERROR
, "each run with no error");
240 gl
.bindFramebuffer(gl
.FRAMEBUFFER
, null);
243 debug("fbos allocated:" + numFBOs
);
244 if (!checkPixels(gl
)) {
245 testFailed("final check of canvas drawing buffer pixels failed");
252 var successfullyParsed
= true;