I'm facing a problem where SDL says it does not support OpenGL 3.x contexts. I am trying to follow this tutorial: Creating a Cross Platform OpenGL 3.2 Context in SDL (C / SDL). I am using GLEW in this case, but I couldn't get gl3.h to work with this either. This is the code I ended up with:
#include <glew.h>
#include <SDL.h>
int Testing::init()
{
if(SDL_Init(SDL_INIT_EVERYTHING) < 0)
{
DEBUGLINE("Error initializing SDL.");
printSDLError();
system("pause");
return 1; // Error
}
//Request OpenGL 3.2 context.
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
//set double buffer
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
//Create window
window = SDL_CreateWindow("OpenGL 3.2 test",
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
600, 400, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
if(window == NULL) return 3; // Error
//Print errors to console if there are any
printSDLError(__LINE__);
//Set up OpenGL context.
glContext = SDL_GL_CreateContext(window);
printSDLError(__LINE__);
if(glContext == NULL)
{
DEBUGLINE("OpenGL context could not be created.");
system("pause");
return 4;
}
//Initialize glew
GLenum err = glewInit();
if(err != GLEW_OK)
{
DEBUGLINE("GLEW unable to be initialized: " << glewGetErrorString(err));
system("pause");
return 2;
}
return 0; // OK code, no error.
}
The only problem that is reported is after trying to call SDL_GL_CreateContext(window), where SDL reports "GL 3.x is not supported". However, both the tutorial and this sample pack (which I have not bothered to test with) report success in combining SDL 1.3 and OpenGL 3.2. I am aware that SDL 1.3 is in the middle of development, but I somewhat doubt that even unintentional support would be removed.
A context is still created, and GLEW is able to initialize just fine. (I can't figure out for the life of me how to see the version of the context that was created, since it's supposed to be the core profile, and I don't know how to find that either. According to the tutorial, SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3) doesn't actually do anything, in which case I have no clue how to get the appropriate context created or change the default context.)
EDIT: After some testing thanks to the helpful function Nicol gave me, I have found that, regardless of the parameters I pass to SDL_GL_SetAttribute, the context is always version 1.1. However, putting in any version below 3.0 doesn't spit out an error saying it is not supported. So the problem is that the "core" version SDL sees is only 1.1.
For the record, I am using Visual C++ 2010 express, GLEW 1.7.0, and the latest SDL 1.3 revision. I am fairly new to using all three of these, and I had to manually build the SDL libraries for both 32 and 64 bit versions, so there's a lot that could go wrong. So far however, the 32 and 64 bit versions are doing the exact same thing.
EDIT: I am using an nVidia 360M GPU with the latest driver, which OpenGL Extension Viewer 4.04 reports to have full compatibility up to OpenGL 3.3.
Any help is appreciated.
UPDATE: I have managed to get SDL to stop yelling at me that it doesn't support 3.x contexts. The problem was that the SDL_GL_SetAttribute must be set BEFORE SDL_Init is called:
//Request OpenGL 3.2 context.
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
//Initialize SDL
if(SDL_Init(SDL_INIT_EVERYTHING) < 0)
{
DEBUGLINE("Error initializing SDL.");
return 1; // Error
}
Unfortunately, GLEW still refuses to acknowledge anything higher than OpenGL 1.1 (only GLEW_VERSION_1_1 returns true), which still has me puzzled. glGetString(GL_VERSION) also reports 1.1.0. It seems that my program simply doesn't know of any higher versions, as if I don't have them installed at all.
since I don't know if you already found a solution, here is mine:
I struggled around a lot today and yesterday with this stuff. Advanced GL functions couldn't be used, so I even debugged into opengl32.dll just to see it really works and wraps the calls into the hardware-specific OpenGL DLL (nvoglnt.dll). So there must have been another cause. There were even tips in the internet to link to opengl32.lib before all other libraries, because ChoosePixelFormat and some other functions are overwritten by each other.
But that wasn't the cause, too. My solution was to enable the accelerated visuals here:
// init SDL
if(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_HAPTIC | SDL_INIT_TIMER) < 0) {
fprintf(stderr, "Could not init SDL");
return 1;
}
// we must wish our OpenGL Version!!
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1);
because in the current SDL revision (Dec 15, 2011) he checks for it in SDL_windowsopengl.c
if (_this->gl_config.accelerated >= 0) {
*iAttr++ = WGL_ACCELERATION_ARB;
*iAttr++ = (_this->gl_config.accelerated ? WGL_FULL_ACCELERATION_ARB :
WGL_NO_ACCELERATION_ARB);
}
and this attribute is initialized to -1 if you did not define it on your own.
And: Never set the version attributes before initializing SDL, because settings attributes needs the video backend to be initialized properly!
I hope this helps.
I followed this tutorial. Everything works fine on windowz and linux.
http://people.cs.uct.ac.za/~aflower/tutorials.html
Related
I want to debug my program with renderdoc. I created my context with SDL_GL standard function. I get this error when running the application using render doc.
"OpenGL. Context not created via CreateCont Only OpenGL 3.2+ contexts are supported"
I added this argument before I created my context:
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
That should force a core profile, yet the error is still there.
What am I doing wrong here?
-----Edit-----
Even after forcing version 3.2 (exact version required) the thing still complaints.
Here is the init block of my window class:
//System init
if(!SDL_WasInit(SDL_INIT_EVERYTHING))
SDL_Init(SDL_INIT_EVERYTHING);
this->SDL_window = SDL_CreateWindow(title,10,10,w,h,SDL_WINDOW_OPENGL);
if(this->SDL_window!=NULL)
{
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
this->context = SDL_GL_CreateContext(SDL_window);
if(!this->context)
{
SDL_DestroyWindow(SDL_window);
COUT<<"FAILED TO CREATE CONTEXT. PRINTING ERROR AND THROWING EXCEPTION"<<ENDL;
COUT<<SDL_GetError()<<ENDL;
throw "ENGINE::WINDOW::GLCONTEXTERR";
}
glewExperimental = GL_TRUE;
glewInit();
}
else
{
COUT<<"FAILED TO CREATE WINDOW. PRINTING ERROR AND THROWING EXCEPTION"<<ENDL;
COUT<<SDL_GetError()<<ENDL;
throw "ENGINE::WINDOW::SDLWINDOWERR";
}
The error message is very clear: Your program doesn't use a OpenGL 3.2+ context.
Since you only request a specific major version but not a minor version, you most probably get a 3.0 context. To solve the problem add
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
Summary:
An OpenGL context is created successfully on the development computer, but when trying to distribute the application, the screen only shows black. What kind of issues need to be considered when distributing an OpenGL application?
Details:
I am using SDL2 to create a OpenGL 3.1 context. The context has to be at least 3.1 to work.
I have not thoroughly tested the issue, so I do not have information such as the graphics cards in use. However, I am more interested in the general question asked in the summary about what needs to be considered when distributing an OpenGL application.
Here is the context creation code.
// CREATE SDL
U32 flags;
flags |= SDL_INIT_VIDEO;
flags |= SDL_INIT_EVENTS;
if(!SDL_WasInit(0)) // Make sure SDL is initialized.
SDL_Init(0);
CHECK(!SDL_InitSubSystem(flags));
// SET OPENGL ATTRIBUTES
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, config.glVersionMajor);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, config.glVersionMinor);
if(config.glCoreProfile)
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
else
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY);
//SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, config.glDepthBuffer);
SDL_GL_SetSwapInterval(0);
// CREATE WINDOW
flags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN;
if(config.fullscreen)
flags = flags | SDL_WINDOW_FULLSCREEN_DESKTOP;
else if(config.maximized)
flags = flags | SDL_WINDOW_MAXIMIZED;
if(config.resizable)
flags = flags | SDL_WINDOW_RESIZABLE;
mainWindow = SDL_CreateWindow(config.programName, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
config.windowWidth, config.windowHeight, flags);
SDL_GetWindowSize(mainWindow, (int*)&windowWidth, (int*)&windowHeight);
CHECK(mainWindow != NULL);
// CREATE OPENGL CONTEXT
mainContext = SDL_GL_CreateContext(mainWindow);
CHECK(mainContext != NULL);
// INIT GLEW
#ifdef _WIN32
CHECK(GLEW_OK == glewInit());
#endif
glEnable(GL_DEPTH_TEST);
glViewport(0,0,windowWidth,windowHeight);
glClearColor(0,0,0,1);
//glEnable(GL_PRIMITIVE_RESTART);
glEnable(GL_CULL_FACE);
//glPrimitiveRestartIndex(0xFFFFFFFF);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
TTF_Init();
Make sure you know what your application is dependent on, and demand it from the platform. Saying "Core profile" means little in my experience. Better query each and every extension your application need and shut the application down (gracefully and kindly in the eyes of the user) if something is missing. And extensions are not everything. Check maximum sizes of all buffers, too. Of that I have real life experience.
Never rely on standard compliance. Yes, the standard says that GL_DEPTH is intially disabled. And no, thou shalt never rely on that the driver is compliant to that rule. And yes, that was a real life scenario.
Run proper tests on a variaty of hardwares. Vendors implement drivers differently. Some may think negative vertex index is perfectly fine. Some may not. Real life experience there as well...
Never accept a silent OpenGL error. "Something went wrong and it is probably nothing to worry about. For this hardware. For this driver. For this version. For this OS. Maybe."
Do the math. Floating point precision is not that strict by the OpenGL standard (more strict in OpenGL) and behavior for operations with undefined behavior, such as division by zero or any operations based on NaN, is never something you want to rely on.
Read the standard. Yes it is a pain, but trust me it will pay out. You won´t feel it of course since you will never experience problems you will never have.
As a side note, nobody really follow this practice. Everybody code first and then debug forever.
I am running Mac OSX Yosemite Version 10.10 and the latest version of SDL (2.0.3).
I am trying to use at least OpenGL version 3+. Without doing anything, my OpenGL version returns 2.1 INTEL-10.0.86.
The OpenGL commands work, but this is obviously not the version I need.
So, after doing some research I found the way to change the version with SDL is through the SDL_GL_SetAttribute(SDL_GLattr attr, int value) function after you initialize SDL but before you define the context. So here is my code:
if (SDL_Init(SDL_INIT_EVERYTHING) < 0)
{
printf("Failed to initialize SDL. Error (SDL): %s.\n", SDL_GetError());
return false;
}
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1); //I read somewhere that this may help
window = SDL_CreateWindow("Window", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 640, 480, (SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN));
if (!window)
{
printf("Failed to create the window. Error (SDL): %s.\n", SDL_GetError());
return false;
}
context = SDL_GL_CreateContext(window);
Using this code, the OpenGL version reports 4.1 INTEL-10.0.86. This would work well but none of my OpenGL calls work anymore so I checked for an OpenGL error after a function is called and it returns 1282.
The strange thing is that when I change the code to this
...
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
//SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
//SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
//SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1); //I read somewhere that this may help
...
It gives the same output 4.1 INTEL-10.0.86 and returns the same OpenGL error (1282) and none of the OpenGL functions work.
And my last attempt failed as well with a different outcome. Here was my code:
...
//SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_ACCELERATED_VISUAL, 1); //I read somewhere that this may help
...
The new OpenGL version returned is null but if I change the major_version to 2 and minor_version to 1 it returns to my original version 2.1 INTEL-10.0.86.
Does anyone know a solution to this problem?
--Edit--
After doing some additional research, if OpenGL returns 1282 after every call the context is not initialized correctly. This leads me to believe that this may be a bug with SDL not correctly creating the context? (I honestly don't know that much so I'm going on a limb). I'll submit a bug to SDL and see if that helps anything.
SDL_GL_CONTEXT_PROFILE_CORE
...
...none of my OpenGL calls [glMatrixMode, glLoadIdentity, glLoadIdentity, glBegin] work anymore...
Those are all deprecated and will not work in a Core context.
If you want to continue using a Core context you'll have to re-write your program to not use deprecated functionality.
I am trying to load a specific OpenGL version functions, but it seems that GLEW loads all of the functions regardless what I specify prior to creation of the GL context.
The reason that I know that it's not loading the specified version that I want is because it returns the function pointer to the function that is available in the later version of OpenGL.
glBlendFunci is only available in >= 4.0, whereas I want the 2.1 version of OpenGL, but glBlendFunci gets loaded regardless.
Here's what I'm trying to do:
int main(int argc, char** args)
{
SDL_Init(SDL_INIT_EVERYTHING);
window = SDL_CreateWindow("Game",
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
width, height,
SDL_WINDOW_SHOWN | SDL_WINDOW_OPENGL);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GLContext glContext = SDL_GL_CreateContext(window);
glewInit();
std::cout << glBlendFunci << std::endl;
//Initialize();
SDL_GL_DeleteContext(glContext);
SDL_DestroyWindow(window);
SDL_Quit();
return 0;
}
P.S. This is just a some prototyping code and I was just messing around with OpenGL.
The behavior you have observed is well within the spec (see WGL_ARB_create_context or GLX_ARB_create_context):
If a version less than or equal to 3.0 is requested, the context
returned may implement any of the following versions:
Any version no less than that requested and no greater than 3.0.
Version 3.1, if the GL_ARB_compatibility extension is also
implemented.
The compatibility profile of version 3.2 or greater.
What you get is a context which supports GL 2.1 completely, so any code written for GL 2.1 should run - but you may get way more than that - a compatibility profile of the highest GL version your vendor supports is not uncommon.
I'm following a tutorial which uses glfwWindowHint() to set the version of GLFW that he is using. He's on OSX and I'm on Windows. I have the exact same code as his. When I do this:
glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_COMPAT_PROFILE);
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
And then this:
GLFWwindow* window = glfwCreateWindow(640, 360, "Modern OpenGL", NULL, NULL);
It always returns NULL. But in the tutorial he said that setting the window hints was necessary to use the code that the program uses. When I take out the window hints the window is created sucessfully, but then it crashes (because of the other code that probably required the window hint changes).
I'm on Windows XP. How do I fix this?
Interestingly, this code should always return NULL on OSX, as OSX supports OpenGL >=3 only in core profiles, while this code requests a compatibility profile.
On Windows, a compatibility profile of that version might be supported. But this will depend on the GPU and the drivers you have installed. It might very well be the case that your system does simply not support GL3.2. Make sure you are using recent drivers. And check what GL version your GPU actually supports. One thing you could try though is setting the GLFW_OPENGL_FORWARD_COMPAT hint to GL_FALSE.