34

私はドキュメント ベースのアプリを持っています。各ドキュメントには、Cocoa のみを使用して (かなり連続的な) 描画を行う NSScrollView を備えた 1 つのウィンドウがあります。

図面を呼び出すには、次のコードで概説する CVDisplayLink を使用しています。

- (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);
    }
}

レンダリング コード:

- (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]];
}

これはうまく機能し、アニメーションはバタフライです... 1つの画面で。

1 つのドキュメントをメイン画面から 2 番目のモニターに移動するとすぐに、アニメーションは四角い車輪の車と同じくらい滑らかになります。1 つ (または複数) のドキュメントが 2 番目の画面にある場合、すべてのドキュメントでアニメーションが低下します。メイン画面にドキュメントがなく、セカンダリ画面にドキュメントがない場合、アニメーションも低下します。

複数の種類のモニターと複数の Mac でこれを試しましたが、常にこれらの結果に終わります。これが CVDisplayLink 関連の問題ではないことを確認するために、NSTimer (CVDisplayLink の方が望ましい) を使用してレンダリングを試みましたが、同じ結果が得られました。

私は何を間違っていますか?どんな助けでも大歓迎です。

編集:スレッドベースの描画も使用してみましたが、同じ結果が得られました。

編集:whileスレッドベースの描画 (基本的にはループ) が 1 つの画面のみで非常にうまく機能するという点で、ある程度の進歩を遂げました。(2 番目または 1 番目のいずれか)。

4

2 に答える 2

1

ドキュメントが新しい画面に入るたびに prepareDisplayLink を呼び出してみましたか? 仕事をするかもしれません。windowDidMove 関数からそれを検出できます。

于 2011-10-20T00:08:01.153 に答える
0

フレームを再描画する速度はどれくらいですか? 問題は、カードが一定量のデータしか再描画し続けることができないことです。各アニメーションを互いに独立して再描画していますか? すべてのアニメーションを同時に再描画してみてください。

問題は、ビデオ カードのデバイス ドライバーおよびロジックとの amdirect のやり取りから発生しているようです。幸運を。

于 2011-09-18T20:48:01.880 に答える