blob: 04d6a34bfa6ef55c90b0e1dfeaaba804d995665b [file] [log] [blame] [edit]
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link rel="stylesheet" href="resources/webgl_test_files/resources/js-test-style.css"/>
<script src="resources/webgl_test_files/js/js-test-pre.js"></script>
<script src="resources/webgl_test_files/js/webgl-test-utils.js"></script>
</head>
<body onload="test()">
<div id="description"></div>
<div id="console"></div>
<canvas id="canvas" width="2" height="2"></canvas>
<script>
"use strict";
description("Test that draw buffer state is properly synced when framebuffer is bound to DRAW after modifications while bound to READ.");
var wtu = WebGLTestUtils;
var gl;
function test()
{
var canvas = document.getElementById("canvas");
gl = wtu.create3DContext(canvas, undefined, 2);
if (!gl) {
testFailed("WebGL2 context does not exist");
finishTest();
return;
}
testDetachWhileBoundToRead();
testAttachWhileBoundToRead();
testMultipleDrawBuffers();
finishTest();
}
// Test 1: Detach texture while bound to READ, then rebind to DRAW
function testDetachWhileBoundToRead()
{
debug("");
debug("Test 1: Detach while bound to READ_FRAMEBUFFER, then rebind to DRAW_FRAMEBUFFER");
var fb = gl.createFramebuffer();
var texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
// Bind to DRAW, configure draw buffers, attach texture
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb);
gl.drawBuffers([gl.COLOR_ATTACHMENT0]);
gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
// Verify initial state
shouldBe("gl.getParameter(gl.DRAW_BUFFER0)", "gl.COLOR_ATTACHMENT0");
shouldBe("gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "setup should succeed");
// Switch to READ only
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fb);
// Detach texture while bound to READ only
gl.framebufferTexture2D(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, null, 0);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "detach while bound to READ should succeed");
// Bind back to DRAW - draw buffer state should be synced
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb);
// getParameter returns user-set values, not internal filtered state
shouldBe("gl.getParameter(gl.DRAW_BUFFER0)", "gl.COLOR_ATTACHMENT0");
// Framebuffer has no attachments, so it's incomplete
shouldBe("gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER)", "gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT");
// Cleanup
gl.deleteFramebuffer(fb);
gl.deleteTexture(texture);
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null);
}
// Test 2: Attach texture while bound to READ, then rebind to DRAW
function testAttachWhileBoundToRead()
{
debug("");
debug("Test 2: Attach while bound to READ_FRAMEBUFFER, then rebind to DRAW_FRAMEBUFFER");
var fb = gl.createFramebuffer();
var texture = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
// Bind to DRAW, configure draw buffers (but don't attach yet)
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb);
gl.drawBuffers([gl.COLOR_ATTACHMENT0]);
// getParameter returns user-set values
shouldBe("gl.getParameter(gl.DRAW_BUFFER0)", "gl.COLOR_ATTACHMENT0");
// Framebuffer is incomplete - no attachment yet
shouldBe("gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER)", "gl.FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT");
// Switch to READ only
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fb);
// Attach texture while bound to READ only
gl.framebufferTexture2D(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture, 0);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "attach while bound to READ should succeed");
// Bind back to DRAW - draw buffer state should be synced
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb);
// Draw buffer should now be COLOR_ATTACHMENT0 (attachment exists)
shouldBe("gl.getParameter(gl.DRAW_BUFFER0)", "gl.COLOR_ATTACHMENT0");
// Framebuffer should be complete
shouldBe("gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
// Cleanup
gl.deleteFramebuffer(fb);
gl.deleteTexture(texture);
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null);
}
// Test 3: Multiple draw buffers with partial detachment
function testMultipleDrawBuffers()
{
debug("");
debug("Test 3: Multiple draw buffers with partial detachment while bound to READ");
var fb = gl.createFramebuffer();
var texture0 = gl.createTexture();
var texture1 = gl.createTexture();
gl.bindTexture(gl.TEXTURE_2D, texture0);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
gl.bindTexture(gl.TEXTURE_2D, texture1);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA8, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, null);
// Bind to DRAW, configure both draw buffers, attach both textures
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb);
gl.drawBuffers([gl.COLOR_ATTACHMENT0, gl.COLOR_ATTACHMENT1]);
gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, texture0, 0);
gl.framebufferTexture2D(gl.DRAW_FRAMEBUFFER, gl.COLOR_ATTACHMENT1, gl.TEXTURE_2D, texture1, 0);
// Verify initial state
shouldBe("gl.getParameter(gl.DRAW_BUFFER0)", "gl.COLOR_ATTACHMENT0");
shouldBe("gl.getParameter(gl.DRAW_BUFFER1)", "gl.COLOR_ATTACHMENT1");
shouldBe("gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
// Switch to READ only
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, fb);
// Detach texture1 from COLOR_ATTACHMENT1 while bound to READ
gl.framebufferTexture2D(gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT1, gl.TEXTURE_2D, null, 0);
wtu.glErrorShouldBe(gl, gl.NO_ERROR, "partial detach while bound to READ should succeed");
// Bind back to DRAW - draw buffer state should be synced
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, fb);
// getParameter returns user-set values
shouldBe("gl.getParameter(gl.DRAW_BUFFER0)", "gl.COLOR_ATTACHMENT0");
shouldBe("gl.getParameter(gl.DRAW_BUFFER1)", "gl.COLOR_ATTACHMENT1");
// Framebuffer should be complete (internal state filters out detached COLOR_ATTACHMENT1)
shouldBe("gl.checkFramebufferStatus(gl.DRAW_FRAMEBUFFER)", "gl.FRAMEBUFFER_COMPLETE");
// Cleanup
gl.deleteFramebuffer(fb);
gl.deleteTexture(texture0);
gl.deleteTexture(texture1);
gl.bindFramebuffer(gl.DRAW_FRAMEBUFFER, null);
gl.bindFramebuffer(gl.READ_FRAMEBUFFER, null);
}
</script>
</body>
</html>