Getting direct OpenGL commands to work

Hi. I’m trying to render to texture using openGL commands but they won’t seem to render.

I create the window with this:
window=SDL_CreateWindow(“OutThink”, 0, 0, mode.w, mode.h, SDL_WINDOW_FULLSCREEN_DESKTOP | SDL_WINDOW_OPENGL);

I create the renderer with this:
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_TARGETTEXTURE);

I create the texture target with this:
texTarget=SDL_CreateTexture(Window_GetRenderer(), SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_TARGET, UserInterface.ViewportWidth, UserInterface.ViewportHeight);

Inside the “render to texture” function I call these:
SDL_SetRenderTarget(Window_GetRenderer(), texTarget);
SDL_GL_BindTexture(texTarget, NULL, NULL);
//Then a few OpenGL commands that don’t work.
SDL_GL_UnbindTexture(texTarget);
SDL_SetRenderTarget(Window_GetRenderer(), NULL);

The texture appears onscreen but the openGL commands don’t seem to work.
Have I forgot some OpenGL settings? I’m just wondering if I’ve done everything I need to SDL-wise.

Thanks.

A warning upfront: If you want to interact with the OpenGL context that the SDL renderer is using, you have to be very careful what gets used and changed. Some parts of the state are cached by SDL and things will not work correctly if they’re not reset to the value SDL expects. Reading into the SDL renderer source code is recommended.

If you want an OpenGL renderer, you need to ask for one. Passing -1 as the second argument to SDL_CreateRenderer makes SDL use an automatic selection (unless you have a environment variable or hint set).

Note that sampling from a texture while it is attached to a bound framebuffer object (drawing a texture to itself) is undefined behavior.

The opengl renderer of SDL may use shaders. Did you account for that?

Here’s a simple example I managed to get running by disabling shaders. I don’t have much experience with interfacing with the renderer like this. Seems too unpractical to me anyway as there’s now much more to keep track of.

directglcalls.c
#include <SDL.h>
#include <SDL_opengl.h>

static SDL_Window * window;
static SDL_Renderer * renderer;
static SDL_Texture * texture;
static struct {
	void (GLAPIENTRY * ClearColor)(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
	void (GLAPIENTRY * Color4b)(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha);
	void (GLAPIENTRY * Clear)(GLbitfield mask);
	void (GLAPIENTRY * Begin)(GLenum mode);
	void (GLAPIENTRY * End)();
	void (GLAPIENTRY * Vertex2f)(GLfloat x, GLfloat y);
	void (GLAPIENTRY * Enable)(GLenum cap);
	void (GLAPIENTRY * Disable)(GLenum cap);
	void (GLAPIENTRY * Color4f)(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
} gl;

static int maxs32(int a, int b) { return a > b ? a : b; }
static float modf32(float x) { return x - SDL_floorf(x); }

#define DICEROLL 0x1B949B6D

static int run()
{
	int i, width, height;
	SDL_Event e;
	int done = 0;
	int rendercount, glrender = -1;
	SDL_Rect dst_rect1 = {0, 0, 140, 140};
	SDL_Rect dst_rect2 = {0, 0, 128, 128};
	struct {
		float x1, x2, x3;
		float y1, y2, y3;
		float r1, g1, b1;
	} triangle;

	if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS | SDL_INIT_TIMER) < 0) {
		SDL_Log("Failed to initialize SDL: %s", SDL_GetError());
		return 1;
	}

	/* Disable OpenGL shaders so we don't need to change that much of the state. */
	SDL_SetHint(SDL_HINT_RENDER_OPENGL_SHADERS, "0");

	window = SDL_CreateWindow("GL context test", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 500, SDL_WINDOW_RESIZABLE | SDL_WINDOW_OPENGL);
	if (window == NULL){
		SDL_Log("Failed to create window: %s", SDL_GetError());
		return 1;
	}

	SDL_GetWindowSize(window, &width, &height);

	/* Make sure the renderer is OpenGL. */
	rendercount = SDL_GetNumRenderDrivers();
	for (i = 0; i < rendercount; i++) {
		SDL_RendererInfo info;
		SDL_GetRenderDriverInfo(i, &info);
		if (SDL_strcmp(info.name, "opengl") == 0) {
			glrender = i;
			break;
		}
	}
	if (glrender == -1) {
		SDL_Log("No OpenGL renderer available.");
		return 1;
	}

	renderer = SDL_CreateRenderer(window, glrender, 0);
	if (renderer == NULL){
		SDL_Log("Failed to create renderer: %s", SDL_GetError());
		return 1;
	}

	SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
	SDL_RenderClear(renderer);
	SDL_RenderPresent(renderer);

