OpenGL 3.x context creation using SDL2 on OSX (Macbook Air 2012) - macos

As far as I'm aware, the Macbook Air 2012 supports OpenGL 3.2. When using SDL 2.0 to create the OpenGL context, however, the context is only opengl version 2.1.
Is it possible for SDL 2.0 to create a GL 3.2 context?

For everyone who still has this problem as of Wednesday, Oct 10th, SDL2 allows you to create an OpenGL 3.2 context on Macs running Mac OS X 10.7 (Lion) and up.
You just need to add this code:
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
If you're running OS X 10.10, or the solution above still does not resolve the problem, changing the second line of the above example from
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
to
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 1);
may work for you.

EDIT: See https://stackoverflow.com/a/13095742/123387 -- SDL2 should support this natively now. The note below is for versions before the latest SDL2 release.
The current version (as of Wed Aug 15 21:00:33 2012 -0400;
6398:c294faf5fce5) does not support 10.7 series. However, there is a
way to add support if you're willing to run an unstable SDL for kicks.
Give this a shot:
src/video/cocoa/SDL_cocoaopengl.m +90 (Cocoa_GL_CreateContext)
if(_this->gl_config.major_version == 3 &&
_this->gl_config.minor_version == 2)
{
attr[i++] = NSOpenGLPFAOpenGLProfile;
attr[i++] = NSOpenGLProfileVersion3_2Core;
}
Then in your application, something along these lines.
SDL_Init(SDL_INIT_EVERYTHING);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
window = SDL_CreateWindow("3.2", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
640, 480, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
context = SDL_GL_CreateContext(window);
I am running 10.7.4 under my Mac Air from 2011 and when I run a few GL
diagnostics from a 3.2 SDL enable application I get:
Driver : cocoa
Renderer : Intel HD Graphics 3000 OpenGL Engine
Vendor : Intel Inc.
Version : 3.2 INTEL-7.18.18
GLSL : 1.50
I haven't tested much outside of this, but hopefully someone else can
give it a stab and have a bit more success.
EDIT: If you're using GLEW you will want to enable glewExperimental.
Note that there is a bug in the 3.2 core profile when you query
GL_EXTENSIONS. It will report 1280 (as if it wasn't
supported)--however that shouldn't impact you from using 1.50 shaders
and so on.

That should be possible:
#include <stdio.h>
#include <stdlib.h>
/* If using gl3.h */
/* Ensure we are using opengl's core profile only */
#define GL3_PROTOTYPES 1
#include <GL3/gl3.h>
#include <SDL.h>
#define PROGRAM_NAME "Tutorial1"
/* A simple function that prints a message, the error code returned by SDL,
* and quits the application */
void sdldie(const char *msg)
{
printf("%s: %s\n", msg, SDL_GetError());
SDL_Quit();
exit(1);
}
void checkSDLError(int line = -1)
{
#ifndef NDEBUG
const char *error = SDL_GetError();
if (*error != '\0')
{
printf("SDL Error: %s\n", error);
if (line != -1)
printf(" + line: %i\n", line);
SDL_ClearError();
}
#endif
}
/* Our program's entry point */
int main(int argc, char *argv[])
{
SDL_Window *mainwindow; /* Our window handle */
SDL_GLContext maincontext; /* Our opengl context handle */
if (SDL_Init(SDL_INIT_VIDEO) < 0) /* Initialize SDL's Video subsystem */
sdldie("Unable to initialize SDL"); /* Or die on error */
/* Request opengl 3.2 context.
* SDL doesn't have the ability to choose which profile at this time of writing,
* but it should default to the core profile */
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 2);
/* Turn on double buffering with a 24bit Z buffer.
* You may need to change this to 16 or 32 for your system */
SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24);
/* Create our window centered at 512x512 resolution */
mainwindow = SDL_CreateWindow(PROGRAM_NAME, SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
512, 512, SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN);
if (!mainwindow) /* Die if creation failed */
sdldie("Unable to create window");
checkSDLError(__LINE__);
/* Create our opengl context and attach it to our window */
maincontext = SDL_GL_CreateContext(mainwindow);
checkSDLError(__LINE__);
/* This makes our buffer swap syncronized with the monitor's vertical refresh */
SDL_GL_SetSwapInterval(1);
/* Clear our buffer with a red background */
glClearColor ( 1.0, 0.0, 0.0, 1.0 );
glClear ( GL_COLOR_BUFFER_BIT );
/* Swap our back buffer to the front */
SDL_GL_SwapWindow(mainwindow);
/* Wait 2 seconds */
SDL_Delay(2000);
/* Same as above, but green */
glClearColor ( 0.0, 1.0, 0.0, 1.0 );
glClear ( GL_COLOR_BUFFER_BIT );
SDL_GL_SwapWindow(mainwindow);
SDL_Delay(2000);
/* Same as above, but blue */
glClearColor ( 0.0, 0.0, 1.0, 1.0 );
glClear ( GL_COLOR_BUFFER_BIT );
SDL_GL_SwapWindow(mainwindow);
SDL_Delay(2000);
/* Delete our opengl context, destroy our window, and shutdown SDL */
SDL_GL_DeleteContext(maincontext);
SDL_DestroyWindow(mainwindow);
SDL_Quit();
return 0;
}

