Colour indexed mode fast + clear, RGBA not

Hi there,

I have a (2D) app running in Windows 2k. The app used to be in colour indexed mode. When I converted it to RGB, several weird things started happening. I’ll list them, plus anything I think may be relevant;

Problems:

  • The biggest problem is that when my desktop is in 24 bpp, the speed of the program drops dramatically. The speed is OK for 8 and 16 bpp display modes.

  • The next biggest problem is that when my desktop is in 16 or 24 bpp, the lines drawn with glBegin(GL_LINES) aren’t being drawn as sharp - it’s only noticeable when the lines aren’t vertical or horizontal, but they’re definitely thicker than they were in colour indexed mode. I thought maybe this is something to do with anti-aliasing, but to my knowledge I’ve not turned it on. The only possibly relevant calls I make are glClearColor(0.0, 0.0, 0.0, 0.0); glShadeModel(GL_FLAT); in my init().

  • I’m drawing several box outlines like this:
    Draw_Line(border.x(),border.y(), border.x() + size.x(), border.y(), colour);
    Draw_Line(border.x() + size.x(), border.y(), border.x() + size.x(), border.y() + size.y(), colour);
    Draw_Line(border.x() + size.x(), border.y() + size.y(), border.x(), border.y() + size.y(), colour);
    Draw_Line(border.x(), border.y() + size.y(), border.x(), border.y(), colour);
    When my desktop is in 16 or 24 bpp, the top-left pixel of each box is missing. Sometimes it’s the lower-right pixel which goes AWOL. This does not happen when I run the program in colour indexed mode – but then I can only test it in an 8 bpp display mode when I am in colour indexed mode – and the problem doesn’t occur in 8 bpp modes, regardless.

  • Finally, when my desktop is in 24 bpp only, the mouse is flickering when over the window. This is really the least of my worries!

Here is my Draw_Line;

void Draw_Line(int x1, int y1, int x2, int y2, GLfloat *colour)
{
glColor3fv(colour);

    glBegin(GL_LINES);
            glVertex2f(x1, y1);
            glVertex2f(x2, y2);
    glEnd();

}

This is basically the only drawing command in the program – the entire program just consists of a hundred or so lines being drawn in an animation (a set of 2D stick characters pretending to walk along). I tried using vertex arrays for the coordinates and the colours, but this didn’t help either – in both the speed and the line-drawing problem.

Only a few colours are used. They are defined as follows:

GLfloat red[] = {1.0, 0.0, 0.0}, green[] = {0.0, 1.0, 0.0}, blue[] = {0.0, 0.0, 1.0}, white[] = {1.0, 1.0, 1.0}, darkred[] = {0.5, 1.0, 1.0};

I thought maybe I’m doing something wrong with the arrays – my C isn’t great – and so I replaced the glColor3fv() in Draw_Line with glColor3f(1.0, 1.0, 1.0) as a test – but this made no difference.

I’ve also got a couple of text-printing functions:

void Draw_Text(char *s, int x, int y, GLfloat *colour)
{
glRasterPos2f(x, y + 12);
glColor3f(1.0, 1.0, 1.0); //glColor3fv(colour);

    while (*s)
            glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, (int) *s++);

}

void Draw_Text(const std::string& s, Point loc, GLfloat *colour)
{
char *buf, *top;
buf = (char *) malloc(sizeof(char) * ((s.size() + 1)));
strcpy(buf, s.c_str());
top = buf;

    glRasterPos2f(loc.x(), loc.y() + 12);
    glColor3f(1.0, 1.0, 1.0); //glColor3fv(colour);

    while (*buf)
            glutBitmapCharacter(GLUT_BITMAP_HELVETICA_12, (int) *buf++);

    free(top);

}

I tried commenting out the contents of both of these functions, to eliminate text-printing from causing the problem – but doing so slowed the program down even further – this I have no idea why it’s happening!

Finally, here is my entire main.cpp:

#include <ctime>

#include <GL/glut.h>

#include “Justlegs.h”
#include “util.h”
#include “ea.h”

// the main application object
Justlegs *justlegs;

