On 05/02/2012 06:32 PM, Chad Versace wrote:
Mesa has problems in the way it implements glBindFramebuffer and
glBindFramebufferEXT due to both being implemented by an overloaded
_mesa_BindFramebufferEXT.  This problem causes an Android app [1] to crash,
and I want your opinion on how we should fix it.

The problem is that in the five specs in the subject line, the specified
behavior of glBindFramebuffer falls into two incompatible categories.
Mesa implements the wrong behavior for OES_fbo, EXT_fbo, and GLES2 when
ARB_fbo is internally enabled.

[1] Pauli and Charles (CC'd) have more details about this crash, including an
     apitrace, if you're curious.


Behavior in Category A: ARB_fbo and GL3.0
-----------------------------------------

The behavior in these specs can be summarized as:

     1a. glBindFramebuffer may be called only on fb names produced by
         glGenFramebuffers.
     2a. glBindFramebuffer may not be called on an fb name previously deleted
         with glDeleteFramebuffers.

Below is the pertinent quote from the ARB_fbo spec. The language in the GL 3.0
spec is nearly identical.

     A framebuffer object is created by binding
     a name returned by GenFramebuffers (see below) to
     DRAW_FRAMEBUFFER or READ_FRAMEBUFFER.  The binding is
     effected by calling

         void BindFramebuffer(enum target, uint framebuffer);

     [...]

     BindFramebuffer fails and an INVALID_OPERATION error is generated if
     <framebuffer>  is not zero or a name returned from a previous call to
     GenFramebuffers, or if such a name has since been deleted with
     DeleteFramebuffers.


Behavior in Category B: EXT/OES_fbo and GLES2
----------------------------------------------

The behavior in these specs can be summarized as below. This behavior is
incompatible with points 1a and 2a.

     1b. glBindFramebuffer may be called on any unused fb name.
     2b. glBindFramebuffers may be called on an fb name previously deleted with
        glDeleteFramebuffers because, according to these specs, deletion marks
        a name as unused.

Below is the pertininent quote from the EXT_fbo spec. The language of the GLES
2 spec is nearly identical, but without the EXT suffix. The OES_fbo spec
refers to the EXT_fbo spec.

     The namespace for framebuffer objects is the unsigned integers, with
     zero reserved by the GL to refer to the default framebuffer.  A
     framebuffer object is created by binding an unused name to the
     target FRAMEBUFFER_EXT.  The binding is effected by calling

         void BindFramebufferEXT(enum target, uint framebuffer);

     [...]

     Framebuffer objects are deleted by calling

       void DeleteFramebuffersEXT(sizei n, uint *framebuffers);

     <framebuffers>  contains<n>  names of framebuffer objects to be
     deleted.  After a framebuffer object is deleted, [...],
     and its name is again unused.


The Crashing App
----------------

We have an Android app that does this:
     glGenFramebuffers(1,&fb);
     glBindFramebuffer(GL_FRAMEBUFFER, fb);
     // render render render...
     glDeleteFramebuffers(1,&fb);
     // go do other stuff...
     glBindFramebuffer(GL_FRAMEBUFFER, fb);
     // This bind unexpectedly failed, and the app panics.

So... the app is expecting this to create a "fresh" FBO?

The call to glBindFramebuffer fails because, in GLES1 and GLES2 contexts, the
Intel drivers internally enables both ARB_fbo and EXT_fbo. In
_mesa_BindFramebufferEXT, the ARB_fbo behavior wins.


Solutions for core Mesa
-----------------------

As for fixing _mesa_BindFramebufferEXT, I have two ideas.

1. Enforce in _mesa_BindFramebufferEXT that no more than one of ARB_fbo
    and EXT_fbo is enabled, then clean up its validation logic. This is
    a big hammer, and, if done right, can eliminate any ambiguities in behavior.
    (FYI, if I understand the gallium code, the only drivers that currently
    enable both are Intel, swrast, and OSMesa).

I'm not a fan of this. We only redact functionality that don't believe anyone uses. I'm fairly sure there are still apps that will use EXT_fbo.

2. Create separate entry points:
       - _mesa_BindFramebufferEXT, which implements
           - glBindFramebufferEXT
           - glBindFramebufferOES
           - glBindFramebuffer in GLES2
       - _mesa_BindFramebufferARB, which implements
           - glBindFramebufferARB
           - glBindFramebuffer in GL 3.x

This is my preference. I believe vertex array objects work like this. See src/mesa/main/arrayobj.c.

Any opinions? (I slightly prefer 2).


Quick Solution for the Intel drivers
------------------------------------

A quick solution may be as simple as removing ARB_fbo from the Intel drivers'
GLES1/2 extension lists.

Do you see any problem in doing this?

Charles, you have experimented with disabling ARB_fbo from GLES1/2 contexts.
Did you observe any negative consequences?
_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to