Implementors can exploit their render-to-texture capabilities to downsample textures. This requires being able to sample from miplevel n and write to miplevel n+1 simultaneously. While that’s a novelty for users of OpenGL, I’m sure that driver writers have been able to do it, under controlled circumstances, for a long time already.
For a simple equal-weight 2x2 box filter, the linear texture filter is all you need. You want to sample exactly between the four source texels, so that they contribute the same amount to the single downsampled target texel.
For a nxm source level, the correct sample points are of the form
(1/n;1/m) (3/n;1/m) (5/n;1/m) ...
(1/n;3/m) (3/n;3/m) (5/n;3/m) ...
(1/n;5/m) (3/n;5/m) (5/n;5/m) ...
... ... ... ...
(NOTE that if n=1 or m=1, the coords theoretically need to be adjusted. But because of how we’re going to implement it, it’ll all work out nicely regardless)
And you can easily generate these sample coords with the texcoord interpolator and careful sizing of the target drawing region.
E.g.
glBindTexture(GL_TEXTURE_2D,source_level_128x128);
glTexParameteri(GL_TEXTURE_2D,GL_MIN_FILTER,GL_LINEAR);
glEnable(GL_TEXTURE_2D);
//quick-hackish way to draw an exact pixel sized quad
//feel free to do it properly
glViewport(0,0,64,64); //size of target level
glMatrixMode(GL_PROJECTION);
glLoadIdentitiy();
glMatrixMode(GL_MODELVIEW);
glLoadIdentitiy();
glBegin(GL_QUADS);
glTexCoord2f(0.0f,0.0f); glVertex2f(-1.0f,-1.0f);
glTexCoord2f(1.0f,0.0f); glVertex2f( 1.0f,-1.0f);
glTexCoord2f(1.0f,1.0f); glVertex2f( 1.0f, 1.0f);
glTexCoord2f(0.0f,0.0f); glVertex2f(-1.0f, 1.0f);
glEnd();
Then you “rebind” the generated level as the new source level (which you can’t currently, you need to use glCopyTex(Sub)Image), and repeat the process until you’ve generated the 1x1 level.