void init()
{
// build the 360 degree look ups
build_sin_cos_tables();

    //build_palette();

    glClearColor(0.0, 0.0, 0.0, 0.0);
    glShadeModel(GL_FLAT);

    glEnableClientState(GL_VERTEX_ARRAY);
    glEnableClientState(GL_COLOR_ARRAY);

    glColorPointer(3, GL_FLOAT, 0, colours);
    glVertexPointer(2, GL_INT, 0, coords);

    screen_width = 640;
    screen_height = 480;
    aspect_mult_x = aspect_mult_y = 1;
    fullscreen = false;
    
    srand((unsigned long) time(NULL));

    // construct our application object with parameters from ea.h
    justlegs = new Justlegs(POP_SIZE, INTERVAL, CONTROL_POINTS, SAMPLE_SIZE);

}

void display()
{
glClear(GL_COLOR_BUFFER_BIT);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    // this projection inverts the y axis because the code thinks (0,0)
    // is in the top-right - this is a legacy of its DirectDraw roots...
    gluOrtho2D(0.0, (GLfloat) screen_width, (GLfloat) screen_height, 0.0);

    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

    justlegs-&gt;run();

    Draw_Arrays();

    glFlush();
    glutSwapBuffers();

}

void keyboard(unsigned char key, int x, int y)
{
// escape
if (key == 27)
if (!justlegs->pop_state())
exit(0);

    // tab
    if (key == 9) {
            if (!fullscreen)
                    glutFullScreen();
            else {
                    glutPositionWindow(50, 50);
                    glutReshapeWindow(640, 480);
            }
            fullscreen = !fullscreen;
    }

}

void mouse(int button, int state, int x, int y)
{
Point loc(x * aspect_mult_x, y * aspect_mult_y);

    justlegs-&gt;notify(button, state, loc);

}

void idle()
{
justlegs->run();
glutPostRedisplay();
}

void reshape(int w, int h)
{
glViewport(0, 0, (GLsizei) w, (GLsizei) h);

    aspect_mult_x = (double) glutGet(GLUT_INIT_WINDOW_WIDTH)
                           / glutGet(GLUT_WINDOW_WIDTH);
    aspect_mult_y = (double) glutGet(GLUT_INIT_WINDOW_HEIGHT)
                           / glutGet(GLUT_WINDOW_HEIGHT);

}

int main(int argc, char** argv)
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB);
glutInitWindowSize(640, 480);
glutInitWindowPosition(50, 50);
glutCreateWindow(“Walker”);

    init();

    glutDisplayFunc(display);
    glutReshapeFunc(reshape);
    glutKeyboardFunc(keyboard);
    glutMouseFunc(mouse);
    glutIdleFunc(idle);

    glutMainLoop();
    return 0;

}

If anyone can help, I’d really appreciate it.

Many thanks in advance,
Darren

So what video hardware do you use ?

Originally posted by mikael_aronsson:
So what video hardware do you use ?

Well, it’s onboard. Intel 82810E Graphics Controller.

Darren

Argh! Go buy some decent graphics board.

  • 8 bit color indexed mode is not supported in hardware on most modern graphics chips.
    You got the Microsoft GDI Generic OpenGL implementation in that case. Check glGetString(GL_VENDOR)! The CPU is rendering into a host bitmap and blits it to the screen then.
  • If the same is happening in RGB mode, the performance will drop because the CPU needs to write and copy more data.
    If this is slow and hardware accellerated then buy something more decent.
  • Without line smoothing there is nothing which would result in smoother lines except fullscene antialiasing (uncommon with onboard graphics) or really bad RAMDACs. You need to read a lot more data per second and maybe the onboard graphics just doesn’t cut it.
  • Line drawing on integer coordinates is bad. OpenGL uses the diamond exit rule most of the pixel drawing. Simplified, it’s better to draw lines and points on the center of a pixel, that is at screen pixel coordinates (0.5, 0.5), otherwise you can fall on the one or the other side of a pixel edge with the slightest floating point rounding error.
  • Watch out for precise glOrtho settings, too, these need to start and end on pixel edges, if lines are drawn on pixel centers.
    Filled geometry should cover whole pixels from one to the other edge.
    (These are all rules for 2D drawing, for 3D perspective these are mainly irrelevant.)
  • The mouse can flicker if it is not a hardware cursor. The SwapBuffers will need to take it away, blit the color buffer and put it back on. Try a monochrome cursor, and switch off the useless mouse shadow. Same for the crappy menu fade effects.