I once tried to open a GLUT window from a sub-thread and got lots of nasty problems. I remember this post on lists.apple.com:
GLUT functions may only be called from the application's main thread
Has anything changed in this regard with GLUT on Mac OS X ? Is there a thread-safe GLUT that let's you open windows from any thread ?
If GLUT is not an option, is there a tiny library that replaces GLUT and would work from any thread ?
[edit]
Here is the result of my tests triggered by the various solutions proposed as answers:
GLFW looked nice but did not compile (current branch is 3 years old)
Agar was another pretender but it's too big for the tiny need I had
SDL is not BSD-license compatible and it's a huge library for code that should fit on a single file
GLUT cannot run in any thread.
I decided to reinvent the wheel (yes, that's good sometimes) and the final class is just 200 lines of code. It let's me open and close a window from any thread (openGL draw in new thread) and I have full control on vertical sync and such (SDL uses double buffering = slow for openGL). I had to trick around the NSApp to properly start and stop the application (which does not use an event loop otherwise).
To those telling me that OpenGL is not thread-safe, that's not exactly true: you can run multiple OpenGL threads and the draw commands will be executed in the OpenGL state assigned to that thread. OpenGL is thread-specific.
If anyone needs some bare-bones code to create OpenGL windows using Cocoa: gl_window.mm
GLUT is not thread safe. You'll need locking primitives with whatever solution you choose to implement. I'd recommend setting up your own GL view in Cocoa and rewriting the plumbing that GLUT provides.
Take a look at SDL as a modern GLUT replacement. It should give you all the cross-platform you want. As far a cross-platform threading, Boost provides a portable library.
As a replacement for GLUT, have a look at GLFW. It's similar in purpose and workings, but better. And it does not have a glfwMainLoop that your program is stuck with; it allows you full control. Never since I discovered GLFW have I had a need to switch back to GLUT.
Note that GLFW is not thread-safe, in the sense that it is unsafe to call GLFW functions from different threads (FAQ entry). However, as long as you call all GLFW functions from the same thread, it's your choice which thread that will be.
Not only is GLUT is not thread safe, but OpenGL is a state machine, and therefore isn't thread safe. Having said that, you can have multithreaded applications that use OpenGL. Just make sure all your OpenGL calls are made from the same thread.
The next step up from GLUT on Mac OS X is the Cocoa OpenGL Sample Code. This is a true Cocoa application that demonstrates the Cocoa way of setting up an OpenGL window, with interactivity using the Cocoa event model. From this starting point, it's fairly easy to add code to handle your program logic in a separate thread (or threads) from your OpenGL drawing code.
Related
I am trying to figure out the relationship between CGL and OpenGL on Mac platform.
More specifically about the context. Do they share context? If yes, how? Please give me a link to some related examples.
If no, then are there two contexts working in Core Animation applications which make use of OpenGL?
I am very confused by the use of OpenGL by Mac. Can somebody clarify?
CGL sets up device specific contexts suitable for OpenGL to render to. Compare to wgl and xgl on Windows and X respectively. CGL understands how to query the graphics hardware for its pixel format, and then how to set up and configure a context (e.g. double-buffered or single-buffered, what resolution depth, stencil, accumulation buffer, etc). But it doesn't provide functions to draw in that context. Once you have created the context with CGL, you make it current, and then you can call OpenGL to render in that context.
In Core Graphics (do not confuse it with CGL), both context initialization and drawing into the context are handled by the same framework. But because OpenGL is an open standard and designed to be cross-platform, the rendering functionality and the device context functionality have been abstracted into separate frameworks.
CGL is the low-level interface to OpenGL on a Mac. You probably don't want to be using it if you are writing an OpenGL Mac app. I am currently in the process of creating a intuitive OpenGL Mac application template for XCode 4, but in the mean time you can look at https://github.com/mk12/Pong-Ultimate, a pong clone I made using OpenGL. It uses NSOpenGL, a higher-level Cocoa interface to OpenGL.
You may also find the Apple docs helpful: http://developer.apple.com/library/mac/#documentation/GraphicsImaging/Conceptual/OpenGL-MacProgGuide/opengl_intro/opengl_intro.html.
I have been studying the Qt Quarterly article about QGraphicsScene and OpenGL for the purpose of using it in a project. I have already decided to use Qt, given its all-round excellence, but have gone down the road of implementing a class derived from QGLWidget, however I would then still need to implement the UI elements. Using techniques from the quoted article would mean I could also use Qt widgets for the UI as well, making the program dependent on Qt alone (and not CEGUI or similar).
Anyway I have been running the sample under a desktop Linux machine, which has an Core i7 and a fairly good Nvidia card and it runs well, however my on my 2010 MacBook Pro (Core i5 and Nvidia 330) it runs very poorly indeed, especially when interacting with it using the mouse.
Question: can anyone suggest ways of improving the performance of this sample? I'm no Qt expert but I think the poor response is due to calls to update() from within the mouse handling code coupled with the timed calls to update() at the end of the method itself. I think what is needed is a background thread to update the object movement and a timed but constant call to update().
Can anyone comment on this?
EDIT: I have already tried removing all calls to update(), apart from the timer reset, and it makes very little difference.
Unfortunately the performance that you get when using the suggestions from that article is pretty bad. We tried that on an embedded system and it was far to slow.
For us the solution was to use QML, the new "declarative" UI capability in Qt 4.7. We have QML embedded in our C++ application. We are seeing huge speed improvements with QML widgets overlaid on top of our GL scene.
We are using the QDeclarativeView widget in our C++ application, which is capable of displaying our QML content. See: http://doc.qt.io/archives/qt-4.7/qdeclarativeview.html.
This should work fine on the desktop (works for me on Ubuntu).
More useful links:
Using QML Bindings in C++ Applications
Integrating QML Code with Existing Qt UI Code
UPDATE! 1/20/2015:
In Qt5.4 there is a new class called QOpenGLWidget that basically makes it so you can use "classic" Qt widgets with an OpenGL background with great performance. They finally adressed this issue directly! Read the blog post, and then the docs:
Qt Blog Entry about QOpenGLWidget
QOpenGLWidget Docs
I'm developing a very simple application for the Mac OSX platform making use of Qt and OpenGL (and QtOpenGL) so crossplatform gets easier.
The application receive a variable number of video streams that have to be rendered to the screen. Each frame of these video streams is used as a texture for mapping a rectangle in 3D space (very similar to a videowall).
Apart from the things such as receiving, locking, uploading video data, synchronizing threads... i consider it is clear that it's a quite simple application.
The fact is that all behaves ok when using cocoa based Qt 4.7 binaries (the default ones) in a 10.5 Mac.
But my code has to run fine at all of the OSX versions starting from (and including to) 10.4. So i tried the code in a 10.4 machine and it crashed just when starting. After a few hours of internet reading, i discovered that for a Qt Application to be targeted at 10.4, carbon Qt based has to be used. So i rebuild the whole project with the new framework.
When the new resulting binary gets run, all works well except by the fact that application's fps fall to about 2 fps!! And it behaves the same at both machines (10.5 computer has sensibly better features)
I've spent quite time working on this but i have not reached a solution. Any suggest?
More information about the application and things i've tried
code has not been modified when recompiling carbon based
only two (256x256 textures) videos ar used in order to assure it's not a bandwidth limit problem (although i know it shouldn't because the first code worked)
the 2 video streams arrive from network (local)
when a video stream arrives, a signal is emmited and the data will be uploaded to an OpenGL texture (glTexSubImage2D)
a timer makes render (paintGL) happen at about 20ms (~50 fps)
the render code use the textures (updated or not) to draw the rectangles.
rendering only when a video arrives won't work because of having 2 (asynchronous) video streams; besides more things have to be draw at screen.
only basic OpenGL commands are used (no PBO,FBO,VBO,...) The only one problematic thing could be the use of shaders (available only from Qt 4.7), but its code is trivial.
i've made use of OpenGLProfiler and Instruments. Nothing special/strange was observed.
Some things i suspect (conclusions)
it's clear it's not a hardware issue. The same computer behave differently
it gives me the sensation it's a threading/locking problem but, why?
carbon is 32 bits. The 10.5 application was 64. It's not possibly develop 64 bits in carbon.
for giving away the 32 bits possible cause, i also rebuild the first project for 32 bits. It worked partically the same.
i've read something about carbon having problems (more than usual) with context switching.
maybe OpenGL implementation is Multithread and code is not? (or the opposite?) That could cause a lot of stalls.
maybe carbon handle events differently from cocoa's? (i mean signal/event dispatching, main loop...)
Ok, this is (sorry for the so long writing) my actual headache. Any suggestion, idea.. would be very appreciated.
Thx in advance.
May I ask a diagnostic question? Can you ensure that it's not being passed to the software renderer?
I remember that when 10.4 was released, there was some confusion about quartz extreme, quartz and carbon, with some of it disabled, and hardware renderers disabled by default on some of them, which required configuration by the end user to get it working correctly. I'm not sure whether this information is pertinent, because you say that, having targetted 10.4, the problem exhibits on both the 10.4 and the 10.5, yes?
It's possible (though admittedly I'm grasping at straws here) that even in 10.5 carbon doesn't use the hardware renderers by default. I'd like to think though that OSX prefers hardware renderers to software renderers in all scenarios, but it may be worth spending a little time looking into, given how thoroughly you're already looking into other options.
Good luck.
If you are using Qt, I guess your code would work on a windows or linux platform. Have you tried your application under these platforms ?
This would quickly reveal if it comes from Qt or the mac OSX version.
SDL on OS X uses preprocessor tricks to overload main() with their own entry point, written in Objective C, which calls the user's main.
These tricks make the lives of non-C SDL users (e.g: the Haskell bindings) very difficult.
Is there a good reason for this?
Why couldn't SDL do the objective-C Cocoa initialization in SDL_init?
The approach for Mac OS X is not much different from the approach for other non-Linux platforms (Windows, old Mac, BeOS). You could ask the SDL developers themselves why they did it this way, but I can see several reasons they may have chosen to do this:
This keeps the dependencies of SDL code, which is focused on initializing SDL-specific subsystems (video, audio, timing, etc.) limited to the specific subsystems that SDL is especially designed to work with. I.e. this way, SDL stays lean and mean.
It avoids having to introduce a new platform-specific subsystem for application initialization. Not everyone is going to want the bare-bones application object and menu that SDL sets up for Mac apps, not by a long shot – so if you were going to put it into SDL_init, you'd need to make it an optional subsystem so as not to inconvenience developers who don't need it.
It handles inversion of control correctly, which is how Mac OS X and other application frameworks typically operate, while maintaining the operational semantics of SDL routines. SDL_init assumes it's going to be returning to the caller after initialization is complete, but if you tried naively to create an application object in SDL_init and invoke [app run] on it to finish initializing the application and launching, you'd never return. If you didn't call run there, you'd have to create a separate SDL function to set up the application run loop. This could complicate the SDL library quite a bit. The approach that was chosen avoids all this, by letting the framework take care of all the application set up first, and invoke the SDL_main() routine from applicationDidFinishLaunching.
It makes it easy to convert SDL demos coded on Linux over to Mac OS X. You don't even have to rename main – the preprocessor renaming of main() to SDL_main() takes care of that for you!
I'm guessing the last of these reasons is the primary driver behind the redefinition of main in SDL_main.h, which I agree is an ugly hack.
If you're prepared to give up that level of cross-platform portability for your library and apps, I'd suggest simply modifying your SDL_main.h to remove the following line:
#define main SDL_main
and removing the following from the SDLMain.m in your project:
#ifdef main
# undef main
#endif
You shouldn't even need to recompile SDL if you do this. Note that SDLMain.m is already set up to invoke SDL_main() without the preprocessor hack, and nothing else in SDL is going to use this, so in this way you can you simply provide SDL_main() as your game's entry point.
If you want to go the other way, taking over main() yourself, you'd still want to get rid of the #define main SDL_main hack in SDL_main.h, but other than that, you're not beholden to the main() that SDL provides for you. First, note that SDLMain.{h,m} are not part of the library proper; you must include them separately in your project. Second, note the following comments in SDLMain.h:
/* SDLMain.m - main entry point for our Cocoa-ized SDL app
Initial Version: Darrell Walisser <dwaliss1#purdue.edu>
Non-NIB-Code & other changes: Max Horn <max#quendi.de>
Feel free to customize this file to suit your needs
*/
That sounds to me like an invitation to go roll your own if these aren't working for you, starting with SDLMain.{h,m} as a model. And if you're rolling your own, you can do what you want! For that matter, you could write the equivalent of SDLMain.m in Haskell, using HOC, if that's what you want. Unless you're a whiz with HOC, though, I'd keep it simple.
I'm having a problem getting OpenMP and OpenCV to play nicely with a new project in Xcode. The project in its current state does nothing but grab frames from the default camera and put them into a window. This functionality works. However, I would like to grab the frames in a separate thread, and I was hoping I could get some experience with OpenMP.
Merely checking the checkbox to enable OpenMP in Xcode wreaks havoc. The program, while it will compile, load and run just fine, will not respond to any events -- period. It just sits there, drawing grabbed frames. (I do get the OS X beachball, too, even though it's running fine.) I eventually have to force quit the app or kill it from Xcode. Keep in mind I get this behavior even without any OpenMP #pragmas -- I have only to enable the option in Xcode.
Any ideas on how to solve this?
I'm just guessing here. You might need to make sure that all OpenGL drawing commands are called from one thread.