1

Brad Larson は、スクロール ビューがスクロールしているときにフリーズする問題の解決策を提供しました。CADisplayLink

私の OpenGL ES 描画メソッドは a によって呼び出され、CADisplayLinkBrad の手法を試しましたが、うまくいきません。中心的な問題は、私の OpenGL ES ビューが によってホストされておりUIScrollView、UがIScrollViewスクロールするとが起動しなくなるCADisplayLinkことです。

Brad が説明した手法は、CADisplayLinkスクロール中でも (NSRunLoopCommonModesデフォルトの runloop モードの代わりに追加することで) を起動し続けることになっています。忙しすぎる。

問題は、セマフォのトリックによってレンダリング コールバックが何があっても描画されないことです。

最初に、シリアル GCD キューとセマフォを、次のinitWithFrameように (メイン スレッドで) OpenGL ES ビューのメソッドに作成します。

frameRenderingQueue = dispatch_queue_create("com.mycompany.crw", DISPATCH_QUEUE_SERIAL);
frameRenderingSemaphore = dispatch_semaphore_create(1);

表示リンクが作成され、次の場所に追加されNSRunLoopCommonModesます:

CADisplayLink *dl = [[UIScreen mainScreen] displayLinkWithTarget:self selector:@selector(renderFrame)];
[dl addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];

render コールバックは Brad の手法を実行します。

- (void)renderFrame {
    if (dispatch_semaphore_wait(frameRenderingSemaphore, DISPATCH_TIME_NOW) != 0) {
        NSLog(@"return"); // Gets called ALWAYS!
        return;
    }

    dispatch_async(drawingQueue, ^{
        @autoreleasepool {

            // OpenGL ES drawing code

            dispatch_semaphore_signal(frameRenderingSemaphore);
        }
    });
}

関数はdispatch_semaphore_wait常に戻るYESため、render コールバックは決してレンダリングしません。スクロールしていないときでも。

ここで何か重要なことを見逃していたと思います。誰かがそれを指摘できますか?

編集:dispatch_syncの代わりに呼び出す場合にのみ機能するようですdispatch_asyncが、ブラッドによると、dispatch_asyncここでより良いパフォーマンスが得られます。

4

1 に答える 1

0

コードの構造を次のように変更する必要がありました。

- (void)renderFrame {
    dispatch_async(drawingQueue, ^{
        if (dispatch_semaphore_wait(frameRenderingSemaphore, DISPATCH_TIME_NOW) != 0) {
            return;
        }

        @autoreleasepool {
            // Drawing code...
        }

        dispatch_semaphore_signal(frameRenderingSemaphore);
    });
}

このように再構築した後、dispatch_semaphore_wait呼び出しは常に YES を返さなくなりました。これが効果的にブラッドのセマフォ待機トリックを無効にするだけなのかどうかはわかりません。しかし、それは機能します。

于 2012-09-27T18:43:15.743 に答える