How does FBO realize nested use?

Usually, we use an FBO for rendering without problems, such as:

     // Store the current frame buffer
        glGenTextures(1, &offscreen_fbo_texture);
        glBindTexture(GL_TEXTURE_2D, offscreen_fbo_texture);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
        glBindTexture(GL_TEXTURE_2D, 0);

        //Depth buffer
        glGenRenderbuffers(1, &offscreen_fbo_depth);
        glBindRenderbuffer(GL_RENDERBUFFER, offscreen_fbo_depth);
        glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, width, height);
        glBindRenderbuffer(GL_RENDERBUFFER, 0);

        //Framebuffer to link everything together
        glGenFramebuffers(1, &offscreen_fbo);
        glBindFramebuffer(GL_FRAMEBUFFER, offscreen_fbo);
        glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, offscreen_fbo_texture, 0);
        glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, offscreen_fbo_depth);

        if ((status = glCheckFramebufferStatus(GL_FRAMEBUFFER)) != GL_FRAMEBUFFER_COMPLETE) {
                fprintf(stderr, "glCheckFramebufferStatus returned error %d", status);
                return -1;
        }
        
        // Bind back original frame buffer
        glBindFramebuffer(GL_FRAMEBUFFER, 0);
        
        // To draw to offscreen fbo, bind offscreen_fbo
        glBindFramebuffer(GL_FRAMEBUFFER, offscreen_fbo);
        // DrawA()
        // DrawB()
        // ....
         glBindFramebuffer(GL_FRAMEBUFFER, 0);
        // Draw offscreen_fbo_texture
        Draw(offscreen_fbo_texture)

But now I want to nest another FBO inside one FBO, but report 0x506 error GL_INVALID_FRAMEBUFFER_OPERATION. The specific process is as follows:

  1. Initialize and bind an FBO, temporarily name it FBO_A, texture Tex_A
  2. Drawing and rendering function FuncA:
    2.1. Initialize and bind another FBO, named FBO_B for the time being, texture Tex_B
    2.2, Draw1()
    Draw2()
    2.3, glBindFramebuffer(GL_FRAMEBUFFER, 0);
    2.4. Render Tex_B after processing
  3. glBindFramebuffer(GL_FRAMEBUFFER, 0);
  4. Render Tex_A

How to achieve similar FBO? Or is there any other way to achieve this?

Taken literally, this makes no sense.

I would suggest that you put the code aside and describe what rendering result you want to achieve in the final framebuffer (window usually). Then describe why you think you need an FBO to render this at all. And then describe why you think you might need more than one FBO.

You might, but it’s far from clear what you’re even talking about here.

Since item 2 has nothing to do with item 1, I fail to see why you can’t just do it first. In fact, I don’t see where you’re rendering to Tex_A at all. Do you expect item 2 to render to both Tex_A and Tex_B?

In short, you have 2 completely independent operations. You can just do one after the other.

You’re over-thinking this. There is no concept of nested framebuffers in OpenGL, so by trying to implement “framebuffers inside framebuffers” you’re just making a mess with code that will fight against the API design rather than work with it.

What I think you’re trying to do, based on your question, is this:

  • Create 2 framebuffers, let’s call them fb1 and fb2.
  • Render the scene to fb2 normally.
  • Render fb2 to fb1 with one post-processing effect.
  • Render fb1 to the default framebuffer (we’ll call it fb0) with another post-processing effect.

And the way to do that is to just simply do it as I’ve described above. Don’t think about interactions or links between framebuffers because they don’t exist, and you’ll have a mental model that doesn’t match the API. The framebuffers are independent of each other and just simply use them as I’ve described.

Thank you for your answer. Yes, you understand what I want to do.
Let me talk about the background of the problem:
Use TI chip TDA4 (based on OpenVX architecture) for rendering.
As they(TI) said before, in the case of TDA4, the display is driven by R5, so TDA4 uses FBO for rendering outside.

The rendering process in TDA4:

… …

  1. texYuv[i] = appEglWindowGetTexYuv(pEglWindowObj, &texProp[i]);
    … …
  2. appEglBindFrameBuffer(glSrvParams->eglWindowObj, &renderTexProp);

FBO is used in this function

glGenTextures(1, &tex_obj->tex);
glBindTexture(GL_TEXTURE_2D, tex_obj->tex);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glGenFramebuffers(1, &tex_obj->fboId);
glBindFramebuffer(GL_FRAMEBUFFER, tex_obj->fboId);
GLuint rboDepthStencil;
glGenRenderbuffers(1, &rboDepthStencil);
glBindRenderbuffer(GL_RENDERBUFFER, rboDepthStencil);
glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH24_STENCIL8_OES, prop->width, prop->height);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, rboDepthStencil);
glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_RENDERBUFFER, rboDepthStencil);
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, tex_obj->tex);
glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, (GLeglImageOES)tex_obj->img);
glBindFramebuffer(GL_FRAMEBUFFER, tex_obj->fboId);
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,GL_TEXTURE_2D, tex_obj->tex, 0);

… …
3. render_renderFrame(&glSrvParams->render3DSRVObj,glSrvParams->eglWindowObj,texYuv);
Here is the texture unit texYuv that has been bound in step 1.
Now the problem is here: if I use a new FBO in render_renderFrame (not the same as tex_obj->fboId in appEglBindFrameBuffer in step 2),
Here it will report 0x506 GL_INVALID_FRAMEBUFFER_OPERATION error, so nothing can be drawn.
The reason why I use a new FBO here is that I want to draw A first, then draw B, and finally display it as a new texture after processing.

My usage is as described before, here is the wrong method I used?
Or is there any other way to achieve what I want?

  1. glFinish();
    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    appEglSwap(glSrvParams->eglWindowObj);

I feel that the crux of the problem lies in:
In the case of TDA4, the display is driven by R5, so TDA4 uses FBO for rendering outside.(The display in other case such as TDA2 was driven by EGL and thus the swap.)
In this way, we can no longer create and use other FBOs in render_renderFrame().

What needs to be solved now is:
TDA4 uses FBO outside,
How to create and use other FBOs in render_renderFrame()?

Thanks.

Recently I am using TI chip TDA4 (based on OpenVX architecture) for rendering.

The reason why TDA4 uses FBO for rendering is because of how the display works. The display in case of TDA2 was driven by EGL and thus the swap.
In case of TDA4, the display is being driven by R5. The GPU rendered buffer is passed on to display node that takes care of displaying the buffer. This is why we need off screen buffer

Hi,
what I want to do is this:

  • Create 2 framebuffers, let’s call them fb1 and fb2.
  • Render the scene to fb2 normally.
  • Render fb2 to fb1 with one post-processing effect.
  • Render fb1 to the default framebuffer (we’ll call it fb0) with another post-processing effect.

In this way, the rendering is successful, but there is a splash screen, how to solve it?

Continued here: