CreateCompatibleBitmap和CreateDIBSection(Memory DC's)

dem*_*rge 8 c++ memory winapi gdi

从我在这里看到的,似乎大多数Windows GDI功能都加速了.例如,如果可用的话,调用BitBltAlphaBlend使用硬件加速.它还提到窗口的内容仅保存在视频内存中.现在这对于窗口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);
    
    Run Code Online (Sandbox Code Playgroud)

    然后调用以获取位

    GetBitmapBits(...)
    
    Run Code Online (Sandbox Code Playgroud)

    根据各种评论,这确实应该在视频内存中创建兼容的位图,但为什么我仍然可以看到系统内存的增加(即使我不调用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);
    
    Run Code Online (Sandbox Code Playgroud)

    在这种情况下,我们立即收到指向位的指针(m_pBits),因此很明显它们驻留在系统内存中......

或者它是两个方法保存在系统内存中的副本?但是,如果我改变系统内存中的位,调用BitBlt仍然需要再次从系统内存中检查/复制...不是非常优化恕我直言.

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

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

MSN*_*MSN 5

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

从MSDN 上的内存设备上下文

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

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