c++ - CreateCompatibleBitmap 和 CreateDIBSection(内存 DC)

标签 c++ winapi memory gdi

从我读到的 here似乎大多数 Windows GDI 功能都被加速了。因此,例如对 BitBltAlphaBlend 的调用使用硬件加速(如果可用)。它还提到窗口的内容仅保存在视频内存中。现在,对于 window DC 来说这一切都很好,但我如何才能使用驻留在显卡内存中的 memory DC?一旦我们完成了如何获得对像素的直接访问,我认为这将涉及 1. 将数据临时复制到系统内存 2. 更改像素数据 3. 复制回视频内存。

我尝试了两种方法,都可以在任务管理器中看到分配系统内存...

  1. 创建兼容位图

    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(...)
    

    根据各种评论,这确实应该在视频内存中创建兼容的位图,但为什么我仍然可以看到系统内存增加(即使我不调用 GetBitmapBits)?

  2. 创建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 的调用仍然需要再次从系统内存中检查/复制...恕我直言,不是很优化。

编辑:我还尝试使用 BeginBufferedPaintGetBufferedPaintBits 创建内存 DC。它也分配系统内存,所以在这方面我认为它只是上述方法的包装器,但缓存了 DC,因此下一次调用不一定要重新创建内存 DC。见 Raymond Chen 的 article .

编辑 #2:我想实际的问题是:我是否在方法 1 或 2 中正确创建内存 DC 以获得硬件加速的 GDI 操作? 对我来说,这一切似乎都很快,而且两者都方法也提供相同的速度,所以没有真正的方法来检查它......

最佳答案

内存 DC 不在设备上创建。它们旨在将 GDI 输出放入内存中。

来自 Memory Device Contexts在 MSDN 上:

To enable applications to place output in memory rather than sending it to an actual device, use a special device context for bitmap operations called a memory device context. A memory DC enables the system to treat a portion of memory as a virtual device.

如果您想要硬件加速的 2d 图形,您应该考虑使用 Direct2D .

关于c++ - CreateCompatibleBitmap 和 CreateDIBSection(内存 DC),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7502588/

相关文章:

c++ - 使用 std::get 作为 std::transform 的参数

c++ - 我将如何为下一次迭代清理 SDL_surface 中的翻转图像?

c++ - 在哪里初始化另一个对话框上的丰富编辑控件?

c - .dll 中的 Win32 : Using functions from a static . lib

iOS 内存使用分析

c++ - 虚拟继承、默认构造函数和额外复制

c - 如何为 GetModuleFileNameEx 禁用 WOW64 文件系统重定向?

c++ - 获取域 Controller 名称

c - Wireshark 插件导致 'heap corruption'

c++ - 为什么我不能在特定进程的范围内使用 MPI_Scatter()?