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.


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).

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

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?


- Chad
_______________________________________________
mesa-dev mailing list
mesa-dev@lists.freedesktop.org
http://lists.freedesktop.org/mailman/listinfo/mesa-dev

Reply via email to