SDL will always include gl extensions, creating a compatibility profile

Hello, I’m trying to create my OpenGL context in a core profile mode, which I’m doing with this code:

SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
	
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);

	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
	SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);

	char _title[16];
	snprintf(_title, 10, "%d", (int)_free_window_index);

	_window->sdl_window = SDL_CreateWindow(_title, 0, 0, 1280, 720, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
	rde_critical_error(_window->sdl_window == NULL, RDE_ERROR_SDL_WINDOW, SDL_GetError());

	_window->sdl_gl_context = SDL_GL_CreateContext(_window->sdl_window);
	rde_critical_error(_window->sdl_gl_context == NULL, RDE_ERROR_SDL_OPENGL, SDL_GetError());

	SDL_GL_MakeCurrent(_window->sdl_window, _window->sdl_gl_context);

	rde_critical_error(!gladLoadGLLoader((GLADloadproc)SDL_GL_GetProcAddress), RDE_ERROR_GLAD_INIT);
	
	rde_log_level(RDE_LOG_LEVEL_INFO, "GLAD and SDL2 loaded successfully for windows");

	SDL_GL_SetSwapInterval(1);

The thing is that when I run my program, the compatibility mode is used, and I checked the following:

int num_ext = 0;
	glGetIntegerv(GL_NUM_EXTENSIONS, &num_ext);
	for(int i=0; i<num_ext; i++) {
		printf("Extension %d = %s\n", i, glGetStringi(GL_EXTENSIONS, i));
		if(!strcmp((char*)glGetStringi(GL_EXTENSIONS,i), "GL_ARB_compatibility"))
			printf("2 - Compatiblity Profile\n");

	}

It prints 402 extensions of OpenGL, and it triggers the ‘2 - Compatiblity Profile’ log. I’m using Glad as OpenGL lib and I compile it with my source code (from here, https://glad.dav1d.de/ profile → core, gl → 4.0).

I searched in the whole project for the ‘GL_ARB_compatibility’ and it is defined in ‘SDL_opengl_glext.h’ and it is always being included, I don’t know why. I tried to compile from source code defining ‘NO_SDL_GLEXT’ so the extensions are not included, but this creates so many undefined references:

C:\Users\vazqu\Documents\SDL\src\render\opengl\SDL_render_gl.c(97,5): error C2061: syntax error: identifier 'GLDEBUGPROCARB'
1>C:\Users\vazqu\Documents\SDL\src\render\opengl\SDL_glfuncs.h(33,1): error C2365: 'glBegin': redefinition; previous definition was 'function'
1>C:\Users\vazqu\Documents\SDL\include\SDL_opengl.h(984): message : see declaration of 'glBegin'
1>C:\Users\vazqu\Documents\SDL\src\render\opengl\SDL_glfuncs.h(34,1): error C2365: 'glBindTexture': redefinition; previous definition was 'function'
...
1>C:\Users\vazqu\Documents\SDL\src\render\opengl\SDL_render_gl.c(117,33): error C2061: syntax error: identifier 'glGenFramebuffersEXT'
1>C:\Users\vazqu\Documents\SDL\src\render\opengl\SDL_render_gl.c(117,33): error C2059: syntax error: ';'
1>C:\Users\vazqu\Documents\SDL\src\render\opengl\SDL_render_gl.c(118,36): error C2061: syntax error: identifier 'glDeleteFramebuffersEXT'
1>C:\Users\vazqu\Documents\SDL\src\render\opengl\SDL_render_gl.c(118,36): error C2059: syntax error: ';'
1>C:\Users\vazqu\Documents\SDL\src\render\opengl\SDL_render_gl.c(119,38): error C2061: syntax error: identifier 'glFramebufferTexture2DEXT'
1>C:\Users\vazqu\Documents\SDL\src\render\opengl\SDL_render_gl.c(119,38): error C2059: syntax error: ';'
...
1>C:\Users\vazqu\Documents\SDL\src\render\opengl\SDL_shaders_gl.c(508,9): error C2037: left of 'GL_ARB_texture_rectangle_supported' specifies undefined struct/union 'GL_ShaderContext'
1>C:\Users\vazqu\Documents\SDL\src\render\opengl\SDL_shaders_gl.c(517,9): error C2037: left of 'glGetError' specifies undefined struct/union 'GL_ShaderContext'
1>C:\Users\vazqu\Documents\SDL\src\render\opengl\SDL_shaders_gl.c(518,9): error C2037: left of 'glAttachObjectARB' specifies undefined struct/union 'GL_ShaderContext'
1>C:\Users\vazqu\Documents\SDL\src\render\opengl\SDL_shaders_gl.c(518,59): error C2065: 'PFNGLATTACHOBJECTARBPROC': undeclared identifier

Among others. My platform is Windows 11, with SDL version 2.26.5.

The current libs I’m using are built from vcpkg (both lib and dll). I also tried with the pre-built libs on the release section of SDL github repo, getting the same result (tried several versions).

Do anyone of you guys know what can I do so the extensions are not included and I can finally create a Core Profile instead of a compatibility profile?

  1. Don’t include SDL’s OpenGL headers
  2. Make sure glad.h is included before any other OpenGL headers
  3. Make sure glad.h is included before any of SDL’s headers (since they may include an OpenGL header)
  4. You don’t need to recompile SDL to create an OpenGL core profile context
  5. Even a core profile will have extensions

Also, this isn’t the most reliable way to see if you got a core vs compatibility profile context. Technically, yes, it should work, since the spec says GL_ARB_compatibility shouldn’t be available in core profile contexts, but one of the many “fun” things about OpenGL is implementations that don’t adhere to the spec and/or lie about capabilities, what’s available, etc., including getting GL_ARB_compatibility in the extensions string for core profiles.

If you request a core profile context from SDL, and creation succeeds, that means you got a core profile context. You can query this with glGetIntegerv(GL_CONTEXT_PROFILE_MASK) which will contain a bitmask with either GL_CONTEXT_CORE_PROFILE_BIT or GL_CONTEXT_COMPATIBILITY_PROFILE_BIT

So I did like you said, I have included glad.h before anything else and this made renderdoc not to load ‘GL_ARB_compatibility’ therefor this log ‘2 - Compatiblity Profile’ went away, so thanks for this. The problem still persists tho, I used the code you provided to check the compatibility or core mode and this is the code:

GLint profile;
	glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &profile);
	rde_util_check_opengl_error("getting profile mask");
	if (profile & GL_CONTEXT_CORE_PROFILE_BIT) {
		printf("1 - Core profile\n");
	} else if(profile & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT) {
		printf("1 - Compatibility profile\n");
	} else {
		printf("I don't know -> %d \n", profile);
	}

@sjr And this is the output:

I don't know -> 0

Which I find really strange because core is 1 and compatibility is 2

Same result if using GL_CONTEXT_FLAGS instead of GL_CONTEXT_PROFILE_MASK

Another thing, I’m just including “SDL2/SDL.h” as the only header for SDL on the whole program, only once and after including glad.h, how can I prevent it from including SDL_opengl? Or is it not including it already?

Thank you in advance!

Hello,

As stated at glbegin doesn't draw in OpenGL 3.3 core - Stack Overflow**, I’m unsure glBegin will work with openGL 4.x. In my own case, I’m not using glBegin / glEnd, and I limited my expectations to OpenGL 3.2 on Windows (4.6 runs as expected on Linux). It’s difficult to answer you more precisely, because I don’t use glad, but glew or most of the time gl3w (Dear ImGui static implementation).

Feel free to have a look at my implementation (search for engine.cpp, in src/Application) to see what I do on the Windows side (Sources/src/Application/engine.cpp · master · Eric Bachard / miniDart · GitLab).

**where you can read:

" glBegin and friends are deprecated and removed from the newer versions (3.2 onward).

Instead you need to upload the vertex data to Vertex Buffer Objects. Then use glVertexAttribPointer to tell openGL how the data is laid out.

Besides that you need to write shaders."

More precise answer :
"
Fixed function pipeline (glVertex, glBegin etc.) does not exist in Core Profile."

Hope this helps :slight_smile:

@ericb
Thanks for the answer! So in fact I’m using modern OpenGL, not the legacy mode, the glEnd/glBegin problems where happening when compiling SDL from source. I checked your implementation and notice that you use:

SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS,SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG);

