我使用Ubuntu Server 16.04.3和使用EGLFS QPA后端编写的Qt 5.9.2图形应用程序。它从第一个虚拟终端开始(如果有影响),然后将显示切换到完整高清图形模式输出。
当我使用实用程序(例如
fb2png
)对/dev/fb?
进行操作时,只保存第一个虚拟终端(Ctrl + Alt + F1)的文本模式内容作为屏幕截图。很难想象,有EGL API可以从另一个进程的上下文中获取任何缓冲区的内容(这将是不安全的),但也许有一些机制(和库)可以访问GPU的最终输出?
fb2png
)对/dev/fb?
进行操作时,只保存第一个虚拟终端(Ctrl + Alt + F1)的文本模式内容作为屏幕截图。一种方法是从应用程序内部获取屏幕截图,使用glReadPixels()
读取后缓冲区的内容。或者使用QQuickWindow::grabWindow(),它在正确的方式下内部使用glReadPixels()
。但这似乎不适用于你,因为你需要在Qt应用程序冻结时进行截图。
另一种方法是使用DRM API映射帧缓冲区,然后memcpy
映射像素。在Chromium OS中使用Python实现,并且可以轻松转换成C语言,详情请参见https://chromium-review.googlesource.com/c/chromiumos/platform/factory/+/367611。DRM API也可以被用于渲染的Qt UI进程之外的其他进程。
这是一个非常有趣的问题,我从多个角度解决了这个问题。
这个问题相当复杂,取决于平台,你似乎在运行EGL,这意味着嵌入式系统,除非你的平台提供其他选项,否则你的选择很少。
你可以选择以下选项:
glTexSubImage2D 可以将OpenGL纹理中的多种缓冲区复制到CPU内存。不幸的是,在GLES 2/3中不支持它,但是你的嵌入式提供商可能通过扩展支持它。这很好,因为你可以渲染到FBO或者从特定的纹理中获取像素。它还需要最少的代码修改。
glReadPixels 是下载已经渲染的GPU像素的最常见方式,虽然速度较慢,但适用于GLES和桌面。在带有良好GPU的桌面上,可承受交互式帧速率,但请注意,在嵌入式设备上可能非常缓慢,因为它会停止您的渲染线程以获取数据(保证了可怕的帧率下降)。您可以节省代码,因为它可以通过最小的代码修改来实现。
一旦您开始进行真正的研究,PBO 就会出现在这里和那里,因为它们可以异步地工作。它们通常不支持嵌入式设备,但即使在普通GPU上也可以很好地工作。设置起来有点棘手,需要特定的渲染修改。
mmap()
将缓冲区映射到文件并轻松获取部分内容。但请注意,在许多嵌入式系统中,EGL不在帧缓冲区上工作,而是在另一个“叠加层”上工作,因此您可能会捕获其背景。还要注意的是,一些多媒体应用程序在EGL上运行UI,并在帧缓冲区上运行媒体播放器。因此,如果您只需要捕获视频播放器,则可能适用于您。在其他情况下,EGL会针对纹理进行定位,然后将其复制到帧缓冲区,这也可以正常工作。
LD_PRELOAD
加载它。 - Velkan