9 | 1月 | 2014 | HMDT Blog

カテゴリー : 2014年 1月9日

iOS 7でCGBitmapContextに対する描画が変わった?


iOSでは、高速なグラフィックを実現するために、GPUの機能を積極的に利用しています。その恩恵を受けるには、UIViewが作成したCGContextRefに対してCore GraphicsのAPIを使う事が必要になります。ここで行われる描画は、オフスクリーンのビットマップに対するものとだいぶ違ったものになります。

何が違うのか、分かりやすい例として矩形の塗りつぶしを考えてみます。矩形の塗りつぶしは、もしオフスクリーンバッファに対して行うとすれば、一定領域へのメモリのセットになるんですね。たとえば、白で塗りつぶすとしたら、0xffffffでメモリ領域を埋める事になります。

スクリーンが小さいうちはこれで問題ないのですが、最近のiPad Retinaとかだと大変です。スクリーンサイズは、1536×2048。ということはオフスクリーンバッファを作るとすると、1536x2048x4byte = 12MByteということになります。12MBの領域をmemsetするとなると、これ時間かかるんですよ。iPad実機だと、1秒から2秒くらいかかります。これでは高速な描画なんかできませんね。

Core Graphicsには、矩形領域塗りつぶしのための、CGContextFillRectというAPIがあります。これの呼び出しは、時間はかかりません。ということは、このAPIではメモリのセットはやっていないはずです。おそらく、「矩形塗りつぶし」という手続きだけを覚えておいて、画面描画時にOpenGLテクスチャを作成していると予想されます。これなら充分に速くなります。

CGContextは、UIViewが用意するもの、つまりdrawRect:で取得できるものの他に、オフスクリーンバッファ用に作る事もできます。CGBitmapContextっていうものです。これで作ったCGContextは、Core GraphicsのAPIを使えるのですが、パフォーマンスでは大きく見劣りします。実際、CGContextFillRectの呼び出しにえらい時間がかかります。だから、iOSではCGBitmapContext使わないようにしましょうね。

…という話だったんです。iOS 6までは。

それが、iOS 7ではどうも変わったような気がするんです。CGBitmapContextに対するCGContextFillRectの呼び出しが、すごい速くなっているみたいです。もしかして、メモリセットしないようになった?でもそれだと、いろいろと破綻しねぇ?オフスクリーン使っているから、遅くてどうしようもなくて放っておいたコードがあるんですが、iOS 7で動かしたら速くなっていてビックリしているところです。いま、検証しようとしています。