Allegro.cc - Online Community

Allegro.cc Forums » Allegro Development » ALLEGRO_OPENGL_MAJOR_VERSION and ALLEGRO_OPENGL_MINOR_VERSION

This thread is locked; no one can reply to it. rss feed Print
ALLEGRO_OPENGL_MAJOR_VERSION and ALLEGRO_OPENGL_MINOR_VERSION
I-am-bigov
Member #16,909
October 2018
avatar

Hi, developers!

I researched the source code of the Allegro library. In the master branch there is no code that controls the loading of the OpenGL version using the parameters ALLEGRO_OPENGL_MAJOR_VERSION and ALLEGRO_OPENGL_MINOR_VERSION! If I'm wrong, correct me.

Eric Johnson
Member #14,841
January 2013
avatar

I believe you use them with al_set_new_display_option.

Edgar Reynaldo
Member #8,592
May 2007
avatar

grep harder man.

e:\LIBS\LIBS81Build\allegro5\src>grep -r -E -I -n ALLEGRO_OPENGL_MAJOR_VERSION .*.*
.\win/wgl_disp.c:963:      ALLEGRO_OPENGL_MAJOR_VERSION, 0);
.\x/xglx_config.c:536:      ALLEGRO_OPENGL_MAJOR_VERSION, 0);

win\wgl_disp.c#SelectExpand
962 major = _al_get_suggested_display_option(disp, 963 ALLEGRO_OPENGL_MAJOR_VERSION, 0); 964 minor = _al_get_suggested_display_option(disp, 965 ALLEGRO_OPENGL_MINOR_VERSION, 0); 966 967 if ((disp->flags & ALLEGRO_OPENGL_3_0) || major != 0) { 968 if (major == 0) 969 major = 3; 970 bool fc = (disp->flags & ALLEGRO_OPENGL_FORWARD_COMPATIBLE) != 0;
971 wgl_disp->glrc = init_ogl_context_ex(wgl_disp->dc, fc, major, minor);
972 } 973 else { 974 wgl_disp->glrc = wglCreateContext(wgl_disp->dc); 975 } 976 977 if (!wgl_disp->glrc) { 978 ALLEGRO_ERROR("Unable to create a render context! %s\n", 979 get_error_desc(GetLastError())); 980 destroy_display_internals(wgl_disp); 981 return false; 982 }

I-am-bigov
Member #16,909
October 2018
avatar

