Since you are probably going for the 4-colour-thing, you might want to read the framebuffer into memory first and apply some colour-reduction-algorithm.
// create buffer for reading back the opengl framebuffer (use a size of 2^n so we can directly dump the buffer into a texture)
uint32 *vbuffer= new uint32[256*128];
// create a texture to hold the framebuffer
unsigned int mOffscreen;
glGenTextures(1, &mOffscreen);
glBindTexture(GL_TEXTURE_2D, mOffscreen);
// disable filtering for this texture
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
while (running)
{
// set desired resolution
glViewport(0,0,160,120);
glClear(...);
// do totally amazing opengl magic here
// read backbuffer (reads more than actually required, so we don't need to convert to texture-size)
glReadPixels(0,0,256,128, GL_BGRA, GL_UNSIGNED_BYTE, vbuffer);
// do wicked colour-reduction-things on the buffer
// remember that you only need to process the first 160 pixels of each scanline
// write buffer to texture
glBindTexture(GL_TEXTURE_2D, mOffscreen);
glTexImage2D(GL_TEXTURE_2D, 0, GL_BGRA, 256, 128, 0, GL_BGRA, GL_UNSIGNED_BYTE, vbuffer);
// viewport to full screen size
glViewport(0,0, 640, 480);
// set up a useful projection to make a fullscreen-polygon (glOrtho does well, too)
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(90.0f, 1.0f, 0.1f, 100.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glDisable(GL_DEPTH_TEST); // don't need to clear again.
// draw quad with framebuffer as texture
glBegin(GL_QUADS);
float y= 120.0 / 128.0; // texcoord of 160,120 on a 256x128 texture.
float x= 160.0 / 256.0;
glColor4f(1,1,1,1);
glTexCoord2f(x,0); glVertex3f( 1,-1,-1);
glTexCoord2f(0,0); glVertex3f(-1,-1,-1);
glTexCoord2f(0,y); glVertex3f(-1, 1,-1);
glTexCoord2f(x,y); glVertex3f( 1, 1,-1);
glEnd();
SwapBuffers();
}
This is far from optimal, but for the required size it doesn't make much sense to think about optimization.