What could be causing GL_INVALID_OPERATION error on glTexSubImage2D call? (OpenGL ES)

(This is an OpenGL ES 2.0 specific question.)

I have a framebuffer called dirty_fbo with a texture backing called DIRTY_FBO_TEXTURE. I am just trying to readPixels from it and write them back. This is only to figure out whether it works correctly. I intend to later use the pixels read to implement an undo redo etc. elsewhere in my code. My code is as below:

...
    glBindFramebuffer(GL_FRAMEBUFFER, dirty_fbo);

    VBounds bounds = [self get_fbo_bounds];
    GLubyte * old_pixel_data = (GLubyte*) malloc(bounds.width * bounds.height * sizeof(GLubyte) * 4);
    GLubyte * new_pixel_data = (GLubyte*) malloc(bounds.width * bounds.height * sizeof(GLubyte) * 4);
    pixel_data = (GLubyte*) malloc(bounds.width * bounds.height * sizeof(GLubyte) * 4);

    glReadPixels(bounds.x, bounds.y, bounds.width, bounds.height, GL_RGBA, GL_UNSIGNED_BYTE, old_pixel_data);

    [self draw_path];

    glReadPixels(bounds.x, bounds.y, bounds.width, bounds.height, GL_RGBA, GL_UNSIGNED_BYTE, new_pixel_data);

    glBindTexture(GL_TEXTURE_2D, DIRTY_FBO_TEXTURE);
    glTexSubImage2D(GL_TEXTURE_2D, 0, bounds.x, bounds.y, bounds.width, bounds.height, GL_RGBA, GL_UNSIGNED_BYTE, old_pixel_data);

    free(old_pixel_data);
    free(new_pixel_data);
    free(pixel_data);
...

But for some reason I keep getting GL_INVALID_OPERATION for the glTexSubImage2D call. And I have no idea why. Any pointers at all will be helpful.

Note:

It really is the glTexSubImage2D call that is causing the error. I’ve verified this.

The bounds calculated are correct.

The DIRTY_FBO_TEXTURE does get drawn to correctly with the draw_paths call. I use the DIRTY_FBO_TEXTURE as a texture for a full-screen quad elsewhere in the program and that works correctly too.

The glTexSubImage2D call params use the same respective values as the initial glTexImage2D call made on the texture at the beginning of the application.

What were the arguments to the original glTexImage2D (or glTexStorage2D) call that defined that texture?

The original call is done so:

glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA,  w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);

In GL, I would advise you to introspect the texture via glGetTexLevelParameter, to verify it is really as you expect (i.e. the subimage dimensions are within the actual defined dimensions, and the internalformat is compatible with the subimage format,type per ES constraints.)

However, ES removed glGetTexLevelParameter, so you’ve no way to directly introspect. You could try the state inspector in the Xcode ES debugger.

So I did go through the Debugger and it was the stupidest thing: I was binding the wrong texture name. DIRTY_FBO_TEXTURE is a dedicated texture unit. What I needed to use was dirty_fbo_texture, which is the texture name. I had already looked at it in the debugger, but had somehow missed this obvious error. Looked again as per your suggestion and there it was. Thanks.