CreateCompatibleBitmap 和 CreateDIBSection(内存 DC)

发布于 2024-12-05 21:57:31 字数 2114 浏览 0 评论 0原文

从我读到的这里< /a> 看来大多数Windows GDI 功能都被加速了。例如,调用 BitBlt()AlphaBlend() 使用硬件加速(如果可用)。它还提到窗口的内容仅保存在视频内存中。现在,对于窗口 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)选择对象(m_hDC, m_hBmp);
    

    然后调用获取位

    GetBitmapBits(...)
    

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

  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; // 自顶向下
    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)选择对象(m_hDC, m_hBmp);
    

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

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

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

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

From what I've read here it seems that most of the Windows GDI functions are accelerated. So for instance a call to BitBlt() or AlphaBlend() uses 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 DC that 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.

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

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 BitBlt() would still have to check/copy from system memory again... not very optimized IMHO.

EDIT: I've also tried creating memory DC's by using the BeginBufferedPaint() and 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.

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

懒的傷心 2024-12-12 21:57:31

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

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

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

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

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

From Memory Device Contexts on 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.

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

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文