Well, I'm not sure of X11 is even required. I am not using it directly, as far as I know. I let GLUT take care of the platform-specific windowing stuff. Which is why it also works on Windows without a problem.
So it mostly depends on what GLUT does on OS X, I think.

I have been thinking of dropping GLUT in favour of my own code though... GLUT has a few bugs, and it is abandoned anyway. GLUT also doesn't allow you to use a specific version for an OpenGL context, as far as I know... Which is one of the points I mentioned above, I'd like to support OGL 4.1 directly.
In that case I'd need a Windows, X and native OS X implementation.

How does OS X handle 32/64-bit by the way? Is it the same as in Windows, where a 32-bit executable will just work transparently on a 64-bit OS? In that case I wouldn't mind including a 32-bit version only, for x86. And I think ignoring PowerPC isn't a big deal either. Don't think many people still use those.
Posted on 2011-07-09 15:15:41 by Scali
Same as Windows, utilizing Compatibility Mode to run 32-bit apps natively in 64-bit Long Mode.
Posted on 2011-07-09 20:20:00 by SpooK

I have been thinking of dropping GLUT in favour of my own code though... GLUT has a few bugs, and it is abandoned anyway.


SFML might be a decent compromise between legacy GLUT and rolling your own.
Posted on 2011-07-09 22:59:04 by SpooK
Native OpenGL for Mac OS X Instructions


On top of the previous instructions, modify BHMFile-0.1a/src/BHM3DSample/GL/GLUX.cpp as follows...


/*
GLUX (GL Useful eXtensions)
Author: Scali

This code is released under the BSD license. See COPYRIGHT.txt for more information.
*/

#include "GLUX.h"
#ifdef _WINDOWS
#include <Windows.h>
#include <Wingdi.h>
#elif defined(__APPLE__)
#include <GLUT/glut.h>
#else
#include <GL/glx.h>
#endif
#include "FreeImage.h"
#include <stdio.h>
#include <string.h>

void gluxSwapInterval(int interval)
{
#ifdef _WINDOWS
// http://www.opengl.org/registry/specs/EXT/wgl_swap_control.txt
#ifndef PFNWGLSWAPINTERVALFARPROC
typedef BOOL (APIENTRY *PFNWGLSWAPINTERVALFARPROC)( int );
#endif /* PFNWGLSWAPINTERVALFARPROC */

PFNWGLSWAPINTERVALFARPROC wglSwapIntervalEXT = 0;

wglSwapIntervalEXT = (PFNWGLSWAPINTERVALFARPROC)wglGetProcAddress( "wglSwapIntervalEXT" );

if( wglSwapIntervalEXT )
wglSwapIntervalEXT(interval);
#elif defined(__APPLE__)
// Support for MESA swap control
#ifndef PFNGLXSWAPINTERVALMESAPROC
typedef int (*PFNGLXSWAPINTERVALMESAPROC)(unsigned int interval);
#endif /* PFNGLXSWAPINTERVALMESAPROC */

PFNGLXSWAPINTERVALMESAPROC glXSwapIntervalMESA = (PFNGLXSWAPINTERVALMESAPROC)glutGetProcAddress("glXSwapIntervalMESA");

if (glXSwapIntervalMESA != NULL)
{
glXSwapIntervalMESA(interval);
return;
}

// Support for SGI swap control
// http://www.opengl.org/registry/specs/SGI/swap_control.txt
#ifndef PFNGLXSWAPINTERVALSGIPROC
typedef int ( * PFNGLXSWAPINTERVALSGIPROC) (int interval);
#endif /* PFNGLXSWAPINTERVALSGIPROC */

PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)glutGetProcAddress("glXSwapIntervalSGI");

if (glXSwapIntervalSGI != NULL)
{
glXSwapIntervalSGI(interval);
return;
}

// Support for SGI WaitVideoSync
// http://www.opengl.org/registry/specs/SGI/video_sync.txt
#ifndef PFNGLXWAITVIDEOSYNCSGIPROC
typedef int ( * PFNGLXWAITVIDEOSYNCSGIPROC) (int divisor, int remainder, unsigned int *count);
#endif /* PFNGLXWAITVIDEOSYNCSGIPROC */

PFNGLXWAITVIDEOSYNCSGIPROC glXWaitVideoSyncSGI = (PFNGLXWAITVIDEOSYNCSGIPROC)glutGetProcAddress("glXWaitVideoSyncSGI");

