Retire the GL_GENERATE_MIPMAP hack for FlatInput.
authorSteinar H. Gunderson <sgunderson@bigfoot.com>
Mon, 20 Jan 2014 23:56:27 +0000 (00:56 +0100)
committerSteinar H. Gunderson <sgunderson@bigfoot.com>
Mon, 20 Jan 2014 23:56:27 +0000 (00:56 +0100)
I found very similar workaround code for this bug in Chromium,
with the following comment:

  // Workaround for Mac driver bug. In the large scheme of things setting
  // glTexParamter twice for glGenerateMipmap is probably not a lage performance
  // hit so there's probably no need to make this conditional. The bug appears
  // to be that if the filtering mode is set to something that doesn't require
  // mipmaps for rendering, or is never set to something other than the default,
  // then glGenerateMipmap misbehaves.

Going back all the way to the point in which this code was written,
it is indeed true; we called glGenerateMipmap(), and then right afterwards
set the mode to GL_LINEAR_MIPMAP_NEAREST. Since then, the code has been
reorganized and moved around a lot, and now we set the mode long before
the first call to glGenerateMipmap(), and thus we can retire the hack;
simply generate mipmaps on-demand, and that's the end of it. I tested
with the Mesa 8.0.x version where I originally saw this bug, and it passes
flat_input_test without any problems (well, actually all tests except
the tests for deconvolution sharpen, whose shaders are too big for it).

This is nice not only because it gives us a less hacky structure, but also
because GL_GENERATE_MIPMAPS is a nightmare for the driver to handle;
several edge conditions are tricky, from what I've been told.

flat_input.cpp

index cf53034..b147725 100644 (file)
@@ -70,10 +70,6 @@ void FlatInput::finalize()
        check_error();
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, needs_mipmaps ? GL_LINEAR_MIPMAP_NEAREST : GL_LINEAR);
        check_error();
-       // Intel/Mesa seems to have a broken glGenerateMipmap() for non-FBO textures, so do it here
-       // instead of calling glGenerateMipmap().
-       glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, needs_mipmaps ? GL_TRUE : GL_FALSE);
-       check_error();
        glTexImage2D(GL_TEXTURE_2D, 0, internal_format, width, height, 0, format, type, NULL);
        check_error();
        glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
@@ -102,6 +98,10 @@ void FlatInput::set_gl_state(GLuint glsl_program_num, const std::string& prefix,
                check_error();
                glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, format, type, pixel_data);
                check_error();
+               if (needs_mipmaps) {
+                       glGenerateMipmap(GL_TEXTURE_2D);
+                       check_error();
+               }
                glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
                check_error();
                glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);