Recent

Author Topic: [Solved] glActiveTexture - SIGSEGV error  (Read 10027 times)

Handoko

  • Hero Member
  • *****
  • Posts: 5131
  • My goal: build my own game engine using Lazarus
[Solved] glActiveTexture - SIGSEGV error
« on: June 28, 2017, 10:57:19 am »
I found that glActiveTexture (in GLext unit) will always cause "External SIGSEGV" error. Tested on Lazarus 1.6.4 Linux 64-bit.

Example code:
Code: Pascal  [Select][+][-]
  1. uses
  2.   OpenGLContext, GLext, ...
  3.  
  4. procedure TForm1.myGLPaint(Sender: TObject);
  5. begin
  6.   glActiveTexture(GL_TEXTURE0); // this line causes SIGSEGV error  
  7.   ...
  8. end;

But if I put gles20 unit after GLext, the error won't happen:

Example code:
Code: Pascal  [Select][+][-]
  1. uses
  2.   OpenGLContext, GLext, gles20, ...
  3.  
  4. procedure TForm1.myGLPaint(Sender: TObject);
  5. begin
  6.   glActiveTexture(GL_TEXTURE0); // will not cause SIGSEGV error  
  7.   ...
  8. end;

I examined the code inside them, they are different:

Code: Pascal  [Select][+][-]
  1. // GLext.pas
  2.   glActiveTexture: procedure(texture: GLenum); extdecl;
  3.  
  4. // gles20.pas
  5.   glActiveTexture: procedure(texture:GLenum);{$ifdef windows}stdcall;{$else}cdecl;{$endif}

I don't understand what extdecl and cdecl are. Is it a bug in GLext.pas? Should I submit a bug report?
« Last Edit: June 29, 2017, 10:20:57 am by Handoko »

marcov

  • Administrator
  • Hero Member
  • *
  • Posts: 11383
  • FPC developer.
Re: glActiveTexture - SIGSEGV error
« Reply #1 on: June 28, 2017, 11:22:33 am »
extdecl is a macro that is often defined in FPC headers to not have to repeat an ifdef for calling conventions all over again,  and it is probably the same  as {$ifdef windows}stdcall;{$else}cdecl;{$endif}

It might be that the changing in unit order cause some other function to change meaning leading to the activetexture crash. Do you have proper errorhandling in place?

Handoko

  • Hero Member
  • *****
  • Posts: 5131
  • My goal: build my own game engine using Lazarus
Re: glActiveTexture - SIGSEGV error
« Reply #2 on: June 28, 2017, 03:54:39 pm »
Can anyone help me test the code? I always get SIGSEGV error when run the code on Linux. To able to compile it on Linux, your computer should have libgl1-mesa-dev installed. Also, make sure your Lazarus has LazOpenGLContex 0.0.1 installed. Please let me know if the error also reproducible on other OS.

If you have problem compiling the code, read here:
http://forum.lazarus.freepascal.org/index.php/topic,35807.0.html

...  Do you have proper errorhandling in place?

No, I have only very simple code to test the issue.

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Forms, Controls, OpenGLContext, GL, GLext;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     procedure FormCreate(Sender: TObject);
  16.   public
  17.     procedure GLPaint(Sender: TObject);
  18.   end;
  19.  
  20. var
  21.   Form1: TForm1;
  22.   GLBox: TOpenGLControl;
  23.  
  24. implementation
  25.  
  26. {$R *.lfm}
  27.  
  28. { TForm1 }
  29.  
  30. procedure TForm1.FormCreate(Sender: TObject);
  31. begin
  32.   GLBox := TOpenGLControl.Create(Self);
  33.   GLBox.Parent := Self;
  34.   GLBox.Align := alClient;
  35.   GLBox.OnPaint := @GLPaint;
  36.   GLBox.Paint;
  37. end;
  38.  
  39. procedure TForm1.GLPaint(Sender: TObject);
  40. begin
  41.  
  42.   glActiveTexture(GL_TEXTURE0);  // This line will cause SIGSEGV error
  43.  
  44.   glBegin(GL_TRIANGLES);
  45.     glVertex3f( 0, 1, 0);
  46.     glVertex3f(-1,-1, 0);
  47.     glVertex3f( 1,-1, 0);
  48.   glEnd;
  49.   GLBox.SwapBuffers;
  50. end;
  51.  
  52. end.