But this did not help either

Which is strange, since it works perfectly on my system.

GLint profile;
glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &profile);
if(profile & GL_CONTEXT_CORE_PROFILE_BIT) {
	printf("Profile: Core\n");
} else if(profile & GL_CONTEXT_COMPATIBILITY_PROFILE_BIT) {
	printf("Profile: Compatibility\n");
} else {
	printf("Profile: Unknown\n");
}

gives

Profile: Core

Just including glad.h first will preclude any other OpenGL headers from working, even if they get included later on.

When you generated glad.h you made sure to choose Core Profile, right?

Should it be of interest, I managed to write shader code to emulate (sufficient for my application, anyway) the fixed-function pipeline. I was actually surprised by how easy this turned out to be, since I had read comments elsewhere that it was not worth attempting.

Maybe some of the features that I don’t need would indeed have been more challenging, but my emulation includes a fairly complete lighting model and does a far better job of specular reflections than the standard fixed-function pipeline (since they are calculated per-pixel rather than per-vertex).

@sjr
100% sure, here is the glad.h file so you can check it out, even the automated comment says it is core:

I also have just tried using OpenGL with this GitHub - skaslev/gl3w: Simple OpenGL core profile loading and I get the exact same behaviour, eventho in the repo says it is core profile only, which I checked by searching compatibility in the whole repo and there are no matches. It seems SDL2 is including the extensions without me knowing how.

Also, do you know what can cause glGetIntegerv(GL_CONTEXT_PROFILE_MASK, &profile); to return 0?

Guys, I have found the error after revising every inch of my program. This is a bit embarrassing, but the error is generated due to the fact that I forgot to do SDL_Init(Video…). First of all I don’t event understand why my whole engine and demos were working without initializing the engine, but somehow when porting my engine from C++ to C I forgot that part… Once I initiated it, everything started to work like a charm. Anyways, thank you so much for the help guys.

3 Likes