For my first entry on this blog let me tell you a tale, it’s about OpenGL framebuffer and vertical flipping…

Once upon a time a little fool called Encelo used to perform, in a little testing program, a vertical flip of the entire OpenGL framebuffer this way:
if(_flags & SDL_OPENGL)
{
GLvoid * pixels;
pixels = (GLvoid *) malloc(_width * _height * 4);
glPushAttrib(GL_COLOR_BUFFER_BIT | GL_CURRENT_BIT | GL_PIXEL_MODE_BIT);
glReadBuffer(GL_FRONT);
glReadPixels(0, 0, _width, _height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
glDrawBuffer(GL_BACK);
glRasterPos2f(-1.0f, 1.0f);
glPixelZoom(1.0f, -1.0f);
glDrawPixels(_width, _height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
glReadBuffer(GL_BACK);
glReadPixels(0, 0, _width, _height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
glPopAttrib();
output_surf = SDL_CreateRGBSurfaceFrom(pixels, _width, _height, 32, _surface->pitch, rmask, gmask, bmask, amask);
}
It wasn’t really bad, it performed some interesting tricks with buffers, and, as a matter of fact, Encelo was really proud of this implementation. 
But… it didn’t work on Mars. Yes, no matter how much Encelo tested, changed, and tested again, it simply didn’t work on anything else than the original testing program.
A decision had to be taken soon, to persevere or not to persevere? That was the question.
Encelo chose not to persevere and to try a completely different approach… memcpy() flipping! 
Yeah, something as simple, elegant, fast and smart as this:
if(_flags & SDL_OPENGL)
{
int row, stride;
GLubyte * swapline;
GLubyte * pixels;
stride = _width * 4; // length of a line in bytes
pixels = (GLubyte *) malloc(stride * _height);
swapline = (GLubyte *) malloc(stride);
glReadPixels(0, 0, _width, _height, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
// vertical flip
for(row = 0; row < _height/2; row++)
{
memcpy(swapline, pixels + row * stride, stride);
memcpy(pixels + row * stride, pixels + (_height - row - 1) * stride, stride);
memcpy(pixels + (_height - row -1) * stride, swapline, stride);
}
output_surf = SDL_CreateRGBSurfaceFrom(pixels, _width, _height, 32, _surface->pitch, rmask, gmask, bmask, amask);
}
This story is true, and happened exactly a month ago, on the 30 of November 2006.
As a proof have a look at r594 log and at Screen.cpp changes.