Related

SDL in Xcode on MacMini M1 - Window not showing

I know this is similar to some other posts but still a little different...
I'm using the newest version of Xcode with SDL. The following code should show me a window but nothing happens except that I get the following message: Metal API Validation Enabled
Program ended with exit code: 0
When I disable this validation nothing happens at all. Any ideas on what might be wrong?
#include <SDL2/SDL.h>
#include <iostream>
int main() {
SDL_Init((SDL_INIT_VIDEO) <0);
SDL_Window *window;
window = SDL_CreateWindow("Title", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, 800, 600, SDL_WINDOW_SHOWN); //also tried different WINDOW_ input here
if (window == NULL) {
// In the case that the window could not be made...
printf("Could not create window: %s\n", SDL_GetError());
return 1;
}
SDL_Renderer *renderer = SDL_CreateRenderer(window, -1, 0);
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255);
SDL_RenderClear(renderer);
SDL_RenderPresent(renderer);
SDL_Delay(3000);
}
````
I don't have enough reputation to comment, but for a start, the int main() should be replaced with int main(int argc, char* argv[]) and i'm not sure about SDL_Init((SDL_INIT_VIDEO) <0); just try SDL_Init(SDL_INIT_VIDEO); also, im not 100% about this I don't use mac, but if there are .dll on mac make sure you have the correct .dll files aswell (note what you're compiling (64bit or 32bit) use the corresponding .dll files)

How to use Cmake for OpenGL + Qt 5.8 in OS X Sierra?

