How does glGenLists() work?

Hi,

I was playing around with glGenLists(), I wrote a minimal example to test the return value of glGenLists(); however, I did not get the expected result as the book claimed. The return value of glGenLists() should be 1 when it succeeds and 0 when it fails.
This is my code:


#include <string>
#include <iostream>
#include <cstdio>

#include <GL/glut.h>

using namespace std;

string getOpenGLErrorMessage( GLenum error ) {
	switch( error ) {
		case GL_NO_ERROR:
			return "GL_NO_ERROR";
		case GL_INVALID_ENUM:
			return "GL_INVALID_ENUM";
		case GL_INVALID_VALUE:
			return "GL_INVALID_VALUE";
		case GL_INVALID_OPERATION:
			return "GL_INVALID_OPERATION";
		case GL_STACK_OVERFLOW:
			return "GL_STACK_OVERFLOW";
		case GL_STACK_UNDERFLOW:
			return "GL_STACK_UNDERFLOW";
		case GL_OUT_OF_MEMORY:
			return "GL_OUT_OF_MEMORY";
	}
}

int main() {
	int index = glGenLists( 5 );
	cout << index << '
';
	GLenum error = glGetError();
	cout << getOpenGLErrorMessage( error ) << endl;
	glNewList( index, GL_COMPILE );
		glVertex3f( 0.0, 0.0, 0.0 );
	glEndList();
}

Next, I compare my code example with the code from the book (The Red Book)


/*
 *  torus.c
 *  This program demonstrates the creation of a display list.
 */

#include <GL/glut.h>
#include <stdio.h>
#include <math.h>
#include <stdlib.h>

#define PI_ 3.14159265358979323846

GLuint theTorus;

/* Draw a torus */
static void torus(int numc, int numt)
{
   int i, j, k;
   double s, t, x, y, z, twopi;

   twopi = 2 * PI_;
   for (i = 0; i < numc; i++) {
      glBegin(GL_QUAD_STRIP);
      for (j = 0; j <= numt; j++) {
         for (k = 1; k >= 0; k--) {
            s = (i + k) % numc + 0.5;
            t = j % numt;

            x = (1+.1*cos(s*twopi/numc))*cos(t*twopi/numt);
            y = (1+.1*cos(s*twopi/numc))*sin(t*twopi/numt);
            z = .1 * sin(s * twopi / numc);
            glVertex3f(x, y, z);
         }
      }
      glEnd();
   }
}

/* Create display list with Torus and initialize state */
static void init(void)
{
   theTorus = glGenLists (1);
   glNewList(theTorus, GL_COMPILE);
   torus(8, 25);
   glEndList();

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

/* Clear window and draw torus */
void display(void)
{
   glClear(GL_COLOR_BUFFER_BIT);
   glColor3f (1.0, 1.0, 1.0);
   glCallList(theTorus);
   glFlush();
}

/* Handle window resize */
void reshape(int w, int h)
{
   glViewport(0, 0, (GLsizei) w, (GLsizei) h);
   glMatrixMode(GL_PROJECTION);
   glLoadIdentity();
   gluPerspective(30, (GLfloat) w/(GLfloat) h, 1.0, 100.0);
   glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
   gluLookAt(0, 0, 10, 0, 0, 0, 0, 1, 0);
}

/* Rotate about x-axis when "x" typed; rotate about y-axis
   when "y" typed; "i" returns torus to original view */
void keyboard(unsigned char key, int x, int y)
{
   switch (key) {
   case 'x':
   case 'X':
      glRotatef(30.,1.0,0.0,0.0);
      glutPostRedisplay();
      break;
   case 'y':
   case 'Y':
      glRotatef(30.,0.0,1.0,0.0);
      glutPostRedisplay();
      break;
   case 'i':
   case 'I':
      glLoadIdentity();
      gluLookAt(0, 0, 10, 0, 0, 0, 0, 1, 0);
      glutPostRedisplay();
      break;
   case 27:
      exit(0);
      break;
   }
}

int main(int argc, char **argv)
{
   glutInitWindowSize(200, 200);
   glutInit(&argc, argv);
   glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
   glutCreateWindow(argv[0]);
   init();
   glutReshapeFunc(reshape);
   glutKeyboardFunc(keyboard);
   glutDisplayFunc(display);
   glutMainLoop();
   return 0;
}

The output of glGenLists() in this example was 1 as expected. When looking at this code and comparing it with mine, I don’t see any difference. The first four subroutines are:

  • glutInitWindowSize(200, 200);
  • glutInit(&argc, argv);
  • glutInitDisplayMode(GLUT_SINGLE | GLUT_RGB);
  • glutCreateWindow(argv[0]);
    which come from glut not openGL. Hence the first openGL call to openGL must be init() which in turn called glGenLists(). Apparently, mine above code did exactly the same. So I guess my question is, is there any constraint on using glGenLists?

Thank you

The return value of glGenLists() should be 1 when it succeeds and 0 when it fails.

No, it shouldn’t.

As per the documentation, glGenLists returns the first list name in a range of the length you pass to glGenLists. This means that the usable display list names are its return value and its return value + (param - 1). It will return 0 when it fails, but it can return any unusued range above zero.

You should not rely on it returning any specific value. If it returns zero, it failed. Otherwise it succeeded and returned that many display lists.

Why do people setup the pixelformat?
Why do people create a context?
Why do people make the GL context current?

In case you didn’t understand why I’m asking those questions, you need a GL context for GL to work.
It is the same with Direct3D. You need to setup a D3D device so that the drivers gets setup and allocates buffers.

There are a large amount of code samples here http://nehe.gamedev.net

If you want to know how to setup a pixelformat on different OSes and with different toolkits.

Thanks all. I think I figured it out, glGenList need glut set up routine in order to perform correctly.

I think I figured it out, glGenList need glut set up routine in order to perform correctly.

No, it’s doesn’t. OpenGL does not require GLUT in any way, shape or form.

What OpenGL needs is for you to create an OpenGL context via whatever means are available on that platform. GLUT is merely one of many cross-platform ways of doing this.

@Alfonse Reinheart: Hm, but when I added glut routine, glGenLists() yielded a value which was different from 0. I guess I misunderstood you at some points.

@Alfonse Reinheart: Hm, but when I added glut routine, glGenLists() yielded a value which was different from 0.

Yes; I know that you got it to work. I was saying that the reason you gave for it working is mistaken.

Yes, if you put the GLUT routines there, it will work. You could also get it to work by running the NeHe basecode you were linked to instead of GLUT. Or you could use GLFW. Or Qt. Or any number of other tools that create windows and attach OpenGL to them.

I’m trying to get you to not think “I need the GLUT functions to make OpenGL work.” That’s wrong. You should be thinking instead, “I need to initialize OpenGL, and GLUT is one way I can do that.”

Got it! Thanks for such a great explanation.