how to use opengl on Mac, hardware acceleration

48 views
Skip to first unread message

Ondrej Certik

unread,
Jun 29, 2009, 11:51:26 PM6/29/09
to sage-...@googlegroups.com, hpfem
Hi,

we have some nice opengl visualisation, that only works on linux, but
I would like to make it work with Sage and on all platforms.

So I first thought I would rewrite it in pyglet, that works everywhere
(I tested a prototype already and it indeed works). However, pyglet is
not easy to fix for offscreen rendering, which is one of my
requirements, so that it can run on the notebook server.

Mesa is an implementation of opengl, here is a spkg package:
http://femhub.googlecode.com/files/mesa-7.4.4.p3.spkg, it builds
without any problems on all platforms (32bit, 64bit, linux, Mac). So I
just wrapped a few mesa commands here:

http://github.com/certik/osmesa

and made it work with offscreen rendering, and it just works, both on
linux and Mac (in Sage) in produces "a.pnm" with an image rendered
using opengl. So I am positive that I can get the job done using this
approach. I have to ditch pyglet, but that's life (if it doesn't work
offscreen, then it's useless).

So why I am asking here. :) I am baffled why pyglet uses this library
on Mac: "AGL_H =
'/System/Library/Frameworks/AGL.framework/Headers/agl.h'. Is it
because this library is on Mac by default, so pyglet tries to use it,
so that users don't have to install anything? However, if I install
mesa (which I do anyways), then I don't need it?

Or could it be that if I install mesa on Mac, I never get hardware
acceleration, while if I use agl, I get it?

If I install mesa on linux, do I get hardware acceleration? Do I need
to enable it somehow? It works fast enough on my laptop, but I don't
know if it's software rendering or hardware one.

Many thanks for any feedback,
Ondrej

Jakub Cerveny

unread,
Jun 30, 2009, 5:43:46 AM6/30/09
to hp...@googlegroups.com
> http://github.com/certik/osmesa
>
> and made it work with offscreen rendering, and it just works, both on
> linux and Mac (in Sage) in produces "a.pnm" with an image rendered
> using opengl. So I am positive that I can get the job done using this
> approach.

That's nice.

Instead of writing PNM images you may want to use PNG which is better.
However, libpng is quite complex so I am attaching a simple example I
found a while ago on reading and writing PNG.

> Or could it be that if I install mesa on Mac, I never get hardware
> acceleration, while if I use agl, I get it?

I am not really sure how this works, but here is my theory: normally
Mesa serves as an OpenGL interface to the hardware drivers, like
fglrx, nvidia, intel. The hardware drivers handle all the
acceleration. If I understand it correctly, OSMesa is a software
renderer which replaces the hardware driver when used. No graphics
card, its driver and the X server are probably needed at all.

I think using the software renderer is actually not a problem, since
it circumvents the buggy hardware drivers and it should produce more
accurate and stable results (I read somewhere that it is used as a
reference renderer to validate the HW drivers). The performance is not
a big deal because (1) you typically only want to render a single
image, (2) our datasets are small and (3) our visualization is simple
and we use things like lines and 1D textures which have to be emulated
in software in some HW drivers anyway.

Jakub

libpng-short-example.c

Ondrej Certik

unread,
Jun 30, 2009, 12:28:33 PM6/30/09
to hp...@googlegroups.com, Brian Granger
On Tue, Jun 30, 2009 at 3:43 AM, Jakub Cerveny<jakub....@gmail.com> wrote:
>> http://github.com/certik/osmesa
>>
>> and made it work with offscreen rendering, and it just works, both on
>> linux and Mac (in Sage) in produces "a.pnm" with an image rendered
>> using opengl. So I am positive that I can get the job done using this
>> approach.
>
> That's nice.
>
> Instead of writing PNM images you may want to use PNG which is better.
> However, libpng is quite complex so I am attaching a simple example I
> found a while ago on reading and writing PNG.

Thanks. I used a similar code long time ago, so I know it's a bit
tricky to get it done.

But this time I will just use Python, where it's a matter of something like:

from PIL.Image import Image
image = Image.fromstring(mode,shape,data32) # you just tell it the
format of the buffer and the opengl buffer itself
a.save("a.png")

that's what I like about python, that once you have the data in (any!)
raw format, it's just a matter of two lines to convert it to anything
I need.

>
>> Or could it be that if I install mesa on Mac, I never get hardware
>> acceleration, while if I use agl, I get it?
>
> I am not really sure how this works, but here is my theory: normally
> Mesa serves as an OpenGL interface to the hardware drivers, like
> fglrx, nvidia, intel. The hardware drivers handle all the
> acceleration. If I understand it correctly, OSMesa is a software
> renderer which replaces the hardware driver when used. No graphics
> card, its driver and the X server are probably needed at all.


