【问题标题】:obtaining full desktop screenshot from the GPU从 GPU 获取完整的桌面截图
【发布时间】:2011-09-24 15:32:57
【问题描述】:

我一直在使用 Windows API 的 BitBlt 函数来执行屏幕抓取。

但是有很多缺点:

  1. DWM 和 Aero 会导致大幅减速(3 毫秒 --> 35 毫秒,只需调用 BitBlt)——要解决这个问题,需要禁用 Aero,而我宁愿不这样做。屏幕闪烁,事情发生了变化。
  2. 必须将数据重新传输到 GPU 才能将数据加载为纹理
  3. 如果没有CAPTUREBLT 标志,则无法捕获分层窗口。启用后,捕获时鼠标光标会闪烁。这似乎是一个小问题,但当应用程序没有错误时,它会非常烦人。作为解决方法,我打算将分层窗口渲染为附加光标。

我已经在使用 OpenGL 来显示和操作捕获的屏幕数据。 BitBlt 给了我像素数据,将它加载到纹理中相对容易。然而,这有点荒谬,因为当数据应该在 GPU 上可用时,我手动将数据重新发送回 GPU。数据肯定在那里,但尝试访问它是另一回事。

我认为此功能在供应商的待办事项列表中(或可能在任何列表中)并不高,但我想问问知情人士 AMD 是否提供了任何规定( ATI)或 NVidia 在其驱动程序中用于读取屏幕缓冲区(例如,进入 OpenGL 上下文)。我对现代 GPU 架构的了解还不够,不知道从哪里开始寻找答案。

【问题讨论】:

    标签: windows opengl screenshot fullscreen


    【解决方案1】:

    OpenGL 只能读取上下文帧缓冲区(一个窗口),以及您创建的任何帧缓冲区或 pbuffer。 OpenGL 无法触摸桌面或任何其他窗口。

    【讨论】:

    • 显然 Aero Peek 等人实时捕获硬件加速的其他窗口。因此,只需找到合适的 API。
    • 正式地说你是对的。然而,在合成窗口管理器出现之前,顶层窗口会接收部分可见屏幕帧缓冲内存。这使得通过创建全屏 OpenGL 窗口并在创建后立即执行 glReadPixels 来获取屏幕截图成为可能。今天,对于合成窗口管理器,这不再有效,因为每个窗口都有自己的屏幕外缓冲区。就像@Ben Voigt 说的那样,你需要使用 Compositing API。在 X11 中,这是相当有据可查的:Composite X11 and GLX_EXT_texture_from_pixmap GLX extensions。
    【解决方案2】:

    这是一个有趣的问题。不幸的是,我认为这并不真正得到支持。我发现在创建全屏不可见窗口和使用 glReadPixels 读取像素数据方面取得了一定程度的成功:

    http://www.virtualdub.org/blog/pivot/entry.php?id=142

    http://www.opentk.com/node/2430

    但是,我认为这样做的行为是未定义的,并且仅适用于特定的硬件/操作系统配置。

    【讨论】:

    • 这种行为确实是未定义的,并且利用了第一代窗口管理的工作原理(窗口接收像素所有权掩码和一些指针 + 跨步进入屏幕帧缓冲区)。在第 2 代,合成窗口管理器(Aero、AIGLX、MacOS X Quartz Extreme)窗口绘制到屏幕外缓冲区,可见的内容是由所有这些合成的。
    猜你喜欢
    • 1970-01-01
    • 2021-02-09
    • 2017-05-10
    • 2011-07-14
    • 1970-01-01
    • 2019-01-11
    • 1970-01-01
    • 2019-02-12
    • 2018-11-25
    相关资源
    最近更新 更多