2

I am building an Cocoa/OpenGL app, for periods of about 2 second at a time, I need to control every video frame as well as writing to a digital IO device. If after I make the openGL calls I let go of the main thread (like if I make the openGL calls inside a timer fire-method with an interval of like 0.01 Sec) openGLview is refreshed with every call to glFinish().
But If I instead keep the main thread busy like in a 2 second long while loop, openGl calls won't work (surprisingly the first call to glFinish() would work but the rest won't). The documentation says that glFinish should block the thread until the gl commands are executed. Can anybody please help me understand what is going on here or provide a solution to this problem. To make it clear, I want to present 200 frames one after another without missing a frame and marking each frame refresh by writing to a digital IO port (I don't have a problem with this) all on Snow Leopard.

Ali
  • 18,665
  • 21
  • 103
  • 138

1 Answers1

4

This is not quite my department - pretty vanilla NSOpenGLView user myself - but from the Mac OpenGL docs it looks like you might want to use a CVDisplayLink (Q&A1385) for this. Even if that won't do it, the other stuff there should probably help.

EDIT

I've only done some basic testing on this, but it looks like you can do what you want as long as you first set the correct OpenGL context and then swap buffers after each frame (assuming you're using a double buffered context):

// inside an NSOpenGLView subclass, somewhere outside the usual drawing loop
- (void) drawMultipleFrames
{
    // it might be advisable to also do a [self lockFocus] here,
    // although it seems to work without that in my simple tests

    [[self openGLContext] makeCurrentContext];

    // ... set up common OpenGL state ...

    for ( i = 0; i < LOTS_OF_FRAMES; ++i )
    {
        // ... draw your frame ...

        glFinish();
        glSwapAPPLE();
    }

    // unlockFocus here if locked earlier
}

I previously tried using [[self openGLContext] flushBuffer] at the end of each frame instead -- that doesn't need glSwapAPPLE but doesn't block like glFinish so you might get frames trampling over one another. This seems to work OK with other apps, runs in the background etc, but of course YMMV.

walkytalky
  • 9,453
  • 2
  • 36
  • 44
  • thanks, that help me understand some other issues I am dealing with. But here I want to avoid an event based solution if possible (setting the needsDisplay to YES or things of that nature does not tell me when "EXACTLY" a frame is being displayed). – Ali Jun 21 '11 at 01:05
  • @Ali Well, looks like that can work too -- see edit. That's enough procrastination, anyway. Back to the grindstone! – walkytalky Jun 21 '11 at 10:58
  • You saved me! Actually I didn't know about these APPLE gl functions! I replaced all my `glFinish` and `glFlush` with `glFlushRenderAPPLE` and `glFinishRenderAPPLE` and added a glSwapAPPLE at the end and it works like a charm! Thanks man. – Ali Jun 22 '11 at 11:36