if (glXWaitVideoSyncSGI != NULL)
{
unsigned int count = 0;

glXWaitVideoSyncSGI((interval+1), 0, &count);
}
#else
// Support for MESA swap control
#ifndef PFNGLXSWAPINTERVALMESAPROC
typedef int (*PFNGLXSWAPINTERVALMESAPROC)(unsigned int interval);
#endif /* PFNGLXSWAPINTERVALMESAPROC */

PFNGLXSWAPINTERVALMESAPROC glXSwapIntervalMESA = (PFNGLXSWAPINTERVALMESAPROC)glXGetProcAddress((GLubyte*)"glXSwapIntervalMESA");

if (glXSwapIntervalMESA != NULL)
{
glXSwapIntervalMESA(interval);
return;
}

// Support for SGI swap control
// http://www.opengl.org/registry/specs/SGI/swap_control.txt
#ifndef PFNGLXSWAPINTERVALSGIPROC
typedef int ( * PFNGLXSWAPINTERVALSGIPROC) (int interval);
#endif /* PFNGLXSWAPINTERVALSGIPROC */

PFNGLXSWAPINTERVALSGIPROC glXSwapIntervalSGI = (PFNGLXSWAPINTERVALSGIPROC)glXGetProcAddress((GLubyte*)"glXSwapIntervalSGI");

if (glXSwapIntervalSGI != NULL)
{
glXSwapIntervalSGI(interval);
return;
}

// Support for SGI WaitVideoSync
// http://www.opengl.org/registry/specs/SGI/video_sync.txt
#ifndef PFNGLXWAITVIDEOSYNCSGIPROC
typedef int ( * PFNGLXWAITVIDEOSYNCSGIPROC) (int divisor, int remainder, unsigned int *count);
#endif /* PFNGLXWAITVIDEOSYNCSGIPROC */

PFNGLXWAITVIDEOSYNCSGIPROC glXWaitVideoSyncSGI = (PFNGLXWAITVIDEOSYNCSGIPROC)glXGetProcAddress((GLubyte*)"glXWaitVideoSyncSGI");

if (glXWaitVideoSyncSGI != NULL)
{
unsigned int count = 0;

glXWaitVideoSyncSGI((interval+1), 0, &count);
}
#endif
}


... and utilize the following Makefile to build:


INCLUDE = -I/usr/X11R6/include/ -I/usr/local/include -I/opt/local/include -I. -I../BHMFile -I../
LIBDIR  = -L/usr/X11R6/lib -L/usr/local/lib -L/opt/local/lib -L../ -L.

COMPILERFLAGS = -Wall
CC = c++
CFLAGS = $(COMPILERFLAGS) $(INCLUDE)
LIBRARIES = -framework OpenGL -framework GLUT \
-lGLEW -lm -lfreeimage -lbhmfile -lglux

HEADERS = State.h \
Geometry/Object3D.h Geometry/Mesh.h Geometry/BHMObject.h \
Geometry/VertexDescriptor.h Geometry/Buffer.h Geometry/VBOMesh.h \
Material/Material.h Material/FFMaterial.h \
Material/ShaderMaterial.h Material/SkinnedMaterial.h \
Material/ASMMaterial.h Material/Texture.h Material/ASMShader.h \
Material/Shader.h Material/Program.h Material/SkinnedASMMaterial.h  \
Anim/Interpolate.h Anim/Movable.h Anim/AnimKey.h Anim/PosKey.h  \
Anim/RotKey.h Anim/BezPosKey.h Anim/TCBRotKey.h


SOURCES = Main.cpp State.cpp \
Geometry/Object3D.cpp Geometry/Mesh.cpp Geometry/BHMObject.cpp \
Geometry/VertexDescriptor.cpp Geometry/Buffer.cpp Geometry/VBOMesh.cpp \
Material/Material.cpp Material/FFMaterial.cpp \
Material/ShaderMaterial.cpp Material/SkinnedMaterial.cpp \
Material/ASMMaterial.cpp Material/Texture.cpp Material/ASMShader.cpp \
Material/Shader.cpp Material/Program.cpp Material/SkinnedASMMaterial.cpp \
Anim/Interpolate.cpp Anim/Movable.cpp

BHM3DSample: $(HEADERS) $(SOURCES) libglux.a
$(CC) $(CFLAGS) -g -o $@ $(LIBDIR) $< $(SOURCES) $(LIBRARIES)

libglux.a: GLUX
ar rv libglux.a GLUX.o GLUXMath.o
ranlib libglux.a

