[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Public WebGL] framebuffer-object-attachment test is not passable



Here is a work-in-progress patch for the framebuffer-object-attachment test. Does this look OK?

Benoit

On 03/12/11 02:12 AM, Benoit Jacob wrote:

Hi,

If I'm not mistaken, the second testAttachment call in
framebuffer-object-attachment is not passable. It is:

debug("Attach depth using STENCIL_ATTACHMENT");
testAttachment(gl.STENCIL_ATTACHMENT, depthBuffer, true);

This is attaching a renderbuffer with DEPTH format to the STENCIL
attachment point of a newly created framebuffer, and requiring the
resulting framebuffer status to be FRAMEBUFFER_UNSUPPORTED.

If I understand it correctly, the OpenGL ES 2.0.25 spec requires the
status to be FRAMEBUFFER_INCOMPLETE_ATTACHMENT in this case. Indeed, on
page 118 it says that FRAMEBUFFER_INCOMPLETE_ATTACHMENT is returned if
some framebuffer attachment point is not "Framebuffer Attachment
Complete" while FRAMEBUFFER_UNSUPPORTED is returned in
implementation-dependent cases.

The present case (DEPTH format buffer attached to STENCIL attachment
point) is not an implementation-dependent case, and violates the
"Framebuffer Attachment Complete" rules given on page 117: "If
attachment is STENCIL_ATTACHMENT, then image must have a
stencil-renderable internal format."

Thus, FRAMEBUFFER_INCOMPLETE_ATTACHMENT must be returned in this case.

To fix this, I propose that instead of the current isConflicted
parameter, the testAttachment takes a bit-field, each bit allowing a
different error status.

Cheers,
Benoit

-----------------------------------------------------------
You are currently subscribed to public_webgl@khronos.org.
To unsubscribe, send an email to majordomo@khronos.org with
the following command in the body of your email:
unsubscribe public_webgl
-----------------------------------------------------------


diff --git a/content/canvas/test/webgl/conformance/renderbuffers/framebuffer-object-attachment.html b/content/canvas/test/webgl/conformance/renderbuffers/framebuffer-object-attachment.html
--- a/content/canvas/test/webgl/conformance/renderbuffers/framebuffer-object-attachment.html
+++ b/content/canvas/test/webgl/conformance/renderbuffers/framebuffer-object-attachment.html
@@ -22,68 +22,78 @@ var gl;
 var fbo;
 var depthBuffer;
 var stencilBuffer;
 var depthStencilBuffer;
 var colorBuffer;
 var width;
 var height;
 
-function testAttachment(attachment, buffer, isConflicted)
+const ALLOW_COMPLETE              = 0x01;
+const ALLOW_UNSUPPORTED           = 0x02;
+const ALLOW_INCOMPLETE_ATTACHMENT = 0x04;
+
+function testAttachment(attachment, buffer, allowedStatuses)
 {
     shouldBeNonNull("fbo = gl.createFramebuffer()");
     gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
     gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorBuffer);
     gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachment, gl.RENDERBUFFER, buffer);
     glErrorShouldBe(gl, gl.NO_ERROR);
     // If the framebuffer is in an error state for multiple reasons,
     // we can't guarantee which one will be reported.
-    if ((width == 0 || height == 0) && !isConflicted) {
-        // Zero-sized renderbuffers are supposed to result in an incomplete attachment.
-        // However, certain combination may violate implementation specific restrictions.
-        shouldBeTrue("gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT || gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_UNSUPPORTED");
-    } else if (isConflicted) {
-        shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_UNSUPPORTED");
+    var status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+    var statusAllowed = ((allowedStatuses & ALLOW_COMPLETE) && (status == gl.FRAMEBUFFER_COMPLETE)) ||
+                        ((allowedStatuses & ALLOW_COMPLETE) && (status == gl.FRAMEBUFFER_UNSUPPORTED)) ||
+                        ((allowedStatuses & ALLOW_INCOMPLETE_ATTACHMENT) && (status == gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT));
+    var msg = "gl.checkFramebufferStatus(gl.FRAMEBUFFER) returned " + status;
+    if (statusAllowed)
+        testPassed(msg);
+    else
+        testFailed(msg);
+    if ((allowedStatuses & ALLOW_COMPLETE) == 0) {
         gl.clear(gl.COLOR_BUFFER_BIT);
         glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION);
         gl.readPixels(0, 0, width, height, gl.RGBA, gl.UNSIGNED_BYTE, new Uint8Array(width * height * 4));
         glErrorShouldBe(gl, gl.INVALID_FRAMEBUFFER_OPERATION);
     }
 }
 