	gl.ClearColor = SDL_GL_GetProcAddress("glClearColor");
	gl.Color4b = SDL_GL_GetProcAddress("glColor4b");
	gl.Clear = SDL_GL_GetProcAddress("glClear");
	gl.Begin = SDL_GL_GetProcAddress("glBegin");
	gl.End = SDL_GL_GetProcAddress("glEnd");
	gl.Vertex2f = SDL_GL_GetProcAddress("glVertex2f");
	gl.Disable = SDL_GL_GetProcAddress("glDisable");
	gl.Enable = SDL_GL_GetProcAddress("glEnable");
	gl.Color4f = SDL_GL_GetProcAddress("glColor4f");
	if (gl.ClearColor == NULL) {
		SDL_Log("Failed to load glClearColor: %s", SDL_GetError());
		return 1;
	} else if (gl.Color4b == NULL) {
		SDL_Log("Failed to load glColor4b: %s", SDL_GetError());
		return 1;
	} else if (gl.Clear == NULL) {
		SDL_Log("Failed to load glClear: %s", SDL_GetError());
		return 1;
	} else if (gl.Begin == NULL) {
		SDL_Log("Failed to load glBegin: %s", SDL_GetError());
		return 1;
	} else if (gl.End == NULL) {
		SDL_Log("Failed to load glEnd: %s", SDL_GetError());
		return 1;
	} else if (gl.Vertex2f == NULL) {
		SDL_Log("Failed to load glVertex2f: %s", SDL_GetError());
		return 1;
	} else if (gl.Disable == NULL) {
		SDL_Log("Failed to load glDisable: %s", SDL_GetError());
		return 1;
	} else if (gl.Enable == NULL) {
		SDL_Log("Failed to load glEnable: %s", SDL_GetError());
		return 1;
	} else if (gl.Color4f == NULL) {
		SDL_Log("Failed to load glColor4f: %s", SDL_GetError());
		return 1;
	}

	texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA32, SDL_TEXTUREACCESS_TARGET, 128, 128);
	if (texture == NULL){
		SDL_Log("Failed to create texture: %s", SDL_GetError());
		return 1;
	}

	while (!done) {
		Uint32 now;
		while (SDL_PollEvent(&e)) {
			if (e.type == SDL_QUIT) {
				done = 1;
			} else if (e.type == SDL_KEYDOWN) {
			} else if (e.type == SDL_KEYUP) {
				Uint32 sym = e.key.keysym.sym;
				if (sym == SDLK_ESCAPE) {
					done = 1;
				} else if (sym == SDLK_f) {
					if (SDL_GetWindowFlags(window) & SDL_WINDOW_FULLSCREEN) {
						SDL_SetWindowFullscreen(window, SDL_FALSE);
					} else {
						SDL_SetWindowFullscreen(window, SDL_WINDOW_FULLSCREEN_DESKTOP);
					}
				}
			} else if (e.type == SDL_WINDOWEVENT) {
				if (e.window.event == SDL_WINDOWEVENT_RESIZED || e.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
					SDL_GetWindowSize(window, &width, &height);
				}
			}
		}

		now = SDL_GetTicks();

		SDL_SetRenderDrawColor(renderer, 0, 0, 0, 255);
		SDL_RenderClear(renderer);

		SDL_SetRenderTarget(renderer, texture);

		{ /* Direct calls to OpenGL. */
			gl.ClearColor(modf32(now / 1140.f), modf32(now / 1261.f), modf32(now / 1345.f), 255);
			gl.Clear(GL_COLOR_BUFFER_BIT);

			triangle.x1 = (float)((now / 1000 * DICEROLL) % dst_rect2.w);
			triangle.x2 = (float)((now / 1000 * DICEROLL) / 11 % dst_rect2.w);
			triangle.x3 = (float)((now / 1000 * DICEROLL) / 17 % dst_rect2.w);
			triangle.y1 = (float)((now / 1000 * DICEROLL) / 7 % dst_rect2.h);
			triangle.y2 = (float)((now / 1000 * DICEROLL) / 13 % dst_rect2.h);
			triangle.y3 = (float)((now / 1000 * DICEROLL) / 5 % dst_rect2.h);

			triangle.r1 = modf32(now / 1000 / 3.f);
			triangle.g1 = modf32(now / 1000 / 2.f);
			triangle.b1 = modf32(now / 1000 / 4.f);

			gl.Begin(GL_TRIANGLES);
			gl.Color4f(triangle.r1, triangle.g1, triangle.b1, 1);
			gl.Vertex2f(triangle.x1, triangle.y1);
			gl.Color4f(triangle.r1, triangle.g1, triangle.b1, 1);
			gl.Vertex2f(triangle.x2, triangle.y2);
			gl.Color4f(triangle.r1, triangle.g1, triangle.b1, 1);
			gl.Vertex2f(triangle.x3, triangle.y3);
			gl.End();
		}

		SDL_SetRenderTarget(renderer, NULL);

		dst_rect1.x = now / 18 % maxs32(width - dst_rect1.w, 50);
		dst_rect1.y = now / 16 % maxs32(height - dst_rect1.h, 50);
		dst_rect2.x = dst_rect1.x + (dst_rect1.w - dst_rect2.w) / 2;
		dst_rect2.y = dst_rect1.y + (dst_rect1.h - dst_rect2.h) / 2;

		SDL_SetRenderDrawColor(renderer, now / 4 % 256, now / 4 % 256, now / 4 % 256, 255);
		SDL_RenderFillRect(renderer, &dst_rect1);

		SDL_RenderCopy(renderer, texture, NULL, &dst_rect2);

		SDL_RenderPresent(renderer);
	}

	return 0;
}

int main(int argc, char * argv[])
{
	int retval = run();

	if (texture)
		SDL_DestroyTexture(texture);
	if (renderer)
		SDL_DestroyRenderer(renderer);
	if (window)
		SDL_DestroyWindow(window);
	if (SDL_WasInit(SDL_INIT_EVERYTHING))
		SDL_Quit();

	return retval;
}