CreateCompatibleBitmap 和 CreateDIBSection(内存 DC)

问题描述 投票:0回答:1

从我读到的here看来,大多数Windows GDI函数都被加速了。因此,例如,调用

BitBlt()
AlphaBlend()
使用硬件加速(如果可用)。它还提到窗口的内容仅保存在视频内存中。现在,对于window DC来说这一切都很好,但是我如何使用驻留在显卡内存中的内存DC?一旦我们完成了如何直接访问像素,我认为这将涉及 1. 临时将数据复制到系统内存 2. 更改像素数据 3. 复制回视频内存。

我尝试了两种方法,都分配系统内存,正如我在任务管理器中看到的那样......

  1. CreateCompatibleBitmap()

    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);
    

    然后调用获取bits

    GetBitmapBits(...)
    

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

    GetBitmapBits()
    )?

  2. CreateDIBSection()

    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 的文章

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

c++ winapi memory gdi
1个回答
6
投票

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

来自 MSDN 上的内存设备上下文

使应用程序能够将输出放置在内存中而不是发送 它到实际设备,使用位图的特殊设备上下文 称为“内存设备上下文”的操作。内存 DC 使 系统将一部分内存视为虚拟设备。

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

© www.soinside.com 2019 - 2024. All rights reserved.