~ / software / glut-macosx /
Copyright © 2006—2017, Renaud Blanch.
last updates:
- changed recommended installation directory to /Library/Frameworks because SIP forbids writing to /System/Library/Frameworks (and because that's better anyway) (oct. 2017).
- added horizontal wheel support, added support for modifiers while handling wheel events, slightly changed wheel event semantic (march, 23 2015).
- added homebrew formula for automated source install (february, 25 2015).
- fixed compilation for XCode 5.1 (may, 27 2014).
- added OpenGL 3.2 core profile support (january, 14 2014).
- scale added to window state (september, 19 2013).
- added HiDPI/retina support (april, 23 2013).
- updated to new glut sources from apple (march, 6 2008).
- added intel mac support (september, 27 2007).
I often use GLUT to prototype software using OpenGL. While GLUT is convenient, it lacks features like the support for mouse scroll wheel events or HiDPI (aka retina display). You can find below a binary version of GLUT that support those features, as well as the patches and instructions to build it by your self.
The support for mouse wheel is available for Linux and for GLUT/Win32 using a patched version of GLUT.
It mimics the Linux behaviour, where the vertical scroll wheel is mapped on 2 pseudo-buttons.
It even adds horizontal scroll wheel support with two other pseudo-buttons.
The GLUT_DOWN
and GLUT_UP
state encodes two slightly different pieces of information: one GLUT_DOWN
event is send per unit of scrolling (scroll events have a delta value encoding the amount of scrolling), whereas one GLUT_UP
event is send per wheel event.
So a mouse wheel event with a delta of 3 will emit this sequence of events: GLUT_DOWN
, GLUT_DOWN
, GLUT_DOWN
, GLUT_UP
.
The scroll wheel events are thus received in the traditional mouse callback:
// compatibility with original GLUT #if !defined(GLUT_WHEEL_UP) # define GLUT_WHEEL_UP 3 # define GLUT_WHEEL_DOWN 4 # define GLUT_WHEEL_LEFT 5 # define GLUT_WHEEL_RIGHT 6 #endif void mouse(int button, int state, int x, int y); int main(int argc, char *argv[]) { // ... glutMouseFunc(mouse); // ... } void mouse(int button, int state, int x, int y) { switch(button) { case GLUT_LEFT_BUTTON: case GLUT_RIGHT_BUTTON: // ... break; case GLUT_WHEEL_UP: case GLUT_WHEEL_DOWN: if(state == GLUT_DOWN) { // multiple down events: one for each unit of scrolling } else { assert(state == GLUT_UP); // single up event: one per wheel tick } // ... break; } }
The same code should compile and run unchanged. However, you should be aware that replacing the vendor provided version of GLUT can potentially change the behaviour of existing programs under some circumstances. The following mouse event handler:
void mouse(int button, int state, int x, int y) { switch(button) { case GLUT_LEFT_BUTTON: case GLUT_MIDDLE_BUTTON: case GLUT_RIGHT_BUTTON: // ... break; default: // never reached with original GLUT assert(false); break; } }
will work as expected.
With the original GLUT, the default
clause is never reached whereas with this modified version, it is.
HiDPI support enables GLUT applications to handle an OpenGL context at the backing store resolution (i.e. in real screen pixels) rather than at the screen resolution (i.e. in screen points).
You can find an explanation of the difference between pixels and points in "High Resolution Explained: Features and Benefits".
To enable HiDPI for your windows, a capability has been added to the string accepted by glutInitDisplayString
:
glutInitDisplayString("rgba stencil double samples=8 hidpi");
When the hidpi
capability is enabled, the GLUT functions that deal with coordinates and sizes of the OpenGL context are interpreted as real pixels rather than as screen points.
The functionalities touched are:
glutInitWindowSize
and glutReshapeWindow
);glutGet(GLUT_WINDOW_WIDTH)
, glutGet(GLUT_WINDOW_HEIGHT)
); andThis as some consequences that can be surprising but are logical. First, all pixels are not reachable with the mouse cursor: since the cursor jumps from screen point to screen point, some pixels can not be hovered. This can be annoying if you want to make single pixels clickable (probably a bad idea though), but is not avoidable since the display has then a higher resolution than the input device. Second, the size of the windows will change when dragged from one display that supports HiDPI to another that does not. In fact, the size of the window will remain the same in pixels, but since the ratio between pixels and points (aka backingScaleFactor) changes, its size in screen points changes.
Finally, it can be necessary to set or know the size of a window in points (e.g. to do some window layout on screen).
To suit this use case, we added the scale of each window to its state exported by glutGet
.
For example, an application consisting of two windows (one standard, and one with HiDPI enabled), each occupying half of the screen can be achieved like that:
#include <stdlib.h> #include <stdio.h> #include <GLUT/glut.h> // compatibility with original GLUT #if !defined(GLUT_WINDOW_SCALE) # define GLUT_WINDOW_SCALE 199 #endif void display() { glutSwapBuffers(); } void reshape(int width, int height) { printf("window: %i, (%ix%i at scale %i)\n", glutGetWindow(), glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT), glutGet(GLUT_WINDOW_SCALE) ); } int main(int argc, char *argv[]) { glutInit(&argc, argv); int W = glutGet(GLUT_SCREEN_WIDTH); int H = glutGet(GLUT_SCREEN_HEIGHT); glutInitDisplayString("rgba double hidpi"); int w0 = glutCreateWindow("hidpi"); glutReshapeFunc(reshape); glutDisplayFunc(display); int s0 = glutGet(GLUT_WINDOW_SCALE); if(s0 < 0) // unsupported by original GLUT s0 = 1; glutReshapeWindow(W/2*s0, H*s0); glutPositionWindow(0, 0); glutInitDisplayString("rgba double"); int w1 = glutCreateWindow("non hidpi"); glutReshapeFunc(reshape); glutDisplayFunc(display); int s1 = glutGet(GLUT_WINDOW_SCALE); if(s1 < 0) // unsupported by original GLUT s1 = 1; glutReshapeWindow(W/2*s1, H*s1); glutPositionWindow(W/2, 0); glutMainLoop(); return EXIT_SUCCESS; }
The GLUT framework shipped with Mac OS X 10.8 and 10.9 supports OpenGL 3.2 core profile by the way of an additional capability (specified by the GLUT_3_2_CORE_PROFILE
mask).
Unfortunately, Apple did not release the sources of those GLUT versions.
We have reimplemented this support (as well as the GLUT_NO_RECOVERY
support) in this version of the fork from the latest published GLUT source code.
So, if you want to do some code targeting OpenGL 3.2 core profile with GLUT, you can by specifying:
int main(int argc, char *argv[]) { glutInit(&argc, argv); glutInitDisplayMode(GLUT_RGBA|GLUT_DOUBLE|GLUT_3_2_CORE_PROFILE); ...
or using the display string (addition by our implementation):
int main(int argc, char *argv[]) { glutInit(&argc, argv); glutInitDisplayString("rgba double core"); ...
I provide a build of the modified GLUT framework.
Putting the framework in the right location (/Library/Frameworks/
) will make the new feature available to all GLUT applications.
Be careful to preserve the symbolic links of the framework while putting it there (either use the finder to drag-and-drop the framework to the right location, use the ditto
command line, or decompress the archive at the right location):
[esperluet:~] blanch% cd /Library/Frameworks [esperluet:/Library/Frameworks] blanch% sudo tar xzvf ~/Downloads/GLUT.framework.tgz Password: x GLUT.framework/ [...] [esperluet:/Library/Frameworks] blanch%
If you want to go back to the original framework, simply remove /Library/Frameworks/GLUT.framework
, the system will then fallbak to the Apple provided /System/Library/Frameworks/GLUT.framework
.
The framework has been compiled on an intel MacBook Pro running Mac OS X Snow Lion (10.8.3), using the MacOSX10.5.sdk
deployment target.
The mouse wheel support is still available for older platforms.
If you want (or need) to compile the modified GLUT yourself, you'll need the GLUT-3.4.0 sources (the last version published by Apple is labelled "Version 3.3.2, 2008-02-08") (local mirror), and the following patches:
[esperluet:~] blanch% cd temp/ [esperluet:~/temp] blanch% curl -sO http://iihm.imag.fr/blanch/software/glut-macosx/glut-3.3.2.zip [esperluet:~/temp] blanch% unzip ~/Downloads/glut-3.3.2.zip Archive: /Users/blanch/Downloads/glut-3.3.2.zip creating: glut/ [...] [esperluet:~/temp] blanch% cd glut/ [esperluet:~/temp/glut] blanch% curl -s http://iihm.imag.fr/blanch/software/glut-macosx/patches/glut-3.3.2-0-compilation.patch | patch -p 1 patching file GLUTApplication.h patching file GLUTClipboardController.h patching file GLUTClipboardController.m patching file GLUTWindow.h patching file GLUTWindow.m patching file macx_util.m [esperluet:~/temp/glut] blanch% curl -s http://iihm.imag.fr/blanch/software/glut-macosx/patches/glut-3.3.2-1-mousewheel.patch | patch -p 1 patching file GLUTView.m patching file glut.h [esperluet:~/temp/glut] blanch% curl -s http://iihm.imag.fr/blanch/software/glut-macosx/patches/glut-3.3.2-2-hidpi.patch | patch -p 1 patching file GLUTView.m patching file GLUTWindow.m patching file macx_dstr.m [esperluet:~/temp/glut] blanch% curl -s http://iihm.imag.fr/blanch/software/glut-macosx/patches/glut-3.3.2-3-foreground.patch | patch -p 1 patching file macx_init.m [esperluet:~/temp/glut] blanch% curl -s http://iihm.imag.fr/blanch/software/glut-macosx/patches/glut-3.3.2-4-3.2core.patch | patch -p 1 patching file glut.h patching file macx_dstr.m patching file macx_glut.h patching file macx_win.m
You can now build the GLUT framework using the XCode tools:
[esperluet:~/temp/glut] blanch% xcodebuild -list Information about project "GLUT_External": Targets: GLUT Build Configurations: Debug Release If no build configuration is specified and -scheme is not passed then "Debug" is used. This project contains no schemes. [esperluet:~/temp/glut] blanch% xcodebuild -configuration Release === BUILD NATIVE TARGET GLUT OF PROJECT GLUT_External WITH CONFIGURATION Release === ... ** BUILD SUCCEEDED ** [esperluet:~/temp/glut] blanch% ls -l build/Release/ total 0 drwxr-xr-x 6 blanch staff 204 29 avr 13:18 GLUT.framework [esperluet:~/temp/glut] blanch%
Stéphane Conversy contributed a homebrew formula to automate the build from source and installation process. Thus, you should be able to perform a build and install by just running:
brew install http://iihm.imag.fr/blanch/software/glut-macosx/contribs/glut.rb