NSView
高フレームレートで繰り返し変化するカスタムQuartz2D描画を示す大きな画像があります。ただし、フレームごとに描画の一部のみが変わる場合があります。これまでの私のアプローチは、まずオフスクリーン ビットマップ コンテキストに描画し、次にそのコンテキストから画像を作成し、最後にビューの CoreAnimation レイヤーのコンテンツをその画像で更新することです。
私の最初の質問は、そのアプローチが一般的に理にかなっているのか、それがパフォーマンスに関しては正しいのかということです。
オフスクリーン ビットマップ コンテキストへの描画は十分に高速に動作し、ダーティ エリアのみを再描画するように最適化されています。したがって、そのステップの後、画面に表示する必要があるオフスクリーンバッファー内の領域をマークする一連の長方形があります。今のところ、オフスクリーンのビットマップ コンテキストから作成された画像で CoreAnimation レイヤーのコンテンツを更新するだけです。これは基本的にはうまくいきますが、ちらつきます。すべて)まだ描かれていません。CATransaction lock/unlock/begin/end/flush
、NSView lockFocus/unlockFocus
で遊んでみましNSDisableScreenUpdates/NSEnableScreenUpdates
たが、ちらつきを回避する方法がまだ見つからなかったので、同期を正しく行うための実際の正しいシーケンスは何だろうと思っていましたか?
以下は初期化コードのスケッチです。
NSView* theView = ...
CALayer* layer = [[CALayer new] autorelease];
layer.actions = [NSDictionary dictionaryWithObject:[NSNull null] forKey:@"contents"];
[theView setLayer: layer];
[theView setWantsLayer: YES];
// bitmapContext gets re-created when the view size increases.
CGContextRef bitmapContext = CGBitmapContextCreate(...);
そして、ここに描画コードのスケッチがあります:
CGRect[] dirtyRegions = ...
NSDisableScreenUpdates();
[CATransaction begin];
[CATransaction setDisableActions: YES];
// draw into dirty regions of bitmapContext
// ...
// create image from bitmap context
void* buffer = CGBitmapContextGetData(bitmapContext);
CGDataProviderRef provider = CGDataProviderCreateWithData(NULL, buffer, ...);
CGImageRef image = CGImageCreate(..., provider, ...);
// update layer contents, dirty regions are ignored
layer.contents = image;
[CATransaction commit];
NSEnableScreenUpdates();
汚い地域の知識も活かしたいです。このアプローチを使用して、画面上の汚れた領域のみを更新する方法はありますか?
ご協力いただきありがとうございます!
更新:ちらつきの原因となる問題を見つけたと思います。を使用して、ビットマップ コンテキストからピクセル バッファーを使用してイメージを作成しますCGImageCreate(...)
。CGBitmapContextCreateImage(...)
代わりに使用すると機能します。CGBitmapContextCreateImage
書き込み時にコピーするので、ビットマップコンテキストが再度更新されたときにピクセルを書き込みます。正しく理解できれば、以前は機能しなかった理由が説明されます。パフォーマンスに影響を与える可能性のあるカーネルへの呼び出しを行うため、慎重に使用する必要がある場所を読んだCGBitmapContextCreateImage
ので、ダーティ領域を考慮して、関連するピクセルを新しい画像バッファーにコピーするだけだと思います。これは理にかなっていますか?