Pascal

  • Hero Member
  • *****
  • Posts: 932
Re: glActiveTexture - SIGSEGV error
« Reply #3 on: June 28, 2017, 09:01:20 pm »
Do not do the Paint in FromCreate as the handles are not set there!
Just do Invalidate instead of Paint. Or ues Application.QueueAsyncCall.

Code: Pascal  [Select][+][-]
  1. procedure TForm1.FormCreate(Sender: TObject);
  2. begin
  3.   ...
  4.   Application.QueueAsyncCall(@DoPaint, 0);
  5. end;
  6.  
  7. procedure TForm1.DoPaint(Data: PtrInt);
  8. begin
  9.   GLBox.Paint;
  10. end;
  11.  
laz trunk x64 - fpc trunk i386 (cross x64) - Windows 10 Pro x64 (21H2)

Handoko

  • Hero Member
  • *****
  • Posts: 5131
  • My goal: build my own game engine using Lazarus
Re: glActiveTexture - SIGSEGV error
« Reply #4 on: June 28, 2017, 09:15:19 pm »
Thank you for your reply, unfortunately both solutions didn't work.

I am not familiar with QueueAsyncCall, but I followed your example. The SIGSEGV error still happened.

I also tried to change the Paint to Invalidate, still no luck. Same results.

Can you please download the testgl.zip and test it or fix it?. I am thinking this is a bug, which maybe only happens on Linux. Or perhaps something wrong with my computer.

I can understand what you said about "the handles are not set there". But how can you explain, the code works correctly if I remove line #42:
glActiveTexture(GL_TEXTURE0);
« Last Edit: June 28, 2017, 09:20:23 pm by Handoko »

Pascal

  • Hero Member
  • *****
  • Posts: 932
Re: glActiveTexture - SIGSEGV error
« Reply #5 on: June 28, 2017, 10:31:16 pm »
glActiveTexture is nil !!! It hasn't been initalized during loading of lib.
laz trunk x64 - fpc trunk i386 (cross x64) - Windows 10 Pro x64 (21H2)

Pascal

  • Hero Member
  • *****
  • Posts: 932
Re: glActiveTexture - SIGSEGV error
« Reply #6 on: June 28, 2017, 11:07:43 pm »
Loading of extentions fails.

glext_LoadExtension('GL_version_1_3') fails as
glActiveTexture := wglGetProcAddress('glActiveTexture') sets glActiveTexture  to nil

I don't know what to do here. Maybe some OpenGL experts can help?
laz trunk x64 - fpc trunk i386 (cross x64) - Windows 10 Pro x64 (21H2)

Pascal

  • Hero Member
  • *****
  • Posts: 932
Re: glActiveTexture - SIGSEGV error
« Reply #7 on: June 29, 2017, 05:53:51 am »
The solution is to call   glext_LoadExtension when the context is already set up (not in FormCreate):

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Forms, Controls, OpenGLContext, GL, GLext;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     procedure FormCreate(Sender: TObject);
  16.   public
  17.     procedure GLPaint(Sender: TObject);
  18.     procedure Start(Data: PtrInt);
  19.   end;
  20.  
  21. var
  22.   Form1: TForm1;
  23.   GLBox: TOpenGLControl;
  24.  
  25. implementation
  26.  
  27. {$R *.lfm}
  28.  
  29. { TForm1 }
  30.  
  31. procedure TForm1.FormCreate(Sender: TObject);
  32. begin
  33.   GLBox := TOpenGLControl.Create(Self);
  34.   GLBox.Parent := Self;
  35.   GLBox.Align := alClient;
  36.   Application.QueueAsyncCall(@Start, 0); // Continue after everything is set up
  37. end;
  38.  
  39. procedure TForm1.GLPaint(Sender: TObject);
  40. begin
  41.   glActiveTexture(GL_TEXTURE0);  // This line will cause SIGSEGV error
  42.  
  43.   glBegin(GL_TRIANGLES);
  44.     glVertex3f( 0, 1, 0);
  45.     glVertex3f(-1,-1, 0);
  46.     glVertex3f( 1,-1, 0);
  47.   glEnd;
  48.   GLBox.SwapBuffers;
  49. end;
  50.  
  51. procedure TForm1.Start(Data: PtrInt);
  52. begin
  53.   glext_LoadExtension('GL_version_2_0');
  54.   GLBox.OnPaint := @GLPaint;
  55.   GLBox.Invalidate;
  56. end;
  57.  
  58. end.
  59.  
