Creating a OpenGL context after a window was already created

Hello,

I was wondering, why can’t I create an opengl context using SDL_GL_CreateContext on a window that wasn’t created with SDL_WINDOW_OPENGL? I can do it using wgl on windows, so is there any blocker from other platforms?

In my use case I want to open a window as fast as possible (this means without any renderer) jus to show a splash screen (by just copying the pixels to a surface) and then load vulkan and if that fails load opengl

Good Holidays!

You don’t need to specify SDL_WINDOW_OPENGL when creating the window.

The issue is that accessing the window’s surface disables creating an OpenGL context in that window, because you aren’t supposed to mix the two for drawing to the window.

You could always try creating a window to show the image, with a hidden window that is used for Vulkan/OpenGL. Once they’re ready, close the image window and show the Vulkan window.

My issue is with the design of SDL it self, because I can create a vulkan context no problem without SDL_WINDOW_VULKAN but I can’t do the same with OpenGL, but nothing is stopping me to just call the native context creation api like EGL or WGL or whatever and start using it.

So I should be able to create it using SDL.

EDIT: If you check wgpu-rs you will see they create the GL context by calling EGL/WGL without depending on the windowing lib used

You can create a window for an OpenGL context without specifying SDL_WINDOW_OPENGL these days; the requirement to specify it was removed several versions ago IIRC. I just tried it (SDL 2.28.5) on macOS and it worked fine; if it isn’t working on Windows then that sounds like a bug in SDL’s Windows backend.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define GL_SILENCE_DEPRECATION

// Or from Glad or GLEW or whatever
#include <OpenGL/GL.h>

#include <SDL2/SDL.h>

int main(int argc, char **argv)
{
	if(SDL_Init(SDL_INIT_VIDEO) < 0) {
		fprintf(stderr, "ERROR: can't init SDL: %s\n", SDL_GetError());
		exit(EXIT_FAILURE);
	}

	atexit(SDL_Quit);

	uint32_t windowFlags = SDL_WINDOW_ALLOW_HIGHDPI;
	SDL_Window *window = SDL_CreateWindow("OpenGL Test",
			SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
			800, 600,
			windowFlags);
	if(window == NULL) {
		fprintf(stderr, "ERROR: can't create window: %s\n", SDL_GetError());
		exit(EXIT_FAILURE);
	}

	SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
	SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 0);
	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
	SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
	SDL_GL_SetAttribute(SDL_GL_CONTEXT_FLAGS, SDL_GL_CONTEXT_FORWARD_COMPATIBLE_FLAG);

	SDL_GLContext gl = SDL_GL_CreateContext(window);
	if(gl == NULL) {
		fprintf(stderr, "ERROR: can't create GL context: %s\n", SDL_GetError());
		exit(EXIT_FAILURE);
	}

        // If you need to initialize Glad or GLEW, do it here

	SDL_GL_SetSwapInterval(1);

	const unsigned char *glVersion = glGetString(GL_VERSION);
	printf("GL version: %s\n", glVersion);
	
	int running = 1;
	uint32_t frame = 0;
	while(running) {

		SDL_Event event;
		while(SDL_PollEvent(&event)) {
			switch(event.type) {
			case SDL_QUIT:
				running = 0;
				break;
			}
		}

		glClearColor(0.0f, 0.5f, 1.0f, 1.0f);
		glClear(GL_COLOR_BUFFER_BIT);

		SDL_GL_SwapWindow(window);

	}

	return EXIT_SUCCESS;
}

This clears the window to a light blue color. Notice there is no mention of SDL_WINDOW_OPENGL