4

As the title says really. I'd like to turn on vertical sync in PyOpenGL, but how can I do it? A fairly exhaustive web search didn't turn up anything, but maybe someone has a clever solution? I'm on OS X and I don't mind which package is used to create the window and the application loop. However, I'd rather stay away from developing a full-blown Cocoa app, for reasons discussed below.

I looked into using pyglet rather than PyOpenGL, but the only version of pyglet that runs on a 64 bit OS is an alpha release that's nearly a year old, so I don't want to use it because I'm afraid it might be abandonware. That's a shame because it actually looked much better than PyOpenGL.

On this page I found the following code. The page says it's for pygame, but it looks like it should work for Glut as well. However, when I run it (after creating a context) it just causes a segmentation fault. If anyone can give any insight into why that happens it would be great, because something like this is what I'm looking for.

import sys

def enable_vsync():
    if sys.platform != 'darwin':
        return
    try:
        import ctypes
        import ctypes.util
        ogl = ctypes.cdll.LoadLibrary(ctypes.util.find_library("OpenGL"))
        # set v to 1 to enable vsync, 0 to disable vsync
        v = ctypes.c_int(1)
        ogl.CGLSetParameter(ogl.CGLGetCurrentContext(), ctypes.c_int(222), ctypes.pointer(v))
    except:
        print "Unable to set vsync mode, using driver defaults"

I could try pygame instead and see if this code works with that, but I found a few reports online that this code crashes with pygame as well, so I'm guessing it's something that used to work but now doesn't.

Finally, I'm aware that a solution that will work is to build a Cocoa app with PyObjC. However, there's a pretty big learning curve there, and I would end up with something that's not even close to cross-platform. This code is only for my own personal use, but I'm very concerned with maximising my probability of getting it working again if I come back to it in several years' time on a different machine. For those reasons I really don't think building a Cocoa app is something I want to get into.

N. Virgo
  • 7,970
  • 11
  • 44
  • 65
  • It appears that using any CGL method through ctypes, other than `CGLGetCurrentContext`, causes a segmentation fault. – N. Virgo Jun 14 '13 at 08:55

4 Answers4

4

I managed to fix your segmentation fault. Here is the working code to enable vsync on a mac: -

import sys

def enable_vsync():
    if sys.platform != 'darwin':
        return
    try:
        import ctypes
        import ctypes.util
        ogl = ctypes.cdll.LoadLibrary(ctypes.util.find_library("OpenGL"))
        v = ctypes.c_int(1)

        ogl.CGLGetCurrentContext.argtypes = []
        ogl.CGLGetCurrentContext.restype = ctypes.c_void_p

        ogl.CGLSetParameter.argtypes = [ctypes.c_void_p, ctypes.c_int, ctypes.c_void_p]
        ogl.CGLSetParameter.restype = ctypes.c_int

        context = ogl.CGLGetCurrentContext()

        ogl.CGLSetParameter(context, 222, ctypes.pointer(v))
    except Exception as e:
        print("Unable to set vsync mode, using driver defaults: {}".format(e))

Just call this enable_vsync() function after creating and setting the context.

Stephen Briney
  • 867
  • 5
  • 8
2

In pygame's version 2.0.0, there is a new option called vsync added in pygame.display.set_mode(...)

It's usage should be something like:-

pygame.display.set_mode(screen_size,DOUBLEBUF|OPENGL,vsync=1)

If you don't want vsync, then write vsync=0

However, it is not working for me yet, on the official pygame website, it is written that it is experimental and may change in the future. If if works for me, I will edit this answer.

You can take a look at the website from here if you can't find it :-

https://www.pygame.org/docs/ref/display.html#pygame.display.set_mode

Mudit Bhatia
  • 91
  • 1
  • 4
0

I've solved this by using pyglet for now. Although no code has been checked in for a long time there still seems to be an active community, in which the main developer participates. It's cross-platform and it was very easy to get going. I just use pyglet to manage the windows, and I'm using PyOpenGL for the OpenGL stuff. Later I can use pyglet's faster but lower-level OpenGL bindings if I need to, and I can take advantage of the various extra features that pyglet offers.

However, the situation feels a bit precarious, because there's no official release that works on OS X Mountain Lion (I installed from the latest source), and I'm afraid that my code might just stop working after one or two more major OS X upgrades. So if anyone has a solution that works without using pyglet I would still really appreciate it.

N. Virgo
  • 7,970
  • 11
  • 44
  • 65
0

Try using WinDLL for loading the OpenGL DLL and replacing CGL with GL or gl(whichever works)in the name of the functions. For example: ogl = ctypes.windll.LoadLibrary(ctypes.util.find_library("OpenGL")) Then your functions: [GL,gl(recommended)]GetCurrentContext()

Uchiha Madara
  • 101
  • 1
  • 5