GLUX: GL/GLTypes.h GL/GLUXMath.h GL/GLUX.h GL/GLUXUtil.h \
GL/GLUXMath.cpp GL/GLUX.cpp
$(CC) $(CFLAGS) -g -c $(LIBDIR) $< GL/GLUX.cpp GL/GLUXMath.cpp

clean:
rm -rf *.o *.a BHM3DSample

depend:
$(CC) -E -MM *.c* > .depend


The results: On my computer, the X11 version takes a few seconds to start (busy loading X11) and averages 60 fps, while the native version starts instantly and averages 333 fps. I am not sure if this is a design/implementation characteristic of X11 for Mac, as 60 fps is a little too "perfect" of an arbitrary limit.
Posted on 2011-07-09 23:56:17 by SpooK
Ah, yes, I see the problem... Yea, the makefile would pull in the X11 libraries automatically. Which *can* work on OS X, but apparently they have their own framework with its own GLUT, which works better.
As you can see, the swap interval stuff is a mess. OpenGL never introduced a proper standardized vsync control, so I tried to wrap the different versions into a single function. It's not a catch-all. If it runs 60 fps, it probably couldn't disable vsync. I have the same problem with my FreeBSD system and its Intel IGP, it runs exactly 60 fps, which I think is vsync.
(And as you can see, Microsoft supplies a wgl function which DOES work, nice of them, why can't others follow suit?)

By the way, 333 fps? What kind of machine spec is that?
My system runs at about 4500 fps in Windows. Core2 Duo 3 GHz with a GeForce GTX460.
Posted on 2011-07-10 03:40:49 by Scali

By the way, 333 fps? What kind of machine spec is that?


Core2 Duo 2.8GHz. ATI Radeon 2600HD.
Posted on 2011-07-10 05:27:53 by SpooK


By the way, 333 fps? What kind of machine spec is that?


Core2 Duo 2.8GHz. ATI Radeon 2600HD.


Hum okay... still a tad slow, I guess... The D3D9 version did ~360 fps on an Intel Q35 IGP. But I don't think we can expect 4000+ fps from a 2600HD even under the best of circumstances. I think it would still do 1000+ fps under Windows though.
Posted on 2011-07-10 07:47:22 by Scali

My system runs at about 4500 fps in Windows. Core2 Duo 3 GHz with a GeForce GTX460.


OK... time to break out the test piggy...

Test Box Specs:

  • Dual Core Xeon @ 3GHz

  • 8GB DDR3 1066MHz RAM

  • GeForce GTX 460 w/ 2GB RAM


Results:

  • Windows 7 Home Premium 64-bit using 32-bit Example: ~6150 FPS

  • Windows 7 Home Premium 64-bit using 64-bit Example: ~6400 FPS

  • Mac OS X 10.6.8 under X11/64-bit: ~3000 FPS

  • Mac OS X 10.6.8 Native/64-bit: ~5400 FPS


Both operating systems are kept clean and light, and even with Windows running under Bootcamp (in which shouldn't be a concern as it is mostly BIOS emulation) it does slightly outperform OS X on this setup.
Posted on 2011-07-10 20:57:06 by SpooK


My system runs at about 4500 fps in Windows. Core2 Duo 3 GHz with a GeForce GTX460.


OK... time to break out the test piggy...

Test Box Specs:

  • Dual Core Xeon @ 3GHz

  • 8GB DDR3 1066MHz RAM

  • GeForce GTX 460 w/ 2GB RAM


Results:

  • Windows 7 Home Premium 64-bit using 32-bit Example: ~6150 FPS

  • Windows 7 Home Premium 64-bit using 64-bit Example: ~6400 FPS

  • Mac OS X 10.6.8 under X11/64-bit: ~3000 FPS

  • Mac OS X 10.6.8 Native/64-bit: ~5400 FPS


Both operating systems are kept clean and light, and even with Windows running under Bootcamp (in which shouldn't be a concern as it is mostly BIOS emulation) it does slightly outperform OS X on this setup.


That looks a whole lot better. I think it makes quite a bit of difference that this is an nVidia card. nVidia's drivers for OpenGL have always been more mature, especially on alternative OSes. My Radeon 5770 was fine in Windows, but dramatic in linux, and not even supported at all in FreeBSD (and still isn't).
Interesting to see that the native version is so much faster than X11 by the way.

Mind you, Win7 is not the ideal OS for OpenGL. I tested it in XP and XP x64 yesterday, and it went over 10000 fps.
And to think that DX9 is even faster than that.
Not that it really matters... Once you get to more realistic scenes, the difference will be negligible.
Posted on 2011-07-11 02:57:11 by Scali
That's why it's irrelevant to count in fps instead of milliseconds here, the nonlinearity, the big numbers, the OS and app logic overhead, etc, cant be bothered to look for good articles describing this :)

FPS can have its use, but more in the 2-120 range I'd say, and still it's important to keep nonlinearity in mind.

I cant understand why theres no little moving graph showing the duration of the last few hundred frames in each and every modern graphic developer framework instead of an fps counter, this would be orders of magnitude superior. Imho with complex modern engines another big problem is hidden : heterogenous distribution of frame duration, with microstutters, lag, occasional long frames due to different parts of the engine running at different fps, caching, asynchronic things, multithread, data streaming and all those things that take us farther everyday from a beautiful realtime clockwork-like machine. Find me a modern game that has rock-solid frame rate and as little lag when you shake the mouse like crazy, as quake 3 on  an Athlon 1000 with ps2 mouse and fixed pipe GF2MX on a CRT. (just trolling...am i? :) )
(and I know that the system I described is already incredibly non-deterministic, and that every frame is bound to be dependant on what is displayed. But it was, well. Shockingly fast. It also had windows Me :) )
Posted on 2011-07-11 22:50:40 by HeLLoWorld