I just tried to setup CMake for a project using Qt 5.8 to do OpenGL stuff in OS X Sierra. Here you can see my main CMakeLists
cmake_minimum_required (VERSION 3.8)
set (PROJECT_NAME "FluidEngine")
project (${PROJECT_NAME})
set (CMAKE_PREFIX_PATH "/Users/BRabbit27/Qt/5.8/clang_64")
set (CMAKE_AUTOMOC ON)
find_package (Qt5Widgets)
find_package (Qt5Gui)
find_package (Qt5OpenGL)
set (CPP_SOURCES "")
set (HPP_SOURCES "")
set (INCLUDE_PATHS "")
add_subdirectory (src)
include_directories (${INCLUDE_PATHS} ${OPENGL_INCLUDE_DIRS})
add_executable (${PROJECT_NAME} ${CPP_SOURCES} ${HPP_SOURCES})
target_link_libraries (${PROJECT_NAME} Qt5::Widgets Qt5::Gui Qt5::OpenGL )
It perfectly configures the xcode project, no errors.
Then my code for rendering a basic triangle looks like:
GLWindow::GLWindow(QWidget* parent) : QOpenGLWidget(parent)
{}
void GLWindow::initializeGL()
{
initializeOpenGLFunctions();
GLfloat verts[] =
{
0.f, 1.f,
-1.f, -1.f,
1.f, -1.f
};
GLuint myBufferID;
glGenBuffers(1, &myBufferID);
glBindBuffer(GL_ARRAY_BUFFER, myBufferID);
glBufferData(GL_ARRAY_BUFFER, sizeof(verts), verts, GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glVertexAttribPointer(0, 2, GL_FLOAT, GL_FALSE, 0, 0);
}
void GLWindow::resizeGL(int w, int h)
{
glViewport(0, 0, w, h);
}
void GLWindow::paintGL()
{
glDrawArrays(GL_TRIANGLES, 0, 3);
}
And what I get is a black window. I got this code from this video tutorial
Am I missing something in my cmake file or something subtle in OS X to use OpenGL? Since OS X is now promoting Metal, perhaps something must be enabled but I do not know what.
I already tried setting the version of OpenGL used in the main function
int main(int argc, char** argv)
{
QApplication app(argc, argv);
QSurfaceFormat format;
format.setVersion(4, 1);
format.setProfile(QSurfaceFormat::CoreProfile);
QSurfaceFormat::setDefaultFormat(format);
GLWindow glwindow;
glwindow.show();
return app.exec();
}
Any idea?
UPDATE
Added project to github, you can clone it here to test in your machine.
The way I build the project is just cmake -GXcode .. assuming i'm in /path/to/project/build_xcode directory.
Hope this can help you reproduce and perhaps give me a clue on what I could be doing wrong.
I checked all the error messages and from there make my way to found the solution. Fortunately someone already replied in SO with a related problem and had a solution to the problem. You can find the complete answer here OpenGL: INVALID_OPERATION following glEnableVertexAttribArray
For short
You're seeing this error on OS X because it only supports the OpenGL
Core Profile if you're using OpenGL 3.x or higher. Your code is not
Core Profile compliant. You were most likely using the Compatibility
Profile on Windows.
Specifically, the Core Profile requires a Vertex Array Object (VAO) to
be bound for all vertex related calls. So before calling
glEnableVertexAttribArray(), or other similar functions, you will
need to create and bind a VAO.

Why can't I create an OpenGL ES 3.0 context using SDL2?

I'm using SDL2 2.0.2 on Debian stable, and I'm trying to acquire an OpenGL ES 3.0 context with it. This works if I request an OpenGL ES 2.0 context, but not if I directly request an OpenGL ES 3.0 context.
Consider the following program:
#include <GLES3/gl3.h>
#include <SDL2/SDL.h>
int main(
int argc,
char **argv
) {
SDL_GLContext context;
int rc;
const GLubyte *version;
SDL_Window *window;
rc = SDL_Init(SDL_INIT_VIDEO);
if (rc < 0) {
return EXIT_FAILURE;
}
atexit(SDL_Quit);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_ES);
#ifdef THIS_SHOULD_WORK_TOO
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 3);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
#else
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 2);
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 0);
#endif
window = SDL_CreateWindow("OpenGL", 100, 100, 800, 600, SDL_WINDOW_OPENGL);
context = SDL_GL_CreateContext(window);
version = glGetString(GL_VERSION);
if (version == 0) {
printf(
"Unable to get OpenGL ES version string: %d\n",
glGetError()
);
return EXIT_FAILURE;
}
printf("Version string: %s\n", version);
SDL_GL_DeleteContext(context);
return EXIT_SUCCESS;
}
When I compile this normally, it requests an OpenGL ES 2.0 context, and the program receives an OpenGL ES 3.0 context:
$ c99 example.c -lSDL2 -lGLESv2
$ ./a.out
Version string: OpenGL ES 3.0 Mesa 10.3.2
However, when I request an OpenGL ES 3.0 context, this program fails without a clear error message:
$ c99 -DTHIS_SHOULD_WORK_TOO example.c -lSDL2 -lGLESv2
$ ./a.out
Unable to get OpenGL ES version string: 0
Why is this?
I doubt it is because of -lGLESv2, mostly because the OpenGL ES context reports that it is version 3.0, and because platforms that do ship a libGLESv3.so ship it as a symlink it to libGLESv2.so (Android does this, for example).
This is a bug in SDL2:
SDL's EGL code (used for OpenGL ES context creation on Windows / Linux / Android / etc.) only seems to properly support OpenGL ES 1 and 2 contexts.
In particular, the current code sets the EGL_RENDERABLE_TYPE config attribute to EGL_OPENGL_ES2_BIT if GLES2 is requested and EGL_OPENGL_ES_BIT in all other cases. It never uses EGL_OPENGL_ES3_BIT / EGL_OPENGL_ES3_BIT_KHR even when GLES3.0+ is requested. It also doesn't use EGL_CONTEXT_MINOR_VERSION_KHR to set the version to 3.1 rather than 3.0 in SDL_EGL_CreateContext, when 3.1 is requested.
This means that a request for OpenGL ES 3.0 is translated into a request for OpenGL ES 1.0. Since OpenGL ES 3.0 is backwards incompatible with OpenGL ES 1.0, the request eventually fails (I think).
The fix has been merged into the master branch, and is scheduled to be released as part of SDL2 version 2.0.4:
Added EGL_KHR_create_context support to allow OpenGL ES version selection on some platforms

