所以我有一个用 C 语言编写的老式 GDI 应用程序。它通过直接渲染到屏幕上来重绘,每个像素恰好触摸一次。一切正常。
我现在需要升级它以使用更复杂的渲染系统,我不能保证每个像素都被触摸一次 --- 渲染算法需要黑色背景。但是,如果我直接渲染到屏幕上,我会闪烁。所以我需要双缓冲。
我的问题是,添加双缓冲后,速度非常慢,我不明白为什么。
在 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;
}
(请注意,调用不使用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()
在这里复制太复杂了,但它通过将大量小位图blitting到表面上来工作(它正在渲染文本,每个位图都是一个缓存的字形)。位图按需创建,然后缓存;它们在 WM_SIZE 中被丢弃。位图是使用CreateCompatibleDC()
和CreateCompatibleBitmap()
完全如上创建的。
据我所知,上面的代码完全是香草。这意味着必须有某种我正在做出的假设是无效的。我的推理是:
通过离屏位图渲染很慢,因此在渲染过程中必须进行某种格式转换。
直接渲染速度很快,因此没有。
因此,必须有一些事情
paint_cb()
在做不同的事情,具体取决于它是将 DC 放到屏幕上还是屏幕外位图上。除了没有。
paint_cb()
既不知道也不关心。???
我在这里想念什么?我应该寻找什么?不知何故,我在上面的代码中所做的事情导致paint_cb()
速度降低了大约两个数量级。关于这可能是什么的任何建议?