-function testAttachments(attachment0, buffer0, attachment1, buffer1, isConflicted)
+function testAttachments(attachment0, buffer0, attachment1, buffer1, allowedStatuses)
 {
     shouldBeNonNull("fbo = gl.createFramebuffer()");
     gl.bindFramebuffer(gl.FRAMEBUFFER, fbo);
     gl.framebufferRenderbuffer(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.RENDERBUFFER, colorBuffer);
     gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachment0, gl.RENDERBUFFER, buffer0);
     glErrorShouldBe(gl, gl.NO_ERROR);
     gl.framebufferRenderbuffer(gl.FRAMEBUFFER, attachment1, gl.RENDERBUFFER, buffer1);
     glErrorShouldBe(gl, gl.NO_ERROR);
     // If the framebuffer is in an error state for multiple reasons,
     // we can't guarantee which one will be reported.
-    if ((width == 0 || height == 0) && !isConflicted) {
-        // Zero-sized renderbuffers are supposed to result in an incomplete attachment.
-        // However, certain combination may violate implementation specific restrictions.
-        shouldBeTrue("gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT || gl.checkFramebufferStatus(gl.FRAMEBUFFER) == gl.FRAMEBUFFER_UNSUPPORTED");
-    } else if (isConflicted) {
-        shouldBe("gl.checkFramebufferStatus(gl.FRAMEBUFFER)", "gl.FRAMEBUFFER_UNSUPPORTED");
-    }
+    var status = gl.checkFramebufferStatus(gl.FRAMEBUFFER);
+    var statusAllowed = ((allowedStatuses & ALLOW_COMPLETE) && (status == gl.FRAMEBUFFER_COMPLETE)) ||
+                        ((allowedStatuses & ALLOW_COMPLETE) && (status == gl.FRAMEBUFFER_UNSUPPORTED)) ||
+                        ((allowedStatuses & ALLOW_INCOMPLETE_ATTACHMENT) && (status == gl.FRAMEBUFFER_INCOMPLETE_ATTACHMENT));
+    var msg = "gl.checkFramebufferStatus(gl.FRAMEBUFFER) returned " + status;
+    if (statusAllowed)
+        testPassed(msg);
+    else
+        testFailed(msg);
 }
 
-function testColorRenderbuffer(internalformat)
+function testColorRenderbuffer(internalformat, allowedStatuses)
 {
     shouldBeNonNull("colorBuffer = gl.createRenderbuffer()");
     gl.bindRenderbuffer(gl.RENDERBUFFER, colorBuffer);
     gl.renderbufferStorage(gl.RENDERBUFFER, internalformat, width, height);
     glErrorShouldBe(gl, gl.NO_ERROR);
-    testAttachment(gl.COLOR_ATTACHMENT0, colorBuffer, false);
+    testAttachment(gl.COLOR_ATTACHMENT0, colorBuffer, allowedStatuses);
 }
 
-function testDepthStencilRenderbuffer()
+function testDepthStencilRenderbuffer(allowedStatuses)
 {
     shouldBeNonNull("depthStencilBuffer = gl.createRenderbuffer()");
     gl.bindRenderbuffer(gl.RENDERBUFFER, depthStencilBuffer);
     gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width, height);
     glErrorShouldBe(gl, gl.NO_ERROR);
 
     // OpenGL itself doesn't seem to guarantee that e.g. a 2 x 0
     // renderbuffer will report 2 for its width when queried.
@@ -98,17 +108,17 @@ function testDepthStencilRenderbuffer()
     shouldBe("gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_ALPHA_SIZE)", "0");
     // Avoid verifying these for zero-sized renderbuffers for the time
     // being since it appears that even OpenGL doesn't guarantee them.
     if (width > 0 && height > 0) {
         shouldBeTrue("gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_DEPTH_SIZE) > 0");
         shouldBeTrue("gl.getRenderbufferParameter(gl.RENDERBUFFER, gl.RENDERBUFFER_STENCIL_SIZE) > 0");
     }
     glErrorShouldBe(gl, gl.NO_ERROR);
