だから私は C で書かれた昔ながらの GDI アプリを持っています。それは画面に直接レンダリングして再描画し、各ピクセルを 1 回だけタッチします。すべて正常に動作します。
より複雑なレンダリング システムを使用するようにアップグレードする必要があります。このシステムでは、各ピクセルが 1 回タッチされることを保証できません。レンダリング アルゴリズムには黒の背景が必要です。ただし、画面に直接レンダリングすると、ちらつきが発生します。だから私はダブルバッファする必要があります。
私の問題は、ダブルバッファリングを追加した後、非常に遅くなり、その理由がわかりません。
WM_SIZE で、オフスクリーン サーフェスを作成します。
case WM_SIZE:
{
RECT rect;
GetClientRect(window, &rect);
HDC dc = GetDC(window);
/* omitting freeing cachedc and cachebitmap for brevity */
cachedc = CreateCompatibleDC(dc);
cachebitmap = CreateCompatibleBitmap(dc, rect.right, rect.bottom);
SelectObject(cachedc, cachebitmap);
ReleaseDC(window, dc);
break;
}
( への呼び出しはnotをCreateCompatibleBitmap()
使用することに注意してください。私はその落とし穴について知っています。)dc
cachedc
次に、WM_PAINT で描画を行います。
case WM_ERASEBKGND:
return 1;
case WM_PAINT:
{
PAINTSTRUCT ps;
BeginPaint(window, &ps);
FillRect(cachedc, &ps.rcPaint, GetStockObject(BLACK_BRUSH));
paint_cb(window, &ps, cachedc);
BitBlt(ps.hdc,
ps.rcPaint.left, ps.rcPaint.top,
ps.rcPaint.right, ps.rcPaint.bottom,
cachedc,
ps.rcPaint.left, ps.rcPaint.top,
SRCCOPY);
EndPaint(window, &ps);
break;
}
それがスローコードです。ただし、WM_PAINT を変更してこれを行うと、すばやく実行されます (ちらつきはありますが)。
case WM_PAINT:
{
PAINTSTRUCT ps;
BeginPaint(window, &ps);
FillRect(ps.hdc, &ps.rcPaint, GetStockObject(BLACK_BRUSH));
paint_cb(window, &ps, ps.hdc);
EndPaint(window, &ps);
break;
}
paint_cb()
ここで再現するには複雑すぎますが、多くの小さなビットマップを表面にブリットすることで機能します (テキストをレンダリングし、各ビットマップはキャッシュされたグリフです)。ビットマップはオンデマンドで作成され、キャッシュされます。それらは WM_SIZE で破棄されます。CreateCompatibleDC()
ビットマップは、上記とCreateCompatibleBitmap()
まったく同じようにandを使用して作成されます。
私の知る限り、上記のコードは完全にバニラです。これは、私が行っている、有効ではないある種の仮定があるに違いないことを意味します。私の推論は次のとおりです。
オフスクリーン ビットマップによるレンダリングは遅いため、レンダリング プロセス中に何らかの形式変換が行われている必要があります。
直接レンダリングは高速であるため、そうではありません。
したがって
paint_cb()
、DC を画面に送るか、画面外のビットマップに送るかによって、何かが異なる動作をしているに違いありません。ないことを除いて。
paint_cb()
知らないし気にもしない。???
ここで何が欠けていますか?何を探すべきですか?どういうわけか、上記のコードで私が行っていることは、paint_cb()
約 2 桁の速度低下を引き起こしています。これが何であるかについて何か提案はありますか?