WindowsでのDDBのサイズ制限

何かのグラフィックをディスプレイに描画するようなプログラムでは、画面更新時の目障りなチラツキを抑えるために、ダブルバッファリングという手法がよく使われます。メモリ上に用意した仮想画面に、表示したいものを描き込んでいき、描き終わったら実際のディスプレイにまとめてコピーする、という手法ですね。矩形ビットマップデータのコピー(BitBlt)はOSやビデオカードのドライバの次元で用意されている機能なので、すごく速いんです。だからチラツキが生じない。頻繁な画面更新が必要なゲームなどの分野では昔から当たり前に利用されている手法です。

このダブルバッファリングをMFCで行おうとすると、よく出てくるのがCBitmap::CreateCompatibleBitmap()関数を利用するやり方です。書籍やネット上でサンプルが豊富に見つかります。

ところがですよ。

このCreateCompatibleBitmap()で作成できるビットマップ(=仮想画面として用いる)には、サイズの上限があるんです。今日はこれでハマりました。

とあるCWnd派生クラスの描画処理のチューニングをしているのですが、仮想画面がある程度の大きさ以上になると、CreateCompatibleBitmap()がエラーを返してくるんです。MSDNのドキュメントにはWin95/98では16MBが上限、という記述はありましたがNT系は何も書かれていない。いろいろ条件を変えてCreateCompatibleBitmap()を試したり、ヒープを確保してからCreateBitmap()をやってみたりしましたが、やっぱりダメでした。サイズによってはうまく動いたりするので、確実に何かの制限があるのは分かるのですが、どうも制約条件が判然としないのです。結局いろいろ調べてみて、やっとの思いで見つけたのが下記のページ。

とりあえずほーむぺーじ - 役に立たない私的Tips

どうも画面の色数や搭載メモリによっても影響を受けるようです。Windowsで扱えるビットマップデータにはDDBとDIBの2種類あるのですが、ここで問題になっているのはDDBの方です。通常、CWnd派生クラスのデバイスコンテキストをCreateCompatibleBitmap()に渡すと、作成されるのはDDB形式なんです。そのDDBのサイズの制約は、上記ページによるとOSに原因があるような感じです。ともかく、上記ページの存在が非常に助かりました。仮想画面の生成にCreateCompatibleBitmap()を使うのをやめて、CreateDIBSection()でDIB形式のデータとして扱うように修正して、決着。

大きなサイズのビットマップデータはDIBで扱いましょう。が、結論。

この項読みにくいですね。嘘書いてるところもあるかもしれん。