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