OLD | NEW |
| (Empty) |
1 <!DOCTYPE html> | |
2 <html> | |
3 <head> | |
4 <meta charset="utf-8"> | |
5 <script src="../../../resources/js-test.js"></script> | |
6 <script src="resources/webgl-test.js"></script> | |
7 <script src="resources/webgl-test-utils.js"></script> | |
8 </head> | |
9 <body> | |
10 <div id="description"></div> | |
11 <div id="console"></div> | |
12 | |
13 <script> | |
14 if (window.internals) | |
15 window.internals.settings.setWebGLErrorsToConsoleEnabled(false); | |
16 | |
17 var wtu = WebGLTestUtils; | |
18 var gl; | |
19 var fbo; | |
20 var depthBuffer; | |
21 var stencilBuffer; | |
22 var depthStencilBuffer; | |
23 var colorBuffer; | |
24 var width; | |
25 var height; | |
26 | |
27 const ALLOW_COMPLETE = 0x01; | |
28 const ALLOW_UNSUPPORTED = 0x02; | |
29 const ALLOW_INCOMPLETE_ATTACHMENT = 0x04; | |
30 | |
31 function checkFramebufferForAllowedStatuses(allowedStatuses) | |
32 { | |
33 // If the framebuffer is in an error state for multiple reasons, | |
34 // we can't guarantee which one will be reported. | |
35 var status = gl.checkFramebufferStatus(gl.FRAMEBUFFER); | |
36 var statusAllowed = ((allowedStatuses & ALLOW_COMPLETE) && (status == gl.FRA
MEBUFFER_COMPLETE)) || | |
37 ((allowedStatuses & ALLOW_UNSUPPORTED) && (status == gl.
FRAMEBUFFER_UNSUPPORTED)) || | |
38 ((allowedStatuses & ALLOW_INCOMPLETE_ATTACHMENT) && (sta
tus == gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT)); | |
39 var msg = "gl.checkFramebufferStatus(gl.FRAMEBUFFER) returned " + status; | |
40 if (statusAllowed) | |
41 testPassed(msg); | |
42 else | |
43 testFailed(msg); | |
44 } | |
45 | |
46 function checkBufferBits(attachment0, attachment1) | |
47 { | |
48 if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) | |
49 return; | |
50 | |
51 var haveDepthBuffer = attachment0 == gl.DEPTH_ATTACHMENT || | |
52 attachment0 == gl.DEPTH_STENCIL_ATTACHMENT || | |
53 attachment1 == gl.DEPTH_ATTACHMENT || | |
54 attachment1 == gl.DEPTH_STENCIL_ATTACHMENT; | |
55 var haveStencilBuffer = attachment0 == gl.STENCIL_ATTACHMENT || | |
56 attachment0 == gl.DEPTH_STENCIL_ATTACHMENT || | |
57 attachment1 == gl.STENCIL_ATTACHMENT || | |
58 attachment1 == gl.DEPTH_STENCIL_ATTACHMENT; | |
59 | |
60 shouldBeTrue("gl.getParameter(gl.RED_BITS) + gl.getParameter(gl.GREEN_BITS)
+ gl.getParameter(gl.BLUE_BITS) + gl.getParameter(gl.ALPHA_BITS) >= 16"); | |
61 | |
62 if (haveDepthBuffer) | |
63 shouldBeTrue("gl.getParameter(gl.DEPTH_BITS) >= 16"); | |
64 else | |
65 shouldBeTrue("gl.getParameter(gl.DEPTH_BITS) == 0"); | |
66 | |
67 if (haveStencilBuffer) | |
68 shouldBeTrue("gl.getParameter(gl.STENCIL_BITS) >= 8"); | |
69 else | |
70 shouldBeTrue("gl.getParameter(gl.STENCIL_BITS) == 0"); | |
71 } | |
72 | |
73 function testAttachment(attachment, buffer, allowedStatuses) | |
74 { | |
75 shouldBeNonNull("fbo = gl.createFramebuffer()"); | |
76 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); | |
77 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBU
FFER, colorBuffer); | |
78 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachment, gl.RENDERBUFFER, buff
er); | |
79 glErrorShouldBe(gl, gl.NO_ERROR); | |
80 checkFramebufferForAllowedStatuses(allowedStatuses); | |
81 if ((allowedStatuses & ALLOW_COMPLETE) == 0) { | |
82 gl.clear(gl.COLOR_BUFFER_BIT); | |
83 glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION); | |
84 gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8A
rray(width * height * 4)); | |
85 glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION); | |
86 } | |
87 checkBufferBits(attachment); | |
88 gl.deleteFramebuffer(fbo); | |
89 } | |
90 | |
91 function testAttachments(attachment0, buffer0, attachment1, buffer1, allowedStat
uses) | |
92 { | |
93 shouldBeNonNull("fbo = gl.createFramebuffer()"); | |
94 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); | |
95 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBU
FFER, colorBuffer); | |
96 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachment0, gl.RENDERBUFFER, buf
fer0); | |
97 glErrorShouldBe(gl, gl.NO_ERROR); | |
98 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachment1, gl.RENDERBUFFER, buf
fer1); | |
99 glErrorShouldBe(gl, gl.NO_ERROR); | |
100 checkFramebufferForAllowedStatuses(allowedStatuses); | |
101 checkBufferBits(attachment0, attachment1); | |
102 gl.deleteFramebuffer(fbo); | |
103 } | |
104 | |
105 function testColorRenderbuffer(internalformat, allowedStatuses) | |
106 { | |
107 shouldBeNonNull("colorBuffer = gl.createRenderbuffer()"); | |
108 gl.bindRenderbuffer(gl.RENDERBUFFER, colorBuffer); | |
109 gl.renderbufferStorage(gl.RENDERBUFFER, internalformat, width, height); | |
110 glErrorShouldBe(gl, gl.NO_ERROR); | |
111 testAttachment(gl.COLOR_ATTACHMENT0, colorBuffer, allowedStatuses); | |
112 } | |
113 | |
114 function testDepthStencilRenderbuffer(allowedStatuses) | |
115 { | |
116 shouldBeNonNull("depthStencilBuffer = gl.createRenderbuffer()"); | |
117 gl.bindRenderbuffer(gl.RENDERBUFFER, depthStencilBuffer); | |
118 gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width, height); | |
119 glErrorShouldBe(gl, gl.NO_ERROR); | |
120 | |
121 // OpenGL itself doesn't seem to guarantee that e.g. a 2 x 0 | |
122 // renderbuffer will report 2 for its width when queried. | |
123 if (!(height == 0 && width > 0)) | |
124 shouldBe("gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_W
IDTH)", "width"); | |
125 if (!(width == 0 && height > 0)) | |
126 shouldBe("gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_H
EIGHT)", "height"); | |
127 shouldBe("gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_INTER
NAL_FORMAT)", "gl.DEPTH_STENCIL"); | |
128 shouldBe("gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_RED_S
IZE)", "0"); | |
129 shouldBe("gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_GREEN
_SIZE)", "0"); | |
130 shouldBe("gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_BLUE_
SIZE)", "0"); | |
131 shouldBe("gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_ALPHA
_SIZE)", "0"); | |
132 // Avoid verifying these for zero-sized renderbuffers for the time | |
133 // being since it appears that even OpenGL doesn't guarantee them. | |
134 if (width > 0 && height > 0) { | |
135 shouldBeTrue("gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFF
ER_DEPTH_SIZE) > 0"); | |
136 shouldBeTrue("gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFF
ER_STENCIL_SIZE) > 0"); | |
137 } | |
138 glErrorShouldBe(gl, gl.NO_ERROR); | |
139 testAttachment(gl.DEPTH_STENCIL_ATTACHMENT, depthStencilBuffer, allowedStatu
ses); | |
140 testDepthStencilDepthStencil(); | |
141 } | |
142 | |
143 function testDepthStencilDepthStencil() | |
144 { | |
145 if (!width || !height) { | |
146 return; | |
147 } | |
148 | |
149 var tests = [ | |
150 { firstFormat: gl.DEPTH_COMPONENT16, | |
151 firstAttach: gl.DEPTH_ATTACHMENT, | |
152 secondFormat: gl.DEPTH_STENCIL, | |
153 secondAttach: gl.DEPTH_STENCIL_ATTACHMENT | |
154 }, | |
155 { firstFormat: gl.DEPTH_STENCIL, | |
156 firstAttach: gl.DEPTH_STENCIL_ATTACHMENT, | |
157 secondFormat: gl.DEPTH_COMPONENT16, | |
158 secondAttach: gl.DEPTH_ATTACHMENT | |
159 } | |
160 ]; | |
161 for (var ii = 0; ii < tests.length; ++ii) { | |
162 var test = tests[ii]; | |
163 for (var jj = 0; jj < 2; ++jj) { | |
164 var fbo = gl.createFramebuffer(); | |
165 var tex = gl.createTexture(); | |
166 var firstRb = gl.createRenderbuffer(); | |
167 | |
168 debug(""); | |
169 debug("test: " + wtu.glEnumToString(gl, test.firstFormat) + " vs " +
wtu.glEnumToString(gl, test.secondFormat) + " with " + (jj ? "unbind" : "delete
")); | |
170 | |
171 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); | |
172 // attach texture as color | |
173 gl.bindTexture(gl.TEXTURE_2D, tex); | |
174 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, width, height, 0, gl.RGBA,
gl.UNSIGNED_BYTE, null); | |
175 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEX
TURE_2D, tex, 0); | |
176 | |
177 // attach first | |
178 gl.bindRenderbuffer(gl.RENDERBUFFER, firstRb); | |
179 gl.renderbufferStorage(gl.RENDERBUFFER, test.firstFormat, width, hei
ght); | |
180 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, test.firstAttach, gl.REND
ERBUFFER, firstRb); | |
181 | |
182 if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMP
LETE) { | |
183 gl.enable(gl.DEPTH_TEST); | |
184 var program = wtu.setupColorQuad(gl); | |
185 // Test it works | |
186 wtu.drawUByteColorQuad(gl, [0, 255, 0, 255]); | |
187 wtu.drawUByteColorQuad(gl, [255, 0, 0, 255]); // should not dra
w since DEPTH_FUNC == LESS | |
188 wtu.checkCanvasRect(gl, 0, 0, width, height, [0, 255, 0, 255], "
should be green"); | |
189 | |
190 var secondRb = gl.createRenderbuffer(); | |
191 | |
192 // attach second | |
193 gl.bindRenderbuffer(gl.RENDERBUFFER, secondRb); | |
194 gl.renderbufferStorage(gl.RENDERBUFFER, test.secondFormat, width
, height); | |
195 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, test.secondAttach, gl
.RENDERBUFFER, secondRb); | |
196 | |
197 if (jj == 0) { | |
198 // now delete it | |
199 debug("test deleting second renderbuffer"); | |
200 gl.deleteRenderbuffer(secondRb); | |
201 } else { | |
202 // unbind it | |
203 debug("test unbinding second renderbuffer"); | |
204 gl.framebufferRenderbuffer(gl.FRAMEBUFFER, test.secondAttach,
gl.RENDERBUFFER, null); | |
205 } | |
206 | |
207 // If the first attachment is not restored this may fail | |
208 shouldBe('gl.checkFramebufferStatus(gl.FRAMEBUFFER)', 'gl.FRAMEB
UFFER_COMPLETE'); | |
209 glErrorShouldBe(gl, gl.NO_ERROR); | |
210 | |
211 // If the first attachment is not restored this may fail. | |
212 gl.clear(gl.DEPTH_BUFFER_BIT); | |
213 wtu.drawUByteColorQuad(gl, [0, 255, 0, 255]); | |
214 wtu.drawUByteColorQuad(gl, [255, 0, 0, 255]); // should not dra
w since DEPTH_FUNC == LESS | |
215 wtu.checkCanvasRect(gl, 0, 0, width, height, [0, 255, 0, 255], "
should be green"); | |
216 gl.disable(gl.DEPTH_TEST); | |
217 | |
218 if (jj == 1) { | |
219 gl.deleteRenderbuffer(secondRb); | |
220 } | |
221 } | |
222 | |
223 gl.deleteRenderbuffer(secondRb); | |
224 gl.deleteFramebuffer(fbo); | |
225 } | |
226 } | |
227 glErrorShouldBe(gl, gl.NO_ERROR); | |
228 } | |
229 | |
230 description("Test framebuffer object attachment behaviors"); | |
231 | |
232 for (width = 0; width <= 2; width += 2) | |
233 { | |
234 for (height = 0; height <= 2; height += 2) | |
235 { | |
236 debug(""); | |
237 debug("Dimensions " + width + " x " + height); | |
238 | |
239 debug("Create renderbuffers"); | |
240 shouldBeNonNull("gl = create3DContext()"); | |
241 shouldBeNonNull("colorBuffer = gl.createRenderbuffer()"); | |
242 gl.bindRenderbuffer(gl.RENDERBUFFER, colorBuffer); | |
243 gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, width, height); | |
244 glErrorShouldBe(gl, gl.NO_ERROR); | |
245 shouldBeNonNull("depthBuffer = gl.createRenderbuffer()"); | |
246 gl.bindRenderbuffer(gl.RENDERBUFFER, depthBuffer); | |
247 gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_COMPONENT16, width, hei
ght); | |
248 glErrorShouldBe(gl, gl.NO_ERROR); | |
249 shouldBeNonNull("stencilBuffer = gl.createRenderbuffer()"); | |
250 gl.bindRenderbuffer(gl.RENDERBUFFER, stencilBuffer); | |
251 gl.renderbufferStorage(gl.RENDERBUFFER, gl.STENCIL_INDEX8, width, height
); | |
252 glErrorShouldBe(gl, gl.NO_ERROR); | |
253 shouldBeNonNull("depthStencilBuffer = gl.createRenderbuffer()"); | |
254 gl.bindRenderbuffer(gl.RENDERBUFFER, depthStencilBuffer); | |
255 gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width, height)
; | |
256 glErrorShouldBe(gl, gl.NO_ERROR); | |
257 | |
258 var allowedStatusForGoodCase | |
259 = (width == 0 || height == 0) ? ALLOW_INCOMPLETE_ATTACHMENT : ALLOW_
COMPLETE; | |
260 | |
261 // some cases involving stencil seem to be implementation-dependent | |
262 var allowedStatusForImplDependentCase = allowedStatusForGoodCase | ALLOW
_UNSUPPORTED; | |
263 | |
264 debug("Attach depth using DEPTH_ATTACHMENT"); | |
265 testAttachment(gl.DEPTH_ATTACHMENT, depthBuffer, allowedStatusForGoodCas
e); | |
266 debug("Attach depth using STENCIL_ATTACHMENT"); | |
267 testAttachment(gl.STENCIL_ATTACHMENT, depthBuffer, ALLOW_INCOMPLETE_ATTA
CHMENT); | |
268 debug("Attach depth using DEPTH_STENCIL_ATTACHMENT"); | |
269 testAttachment(gl.DEPTH_STENCIL_ATTACHMENT, depthBuffer, ALLOW_INCOMPLET
E_ATTACHMENT); | |
270 debug("Attach stencil using STENCIL_ATTACHMENT"); | |
271 testAttachment(gl.STENCIL_ATTACHMENT, stencilBuffer, allowedStatusForImp
lDependentCase); | |
272 debug("Attach stencil using DEPTH_ATTACHMENT"); | |
273 testAttachment(gl.DEPTH_ATTACHMENT, stencilBuffer, ALLOW_INCOMPLETE_ATTA
CHMENT); | |
274 debug("Attach stencil using DEPTH_STENCIL_ATTACHMENT"); | |
275 testAttachment(gl.DEPTH_STENCIL_ATTACHMENT, stencilBuffer, ALLOW_INCOMPL
ETE_ATTACHMENT); | |
276 debug("Attach depthStencil using DEPTH_STENCIL_ATTACHMENT"); | |
277 testAttachment(gl.DEPTH_STENCIL_ATTACHMENT, depthStencilBuffer, allowedS
tatusForGoodCase); | |
278 debug("Attach depthStencil using DEPTH_ATTACHMENT"); | |
279 testAttachment(gl.DEPTH_ATTACHMENT, depthStencilBuffer, ALLOW_INCOMPLETE
_ATTACHMENT); | |
280 debug("Attach depthStencil using STENCIL_ATTACHMENT"); | |
281 testAttachment(gl.STENCIL_ATTACHMENT, depthStencilBuffer, ALLOW_INCOMPLE
TE_ATTACHMENT); | |
282 | |
283 var allowedStatusForConflictedAttachment | |
284 = (width == 0 || height == 0) ? ALLOW_UNSUPPORTED | ALLOW_INCOMPLETE
_ATTACHMENT | |
285 : ALLOW_UNSUPPORTED; | |
286 | |
287 debug("Attach depth, then stencil, causing conflict"); | |
288 testAttachments(gl.DEPTH_ATTACHMENT, depthBuffer, gl.STENCIL_ATTACHMENT,
stencilBuffer, allowedStatusForConflictedAttachment); | |
289 debug("Attach stencil, then depth, causing conflict"); | |
290 testAttachments(gl.STENCIL_ATTACHMENT, stencilBuffer, gl.DEPTH_ATTACHMEN
T, depthBuffer, allowedStatusForConflictedAttachment); | |
291 debug("Attach depth, then depthStencil, causing conflict"); | |
292 testAttachments(gl.DEPTH_ATTACHMENT, depthBuffer, gl.DEPTH_STENCIL_ATTAC
HMENT, depthStencilBuffer, allowedStatusForConflictedAttachment); | |
293 debug("Attach depthStencil, then depth, causing conflict"); | |
294 testAttachments(gl.DEPTH_STENCIL_ATTACHMENT, depthStencilBuffer, gl.DEPT
H_ATTACHMENT, depthBuffer, allowedStatusForConflictedAttachment); | |
295 debug("Attach stencil, then depthStencil, causing conflict"); | |
296 testAttachments(gl.DEPTH_ATTACHMENT, depthBuffer, gl.DEPTH_STENCIL_ATTAC
HMENT, depthStencilBuffer, allowedStatusForConflictedAttachment); | |
297 debug("Attach depthStencil, then stencil, causing conflict"); | |
298 testAttachments(gl.DEPTH_STENCIL_ATTACHMENT, depthStencilBuffer, gl.STEN
CIL_ATTACHMENT, stencilBuffer, allowedStatusForConflictedAttachment); | |
299 | |
300 debug("Attach color renderbuffer with internalformat == RGBA4"); | |
301 testColorRenderbuffer(gl.RGBA4, allowedStatusForGoodCase); | |
302 | |
303 debug("Attach color renderbuffer with internalformat == RGB5_A1"); | |
304 testColorRenderbuffer(gl.RGB5_A1, allowedStatusForGoodCase); | |
305 | |
306 debug("Attach color renderbuffer with internalformat == RGB565"); | |
307 testColorRenderbuffer(gl.RGB565, allowedStatusForGoodCase); | |
308 | |
309 debug("Create and attach depthStencil renderbuffer"); | |
310 testDepthStencilRenderbuffer(allowedStatusForGoodCase); | |
311 } | |
312 } | |
313 | |
314 // Determine if we can attach both color and depth or color and depth_stencil | |
315 var depthFormat; | |
316 var depthAttachment; | |
317 | |
318 function checkValidColorDepthCombination() { | |
319 shouldBeNonNull("fbo = gl.createFramebuffer()"); | |
320 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); | |
321 shouldBeNonNull("colorBuffer = gl.createRenderbuffer()"); | |
322 gl.bindRenderbuffer(gl.RENDERBUFFER, colorBuffer); | |
323 gl.framebufferRenderbuffer( | |
324 gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorBuffer); | |
325 gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16); | |
326 | |
327 shouldBeNonNull("depthBuffer = gl.createRenderbuffer()"); | |
328 gl.bindRenderbuffer(gl.RENDERBUFFER, depthBuffer); | |
329 | |
330 return tryDepth(gl.DEPTH_COMPONENT16, gl.DEPTH_ATTACHMENT) || tryDepth(gl.DE
PTH_STENCIL, gl.DEPTH_STENCIL_ATTACHMENT); | |
331 | |
332 function tryDepth(try_format, try_attachment) { | |
333 if (depthAttachment) { | |
334 // If we've tried once unattach the old one. | |
335 gl.framebufferRenderbuffer( | |
336 gl.FRAMEBUFFER, depthAttachment, gl.RENDERBUFFER, null); | |
337 } | |
338 depthFormat = try_format; | |
339 depthAttachment = try_attachment; | |
340 gl.framebufferRenderbuffer( | |
341 gl.FRAMEBUFFER, depthAttachment, gl.RENDERBUFFER, depthBuffer); | |
342 gl.renderbufferStorage(gl.RENDERBUFFER, depthFormat, 16, 16); | |
343 glErrorShouldBe(gl, gl.NO_ERROR); | |
344 return gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_COMPL
ETE; | |
345 } | |
346 } | |
347 | |
348 if (checkValidColorDepthCombination()) { | |
349 testFramebufferIncompleteDimensions(); | |
350 testFramebufferIncompleteAttachment(); | |
351 testFramebufferIncompleteMissingAttachment(); | |
352 testUsingIncompleteFramebuffer(); | |
353 } | |
354 | |
355 function checkFramebuffer(expected) { | |
356 var actual = gl.checkFramebufferStatus(gl.FRAMEBUFFER); | |
357 var msg = "gl.checkFramebufferStatus(gl.FRAMEBUFFER) should be " + wtu.glEnu
mToString(gl, expected) + " was " + wtu.glEnumToString(gl, actual); | |
358 if (expected != gl.FRAMEBUFFER_COMPLETE) { | |
359 msg += " or FRAMEBUFFER_UNSUPPORTED"; | |
360 } | |
361 if (actual == expected || | |
362 (expected != gl.FRAMEBUFFER_COMPLETE && | |
363 actual == gl.FRAMBUFFER_UNSUPPORTED)) { | |
364 testPassed(msg); | |
365 } else { | |
366 testFailed(msg); | |
367 } | |
368 } | |
369 | |
370 function testUsingIncompleteFramebuffer() { | |
371 debug(""); | |
372 debug("Test drawing or reading from an incomplete framebuffer"); | |
373 var program = wtu.setupTexturedQuad(gl); | |
374 var tex = gl.createTexture(); | |
375 wtu.fillTexture(gl, tex, 1, 1, [0,255,0,255]); | |
376 | |
377 shouldBeNonNull("fbo = gl.createFramebuffer()"); | |
378 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); | |
379 shouldBeNonNull("colorBuffer = gl.createRenderbuffer()"); | |
380 gl.bindRenderbuffer(gl.RENDERBUFFER, colorBuffer); | |
381 gl.framebufferRenderbuffer( | |
382 gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorBuffer); | |
383 gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16); | |
384 | |
385 shouldBeNonNull("depthBuffer = gl.createRenderbuffer()"); | |
386 gl.bindRenderbuffer(gl.RENDERBUFFER, depthBuffer); | |
387 gl.framebufferRenderbuffer( | |
388 gl.FRAMEBUFFER, depthAttachment, gl.RENDERBUFFER, depthBuffer); | |
389 gl.renderbufferStorage(gl.RENDERBUFFER, depthFormat, 16, 16); | |
390 glErrorShouldBe(gl, gl.NO_ERROR); | |
391 checkFramebuffer(gl.FRAMEBUFFER_COMPLETE); | |
392 | |
393 // We pick this combination because it works on desktop OpenGL but should no
t work on OpenGL ES 2.0 | |
394 gl.renderbufferStorage(gl.RENDERBUFFER, depthFormat, 32, 16); | |
395 checkFramebuffer(gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS); | |
396 debug(""); | |
397 debug("Drawing or reading from an incomplete framebuffer should generate INV
ALID_FRAMEBUFFER_OPERATION"); | |
398 testRenderingAndReading(); | |
399 | |
400 shouldBeNonNull("fbo2 = gl.createFramebuffer()"); | |
401 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo2); | |
402 checkFramebuffer(gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT); | |
403 debug(""); | |
404 debug("Drawing or reading from an incomplete framebuffer should generate INV
ALID_FRAMEBUFFER_OPERATION"); | |
405 testRenderingAndReading(); | |
406 | |
407 shouldBeNonNull("colorBuffer = gl.createRenderbuffer()"); | |
408 gl.bindRenderbuffer(gl.RENDERBUFFER, colorBuffer); | |
409 gl.framebufferRenderbuffer( | |
410 gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorBuffer); | |
411 gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 0, 0); | |
412 debug(""); | |
413 debug("Drawing or reading from an incomplete framebuffer should generate INV
ALID_FRAMEBUFFER_OPERATION"); | |
414 testRenderingAndReading(); | |
415 | |
416 function testRenderingAndReading() { | |
417 glErrorShouldBe(gl, gl.NO_ERROR); | |
418 wtu.drawQuad(gl); | |
419 glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "drawArrays with i
ncomplete framebuffer"); | |
420 gl.readPixels(0, 0, 1, 1, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(4)); | |
421 glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "readPixels from i
ncomplete framebuffer"); | |
422 // copyTexImage and copyTexSubImage can be either INVALID_FRAMEBUFFER_OP
ERATION because | |
423 // the framebuffer is invalid OR INVALID_OPERATION because in the case o
f no attachments | |
424 // the framebuffer is not of a compatible type. | |
425 gl.copyTexSubImage2D(gl.TEXTURE_2D, 0, 0, 0, 0, 0, 1, 1); | |
426 glErrorShouldBe(gl, [gl.INVALID_FRAMEBUFFER_OPERATION, gl.INVALID_OPERAT
ION], "copyTexImage2D from incomplete framebuffer"); | |
427 gl.copyTexImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 0, 0, 1, 1, 0); | |
428 glErrorShouldBe(gl, [gl.INVALID_FRAMEBUFFER_OPERATION, gl.INVALID_OPERAT
ION], "copyTexSubImage2D from incomplete framebuffer"); | |
429 gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); | |
430 glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION, "clear with incomp
lete framebuffer"); | |
431 } | |
432 } | |
433 | |
434 function testFramebufferIncompleteAttachment() { | |
435 shouldBeNonNull("fbo = gl.createFramebuffer()"); | |
436 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); | |
437 shouldBeNonNull("colorBuffer = gl.createRenderbuffer()"); | |
438 gl.bindRenderbuffer(gl.RENDERBUFFER, colorBuffer); | |
439 gl.framebufferRenderbuffer( | |
440 gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorBuffer); | |
441 gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16); | |
442 checkFramebuffer(gl.FRAMEBUFFER_COMPLETE); | |
443 | |
444 debug(""); | |
445 debug("Wrong storage type for type of attachment be FRAMEBUFFER_INCOMPLETE_A
TTACHMENT (OpenGL ES 2.0 4.4.5)"); | |
446 gl.renderbufferStorage(gl.RENDERBUFFER, depthFormat, 16, 16); | |
447 checkFramebuffer(gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT); | |
448 | |
449 gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16); | |
450 checkFramebuffer(gl.FRAMEBUFFER_COMPLETE); | |
451 | |
452 debug(""); | |
453 debug("0 size attachment should be FRAMEBUFFER_INCOMPLETE_ATTACHMENT (OpenGL
ES 2.0 4.4.5)"); | |
454 gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 0, 0); | |
455 checkFramebuffer(gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT); | |
456 | |
457 glErrorShouldBe(gl, gl.NO_ERROR); | |
458 } | |
459 | |
460 function testFramebufferIncompleteMissingAttachment() { | |
461 debug(""); | |
462 debug("No attachments should be INCOMPLETE_FRAMEBUFFER_MISSING_ATTACHMENT (O
penGL ES 2.0 4.4.5)"); | |
463 shouldBeNonNull("fbo = gl.createFramebuffer()"); | |
464 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); | |
465 checkFramebuffer(gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT); | |
466 | |
467 shouldBeNonNull("colorBuffer = gl.createRenderbuffer()"); | |
468 gl.bindRenderbuffer(gl.RENDERBUFFER, colorBuffer); | |
469 gl.framebufferRenderbuffer( | |
470 gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorBuffer); | |
471 gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16); | |
472 checkFramebuffer(gl.FRAMEBUFFER_COMPLETE); | |
473 | |
474 gl.framebufferRenderbuffer( | |
475 gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, null); | |
476 checkFramebuffer(gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT); | |
477 | |
478 glErrorShouldBe(gl, gl.NO_ERROR); | |
479 } | |
480 | |
481 function testFramebufferIncompleteDimensions() { | |
482 debug(""); | |
483 debug("Attachments of different sizes should be FRAMEBUFFER_INCOMPLETE_DIMEN
SIONS (OpenGL ES 2.0 4.4.5)"); | |
484 | |
485 shouldBeNonNull("fbo = gl.createFramebuffer()"); | |
486 gl.bindFramebuffer(gl.FRAMEBUFFER, fbo); | |
487 shouldBeNonNull("colorBuffer = gl.createRenderbuffer()"); | |
488 gl.bindRenderbuffer(gl.RENDERBUFFER, colorBuffer); | |
489 gl.framebufferRenderbuffer( | |
490 gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorBuffer); | |
491 gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16); | |
492 | |
493 shouldBeNonNull("depthBuffer = gl.createRenderbuffer()"); | |
494 gl.bindRenderbuffer(gl.RENDERBUFFER, depthBuffer); | |
495 gl.framebufferRenderbuffer( | |
496 gl.FRAMEBUFFER, depthAttachment, gl.RENDERBUFFER, depthBuffer); | |
497 gl.renderbufferStorage(gl.RENDERBUFFER, depthFormat, 16, 16); | |
498 glErrorShouldBe(gl, gl.NO_ERROR); | |
499 checkFramebuffer(gl.FRAMEBUFFER_COMPLETE); | |
500 | |
501 gl.renderbufferStorage(gl.RENDERBUFFER, depthFormat, 32, 16); | |
502 checkFramebuffer(gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS); | |
503 gl.renderbufferStorage(gl.RENDERBUFFER, depthFormat, 16, 16); | |
504 checkFramebuffer(gl.FRAMEBUFFER_COMPLETE); | |
505 gl.bindRenderbuffer(gl.RENDERBUFFER, colorBuffer); | |
506 gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 32); | |
507 checkFramebuffer(gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS); | |
508 gl.renderbufferStorage(gl.RENDERBUFFER, gl.RGBA4, 16, 16); | |
509 checkFramebuffer(gl.FRAMEBUFFER_COMPLETE); | |
510 glErrorShouldBe(gl, gl.NO_ERROR); | |
511 | |
512 var tex = gl.createTexture(); | |
513 gl.bindTexture(gl.TEXTURE_2D, tex); | |
514 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 16, 16, 0, gl.RGBA, gl.UNSIGNED_BYT
E, null); | |
515 gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D,
tex, 0); | |
516 glErrorShouldBe(gl, gl.NO_ERROR); | |
517 if (gl.checkFramebufferStatus(gl.FRAMEBUFFER) != gl.FRAMEBUFFER_COMPLETE) { | |
518 return; | |
519 } | |
520 | |
521 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 32, 16, 0, gl.RGBA, gl.UNSIGNED_BYT
E, null); | |
522 checkFramebuffer(gl.FRAMEBUFFER_INCOMPLETE_DIMENSIONS); | |
523 gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, 16, 16, 0, gl.RGBA, gl.UNSIGNED_BYT
E, null); | |
524 checkFramebuffer(gl.FRAMEBUFFER_COMPLETE); | |
525 | |
526 glErrorShouldBe(gl, gl.NO_ERROR); | |
527 } | |
528 | |
529 successfullyParsed = true; | |
530 </script> | |
531 | |
532 </body> | |
533 </html> | |
OLD | NEW |