laz trunk x64 - fpc trunk i386 (cross x64) - Windows 10 Pro x64 (21H2)

Handoko

  • Hero Member
  • *****
  • Posts: 5131
  • My goal: build my own game engine using Lazarus
Re: glActiveTexture - SIGSEGV error
« Reply #8 on: June 29, 2017, 10:19:28 am »
Thank you for your help.

I thought glActiveTexture is a basic command that will be available if the OpenGL library has loaded. Also in the Kronos (developer of OpenGL) page, it does not mentioned glActiveTexture will not be available unless we load it using wglGetProcAddress.

Unit: gles20

In the unit initialization section, LoadGLESv2 will be called automatically and inside it, glActiveTexture will be loaded. So glActiveTexture is ready to be used.

Unit: glExt

In this unit, glActiveTexture will not be loaded automatically. We have to call glext_LoadExtension to load it manually. That is why if we add gles20 unit after glExt, the error won't show up.

Pascal

  • Hero Member
  • *****
  • Posts: 932
Re: glActiveTexture - SIGSEGV error
« Reply #9 on: June 29, 2017, 10:36:25 am »
Thank you for your help.
You are welcome!

Unit: glExt

In this unit, glActiveTexture will not be loaded automatically. We have to call glext_LoadExtension to load it manually. That is why if we add gles20 unit after glExt, the error won't show up.
Yes, but you can't do it in FormCreate, where it will fail!
laz trunk x64 - fpc trunk i386 (cross x64) - Windows 10 Pro x64 (21H2)

Handoko

  • Hero Member
  • *****
  • Posts: 5131
  • My goal: build my own game engine using Lazarus
Re: glActiveTexture - SIGSEGV error
« Reply #10 on: June 29, 2017, 10:48:19 am »
Yes, but you can't do it in FormCreate, where it will fail!

Yes, I understand. Actually, the question is about glActiveTexture. That code is just a quick demo i created to show the problem of glActiveTexture.

Akira1364

  • Hero Member
  • *****
  • Posts: 561
Re: [Solved] glActiveTexture - SIGSEGV error
« Reply #11 on: July 02, 2017, 12:39:06 am »
I know this thread is solved, but it's worth pointing out as a general tip for everyone: never, ever, ever do ANYTHING OpenGL related in "FormCreate" when using Lazarus with the FPC GL headers and/or TOpenGLControl. It will not work. Yes, I know it worked in really old Delphi versions like 6 and 7 but that's irrelevant now. The window initialization code in FPC isn't the same and doesn't do things in the same order. Do your OpenGL-startup related stuff in "FormShow" instead.
« Last Edit: July 02, 2017, 02:07:12 am by Akira1364 »

Handoko

  • Hero Member
  • *****
  • Posts: 5131
  • My goal: build my own game engine using Lazarus
Re: [Solved] glActiveTexture - SIGSEGV error
« Reply #12 on: July 02, 2017, 03:49:02 am »
Thank you for the information.
But there still something I do not fully understand.

For general things (not OpenGL related), we should not do anything that required form handle on FormCreate because as mentioned by @Pascal, the handle has not created on FormCreate. This I already knew.

But how do you explain my code test.zip works:

Code: Pascal  [Select][+][-]
  1. unit Unit1;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Forms, Controls, OpenGLContext, GL;
  9.  
  10. type
  11.  
  12.   { TForm1 }
  13.  
  14.   TForm1 = class(TForm)
  15.     procedure FormCreate(Sender: TObject);
  16.   public
  17.     procedure GLPaint(Sender: TObject);
  18.   end;
  19.  
  20. var
  21.   Form1: TForm1;
  22.   GLBox: TOpenGLControl;
  23.  
  24. implementation
  25.  
  26. {$R *.lfm}
  27.  
  28. { TForm1 }
  29.  
  30. procedure TForm1.FormCreate(Sender: TObject);
  31. begin
  32.   GLBox := TOpenGLControl.Create(Self);
  33.   GLBox.Parent := Self;
  34.   GLBox.Align := alClient;
  35.   GLBox.OnPaint := @GLPaint;
  36.   GLBox.Paint; // <<<---------- Call TOpenGLControl.Paint !!!
  37. end;
  38.  
  39. procedure TForm1.GLPaint(Sender: TObject);
  40. begin
  41.   glBegin(GL_TRIANGLES);
  42.     glVertex3f( 0, 1, 0);
  43.     glVertex3f(-1,-1, 0);
  44.     glVertex3f( 1,-1, 0);
  45.   glEnd;
  46.   GLBox.SwapBuffers;
  47. end;
  48.  
  49. end.

Any explanation why my code works correctly on my tests on Linux64 machine? Does it work by luck?

Also, please see the example "OpenGL Core Profile Tutorials" by @ChrisR:
http://forum.lazarus.freepascal.org/index.php/topic,35649.0.html

On his rendermain.pas, he did this (line #609):

Code: Pascal  [Select][+][-]
  1. procedure TGLForm1.FormCreate(Sender: TObject);
  2. begin
  3.   gMouse.Y := -1;
  4.   {$IFDEF LCLCarbon}
  5.   Error: Carbon only supports Legacy OpenGL. Solution: compile to the Cocoa widgetset (Project/ProjectOptions/Additions&Overrides)
  6.   {$ENDIF}
  7.   {$IFDEF Darwin}
  8.   AppleMenu.Visible := true;
  9.   HelpMenu.Visible := false;
  10.   {$ENDIF}
  11.   GLBox.MakeCurrent();
  12.   InitGL;
  13.   GLBox.invalidate;
  14. end;

Is it okay to call GLBox.Invalidate on FormCreate?

Akira1364

  • Hero Member
  • *****
  • Posts: 561
Re: [Solved] glActiveTexture - SIGSEGV error
« Reply #13 on: July 02, 2017, 04:07:38 am »
Your code works, yes, essentially "by luck" because you aren't attempting to actually initialize any GL functionality. However, it's also completely unnecessary. If you comment out the "GLBox.Paint" line, the visual results will be identical, since the OpenGL control will be painted at least once anyways when the form comes into view. The same goes for GLBox.Invalidate: there is no reason to call it at that point.

The tutorial by ChrisR that you've posted, on the other hand, is an example of something that will fail a large percentage of the time on Windows and the majority of Linux distros at the MakeCurrent line, as the OpenGL control may or may not have initialized its context by that point. It is also equally likely to fail at the InitGL() line. All of that is only relevant when you do it in FormCreate, though: if you copy and paste the entire function into FormShow you should have zero problems overall regardless of platform. So maybe what I said was a bit of an oversimplification, but generally you're basically gambling with FormCreate. It's not guaranteed to work like it was under old Win32-only Delphi compilers. Better to do it in FormShow and be safe!
« Last Edit: July 02, 2017, 05:01:40 am by Akira1364 »

Handoko

  • Hero Member
  • *****
  • Posts: 5131
  • My goal: build my own game engine using Lazarus
Re: [Solved] glActiveTexture - SIGSEGV error
« Reply #14 on: July 02, 2017, 04:20:56 am »
Thank you for the explanation.
I will remember your advice.

 

TinyPortal © 2005-2018