-    testAttachment(gl.DEPTH_STENCIL_ATTACHMENT, depthStencilBuffer, false);
+    testAttachment(gl.DEPTH_STENCIL_ATTACHMENT, depthStencilBuffer, allowedStatuses);
 }
 
 description("Test framebuffer object attachment behaviors");
 
 for (width = 0; width <= 2; width += 2)
 {
     for (height = 0; height <= 2; height += 2)
     {
@@ -129,59 +139,66 @@ for (width = 0; width <= 2; width += 2)
         gl.bindRenderbuffer(gl.RENDERBUFFER, stencilBuffer);
         gl.renderbufferStorage(gl.RENDERBUFFER, gl.STENCIL_INDEX8, width, height);
         glErrorShouldBe(gl, gl.NO_ERROR);
         shouldBeNonNull("depthStencilBuffer = gl.createRenderbuffer()");
         gl.bindRenderbuffer(gl.RENDERBUFFER, depthStencilBuffer);
         gl.renderbufferStorage(gl.RENDERBUFFER, gl.DEPTH_STENCIL, width, height);
         glErrorShouldBe(gl, gl.NO_ERROR);
 
+        var allowedStatusForGoodCase
+            = (width == 0 || height == 0) ? ALLOW_INCOMPLETE_ATTACHMENT : ALLOW_COMPLETE;
+
         debug("Attach depth using DEPTH_ATTACHMENT");
-        testAttachment(gl.DEPTH_ATTACHMENT, depthBuffer, false);
+        testAttachment(gl.DEPTH_ATTACHMENT, depthBuffer, allowedStatusForGoodCase);
         debug("Attach depth using STENCIL_ATTACHMENT");
-        testAttachment(gl.STENCIL_ATTACHMENT, depthBuffer, true);
+        testAttachment(gl.STENCIL_ATTACHMENT, depthBuffer, ALLOW_INCOMPLETE_ATTACHMENT);
         debug("Attach depth using DEPTH_STENCIL_ATTACHMENT");
-        testAttachment(gl.DEPTH_STENCIL_ATTACHMENT, depthBuffer, true);
+        testAttachment(gl.DEPTH_STENCIL_ATTACHMENT, depthBuffer, ALLOW_INCOMPLETE_ATTACHMENT);
         debug("Attach stencil using STENCIL_ATTACHMENT");
-        testAttachment(gl.STENCIL_ATTACHMENT, stencilBuffer, false);
+        testAttachment(gl.STENCIL_ATTACHMENT, stencilBuffer, allowedStatusForGoodCase);
         debug("Attach stencil using DEPTH_ATTACHMENT");
-        testAttachment(gl.DEPTH_ATTACHMENT, stencilBuffer, true);
+        testAttachment(gl.DEPTH_ATTACHMENT, stencilBuffer, ALLOW_INCOMPLETE_ATTACHMENT);
         debug("Attach stencil using DEPTH_STENCIL_ATTACHMENT");
-        testAttachment(gl.DEPTH_STENCIL_ATTACHMENT, stencilBuffer, true);
+        testAttachment(gl.DEPTH_STENCIL_ATTACHMENT, stencilBuffer, ALLOW_INCOMPLETE_ATTACHMENT);
         debug("Attach depthStencil using DEPTH_STENCIL_ATTACHMENT");
-        testAttachment(gl.DEPTH_STENCIL_ATTACHMENT, depthStencilBuffer, false);
+        testAttachment(gl.DEPTH_STENCIL_ATTACHMENT, depthStencilBuffer, allowedStatusForGoodCase);
         debug("Attach depthStencil using DEPTH_ATTACHMENT");
-        testAttachment(gl.DEPTH_ATTACHMENT, depthStencilBuffer, true);
+        testAttachment(gl.DEPTH_ATTACHMENT, depthStencilBuffer, ALLOW_INCOMPLETE_ATTACHMENT);
         debug("Attach depthStencil using STENCIL_ATTACHMENT");
-        testAttachment(gl.STENCIL_ATTACHMENT, depthStencilBuffer, true);
+        testAttachment(gl.STENCIL_ATTACHMENT, depthStencilBuffer, ALLOW_INCOMPLETE_ATTACHMENT);
+
+        var allowedStatusForConflictedAttachment
+            = (width == 0 || height == 0) ? ALLOW_COMPLETE | ALLOW_INCOMPLETE_ATTACHMENT
+                                          : ALLOW_COMPLETE;
 
         debug("Attach depth, then stencil, causing conflict");
-        testAttachments(gl.DEPTH_ATTACHMENT, depthBuffer, gl.STENCIL_ATTACHMENT, stencilBuffer, true);
+        testAttachments(gl.DEPTH_ATTACHMENT, depthBuffer, gl.STENCIL_ATTACHMENT, stencilBuffer, allowedStatusForConflictedAttachment);
         debug("Attach stencil, then depth, causing conflict");
-        testAttachments(gl.STENCIL_ATTACHMENT, stencilBuffer, gl.DEPTH_ATTACHMENT, depthBuffer, true);
+        testAttachments(gl.STENCIL_ATTACHMENT, stencilBuffer, gl.DEPTH_ATTACHMENT, depthBuffer, allowedStatusForConflictedAttachment);
         debug("Attach depth, then depthStencil, causing conflict");
-        testAttachments(gl.DEPTH_ATTACHMENT, depthBuffer, gl.DEPTH_STENCIL_ATTACHMENT, depthStencilBuffer, true);
+        testAttachments(gl.DEPTH_ATTACHMENT, depthBuffer, gl.DEPTH_STENCIL_ATTACHMENT, depthStencilBuffer, allowedStatusForConflictedAttachment);
         debug("Attach depthStencil, then depth, causing conflict");
-        testAttachments(gl.DEPTH_STENCIL_ATTACHMENT, depthStencilBuffer, gl.DEPTH_ATTACHMENT, depthBuffer, true);
+        testAttachments(gl.DEPTH_STENCIL_ATTACHMENT, depthStencilBuffer, gl.DEPTH_ATTACHMENT, depthBuffer, allowedStatusForConflictedAttachment);
         debug("Attach stencil, then depthStencil, causing conflict");
-        testAttachments(gl.DEPTH_ATTACHMENT, depthBuffer, gl.DEPTH_STENCIL_ATTACHMENT, depthStencilBuffer, true);
+        testAttachments(gl.DEPTH_ATTACHMENT, depthBuffer, gl.DEPTH_STENCIL_ATTACHMENT, depthStencilBuffer, allowedStatusForConflictedAttachment);
         debug("Attach depthStencil, then stencil, causing conflict");
-        testAttachments(gl.DEPTH_STENCIL_ATTACHMENT, depthStencilBuffer, gl.STENCIL_ATTACHMENT, stencilBuffer, true);
+        testAttachments(gl.DEPTH_STENCIL_ATTACHMENT, depthStencilBuffer, gl.STENCIL_ATTACHMENT, stencilBuffer, allowedStatusForConflictedAttachment);
 
         debug("Attach color renderbuffer with internalformat == RGBA4");
-        testColorRenderbuffer(gl.RGBA4);
+        testColorRenderbuffer(gl.RGBA4, allowedStatusForGoodCase);
 
         debug("Attach color renderbuffer with internalformat == RGB5_A1");
-        testColorRenderbuffer(gl.RGB5_A1);
+        testColorRenderbuffer(gl.RGB5_A1, allowedStatusForGoodCase);
 
         debug("Attach color renderbuffer with internalformat == RGB565");
-        testColorRenderbuffer(gl.RGB565);
+        testColorRenderbuffer(gl.RGB565, allowedStatusForGoodCase);
 
         debug("Create and attach depthStencil renderbuffer");
-        testDepthStencilRenderbuffer();
+        testDepthStencilRenderbuffer(allowedStatusForGoodCase);
     }
 }
 
 // Determine if we can attach both color and depth or color and depth_stencil
 var depthFormat;
 var depthAttachment;
 
 function checkValidColorDepthCombination() {