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. 😉