16 Display Lists and Vertex Arrays
An OpenGL display list must make a copy of all data it requires to recreate the call sequence that created it. This means that for every glVertex3f() call, for example, the display list must provide storage for 3 values (usually 32-bit float values in most implementations). This is where most of the memory used by a typical display list goes.
However, in most implementations, there's also some memory that's needed to manage the display lists of a given context and other overhead. In certain pathological cases, this overhead memory can be larger than the memory used to store the display list data!
If you're using Microsoft Windows, use the wglShareLists() function. If you are using GLX, see the share parameter to glXCreateContext().
GLUT does not allow display list sharing. You can obtain the GLUT source, and make your own glutCreateWindow() and glutSetWindow() function calls. You can then modify the source to expose display list sharing. When doing so, you need to make sure your modified routines still work with the rest of GLUT.
No. Only the call to the enclosed display list is copied into the parent list. This way a program can delete or replace a child list, call the parent, and see changes that were made.
A display list call is an atomic operation and therefore, it can't be interrupted. You can't call part of it, for example, then do something, then call the rest of it. Nor can you have a display list somehow signal your program from some point within the list.
However, an application doesn't have to create one large monolithic display list. By creating several smaller lists to call sequentially, an application is free to perform tasks between calls to glCallList().
An application can also use multithreading, so one thread can perform one task while another thread is calling a display list.
OpenGL display lists aren't editable, so you can't modify the call sequence in them or even see which calls are embedded in them.
One way of creating a pseudo-editable display list is to create a hierarchical display list. (i.e., create a display list parent that contains calls to glCallList()). Then you can edit the display list by replacing the child display lists that the parent list references.
Currently, there isn't a way to programatically obtain either the function calls contained within a list or the parameters to those calls. An application that requires this information must track the data stored in a display list.
One option is to use an OpenGL call logging utility. These utilities capture the OpenGL calls a program makes, enabling you to see the calls that an application stores in a display list.
Achieving the highest performance from display lists is highly dependent on the OpenGL implementation, but here are a few pointers:
First, make sure that your application's process size isn't becoming so large that it's causing memory thrashing. Using display lists generally takes more memory than immediate mode, so it's possible that your program is spending more time thrashing memory blocks than rendering OpenGL calls.
Display lists won't improve the performance of a fill-limited application. Try rendering to a smaller window, and if your application runs faster, it's likely that it's fill-limited.
Stay away from GL_COMPILE_AND_EXECUTE mode. Instead, create the list using GL_COMPILE mode, then execute it with glCallList().
In some cases if you group your state changes together, the display list can optimize them as a group (i.e., it can remove redundant state changes, concatenate adjacent matrix changes, etc.).
Read the section on Performance for other tips.
No. Most implementations will convert your data to an internal format for storage in the display list anyway, and usually, that format will be single-precision float.
In some implementations, a display list can optimize texture download and use of texture memory. In OpenGL 1.0, storing texture maps in display lists was the preferred method for optimizing texture performance. However, it resulted in increased memory usage in many implementations. Many vendors rallied around a better solution, texture objects, introduced in OpenGL 1.1. If your app is running on OpenGL 1.1 or later, texture objects are preferred.
It depends on the implementation. In most implementations, it might decrease performance because of the increased memory use. However, some implementations may cache display lists on the graphics hardware, so the benefits of this caching could easily offset the extra memory usage.
When a display list is modified in one context (deleting is a form of modification), the results of that modification are immediately available in all shared contexts. So, deleting a display list in one context will cause it to cease to exist in all contexts in which it was previously visible.
There isn't a limit based on the OpenGL spec. Because a display list ID is a GLuint, 232 display list identifiers are available. A more practical limit to go by is system memory resources.
See the first question in this section. It depends on the implementation.
This depends on the implementation. Some implementations free memory as soon as a display list is deleted. Others won't free the memory until it's needed by another display list or until the process dies.
Because vertex arrays let you access a set of vertices and data by index, you might believe that they're designed to optimally share vertices. Indeed, a programmer new to vertex arrays might try to render a cube, in which each vertex is shared by three faces. The futility of this becomes obvious when you add normals for lighting and each instance of the shared vertex requires a unique normal. The only way to render a cube with normals is to include multiple copies of each vertex.
Vertex arrays weren't designed to improve vertex sharing. They were intended to let the programmer to specify blocks of dynamic geometry data with as few function calls as possible.
You can share vertices with vertex arrays the same way you do with OpenGL immediate mode, by the type of primitive used. GL_LINE_STRIP, GL_LINE_LOOP, GL_TRIANGLE_STRIP, and GL_QUAD_STRIP share vertices between their component line segments, triangles, and quads. Other primitives do not. The type of primitive you choose to use when using vertex arrays determines whether you share vertices.
Note, however, that sharing vertices is implementation dependent. The OpenGL Specification dictates vertex array behavior, and as long as an OpenGL implementation conforms to spec, it's free to optimize vertex sharing in vertex arrays.
Some implementations feature the EXT_compiled_vertex_array extension, which is explicitly designed to let implementations share transformed vertex array data.