That's why it's irrelevant to count in fps instead of milliseconds here, the nonlinearity, the big numbers, the OS and app logic overhead, etc, cant be bothered to look for good articles describing this :)

FPS can have its use, but more in the 2-120 range I'd say, and still it's important to keep nonlinearity in mind.


You can easily calc the frame time from fps, so it's no big deal really (Saw the fps-argument before, always thought it was nonsensical. Guess it's another internet hype. You're talking to a guy who's been doing gfx for over 20 years. You develop a natural feel for these things over time).
3000 fps: 1000/3000 = 0.33 ms per frame
5400 fps: 1000/5400 = 0.18 ms per frame
6000 fps: 1000/6000 = 0.16 ms per frame
10000 fps: 1000/10000 = 0.10 ms per frame

Doesn't really change the initial impression you got from fps.
Not sure what your point is about OS/app overhead, since this should show EXACTLY that (the GPU was the same in all cases, so we can assume that the actual render time is constant).
The code is identical for all platforms. Windows XP runs much faster than Windows 7 simply because there's less overhead (probably mostly because it doesn't have Aero).
And on OS X we can clearly see how X11 has a lot of additional overhead compared to native OpenGL as well.

In a way it's amazing to see just how fast a GPU has become these days. This scene has more polygons and more complex rendering than an entire Quake level. Yet the performance is determined more by the OS overhead than by the actual GPU rendering time.
But as I said, when you get into more 'realistic' framerates, these differences won't matter much.
For example, if you want to run at 100 fps, your frame time is 1000/100 = 10 ms. A ~0.3 ms margin between the OSes is negligible... Say you get 10.3 ms frametime instead, that would be 97 fps instead. Not a big deal really.

However, I've seen cases that were far worse. Take for example my Intel X3100 IGP... It gets 360 fps in DX9 if I use software VP. It gets 185 fps in DX9 with hardware vp. It gets 130 fps with OpenGL using vertex/fragment programs, and it gets about 80 fps with GLSL.
These are differences in overhead you're going to notice. Intel's OpenGL implementation is just very spotty, even on Windows.
But the difference between OS X and Windows here is not such a big deal (at least, on an nVidia card), and that's good to know.
Posted on 2011-07-12 04:39:57 by Scali

Native OpenGL for Mac OS X Instructions


On top of the previous instructions, modify BHMFile-0.1a/src/BHM3DSample/GL/GLUX.cpp as follows...


Okay, upon closer inspection it appears that you just use glutGetProcAddress() instead of glXGetProcAddress(), and then the -framework flags in the makefile, rather than regular libs.

