34

I have a document-based app, where each document has one window with an NSScrollView that does some (fairly continuous) drawing using only Cocoa.

To call the drawing, I am using a CVDisplayLink, outlined in the code below:

- (void)windowControllerDidLoadNib:(NSWindowController *) aController {
     //other stuff...
     [self prepareDisplayLink]; //For some reason putting this in awakeFromNib crashes
}

//Prep the display link.
- (void)prepareDisplayLink {
    CVDisplayLinkCreateWithActiveCGDisplays(&displayLink);
    CVDisplayLinkSetCurrentCGDisplay(displayLink, ((CGDirectDisplayID)[[[[[self windowForSheet]screen]deviceDescription]objectForKey:@"NSScreenNumber"]intValue]));
    CVDisplayLinkSetOutputCallback(displayLink, &MyDisplayLinkCallback, self);
}

//Callback to draw frame
static CVReturn MyDisplayLinkCallback(CVDisplayLinkRef displayLink, const CVTimeStamp* now, const CVTimeStamp* outputTime, CVOptionFlags flagsIn, CVOptionFlags* flagsOut, void* displayLinkContext)
{
    NSAutoreleasePool *pool =[[NSAutoreleasePool alloc]init];
    CVReturn result = [(ScrollView*)displayLinkContext getFrameForTime:outputTime];
    [pool drain];
    return result;
}

//Drawing function:
- (CVReturn)getFrameForTime:(const CVTimeStamp*)outputTime
{
    [scrollView lockFocusIfCanDraw];
    [self addToCurrentPostion:(dist/time)*CVDisplayLinkGetActualOutputVideoRefreshPeriod(displayLink)]; //Redraws the scrollview];
    [scrollView unlockFocus];
    return kCVReturnSuccess;

}

//Set the display when the window moves:
- (void)windowDidMove:(NSNotification *)notification {
     if ([notification object] == [self windowForSheet]) {
         CVDisplayLinkSetCurrentCGDisplay(displayLink, ((CGDirectDisplayID)[[[[[self windowForSheet]screen]deviceDescription]objectForKey:@"NSScreenNumber"]intValue]));
     }
}

//Start or stop the animation:
- (IBAction)toggleAnim:(id)sender {
     if (CVDisplayLinkIsRunning(displayLink)) {
        CVDisplayLinkStop(displayLink);
    }
    else {
        CVDisplayLinkStart(displayLink);
    }
}

Rendering Code:

- (void)addToCurrentPostion:(float)amnt {
    fCurrentPosition += amnt; //fCurrentPositon is a float ivar
    if (scrollView) [[scrollView contentView]scrollToPoint:NSMakePoint(0,(int)fCurrentPosition)];
    if (scrollView) [scrollView reflectScrolledClipView:[scrollView contentView]];
}

This works great, and the animation is buttery.....on one screen.

As soon as I move one document off the main screen, onto a second monitor, the animation becomes about as smooth as a car with square wheels. The animation becomes poor in all documents when any one (or more) documents are on the second screen. There can be no documents on the main screen and any on the secondary screen and the animation will degrade also.

I've tried this on multiple types of monitors, and multiple Macs, always ending in these results. To make sure this was not a CVDisplayLink related issue, I also tried rendering using an NSTimer (which the CVDisplayLink is preferable to), with the same results.

What am I doing wrong? Any help is greatly appreciated.

EDIT: I have tried using thread-based drawing too, again with the same results.

EDIT: I've made some progress, in that my thread-based drawing (basically a while loop) works very well on only one screen. (Either the second or first).

spudwaffle
  • 2,905
  • 1
  • 22
  • 29
  • What GPUs and versions of OS X have you tested with? Since you get the same issue when you NSTimer-based refreshes, the problem is more likely in the rendering code you didn't post. – user57368 May 17 '11 at 02:04
  • I have tested on NVIDIA GeForce 9400M, NVIDIA GeForce 9600M GT, and NVIDIA GeForce 320M all with OS X 10.6.7. I edited in the rendering code. – spudwaffle May 17 '11 at 04:02
  • used to see this all the time in old non-linear video editors, where you could only view video playback in the primary monitor, sometimes you could scrub in the secondary monitor, sometimes not. One thing you could try is see what happens if the application opens the window on the second monitor... it is probable that when you move to the second GPU you can't bring your whole context with your view, and are forced into software rendering. – Grady Player Jul 06 '11 at 19:38
  • Second GPU? This happens also on computers with 1 graphics card. Also, see edits. – spudwaffle Jul 06 '11 at 23:16
  • Could you make a minimal example project that exhibits the problem, and post a link to the source? – Orangenhain Oct 09 '11 at 09:15
  • I share with you a similar o problem. But what I realized is that the machine I was using (a Mac Pro) was bugging my animation since the animation worked perfectly on 2 other mac minis with lower configs. Sadly, I don't know what is the real cause of the problem. – Leandro Oct 11 '11 at 18:35
  • @Orangenhain I'll whip up a sample as soon as I can. – spudwaffle Oct 11 '11 at 22:59
  • I have this problem too. I was doing openGL animation, and refreshed by calling `setNeedsDisplay:true` on the `NSOpenGLViews`. When I replaced that with `display`, the animation is much smoother. – Fatso Feb 14 '12 at 09:49
  • @Korion That makes sense. Perhaps there it is something to do with the delay after `setNeedsDisplay:`. I'll check out using `display`. – spudwaffle Feb 16 '12 at 02:10
  • I wanted to ask this to Apple but I don't have any technical support sessions left and it's a bit too expensive to buy new ones. – Fatso Feb 16 '12 at 08:02
  • isn't it more expensive if you are wasting weeks of work getting stuck? – mskw Mar 17 '13 at 03:35

2 Answers2

1

Have you tried calling prepareDisplayLink everytime the document enters a new screen? Might do the job. You can detect that from windowDidMove function.

namar0x0309
  • 2,239
  • 1
  • 15
  • 15
0

How fast are you re-drawing the frames? The problem seems to be that the card can only keep re-drawing a certain amount of data. Are you re-drawing each animation independent from each other? Try re-drawing all the animations at the same time.

Problem seems to come from amdirect interaction with the device driver of the video card and with your logic. Good luck.

Brad Werth
  • 17,411
  • 10
  • 63
  • 88
El Developer
  • 3,345
  • 1
  • 21
  • 40