[SOLVED] Why does rendering in thread doesn't work? lazarus / 70-OpenGL ---------------------------------------------------------------------- Pascal · 2017-07-03 07:40 I am going to put my gl rendering into a thread but i can't get it gooing. If i put the rendering in a OnTimer-Event it works but if i call the same OnTimer-Event in my thread it doesn't work. OnTimer-event:Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TForm1.Timer1Timer(Sender: TObject);var  Speed: Double;begin  glEnable(GL_DEPTH_TEST);  glDepthFunc(GL_GEQUAL);  glEnable(GL_TEXTURE_2D);  glClearDepth(0);   glClearColor(0.0, 0.0, 0.0, 0.0);  glClear(GL_DEPTH_BUFFER_BIT or GL_COLOR_BUFFER_BIT);  glMatrixMode(GL_PROJECTION);  glLoadIdentity();  //glViewport(0,0, pWidth, pHeight);  glOrtho(0, fProject.Width, fProject.Height, 0, -256, 256);  //gluPerspective(45.0, width / height, 0.1, 100.0);  glMatrixMode(GL_MODELVIEW);  glLoadIdentity();  glEnable(GL_BLEND);  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);   fSlide.Render(0);   OpenGLControl1.SwapBuffers;end; Thread:Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i   TPreview = class(TThread)  private    fProc: TNotifyEvent;  protected    procedure Execute; override;  public    constructor Create(pProc: TNotifyEvent);  end;  .  .  .implementation procedure TPreview.Execute;begin  while not Terminated do begin    fProc(nil);  Sleep(40);  end;end; constructor TPreview.Create(pProc: TNotifyEvent);begin  inherited Create(true);  fProc := pProc;end; ---------------------------------------------------------------------- Cyrax · 2017-07-03 08:34 You can't call any component method(s) that interacts with LCL (paint etc), in threads. Only main thread can call these methods. ---------------------------------------------------------------------- Pascal · 2017-07-03 08:40 I know, but OpenGLContext doesn't do any painting just setting up the viewport and calling OnPaint which isn't set up in my case. So it should work. ---------------------------------------------------------------------- Thaddy · 2017-07-03 08:52 The rendering in the thread is not an issue, provided you protect the rendering code with a critical section. But you need to call OpenGLControl1.SwapBuffers; in the context of the main thread. Not IN the thread. Or Syncronize(SwapBuffers), that's also possible. The latter is more or less the same, but easier with your code and does not need a critical section, although I would recommend it anyway. ---------------------------------------------------------------------- Pascal · 2017-07-03 10:10 Thaddy, thanks for the tip. Unfortunately that doesn't make any difference  Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i type  TSimple = procedure of object;   TPreview = class(TThread)  private  fControl: TOpenGLControl;    fProc: TNotifyEvent;    fInit: TSimple;  procedure SwapBuffers;  protected    procedure Execute; override;  public    constructor Create(pInit: TSimple; pProc: TNotifyEvent; pControl: TOpenGLControl);  end;  implementaion procedure TPreview.SwapBuffers;begin  fControl.SwapBuffers;end; procedure TPreview.Execute;var  t: QWord;begin  fInit;  while not Terminated do begin    t := GetTickCount64;    fProc(nil);    if not Terminated then begin      //Synchronize(@SwapBuffers);      t := 40 - (GetTickCount64 - t);      if t > 0 then Sleep(t);    end;  end;end; constructor TPreview.Create(pInit: TSimple; pProc: TNotifyEvent;  pControl: TOpenGLControl);begin  inherited Create(true);  fControl := pControl;  fInit := pInit;  fProc := pProc;end; ---------------------------------------------------------------------- Thaddy · 2017-07-03 10:16 What I was hinting at is the following: You do the full rendering in the thread, on the current off-line buffer. Then call synchronize(swapbuffers). You are doing the painting somewhere else. ---------------------------------------------------------------------- Pascal · 2017-07-03 10:42 The painting is done in the OnTimerEvent (which is called by the thread (Testcase)): Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TForm1.Timer1Timer(Sender: TObject);var  Speed: Double;begin  OpenGLControl1.MakeCurrent;  glEnable(GL_DEPTH_TEST);  glDepthFunc(GL_GEQUAL);  glEnable(GL_TEXTURE_2D);  glClearDepth(0);   glClearColor(1.0, 0.0, 0.0, 0.0);  glClear(GL_DEPTH_BUFFER_BIT or GL_COLOR_BUFFER_BIT);  glMatrixMode(GL_PROJECTION);  glLoadIdentity();  glViewport(0,0, OpenGLControl1.Width, OpenGLControl1.Height);  glOrtho(0, fProject.Width, fProject.Height, 0, -256, 256);  //gluPerspective(45.0, width / height, 0.1, 100.0);  glMatrixMode(GL_MODELVIEW);  glLoadIdentity();  glEnable(GL_BLEND);  glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);  fSlide.Render(0);  OpenGLControl1.SwapBuffers;end;  Slide.Renderer: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TEPSlide.Render(pTime: Int64);var  o: TEPSlideObject;  z: GLfloat;begin  z := 128;  for o in fObjects do begin    o.Render(pTime, z);    z := z - 1  end;end;  Picture Renderer: (Slide contains on TEPPicture) Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i procedure TEPPicture.Render(pTime: Int64; pZ: GLfloat);begin  glBindTexture(GL_TEXTURE_2D, FTexture);  glBegin(GL_QUADS);    glTexCoord2f(0,0); glVertex3f(FLeft,          FTop + FHeight, pZ);    glTexCoord2f(1,0); glVertex3f(FLeft + FWidth, FTop + FHeight, pZ);    glTexCoord2f(1,1); glVertex3f(FLeft + FWidth, FTop,           pZ);    glTexCoord2f(0,1); glVertex3f(FLeft,          FTop,           pZ);  glEnd;   glColor4f(1.0, 1.0, 1.0, 1.0);end;  So no magic here. It works in a timer but not in a thread. ---------------------------------------------------------------------- Pascal · 2017-07-03 10:50 I  have an old delphi prototype where i did rendering in a thread. There everything is done in the thread (including creating context). This prog uses dglOpenGL.pas. Maybe i should use dglOpenGL instead of OpenGLContext and GL. ---------------------------------------------------------------------- Pascal · 2017-07-03 11:39 Okay. Using dglOpenGL works as expected. Maybe this is due to the context beeing created in the main thread.