This makes three different *GetProcAddress() functions already... so I'm going to introduce a gluxGetProcAddress() that takes care of it.
By the looks of it, the rest of the code is the same as for non-Windows versions (the function prototypes and even the function names are the same).
I wonder though... glutGetProcAddress() is a function introduced by openglut (so it's not in *all* implementations of glut, not the one I use on Windows anyway). It abstracts between wglGetProcAddress() and glXGetProcAddress().... But what exactly does it do on Apple machines? Does it redirect to an Apple-specific version? Or is the glut implementation on Apple written in such a way that it *is* the Apple-specific version, and glXGetProcAddress() is some kind of wrapper?

I'll have to look into the makefile syntax more closely, to see if there is a way to do any kind of conditionals (like #if defined(__APPLE__) ). If that doesn't work, I guess I must make different makefiles for different platforms. Which could theoretically be generated by a shell-script or such, which DOES support conditionals.
Posted on 2011-07-12 07:54:45 by Scali
Okay, my virtual Hackintosh can now run the BHM3DSample:


Given that it runs in software, performance is pretty good I guess.
It is running natively as well. No X11.
In fact, the X11 version compiles, but doesn't work in my VM. It complains about an invalid pixel format. Not sure if I can fix that. Could just be a shortcoming of the virtual videocard/poor driver support in X11.

Now if I could package this as a .app, that'd be pretty neat.
I'd need to include FreeImage... the rest is linked statically I suppose, or preinstalled (I guess OpenGL/GLUT are standard on OS X?).

In fact, could you point me to some handy tools for Mac development/deployment? Something similar to Dependency Walker on Windows perhaps? I'm completely new to the platform...
Posted on 2011-07-12 08:56:53 by Scali

I wonder though... glutGetProcAddress() is a function introduced by openglut (so it's not in *all* implementations of glut, not the one I use on Windows anyway). It abstracts between wglGetProcAddress() and glXGetProcAddress().... But what exactly does it do on Apple machines? Does it redirect to an Apple-specific version? Or is the glut implementation on Apple written in such a way that it *is* the Apple-specific version, and glXGetProcAddress() is some kind of wrapper?


I am not sure exactly, but I'd be willing to bet it is a wrapper for something in tthe System or Application frameworks.
Posted on 2011-07-12 10:47:19 by SpooK

In fact, the X11 version compiles, but doesn't work in my VM. It complains about an invalid pixel format. Not sure if I can fix that. Could just be a shortcoming of the virtual videocard/poor driver support in X11.


It would be interesting to see if it works better within VirtualBox.
Posted on 2011-07-12 10:49:27 by SpooK

Something similar to Dependency Walker on Windows perhaps? I'm completely new to the platform...


In my limited experience, the closest tool to that is otool. There is a GUI equivalent for it on Mac: macdependency.
Posted on 2011-07-12 10:53:20 by SpooK

In fact, could you point me to some handy tools for Mac development/deployment?


Beside the standard XCode SDK on Mac, you can try DarwinX for cross-compilation under a Linux-based host.
Posted on 2011-07-12 11:52:10 by SpooK


I wonder though... glutGetProcAddress() is a function introduced by openglut (so it's not in *all* implementations of glut, not the one I use on Windows anyway). It abstracts between wglGetProcAddress() and glXGetProcAddress().... But what exactly does it do on Apple machines? Does it redirect to an Apple-specific version? Or is the glut implementation on Apple written in such a way that it *is* the Apple-specific version, and glXGetProcAddress() is some kind of wrapper?


I am not sure exactly, but I'd be willing to bet it is a wrapper for something in tthe System or Application frameworks.


Well, I did some digging with MacDependency first... didn't find any imports resembling any *GetProcAddress()...
So I dug a bit deeper. Found that the source code for the Mac version of GLUT is actually available on their website (and is just a slight modification of Mark Kilgard's original GLUT codebase).
Here it is:
http://developer.apple.com/library/mac/#samplecode/glut/Listings/macx_util_m.html

Apparently it is just a lowlevel approach, similar to LoadLibrary()/GetProcAddress() in Windows, wrapped into a form that resembles wglGetProcAddress()/glXGetProcAddress(). This is the internal function, that is called by glutGetProcAddress(), which also still has wgl/glX paths in there.

Well, that works for me. Don't see a need to paste this code directly into my codebase, I can just rely on Apple's GLUT to do that for me. That way I don't have to worry about the code breaking either.

As for VirtualBox... might be better, but I haven't found a pre-installed image for it. The VMWare image is just one that I downloaded as-is. I don't have the installation media... and it might not be that easy to get it working in a non-Apple environment.
Posted on 2011-07-12 12:17:56 by Scali
I've tried to package it as a .app: http://scali.scali.eu.org/BHM3DSample.zip
Not sure if I did the libraries right... the .app works in my VM, but I don't know if it picks the right libs, as I have them installed anyway.

Edit: I think I got it now...
I tested it by just renaming my /opt/local/lib, so that it would only work if it grabbed the libraries from the bundle.
I had to use a Python script called macholib which rewrote the paths for the dylds from absolute /opt/local/lib to app-bundle relative references. It also automatically copied them into the app bundle.
Seems to work.
Posted on 2011-07-12 15:07:41 by Scali

Seems to work.


Works on 10.7/Lion.
Posted on 2011-07-12 15:40:59 by SpooK