Strange, "qtcreator" did not find this rows. Maybe this code snippet is not used? But still, in the MinGW-64 environment, my code (https://github.com/bigov/daft-lib/blob/master/OpenGL/allegro.glad/a_win.cpp) does not work as expected:

#SelectExpand
18 al_set_new_display_flags(ALLEGRO_OPENGL_3_0); 19 al_set_new_display_option(ALLEGRO_OPENGL_MAJOR_VERSION, 3, ALLEGRO_REQUIRE); 20 al_set_new_display_option(ALLEGRO_OPENGL_MINOR_VERSION, 2, ALLEGRO_REQUIRE); 21 display = al_create_display(640, 480); 22 if(nullptr == display) ERR ("failed to create display!\n"); 23 al_set_current_opengl_context(display); 24 25 if(!gladLoadGL()) { ERR("FAILURE: can't load GLAD."); } 26 std::cout << "OpenGL Version: " << GLVersion.major << "." << GLVersion.minor << "\n";

I see message: "OpenGL Version: 3.0".

If line N18 only is changed so:

#SelectExpand
18 al_set_new_display_flags(ALLEGRO_OPENGL);

that I see: "OpenGL Version: 4.5". I can't setup OpenGL-3.2 context!

Edgar Reynaldo
Member #8,592
May 2007
avatar

I can confirm your problem. I too get the most current version of allegro, even when requesting or requiring otherwise.

It has to do with the _al_get_suggested_display_option function I would think, possibly returning the wrong values, because when I debugged it major was still zero.

I-am-bigov
Member #16,909
October 2018
avatar

Thanks for your reply. I opened a request on https://github.com/liballeg/allegro5/issues/948

Edgar Reynaldo
Member #8,592
May 2007
avatar

I did some more debugging, and there are a couple of problems. First here is my session with gdb :

Thread 1 hit Breakpoint 1, create_display_internals (wgl_disp=0x2d99ba0)
    at E:\LIBS\LIBS81Build\allegro5\src\win\wgl_disp.c:967
967        if ((disp->flags & ALLEGRO_OPENGL_3_0) || major != 0) {
(gdb) set major = 3
(gdb) set minor = 2
(gdb) continue
Continuing.

Thread 1 hit Breakpoint 2, _al_ogl_manage_extensions (gl_disp=0x2d99ba0)
    at E:\LIBS\LIBS81Build\allegro5\src\opengl\extensions.c:731
731        if (!_al_ogl_version_3_only(gl_disp->flags)) {
(gdb) step
_al_ogl_version_3_only (flags=21) at E:\LIBS\LIBS81Build\allegro5\src\opengl\extensions.c:172
172        const int mask = ALLEGRO_OPENGL_3_0 | ALLEGRO_OPENGL_FORWARD_COMPATIBLE;
(gdb) n
173        return (flags & mask) == mask;
(gdb)
174     }
(gdb)
_al_ogl_manage_extensions (gl_disp=0x2d99ba0) at E:\LIBS\LIBS81Build\allegro5\src\opengl\extensions.c:731
731        if (!_al_ogl_version_3_only(gl_disp->flags)) {
(gdb) n
732           ALLEGRO_DEBUG("OpenGL Extensions:\n");
(gdb)
733           print_extensions((char const *)glGetString(GL_EXTENSIONS));
(gdb) step
[New Thread 12072.0x370]

Thread 1 hit Breakpoint 3, print_extensions (extension=0x0)
    at E:\LIBS\LIBS81Build\allegro5\src\opengl\extensions.c:187
187        ASSERT(extension);
(gdb)

First, _al_get_suggested_display_option has a bug. Second, glGetString(GL_EXTENSIONS) is returning NULL.

The code for getting display options is here :

display_settings.c#SelectExpand
51int _al_get_suggested_display_option(ALLEGRO_DISPLAY *d, 52 int option, int default_value) 53{ 54 ALLEGRO_EXTRA_DISPLAY_SETTINGS *s = &d->extra_settings; 55 uint64_t flags = s->required | s->suggested;
56 if (flags & (1 << option))
57 return s->settings[option]; 58 return default_value; 59} 60 61 62/* Function: al_get_new_display_option 63 */ 64int al_get_new_display_option(int option, int *importance) 65{ 66 ALLEGRO_EXTRA_DISPLAY_SETTINGS *extras; 67 extras = _al_get_new_display_settings();
68 if (extras->required & ((int64_t)1 << option)) {
69 if (importance) *importance = ALLEGRO_REQUIRE; 70 return extras->settings[option]; 71 }
72 if (extras->suggested & ((int64_t)1 << option)) {
73 if (importance) *importance = ALLEGRO_SUGGEST; 74 return extras->settings[option]; 75 } 76 if (importance) *importance = ALLEGRO_DONTCARE; 77 return 0; 78}

The two functions do something slightly different. One uses (int64_t)1 << option) to access extras->suggested and required. The first uses (1 << option). ALLEGRO_OPENGL_MAJOR_VERSION has a value of 33 and ALLEGRO_OPENGL_MINOR_VERSION has a value of 34. Which means 1 << 33 gets bit shifted off of the universe and therefore fails.

I-am-bigov
Member #16,909
October 2018
avatar

I also saw that there was a bug. The truth is not as detailed as you. Great job!

Edgar Reynaldo
Member #8,592
May 2007
avatar

There are more problems.

For one, _al_get_suggested_display_option uses display->extra_settings, and al_get_new_display_option uses tls->new_display_settings, which are completely different.

I changed create_display_internals to use al_get_new_display_option and now it correctly sets a 3.2 OpenGL context, but fails inside the call to glGetString as if the render context was bad.

EDIT
glGetString returns 1280 INVALID_ENUM for getLastError. Don't know what that means. OpenGL 3.2 is being set and made current.

Elias
Member #358
May 2000

glGetString(GL_EXTENSIONS) is not valid OpenGL 3.

--
"Either help out or stop whining" - Evert

Edgar Reynaldo
Member #8,592
May 2007
avatar

EDIT
How am I supposed to know that? They don't list version numbers on any docs I've seen.

https://www.khronos.org/registry/OpenGL-Refpages/es2.0/xhtml/glGetString.xml

https://www.khronos.org/opengl/wiki/GLAPI/glGetString

I also tried to work around with GL get string I and it didn't work either.

EDIT2

#SelectExpand
1Allegro version: 5.2.5.0 23 , MAJOR 32 , MINOR 4[New Thread 3320.0x2c48] 5[New Thread 3320.0x3220] 6[New Thread 3320.0x1310] 7[New Thread 3320.0x2890] 8[Thread 3320.0x3220 exited with code 0] 9[New Thread 3320.0xef4] 10 11Thread 1 received signal SIGSEGV, Segmentation fault. 120x00000000 in ?? () 13(gdb) bt 14#0 0x00000000 in ?? () 15#1 0x0042a771 in print_extensions_3_0 () at E:\LIBS\LIBS81Build\allegro5\src\opengl\extensions.c:214 16#2 0x0043c779 in _al_ogl_manage_extensions (gl_disp=0x10c9be8) 17 at E:\LIBS\LIBS81Build\allegro5\src\opengl\extensions.c:735 18#3 0x0044451e in create_display_internals (wgl_disp=0x10c9be8) 19 at E:\LIBS\LIBS81Build\allegro5\src\win\wgl_disp.c:1000 20#4 0x00444769 in wgl_create_display (w=640, h=480) at E:\LIBS\LIBS81Build\allegro5\src\win\wgl_disp.c:1059 21#5 0x00401a34 in al_create_display (w=640, h=480) at E:\LIBS\LIBS81Build\allegro5\src\display.c:53 22#6 0x004017e9 in main (argc=1, argv=0x10c1d70) at ogltest.cpp:37 23(gdb) frame 1 24#1 0x0042a771 in print_extensions_3_0 () at E:\LIBS\LIBS81Build\allegro5\src\opengl\extensions.c:214 25214 name = glGetStringi(GL_EXTENSIONS, i); 26(gdb) p glGetStringi 27No symbol "glGetStringi" in current context. 28(gdb) p _al_glGetStringi 29$1 = (_ALLEGRO_glGetStringi_t) 0x0 30(gdb)

glGetStringi doesn't exist. It's a macro for _al_glGetStringi, which is NULL.

This is using modified code to use print_extensions_3_0, which uses allegro's stored gl function pointer, which is null.

I'm assuming this needs to be filled in somehow?

Elias
Member #358
May 2000

You may be calling it too early, before the display was created.

--
"Either help out or stop whining" - Evert

Edgar Reynaldo
Member #8,592
May 2007
avatar

Elias
Member #358
May 2000

Basically all the OpenGL functions are loaded dynamically (using glx) after the display is created. If there's code calling an OpenGL function before that then that's indeed a bug.

--
"Either help out or stop whining" - Evert

Edgar Reynaldo
Member #8,592
May 2007
avatar

Elias
Member #358
May 2000

In your link you can see how OpenGL.so is loaded in the lines right afterwards... What if you just move it down a few lines?

--
"Either help out or stop whining" - Evert

Edgar Reynaldo
Member #8,592
May 2007
avatar

The question is how to handle the different versions of opengl.

If the function is an extension, we need to check to see if the extension is supported. In OpenGL versions before 3.0, this was done by calling glGetString(GL_EXTENSIONS). This returned a large string of space-separated extension names. This was abandoned, deprecated in 3.0 and removed in 3.1, because it frequently caused parsing problems for users. Some users also tried to use strcpy to copy the string to a fixed-size buffer, which could easily cause a buffer overrun if the string had too many extensions.

In modern, post GL 3.0 code, the correct way to query which extensions are supported is to use glGetIntegerv(GL_NUM_EXTENSIONS) to get the number of extensions, and then use glGetStringi(GL_EXTENSIONS, i), where i is a number between 0 and the number of extensions - 1. Because glGetStringi is not a GL 1.1 function, you will need to load this function before using it on Windows machines.

Which means we can't always rely on the old buggy code to work. It's amazing it did. I think if we use the new way it will work. I'll try moving it down, but it's part of _al_opengl_manage_extensions().

A few minor revisions and all should be fixed. It's not a far reaching fix though, as there are design problems with _al_get_suggested_display_option that conflict with al_get_new_display_option. That needs to be investigated more thoroughly.

Here's an example program that demonstrates the new patch :

#SelectExpand
1 2#include "allegro5/allegro.h" 3#include "allegro5/allegro_opengl.h" 4#include <iostream> 5 6void ERR(const char* err) { 7 printf("%s\n" , err); 8} 9 10int main(int argc , char** argv) { 11 (void)argc; 12 (void)argv; 13 14 if(!al_init()) ERR("failed to initialize allegro!\n"); 15 16 uint32_t version = al_get_allegro_version(); 17 unsigned int major = version >> 24; 18 unsigned int minor = (version >> 16) & 255; 19 unsigned int revision = (version >> 8) & 255; 20 unsigned int release = version & 255; 21 std::cout << "Allegro version: " 22 << major << "." << minor << "." << revision << "." << release << "\n"; 23 24 al_install_keyboard(); 25 26 auto timer = al_create_timer(1.0 / 30.0); 27 auto queue = al_create_event_queue(); 28 29 al_set_new_display_flags(ALLEGRO_OPENGL | ALLEGRO_WINDOWED | ALLEGRO_RESIZABLE); 30 int vmajor = 4; 31 int vminor = 0; 32 if (argc == 3) { 33 if ((1 == sscanf(argv[1] , "%d" , &vmajor)) && 1 == sscanf(argv[2] , "%d" , &vminor)) { 34 al_set_new_display_option(ALLEGRO_OPENGL_MAJOR_VERSION, vmajor, ALLEGRO_REQUIRE); 35 al_set_new_display_option(ALLEGRO_OPENGL_MINOR_VERSION, vminor, ALLEGRO_REQUIRE); 36 } 37 } 38 39 printf("%d , MAJOR\n" , al_get_new_display_option(ALLEGRO_OPENGL_MAJOR_VERSION , 0)); 40 printf("%d , MINOR\n" , al_get_new_display_option(ALLEGRO_OPENGL_MINOR_VERSION , 0)); 41 42 43 auto display = al_create_display(640, 480); 44 if(nullptr == display) ERR ("failed to create display!\n"); 45// al_set_current_opengl_context(display); 46 47 al_register_event_source(queue, al_get_keyboard_event_source()); 48 al_register_event_source(queue, al_get_timer_event_source(timer)); 49 50 std::cout<<"al opengl version: " << std::hex << al_get_opengl_version() << std::endl; 51 52 std::cout << "disp options: OPENGL_MAJOR = " 53 << al_get_display_option(display, ALLEGRO_OPENGL_MAJOR_VERSION) << ", " 54 << "OPENGL_MINOR = " 55 << al_get_display_option(display, ALLEGRO_OPENGL_MINOR_VERSION) << "\n"; 56 57 al_rest(1.0); 58 59 return 0; 60}

EDIT Removed patch. Not ready yet.

EDIT
It seems I have fixed the problem with glGetString(GL_EXTENSIONS) being used on contexts greater than or equal to 3.

There is another problem though, and that is that the members of the display options are not being filled in with ALLEGRO_OPENGL_MAJOR_VERSION and ALLEGRO_OPENGL_MINOR_VERSION. That should be fixed now too.

My latest pull request is here :
https://github.com/EdgarReynaldo/allegro5/pull/1

Go to: