【发布时间】:2011-11-22 02:06:47
【问题描述】:
从我读到的here 看来,大多数Windows GDI 功能都得到了加速。因此,例如调用BitBlt 或AlphaBlend 会使用硬件加速(如果可用)。它还提到窗口的内容仅保存在视频内存中。现在,对于 window DC 来说这一切都很好,但我如何才能使用驻留在显卡内存中的 memory DC?一旦我们完成了如何获得对像素的直接访问,我认为这将涉及 1. 将数据临时复制到系统内存 2. 更改像素数据 3. 复制回视频内存。
我尝试了两种方法,都可以在任务管理器中看到分配系统内存...
-
创建兼容位图
HDC hDC = GetDC(NULL); m_hDC = CreateCompatibleDC(hDC); m_hBmp = CreateCompatibleBitmap(hDC, cx, cy); ReleaseDC(NULL, hDC); m_hOldBmp = (HBITMAP)SelectObject(m_hDC, m_hBmp);然后调用获取位
GetBitmapBits(...)根据各种 cmets,这确实应该在视频内存中创建兼容的位图,但为什么我仍然可以看到系统内存增加(即使我不调用
GetBitmapBits)? -
创建DIBSection
HDC hDC = GetDC(NULL); m_hDC = CreateCompatibleDC(hDC); BITMAPINFO bmi; memset(&bmi, 0, sizeof(BITMAPINFO)); bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); bmi.bmiHeader.biWidth = cx; bmi.bmiHeader.biHeight = -cy; // top-down bmi.bmiHeader.biPlanes = 1; bmi.bmiHeader.biBitCount = 32; bmi.bmiHeader.biCompression = BI_RGB; m_hBmp = CreateDIBSection(hDC, &bmi, DIB_RGB_COLORS, (void**)&m_pBits, NULL, NULL); ReleaseDC(NULL, hDC); m_hOldBmp = (HBITMAP)SelectObject(m_hDC, m_hBmp);在这种情况下,我们会立即收到指向位的指针 (
m_pBits),因此很明显这些位驻留在系统内存中...
或者它是两种方法都保存在系统内存中的副本?但是,如果我更改系统内存中的位,则对BitBlt 的调用仍然需要再次从系统内存中检查/复制……恕我直言,不是很优化。
编辑:我还尝试使用 BeginBufferedPaint 和 GetBufferedPaintBits 创建内存 DC。它也分配系统内存,所以在这方面我认为它只是上述方法的包装器,但缓存了 DC,因此下一次调用不一定要重新创建内存 DC。见 Raymond Chen 的article。
编辑 #2:我想实际的问题是:我是否在方法 1 或 2 中正确创建内存 DC 以获得硬件加速的 GDI 操作? 对我来说,这一切似乎都很快,而且两者都方法也提供相同的速度,所以没有真正的方法来检查它......
【问题讨论】:
-
我认为它总是驻留在系统内存中,只有在渲染到屏幕时才会被交换到视频内存中......
-
那么这意味着我们不能在显存中创建它,并且在内存 DC 上工作时 GDI 功能没有硬件加速?
-
仅用于blitting 操作的GDI 函数仅在Windows 7 上进行硬件加速。即使在 Windows 7 上 GDI+ 仍然是软件渲染,而且速度仍然较慢。如果您正在做任何需要性能的复杂事情,那么简单的答案就是不要使用 GDI。如果您想直接访问硬件,请使用 OpenGL 或 DirectX。 GDI 一直是一种抽象。
-
从我读到的 GDI 函数在除 Vista 之外的每个版本的 Windows 上都是硬件加速的(由于它是新引入的驱动程序设计)。顺便说一句,我没有使用 GDI+,不建议任何人再使用它,因为它在 Win7 中没有硬件加速。
-
此外,检查系统内存是否被使用并不是硬件加速图形的有效指标。根据图形芯片,甚至驱动程序,纹理数据存储或备份在系统内存中(例如 OpenGL 的默认行为)。 GDI 是硬件加速的,但您无法实际控制它。如果您需要控制,我同意 AJG85 的观点,即您应该使用图形 API。