【问题标题】:CreateCompatibleBitmap and CreateDIBSection (Memory DC's)CreateCompatibleBitmap 和 CreateDIBSection(内存 DC)
【发布时间】:2011-11-22 02:06:47
【问题描述】:

从我读到的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(...)
    

    根据各种 cmets,这确实应该在视频内存中创建兼容的位图,但为什么我仍然可以看到系统内存增加(即使我不调用 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 功能没有硬件加速?
  • 仅用于blitting 操作的GDI 函数仅在Windows 7 上进行硬件加速。即使在 Windows 7 上 GDI+ 仍然是软件渲染,而且速度仍然较慢。如果您正在做任何需要性能的复杂事情,那么简单的答案就是不要使用 GDI。如果您想直接访问硬件,请使用 OpenGL 或 DirectX。 GDI 一直是一种抽象。
  • 从我读到的 GDI 函数在除 Vista 之外的每个版本的 Windows 上都是硬件加速的(由于它是新引入的驱动程序设计)。顺便说一句,我没有使用 GDI+,不建议任何人再使用它,因为它在 Win7 中没有硬件加速。
  • 此外,检查系统内存是否被使用并不是硬件加速图形的有效指标。根据图形芯片,甚至驱动程序,纹理数据存储或备份在系统内存中(例如 OpenGL 的默认行为)。 GDI 是硬件加速的,但您无法实际控制它。如果您需要控制,我同意 AJG85 的观点,即您应该使用图形 API。

标签: c++ winapi memory gdi


【解决方案1】:

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

来自 MSDN 上的Memory Device Contexts

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

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

【讨论】:

  • 啊,说的很清楚,它还说:在调色板设备上显示DIB或从DIB创建的DDB时,您可以提高图像的绘制速度安排逻辑调色板以匹配系统调色板的布局。 这清楚地表明CreateCompatibleBitmap 应该是最快的方法,但由于我的系统以 32 位颜色运行,CreateDIBSection 使用 32-位布局同样快(这两个函数创建的位图格式相同)。
  • 根据我在 Direct2D 与 GDI 性能方面的经验,我不建议使用 Direct2D。它很慢,与 GDI 的速度差不多。
猜你喜欢
  • 2020-11-28
  • 1970-01-01
  • 1970-01-01
  • 2011-06-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多