Maybe true, but using VBOs you have more control over the fonts you're displaying. Besides, the method I know which used display lists was based on Windows-specific functions. This way you can make your code more portable + you can do whatever you want with every character of a font (i.e. rotate it, etc.).

EDIT
I've just discovered a bug in my previous code, here's a quick fix:
[code=delphi]
// Finally, render the text using triangles
glBindVertexArray(GetVAO());
glDrawArrays(GL_TRIANGLES, 0, Vertices.Count);
glBindVertexArray(0);
[/code]

EDIT2
Hm, I found some bugs while testing the code further. First of all, the projection matrix should be calculated as follows:
[code=delphi]
FProjMat := Mat4CreateOrtho(0, FWidth, FHeight, 0, -1.0, 1.0);
[/code]
The difference is that now the origin stays at the top-left corner of the screen instead of the bottom-left.

Of course, I needed to do changes in the drawing itself. Here's the full code now:
[code=delphi]
procedure TBrain2DText.RenderText(const Camera: TBrainCamera;
const AText: String; const ATextSize: Single; const AFont: TBrainFont);
var
CurX: Single;
Ch: Char;
Chaar, I, Ind: Integer;
ProjMat, ModelView: TBrainMatrix;
CameraProjection: TBrainCameraProjectionType;

{ .: AddQuad :. }
procedure AddQuad(X, Y, Wid, Hgt, Tu, Tu2, Tv, Tv2: Single);
var
V: array [0 .. 3] of TBrainVector;
begin
TexCoords.Add(TexCoord(Tu, Tv));
TexCoords.Add(TexCoord(Tu2, Tv));
TexCoords.Add(TexCoord(Tu2, Tv2));
TexCoords.Add(TexCoord(Tu2, Tv2));
TexCoords.Add(TexCoord(Tu, Tv2));
TexCoords.Add(TexCoord(Tu, Tv));

V[0] := Vec3(-X, Y, 0.0);
V[1] := Vec3(-(X + Wid), Y, 0.0);
V[2] := Vec3(-(X + Wid), Y + Hgt, 0.0);
V[3] := Vec3(-X, Y + Hgt, 0.0);

Vertices.Add(V[0]);
Vertices.Add(V[1]);
Vertices.Add(V[2]);
Vertices.Add(V[2]);
Vertices.Add(V[3]);
Vertices.Add(V[0]);
end;

begin
// Before we begin, check if we have everything we need
if not Assigned(Camera) then
exit;
if not Assigned(Shader) then
exit;
if (AText = '') then
exit;
if not Assigned(AFont) then
exit;
if (ATextSize = 0.0) then
exit;

// Switch to the orthographic projection
CameraProjection := Camera.ProjectionType;
Camera.ProjectionType := ptOrthographic2D;
Camera.ForceMatrixRecalc();

// If the desired text is different from the last one rendered, we need to
// rebuild the object. If not, just render what we already have
if (LastText <> AText) then
begin
// If there are any leftovers from previous text, remove them
Vertices.Clear();
TexCoords.Clear();

// We are provided with parameters, so it's time to render
// the text. But first, check if the selected font has been loaded
CurX := 0.0;
if not (AFont.FontLoaded) then
exit;

// Iterate through the text
for I := 1 to Length(AText) do
begin
// Get the current character
Ch := AText[I];
Chaar := Integer(Ch);

// Check if the current character is a legal one
// (i.e. neither #10 nor #13). If it is, also check
// if it's not the Space character. If so, move the cursor.
// Otherwise, just retrieve the character from array
Ind := -1;
case Chaar of
32:
CurX := CurX + AFont.SpaceWidth * ATextSize;
10, 13: // No line-breaks supported
break;
else
Ind := AFont.CharacterLookup[Chaar];
end;

// If we have a valid character...
if (Ind > -1) then
begin
// Setup the cursor
CurX := CurX + AFont.CharacterInfo[Ind].A * ATextSize;

// Add a new quad which contains the character
AddQuad(CurX, 0.0, AFont.CharacterInfo[Ind].Width * ATextSize,
AFont.CharacterInfo[Ind].Height * ATextSize, AFont.CharacterInfo[Ind].x1,
AFont.CharacterInfo[Ind].x2, AFont.CharacterInfo[Ind].y1,
AFont.CharacterInfo[Ind].y2);

// Move the cursor to the next character
CurX := CurX + AFont.CharacterInfo[Ind].C * ATextSize;
end;
end;
// Notify the object that its structure has changed
Self.StructureChanged();

// Remember what the last text was
LastText := AText;
end;

// Enable blending and disable the depth buffer
glDisable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

// Enable the shader and bind the texture
Shader.Enable();
AFont.FontTexture.Bind(0);
AFont.FontTexture.Apply();

// Calculate the matrices
ProjMat := Camera.ProjectionMatrix;
ModelView := Mat4Translate(Camera.Matrix, Vec3(Position.X, Position.Y, 0.0));

// Update the shader
Shader.SetMatrix(ProjectionMatrixUniformName, @ProjMat);
Shader.SetMatrix(ModelViewMatrixUniformName, @ModelView);

// Finally, render the text using triangles
glBindVertexArray(GetVAO());
glDrawArrays(GL_TRIANGLES, 0, Vertices.Count);
glBindVertexArray(0);

// Restore the projection
Camera.ProjectionType := CameraProjection;
Camera.ForceMatrixRecalc();

// Turn OpenGL's state machine back to what we had before
glDisable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
end;
[/code]