SDL 2.26 not rendering on MacOS

I have used SDL for projects previously without trouble, but currently I am trying to build a couple projects from the command line using SDL 2.26, on Monterey and now on Ventura. The projects build successfully, but when run, they mostly produce blank black windows. Printing error messages shows that most drawing operations are yielding the message “invalid renderer.” In almost all cases, it says I’m using an OpenGL renderer, regardless of which API I ask for; I have not been able to get it to use Vulkan or Metal, and the failure to draw affects both the renderer and surface APIs.

I have confirmed that the same code works normally on Windows.

I appreciate any avenues for finding a way to correct this.

So the reason your drawing operations are returning “invalid renderer” is most likely because the renderer isn’t being successfully created. You need to make sure SDL_CreateRenderer() isn’t returning NULL. What does SDL_GetError() say when it does return NULL?

Secondly, what specifically are you passing to SDL_CreateRenderer()?

I’m not having any trouble creating a renderer and drawing things with SDL 2.26 on macOS 13 Ventura.

It would be helpful if you posted your code that creates the window and renderer.

That’s the thing; SDL_CreateRenderer returns a non-null result but ALSO generates the “invalid renderer” error.

You definitely need to actually check return values. The value returned by SDL_GetError() can only be used if the last SDL function call returned an error. It’s just there to provide more information about why an error was returned; if the last SDL call succeeded then it doesn’t tell you anything meaningful. The SDL docs for SDL_GetError() specifically say:

The message is only applicable when an SDL function has signaled an error. You must check the return values of SDL function calls to determine when to appropriately call SDL_GetError(). You should not use the results of SDL_GetError() to decide if an error has occurred! Sometimes SDL will set an error string even when reporting success.

SDL will not clear the error string for successful API calls. You must check return values for failure cases before you can assume the error string applies.

So, check to make sure window creation succeeded before creating the renderer, make sure renderer creation succeeded, and check to make sure your draw call succeeded. Only if they fail should you print SDL_GetError()

Also, because of this, you don’t need to call SDL_ClearError(). Just check function return values.

edit: And another thing: you don’t need to pass SDL_WINDOW_VULKAN to when creating the window unless you’re planning on creating a Vulkan context yourself and doing your own drawing with it. SDL_Renderer has no Vulkan backend.

(This is not production code. This is minimal code intended to explain my test process.)

The VULKAN flag is a holdover from me trying to find some way to get the renderer to obtain a driver other than opengl, which it sounds like you’re saying won’t happen.

So, the documentation says that SDL might generate the “invalid renderer” message even when generating a valid renderer, and that as long as it returns a renderer, that message is to be ignored.

If I am supposed to accept that the renderer is valid, why doesn’t it draw the rectangle?

That said, thank you for your responses so far.

On macOS, you should be getting the Metal backend. You can find out with this:

SDL_RendererInfo info;
SDL_GetRendererInfo(renderer, &info);
printf("Renderer backend: %s\n", info.name);

Yes. Because SDL_GetError() isn’t there to tell you if an error occurred. It’s only there to tell you what the error was if an SDL call fails.

Something I noticed: your sample code calls SDL_SetRenderDrawColor() to clear the screen, but doesn’t call it again before drawing the rectangle, so it’s drawing a rectangle that’s the same color as your clear color. :stuck_out_tongue_winking_eye:

However, if you change the draw color and it isn’t working (or that’s just an oversight from copy/pasting from real code for the sample code) check the return value of SDL_RenderFillRect() and if it really is failing then call SDL_GetError to see what the problem is.

Sadly, it wasn’t anything that simple. There was a SetDrawColor in the original code that got lost. Still doesn’t show up.

I’ve added the renderer name request. This is the code as I ran it minus some of the boilerplate: (The forum seems to be taking umbrage to some of the pastebin links now, but the previous link still works.)

As far as I can tell, I’m requesting Metal and getting OpenGL.

Are you setting any hints?

What do you get if, right after calling SDL_Init(), you insert the line

SDL_LogSetAllPriority(SDL_LOG_PRIORITY_VERBOSE);

You can post formatted code here, using 3 backticks (not apostrophes) on their own line to start a code block, and three more on their own line to end it.

This code works on my system (2018 Mac Mini, Intel, macOS 13 Ventura):

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

#include <SDL2/SDL.h>

#define SCREEN_WIDTH 800
#define SCREEN_HEIGHT 600

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

	SDL_LogSetAllPriority(SDL_LOG_PRIORITY_VERBOSE);

	SDL_Window *window = SDL_CreateWindow("Test", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED,
			SCREEN_WIDTH, SCREEN_HEIGHT, 0);
	if(window == NULL) {
		fprintf(stderr, "ERROR: can't create window: %s\n", SDL_GetError());
		return EXIT_FAILURE;
	}

	SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
	if(renderer == NULL) {
		fprintf(stderr, "ERROR: can't create renderer: %s\n", SDL_GetError());
		return EXIT_FAILURE;
	}

	// The above call to SDL_LogSetAllPriority() should make SDL print which backend was used when
	// creating the renderer, but do it ourselves anyway.
	SDL_RendererInfo info;
	SDL_GetRendererInfo(renderer, &info);
	printf("Renderer backend: %s\n", info.name);

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

		SDL_SetRenderDrawColor(renderer, 128, 196, 255, 255);
		SDL_RenderClear(renderer);

		SDL_Rect rect = { 20, 20, SCREEN_WIDTH - 40, SCREEN_HEIGHT - 40 };
		SDL_SetRenderDrawColor(renderer, 255, 196, 128, 255);
		SDL_RenderFillRect(renderer, &rect);

		SDL_RenderPresent(renderer);
	}

	SDL_Quit();

	return EXIT_SUCCESS;
}

Gives the following output

2022-12-01 18:45:29.308 test[6532:442136] INFO: Created renderer: metal
Renderer backend: metal

and draws everything correctly

Your exact code, compiled on my 2020 MacBook (Intel, Ventura), yields a sky-blue window and the console output:

2022-12-01 21:03:15.216 test[88921:3536266] INFO: OpenGL shaders: ENABLED
2022-12-01 21:03:15.217 test[88921:3536266] ERROR: Invalid renderer
2022-12-01 21:03:15.217 test[88921:3536266] INFO: Created renderer: opengl
Renderer backend: opengl

It feels like something wrong with my system config rather than with SDL or the code, but I have no idea how to diagnose it.

Yeah, it definitely sounds like something’s screwy with your system.

Isn’t there an environment variable that can be set to force a specific renderer backend (or am I thinking of video driver)? Check for something like that with printenv, which will print all environment variables.

Honestly, I have no idea though.

I feel dreadfully embarrassed.

Apparently I’ve been running sdl2-config from the wrong path. It’s been supplying the path to a copy of SDL2 that I compiled seven years ago on a different computer. Forcing the right path appears to produce a working binary.

1 Like