C++ CreateCompatibleBitmap 和 CreateDIBSection(内存 DC)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7502588/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 17:02:57  来源:igfitidea点击:

CreateCompatibleBitmap and CreateDIBSection (Memory DC's)

c++winapimemorygdi

提问by demorge

from what I've read hereit seems that most of the Windows GDI functions are accelerated. So for instance a call to BitBltor AlphaBlenduses hardware acceleration if available. It also mentions that the contents of a window are kept only in video memory. Now this is all good and true for a window DC, but how can I use a memory DCthat resides in video card memory? And once we've accomplished that how to obtain direct access to the pixels, I think that would involve 1. temporary copying the data to system memory 2. alter the pixel data 3. copy back to video memory.

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

I've tried two approaches, both allocate system memory as I can see in the task manager...

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

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

    and then call to obtain the bits

    GetBitmapBits(...)
    

    according to various comments this should indeed create the compatible bitmap in video memory, but why can I still see an increase in system memory (even when I don't call 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);
    

    in this case we receive the pointer to the bits immediately (m_pBits) so it's obvious that these reside in system memory...

  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. 创建DIB节

    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),因此很明显这些位驻留在系统内存中...

Or is it a copy that is kept in system memory for both methods? But if I change the bits in system memory a call to BitBltwould still have to check/copy from system memory again... not very optimized IMHO.

还是两种方法都保存在系统内存中的副本?但是,如果我更改系统内存中的位,则调用BitBlt仍然必须再次从系统内存中检查/复制......不是非常优化恕我直言。

EDIT: I've also tried creating memory DC's by using the BeginBufferedPaintand GetBufferedPaintBits. It allocates system memory as well, so in that respect I suppose it's just a wrapper for the above methods but caches the DC's so a next call doesn't necessarily has to recreate a memory DC. See Raymond Chen's article.

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

EDIT #2: I guess the actual question is: Am I doing the memory DC creation correct in method 1 or 2 to get hardware accelerated GDI operations?To me it all seems fast, and both methods provide the same speed too, so there's not really a way to check it...

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

采纳答案by MSN

Memory DCs are not created on a device. They are designed to put GDI output into memory.

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

From Memory Device Contextson MSDN:

来自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.

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

If you want hardware accelerated 2d graphics, you should consider using Direct2D.

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