title: OpenGL Rapid Flickering Issues - and now not showing image
body: <p>I'm having some troubles with OpenGL. First of all, I have a custom control which I'm building, encapsulating OpenGL. I'm having a problem where it rapidly flickers, like it's 'flashing'. The control was too large and complex to post here, so I made a new small demo app to demonstrate and recreate the same scenario.</p>
  
  <p>The problem now: I'm not getting any image. Things would show fine in my custom control, but since I've copied the code and stripped it down in a small demo app, it won't show the image. So here I have two issues at hand: Flickering (or flashing), and now the image is not even showing. The flickering didn't occur in the past, but after some major code revision, it started flickering. It was too much code change to explain what exactly was changed, just about everything.</p>
  
  <p>The background shows, so I know it's drawing something (it is colored). It should be drawing just a single cube for demo purposes, but I don't see anything. I had to strip this down from around 1,000 lines of code to not even 300.</p>
  
  <p>It's not what you would normally call a flicker, it's actually more of a flashing, or blinking, imagine a car blinker flashing on and off. It definitely has to do with the timer, because the higher interval I put on the timer, the slower it flashes.</p>
  
  <p>Why am I not seeing anything? And once this is fixed, why is it flickering so much?</p>
  
  <p>Here's a single form's code, no DFM necessary:</p>
  
  <pre><code>unit uMain;
  
  interface
  
  uses
    Winapi.Windows, Winapi.Messages, Winapi.OpenGL,
    System.SysUtils, System.Variants, System.Classes,
    Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ExtCtrls;
  
  type
    TForm1 = class(TForm)
      procedure FormCreate(Sender: TObject);
      procedure FormDestroy(Sender: TObject);
      procedure Timer1Timer(Sender: TObject);
      procedure FormResize(Sender: TObject);
    private
      FDrawing: Bool;
      FDC: HDC;
      FRC: HGLRC;
      FDL: glUint;
      FTimer: TTimer;
      procedure Draw;
      procedure SetDC(const Value: HDC);
      procedure SetRC(const Value: HGLRC);
      procedure SetDL(const Value: glUint);
    public
      property DC: HDC read FDC write SetDC;
      property RC: HGLRC read FRC write SetRC;
      property DL: glUint read FDL write SetDL;
    end;
  
  var
    Form1: TForm1;
  
  implementation
  
  {$R *.dfm}
  
  procedure TForm1.FormCreate(Sender: TObject);
  var
    PixelFormat: glUint;
    pfd: TPIXELFORMATDESCRIPTOR;
  begin
    FDrawing := False;
    FDC := GetDC(Handle);
    with pfd do begin
      nSize := SizeOf(TPIXELFORMATDESCRIPTOR);
      nVersion := 1; // The version of this data structure
      dwFlags := PFD_DRAW_TO_WINDOW // Buffer supports drawing to window
        or PFD_SUPPORT_OPENGL // Buffer supports OpenGL drawing
        or PFD_DOUBLEBUFFER; // Supports double buffering
      iPixelType := PFD_TYPE_RGBA; // RGBA color format
      cColorBits := 32; // OpenGL color depth
      cRedBits := 0; // Number of red bitplanes
      cRedShift := 0; // Shift count for red bitplanes
      cGreenBits := 0; // Number of green bitplanes
      cGreenShift := 0; // Shift count for green bitplanes
      cBlueBits := 0; // Number of blue bitplanes
      cBlueShift := 0; // Shift count for blue bitplanes
      cAlphaBits := 0; // Not supported
      cAlphaShift := 0; // Not supported
      cAccumBits := 0; // No accumulation buffer
      cAccumRedBits := 0; // Number of red bits in a-buffer
      cAccumGreenBits := 0; // Number of green bits in a-buffer
      cAccumBlueBits := 0; // Number of blue bits in a-buffer
      cAccumAlphaBits := 0; // Number of alpha bits in a-buffer
      cDepthBits := 16; // Specifies the depth of the depth buffer
      cStencilBits := 0; // Turn off stencil buffer
      cAuxBuffers := 0; // Not supported
      iLayerType := PFD_MAIN_PLANE; // Ignored
      bReserved := 0; // Number of overlay and underlay planes
      dwLayerMask := 0; // Ignored
      dwVisibleMask := 0; // Transparent color of underlay plane
      dwDamageMask := 0; // Ignored
    end;
    PixelFormat := ChoosePixelFormat(FDC, @pfd);
    SetPixelFormat(FDC, PixelFormat, @pfd);
    FRC := wglCreateContext(FDC);
    wglMakeCurrent(FDC, FRC);
    FormResize(nil);
    wglMakeCurrent(FDC, FRC);
    glClearColor(0.8, 0.8, 0.9, 0.0);
    glShadeModel(GL_FLAT);
    glClearDepth(1.0);
    glEnable(GL_DEPTH_TEST);
    glDepthFunc(GL_LESS);
    glEnable(GL_ALPHA_TEST);
    glAlphaFunc(GL_GREATER, 0.4);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_BLEND);
    glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
    glEnable(GL_TEXTURE_2D);
    glNewList(FDL, GL_COMPILE);
      glBegin(GL_QUADS);
        // Front Face
        glTexCoord2f(0.0, 0.0);
        glVertex3f(-2.0, -1.0, 1.0);
        glTexCoord2f(2.0, 0.0);
        glVertex3f(2.0, -1.0, 1.0);
        glTexCoord2f(2.0, 1.0);
        glVertex3f(2.0, 1.0, 1.0);
        glTexCoord2f(0.0, 1.0);
        glVertex3f(-2.0, 1.0, 1.0);
        // Back Face
        glTexCoord2f(2.0, 0.0);
        glVertex3f(-2.0, -1.0, -1.0);
        glTexCoord2f(2.0, 1.0);
        glVertex3f(-2.0, 1.0, -1.0);
        glTexCoord2f(0.0, 1.0);
        glVertex3f(2.0, 1.0, -1.0);
        glTexCoord2f(0.0, 0.0);
        glVertex3f(2.0, -1.0, -1.0);
        // Top Face
        glTexCoord2f(0.0, 1.0);
        glVertex3f(-2.0, 1.0, -1.0);
        glTexCoord2f(0.0, 0.0);
        glVertex3f(-2.0, 1.0, 1.0);
        glTexCoord2f(2.0, 0.0);
        glVertex3f(2.0, 1.0, 1.0);
        glTexCoord2f(2.0, 1.0);
        glVertex3f(2.0, 1.0, -1.0);
        // Bottom Face
        glTexCoord2f(2.0, 1.0);
        glVertex3f(-2.0, -1.0, -1.0);
        glTexCoord2f(0.0, 1.0);
        glVertex3f(2.0, -1.0, -1.0);
        glTexCoord2f(0.0, 0.0);
        glVertex3f(2.0, -1.0, 1.0);
        glTexCoord2f(2.0, 0.0);
        glVertex3f(-2.0, -1.0, 1.0);
        // Left Face
        glTexCoord2f(0.0, 0.0);
        glVertex3f(2.0, -1.0, -1.0);
        glTexCoord2f(1.0, 0.0);
        glVertex3f(2.0, -1.0, 1.0);
        glTexCoord2f(1.0, 1.0);
        glVertex3f(2.0, 1.0, 1.0);
        glTexCoord2f(0.0, 1.0);
        glVertex3f(2.0, 1.0, -1.0);
      glEnd();
    glEndList();
    FTimer:= TTimer.Create(nil);
    FTimer.OnTimer:= Timer1Timer;
    FTimer.Interval:= 100;
  end;
  
  procedure TForm1.FormDestroy(Sender: TObject);
  begin
    FTimer.Free;
    if (not wglMakeCurrent(FDC, 0)) then
      MessageBox(0, 'Release of DC and RC failed!', 'Error', MB_OK or MB_ICONERROR);
    if (not wglDeleteContext(FRC)) then begin
      MessageBox(0, 'Release of rendering context failed!', 'Error', MB_OK or MB_ICONERROR);
      FRC := 0;
    end;
    if ((FDC &gt; 0) and (ReleaseDC(Handle, FDC) = 0)) then begin
      MessageBox(0, 'Release of device context failed!', 'Error', MB_OK or MB_ICONERROR);
      FDC := 0;
    end;
  end;
  
  procedure TForm1.Draw;
  var
    I: Integer;
  begin
    if not FDrawing then begin
      FDrawing := TRUE;
      try
        glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
        glEnable(GL_NORMALIZE);
        glShadeModel(GL_FLAT);
        glCullFace(GL_BACK);
        glLoadIdentity;
        glPushMatrix();
        glCallList(DL);
        glPopMatrix();
        SwapBuffers(wglGetCurrentDC);
      finally
        FDrawing := False;
      end;
    end;
  end;
  
  procedure TForm1.FormResize(Sender: TObject);
  begin
    glViewport(0, 0, Width, Height);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluPerspective(45.0, Width / Height, 0.1, 500.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
  end;
  
  procedure TForm1.SetDC(const Value: HDC);
  begin
    FDC := Value;
  end;
  
  procedure TForm1.SetDL(const Value: glUint);
  begin
    FDL := Value;
  end;
  
  procedure TForm1.SetRC(const Value: HGLRC);
  begin
    FRC := Value;
  end;
  
  procedure TForm1.Timer1Timer(Sender: TObject);
  begin
    Draw;
  end;
  
  end.
  </code></pre>
  
  <p>Now the above code is rather far different from how my original code works. The original <code>Draw</code> procedure does an iteration through a list of objects, each object containing its own <code>Draw</code> procedure. So the control's draw procedure prepares the overall scene, then draws each 'item' one by one, like this:</p>
  
  <pre><code>procedure TGLImage.Draw;
  var
    X: Integer;
  begin
    if not FDrawing then begin
      FDrawing := TRUE;
      try
        glClear(GL_COLOR_BUFFER_BIT or GL_DEPTH_BUFFER_BIT);
        glEnable(GL_NORMALIZE);
        glShadeModel(GL_FLAT);
        glCullFace(GL_BACK);
        glLoadIdentity();
  
        glRotatef(FElapsedTime / 70, 0, 0, 1);
        glRotatef(90, 0, 1, 0);
        glTranslatef(-FElapsedTime / 400, 0, 0);
  
        if FInitialized then begin
          for X := 0 to FItems.Count - 1 do begin
            FItems[X].Draw;
          end;
        end;
  
        SwapBuffers(wglGetCurrentDC);
      finally
        FDrawing := False;
      end;
    end;
  end;
  </code></pre>
  
  <p>And here's one of the items it draws...</p>
  
  <pre><code>constructor TGLBeam.Create(AOwner: TGLItems);
  begin
    inherited;
    glNewList(DL, GL_COMPILE);
      glBegin(GL_QUADS);
        // Front Face
        glTexCoord2f(0.0, 0.0);
        glVertex3f(-2.0, -1.0, 1.0);
        glTexCoord2f(2.0, 0.0);
        glVertex3f(2.0, -1.0, 1.0);
        glTexCoord2f(2.0, 1.0);
        glVertex3f(2.0, 1.0, 1.0);
        glTexCoord2f(0.0, 1.0);
        glVertex3f(-2.0, 1.0, 1.0);
        // Back Face
        glTexCoord2f(2.0, 0.0);
        glVertex3f(-2.0, -1.0, -1.0);
        glTexCoord2f(2.0, 1.0);
        glVertex3f(-2.0, 1.0, -1.0);
        glTexCoord2f(0.0, 1.0);
        glVertex3f(2.0, 1.0, -1.0);
        glTexCoord2f(0.0, 0.0);
        glVertex3f(2.0, -1.0, -1.0);
        // Top Face
        glTexCoord2f(0.0, 1.0);
        glVertex3f(-2.0, 1.0, -1.0);
        glTexCoord2f(0.0, 0.0);
        glVertex3f(-2.0, 1.0, 1.0);
        glTexCoord2f(2.0, 0.0);
        glVertex3f(2.0, 1.0, 1.0);
        glTexCoord2f(2.0, 1.0);
        glVertex3f(2.0, 1.0, -1.0);
        // Bottom Face
        glTexCoord2f(2.0, 1.0);
        glVertex3f(-2.0, -1.0, -1.0);
        glTexCoord2f(0.0, 1.0);
        glVertex3f(2.0, -1.0, -1.0);
        glTexCoord2f(0.0, 0.0);
        glVertex3f(2.0, -1.0, 1.0);
        glTexCoord2f(2.0, 0.0);
        glVertex3f(-2.0, -1.0, 1.0);
        // Left Face
        glTexCoord2f(0.0, 0.0);
        glVertex3f(2.0, -1.0, -1.0);
        glTexCoord2f(1.0, 0.0);
        glVertex3f(2.0, -1.0, 1.0);
        glTexCoord2f(1.0, 1.0);
        glVertex3f(2.0, 1.0, 1.0);
        glTexCoord2f(0.0, 1.0);
        glVertex3f(2.0, 1.0, -1.0);
      glEnd();
    glEndList();
  end;
  
  procedure TGLBeam.Draw;
  var
    I: Integer;
  begin
    glRotatef(Directions.X, 1.0, 0.0, 0.0);
    glRotatef(Directions.Y, 0.0, 1.0, 0.0);
    glRotatef(Directions.Z, 0.0, 0.0, 1.0);
    for I := 1 to 10 do begin
      //Main Center
      glPushMatrix();
      glTranslatef(I * 4 + Owner.Owner.ClockTime * 4, 0, 0);
      glCallList(DL);
      glPopMatrix();
      //Above
      glPushMatrix();
      glTranslatef(I * 4 + Owner.Owner.ClockTime * 4, 6, 0);
      glCallList(DL);
      glPopMatrix();
    end;
  end;
  </code></pre>