I wrote an OpenGL game engine that (so far) works just fine in Windows 7 (NVIDIA), Arch Linux (NVIDIA), and macOS (Radeon). However, I have a friend running Windows 7 who sees nothing but a black window.
SDL_GL_SetSwapInterval succeeded.
OpenGL Vendor: ATI Technologies Inc.
OpenGL Renderer: AMD Radeon R7 200 Series
OpenGL Version: 4.5.13399 Compatibility Profile/Debug Context 15.200.1062.1003
OpenGL Shading Language: 4.40
I am starting to lose my mind over this. My engine is not (yet) very complicated. Like, seriously, it draws textured triangles using OpenGL 2.1 (with shaders that are like 3 lines long). He is able to run a bunch of other games no problem, so I’m pretty sure it’s my code, but even after adding a mountain of verbose logging, I’m not seeing any OpenGL errors or missteps.
I had him build and run this sample program. (It has a couple code mistakes that are easily fixed.) It works fine on my machine and shows a triangle and a square for 5 seconds. On his machine, it’s just another black window… and it’s a really small program. =/
How do I make Radeon happy? T_T
This was the macOS driver (which worked):
SDL_GL_SetSwapInterval succeeded.
OpenGL Vendor: ATI Technologies Inc.
OpenGL Renderer: AMD Radeon Pro 555 OpenGL Engine
OpenGL Version: 2.1 ATI-1.51.8
OpenGL Shading Language: 1.20
I have no idea if this is the cause of the problem, but you are mixing OpenGL and SDL calls to the same context and that is not recommended nor, I think, officially supported. Create your own OpenGL context with SDL_GL_CreateContext
and replace your SDL_RenderPresent
with SDL_GL_SwapWindow
to see if it helps.
My own engine is not doing that, but that sample program might not be the best. I’ll write up a proper minimal example to see if I can replicate it. My own program does use SDL_GL_SwapWindow
.
Just a small observation on the small sample program: It doesn’t explicitly ask for an opengl renderer. For a quick fix, use SDL_SetHint(SDL_HINT_RENDER_DRIVER, "opengl");
before SDL_CreateWindowAndRenderer
. The automatic driver selection of the SDL render API will most likely use Direct3D on Windows and make the OpenGL calls fail, causing a black screen. Perhaps it would have worked on that other system that way.
I wrote this program instead. Lemme know if you see any obvious mistakes here.
EDIT – This program actually worked on the Radeon machine. So I’m going to progressively add features.
#include <iostream>
#include <SDL.h>
#include <GL/glew.h>
using namespace std;
static const char* GetString(GLenum name)
{
auto text = (const char*)glGetString(name);
return text ? text : "(null)";
}
static int GetInt(GLenum name)
{
GLint value;
glGetIntegerv(name, &value);
return value;
}
static void MyCallback(
GLenum source,
GLenum type,
GLuint id,
GLenum severity,
GLsizei length,
const GLchar* msg,
const void* data)
{
if (msg && *msg) cout << "[OpenGL] " << msg << '\n';
}
int main(int argc, char** argv)
{
SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER);
SDL_GL_SetAttribute(
SDL_GL_CONTEXT_FLAGS,
SDL_GL_CONTEXT_DEBUG_FLAG);
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_ALPHA_SIZE, 8);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
auto window = SDL_CreateWindow(
"SDL2 OpenGL Test",
SDL_WINDOWPOS_CENTERED,
SDL_WINDOWPOS_CENTERED,
1024,
768,
SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE);
auto context = SDL_GL_CreateContext(window);
glewInit();
glEnable(GL_DEBUG_OUTPUT);
cout
<< "OpenGL Vendor: " << GetString(GL_VENDOR)
<< "\nOpenGL Renderer: " << GetString(GL_RENDERER)
<< "\nOpenGL Version: " << GetString(GL_VERSION)
<< "\nOpenGL Shading Language: "
<< GetString(GL_SHADING_LANGUAGE_VERSION)
<< "\nOpenGL Max Texture Size: " << GetInt(GL_MAX_TEXTURE_SIZE)
<< '\n';
cout << "OpenGL debug context flag ";
GLint v;
glGetIntegerv(GL_CONTEXT_FLAGS, &v);
if (v & GL_CONTEXT_FLAG_DEBUG_BIT)
{
cout << "enabled\n";
glDebugMessageCallback((GLDEBUGPROC)MyCallback, nullptr);
}
else
{
cout << "disabled\n";
}
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glViewport(0, 0, 1024, 768);
glClearColor(0.0f, 0.25f, 0.25f, 1.0f);
bool run = true;
bool doDraw = true;
while (run)
{
SDL_Event event;
while (SDL_PollEvent(&event))
{
switch (event.type)
{
case SDL_WINDOWEVENT:
switch (event.window.event)
{
case SDL_WINDOWEVENT_EXPOSED:
doDraw = true;
break;
case SDL_WINDOWEVENT_SIZE_CHANGED:
doDraw = true;
glViewport(
0,
0,
event.window.data1,
event.window.data2);
break;
}
break;
case SDL_KEYDOWN:
if (event.key.keysym.sym == SDLK_ESCAPE) run = false;
break;
case SDL_QUIT:
run = false;
break;
default: break;
}
}
if (doDraw)
{
doDraw = false;
glClear(GL_COLOR_BUFFER_BIT);
glBegin(GL_TRIANGLES);
glColor3f(1.0f, 1.0f, 1.0f);
glVertex2f(-0.5f, -0.5f);
glVertex2f(+0.5f, -0.5f);
glVertex2f(0.0f, 0.5f);
glEnd();
SDL_GL_SwapWindow(window);
}
SDL_Delay(1);
}
SDL_GL_DeleteContext(context);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}