Right, I know that during the configuration of mesa, I can tell it
which driver to use, either osmesa (that's what I chose), or DRI
(which imho uses the kernel to access the device drivers like flgrx,
nvidia or intel).

But I think there is one more piece of the puzzle --- mesa itself is
just the low level opengl commands (and for offscreen rendering it's
actually all I need). To actually use it for onscreen rendering, I
need to create some windows to draw the context on. And here is were
glut comes in (or pyglet, that is a python library, that doesn't use
glut, but uses X11 serivces itself to create the window etc).

And on Mac, the AGL actually provides both low level opengl commands
and highlevel interface to the windowing api, so that one can use it
to plot on Mac windows. That's how I understand it so far.

I think opengl itself works nice, but I suspect the glut we use in
hermes is somehow buggy, because pyglet uses the same
/usr/lib/libGL.so libraries just like hermes, but it works on Pavel's
laptop, where hermes itself doesn't.

However, look here:

http://www.mesa3d.org/

and click on download:

http://sourceforge.net/project/showfiles.php?group_id=3

as you can see, mesa provides glut, which is very recent. Is this the
glut we use in hermes (e.g. if you compile on Ubuntu)?

>
> I think using the software renderer is actually not a problem, since
> it circumvents the buggy hardware drivers and it should produce more
> accurate and stable results (I read somewhere that it is used as a
> reference renderer to validate the HW drivers). The performance is not
> a big deal because (1) you typically only want to render a single
> image, (2) our datasets are small and (3) our visualization is simple
> and we use things like lines and 1D textures which have to be emulated
> in software in some HW drivers anyway.

Exactly, it's easy to install (in femhub we already have it and it
works), and it's fast enough and it's easy to get working offscreen.

I am now working on showing hp adaptivity examples in the browser,
e.g. getting it done using offscreen rendering. Originally I thought I
will just use mayavi for everything, but I must say then now, when I
dug into the hermes2d plotting much more, I must say I like it, for
its simplicity and speed. It turns out that opengl is really easy to
use for plotting 2D data. For 3D data, I think mayavi is the only sane
way (or similar packages, like paraview, visit, ...).

However, I don't like that the plotting it is tied to hermes too much.
I'll try to decouple it to a standalone library and write a python
interface to it and make it work offscreen.I found out, that we use
something very similar in sympy --- we use pyglet, but it's basically
just opengl wrapper, and long time I wanted to decouple it from sympy
and port it to matplotlib.

So I'll try to join sympy plotting with hermes2d plotting and try to
make a nice and simple library, that will also work offscreen and that
works on linux, Mac, etc. using mesa. I know that the matplotlib guys
could maybe take it as one of their backends, the last time I talked
about this. Unfortunately, I didn't manage to get pyglet working
offscreen, so I just wrote my own python wrappers to opengl, it's
actually really simple. The following script:

------
#! /usr/bin/env python

from pyparsing import (Word, Combine, Optional, alphas, alphanums, oneOf,
delimitedList, Group)

header = "/usr/include/GL/gl.h"
testdata = open(header).read()

functions_skip = [
"glCreateDebugObjectMESA",
"glBlendEquationSeparateATI",
]

ident = Word(alphas, alphanums + "_")
vartype = (Optional("const") + Combine(ident + Optional(Word("*")),
adjacent = False))
arglist = delimitedList( Group(vartype.setResultsName("type") + \
ident.setResultsName("name")) )
functionCall = ident.setResultsName("name") + \
"(" + (arglist.setResultsName("args") | "void") + ")" + ";"
typedef = "typedef" + Optional("unsigned") + Optional("signed") + \
ident + ident + ";"

known_types = []
print """cdef extern from "%s":""" % (header)
for fn, s, e in typedef.scanString(testdata):
print " ctypedef", " ".join(fn[1:-1])
known_types.append(fn[-2])
print
py_functions = []
for fn, s, e in functionCall.scanString(testdata):
skip = False
if fn.name in functions_skip:
skip = True
func = 'void c_%s "%s"(' % (fn.name, fn.name)
pyfunc = "def %s(" % fn.name
pyfunc_args = ""
for a in fn.args:
a_type = a.type[-1]
if a_type[-1] == "*":
# skip pointers for now
skip = True
if a_type[-1] == "*":
a_type = a_type[:-1]
if a_type[-1] == "*":
a_type = a_type[:-1]
if not a_type in known_types:
skip = True
func += "%s %s, " % (a.type[-1], a.name)
pyfunc_args += "%s, " % (a.name)
if len(fn.args) > 0:
func = func[:-2]
pyfunc_args = pyfunc_args[:-2]
func += ")"
pyfunc += pyfunc_args+"):\n"
pyfunc += " c_%s(%s)\n" % (fn.name, pyfunc_args)
if skip:
func = "# " + func
func = " " + func
print func
if not skip:
py_functions.append(pyfunc)
print
for pyfunc in py_functions:
print pyfunc
--------------


Takes /usr/include/GL/gl.h and writes a cython file that interfaces
it. It's couple hundreds (maybe thousands) of functions, so I am glad
this simple script can do the work for me. Then I just compile it with
cython and I have a library, that works in Python and I can access all
opengl commands. There are still some small things, like I don't yet
wrap functions that have pointers in the arguments (not many
fortunately) and I didn't yet port the opengl constants.

For offscreen rendering, this already works for me. For onscreen
rendering, I plan to use pyglet to create the windows, because this
seems to be working everywhere.

I am CCing Brian, because he is a Mac user and also a Python user, so
he can give me some feedback if the above plan is the way to go, or
not.

Ondrej

Reply all
Reply to author
Forward
0 new messages