GLEW crashing in XCode

I'm trying to run a simple OpenGL program using GLFW (version 3.0.2) and GLEW (version 1.10.0) in XCode (version 4.6.3) on OS X 10.8.4. The entire code is shown below.
#include <GLFW/glfw3.h>
#include <OpenGL/OpenGL.h>
#include <iostream>
using namespace std;
void RenderScene()
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
}
void InitGL()
{
glClearColor(1, 0, 0, 1);
}
void ErrorFunc(int code, const char *msg)
{
cerr << "Error " << code << ": " << msg << endl;
}
int main(void)
{
GLFWwindow* window;
/* Report errors */
glfwSetErrorCallback(ErrorFunc);
/* Initialize the library */
if (!glfwInit())
return -1;
/* Window hints */
glfwWindowHint (GLFW_CONTEXT_VERSION_MAJOR, 3);
glfwWindowHint (GLFW_CONTEXT_VERSION_MINOR, 2);
glfwWindowHint (GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint (GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
/* Create a windowed mode window and its OpenGL context */
window = glfwCreateWindow(640, 480, "Hello World", NULL, NULL);
if (!window)
{
glfwTerminate();
return -1;
}
/* Make the window's context current */
glfwMakeContextCurrent(window);
/* Initialize OpenGL */
InitGL();
/* Loop until the user closes the window */
while (!glfwWindowShouldClose(window))
{
/* Render here */
RenderScene();
/* Swap front and back buffers */
glfwSwapBuffers(window);
/* Poll for and process events */
glfwPollEvents();
}
glfwTerminate();
return 0;
}
Most of this came straight from GLFW's documentation; only the rendering function and GLEW initialization are mine. I have added frameworks for OpenGL, Cocoa and IOKit and linked against libGLEW.a and libglfw3.a. The program compiles successfully but appears to crash when attempting to execute functions GLEW was supposed to take care of. Here, the program crashes on glClearBufferfv. If I comment that out, I get a window with a black background. My guess is GLEW is secretly not working, since it reports no errors but doesn't seem to be doing its job at all.
The exact error message XCode throws at me is error: address doesn't contain a section that points to a section in a object file with an error code of EXC_BAD_ACCESS. If I replace glClearBufferfv with glClearColor the program doesn't crash, but still has a black background when it should actually be red. When queried, OpenGL returns the version string 2.1 NVIDIA-8.12.47 310.40.00.05f01, which explains why calls to newer functions aren't working, but shouldn't GLEW have set up the correct OpenGL context? Moreover, GLFW's documentation says that they've been creating OpenGL 3+ contexts since GLFW 2.7.2. I really don't know what to do.
glClearBuffer (...) is an OpenGL 3.0 function, it is not implemented in all versions of OS X (some only implement OpenGL 2.1). Because OS X does not use runtime extensions, GLEW is not going to fix this problem for you.
You will have to resort to the traditional method for clearing buffers in older versions of OS X (10.6 or older). This means setting the "clear color" and then clearing the color buffer as a two-step process. Instead of a single function call that can clear a specific buffer to a specific value, use this:
#define USE_GL3 // This code requires OpenGL 3.0, comment out if unavailable
void RenderScene()
{
GLfloat color[] = {1.0f, 0.0f, 0.0f};
#ifdef USE_GL3 // Any system that implements OpenGL 3.0+
glClearBufferfv (GL_COLOR, 0, color);
#else // Any other system
glClearColor (color [0], color [1], color [2]);
glClear (GL_COLOR_BUFFER_BIT);
#endif
}
This is not ideal, however. There is no point in setting the clear color multiple times. You should set the clear color one time when you initialize the application and replace the ! USE_GL3 branch of the code with glClear (GL_COLOR_BUFFER_BIT);
Now, because you mentioned you are using Mac OS X 10.8, you can ignore a lot of what I wrote above. OS X 10.8 actually implements OpenGL 3.2 if you do things correctly.
You need two things for glClearBuffer (...) to work on OS X:
Mac OS X 10.7+ (which you have)
Tell glfw to create an OpenGL 3.2 core context
Before you create your window in glfw, add the following code:
glfwWindowHint (GLFW_OPENGL_VERSION_MAJOR, 3);
glfwWindowHint (GLFW_OPENGL_VERSION_MINOR, 2);
glfwWindowHint (GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
glfwWindowHint (GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
Once you have an OpenGL 3.2 core context, you can also eliminate the whole ! USE_GL3 pre-processor branch from your code. This was a provision to allow your code to work on OS X implementations that do not support OpenGL 3.2.
GLEW doesn't really work on mac unless you enable the experimental option. Enable it after setting all your stuff in GLFW.
glewExperimental = GL_TRUE;
Edit:
And you also set to use OpenGL Core with
glfwOpenWindowHint( GLFW_OPENGL_VERSION_MAJOR, 3 );
glfwOpenWindowHint( GLFW_OPENGL_VERSION_MINOR, 2 );
Slightly different from yours.

Multiple Windows OpenGL/Glut

I would like to know how to open multiple OpenGL/Glut windows.
And I mean multiple windows at the same time
not subwindows and
not update the same window
While I believe the above answer is accurate, it is a little more complex then needed and it might be difficult when later having to deal with moving between the windows (say, for example, when drawing into them). This is what we've just done in class:
GLint WindowID1, WindowID2; // window ID numbers
glutInitWindowSize(250.0, 250.0); // set a window size
glutInitWindowPosition(50,50); // set a window position
WindowID1 = glutCreateWindow("Window One"); // Create window 1
glutInitWindowSize(500.0, 250.0); // set a window size
glutInitWindowPosition(500,50); // set a window position
WindowID2 = glutCreateWindow("Window Two"); // Create window 2
You will notice I'm using the same create window function but loading it into a GLint. That is because when we create a window this way, the function actually returns a unique GLint used by glut to identify windows.
We have to get and set windows to move between them and perform appropriate drawing functions. You can find the calls here.
The same way as you would create one window, except you should do it multiple times :
#include <cstdlib>
#include <GL/glut.h>
// Display callback ------------------------------------------------------------
float clr = 0.2;
void display()
{
// clear the draw buffer .
glClear(GL_COLOR_BUFFER_BIT); // Erase everything
// set the color to use in draw
clr += 0.1;
if ( clr>1.0)
{
clr=0;
}
// create a polygon ( define the vertexs)
glBegin(GL_POLYGON); {
glColor3f(clr, clr, clr);
glVertex2f(-0.5, -0.5);
glVertex2f(-0.5, 0.5);
glVertex2f( 0.5, 0.5);
glVertex2f( 0.5, -0.5);
} glEnd();
glFlush();
}
// Main execution function
int main(int argc, char *argv[])
{
glutInit(&argc, argv); // Initialize GLUT
glutCreateWindow("win1"); // Create a window 1
glutDisplayFunc(display); // Register display callback
glutCreateWindow("win2"); // Create a window 2
glutDisplayFunc(display); // Register display callback
glutMainLoop(); // Enter main event loop
}
This example shows how to set the same callback to render in both windows. But you can use different functions for windows.

Resources