QGLWidget - 更快的grabFrameBuffer
Posted
技术标签:
【中文标题】QGLWidget - 更快的grabFrameBuffer【英文标题】:QGLWidget - faster grabFrameBuffer 【发布时间】:2014-01-16 20:17:16 【问题描述】:我有一种流应用程序,它应该捕获窗口的内容。在窗口中,QGLWidget 绘制了这些东西。目前我在每个绘制周期中使用widget.grabFrameBuffer
(必须是实时的)。该应用程序使用 100% 的 CPU,如果没有 widget.grabFrameBuffer
,它会下降到 10-20%。我发现,调用image.bits()
(我需要什么,用于发送 QImage 数据)会创建一个副本(不是解决问题的好方法)。有人知道如何获取指向帧缓冲区或图像数据的指针,还是必须使用 opengl 命令?
【问题讨论】:
您通常无法获得指向帧缓冲区的“the”指针,因为它存储在 GPU 的 VRAM 中。这就是问题所在,您必须同步管道才能读回帧缓冲区,除非您使用 PBO 之类的东西并且不需要立即获得结果。 好的,但是有没有办法避免在qt中复制?不过谢谢! 【参考方案1】:QImage::bits()
只执行深层复制,因为您要求它。
对于常量数据,在不复制QImage
中已有数据的情况下,正确的做法是:
const QImage & frame(widget.grabFrameBuffer());
// compiler enforces const on uchar
const uchar * bits = frame.constBits();
// or
// if you forget const on uchar, this would deep copy
const uchar * bits = frame.constBits();
如果您将位传递给的代码因不正确而被破坏,您可以强制转换位:
class AssertNoImageModifications
const char * m_bits;
int m_len;
quint16 m_checksum;
Q_DISABLE_COPY(AssertNoImageModifications)
public:
explicit AssertNoImageModifications(const QImage & image) :
m_bits(reinterpret_cast<const char*>(image.constBits())),
m_len(image.byteCount())
Q_ASSERT((m_checksum = qChecksum(m_bits, m_len)) || true);
~AssertNoImageModifications()
Q_ASSERT(m_checksum == qChecksum(m_bits, m_len));
;
...
AssertNoImageModifications ani1(frame);
stupidAPI(const_cast<uchar*>(bits));
当然grabFrameBuffer()
必须将数据从 GPU 的内存复制到系统内存,但这应该不会太贵。应该使用 DMA 来完成。
如果您想在将数据转储到图像之前缩小/重新采样数据,您可以通过运行downsampler shader program 并从 FBO 获取图像来节省 CPU 和系统内存带宽。
【讨论】:
正确,但不幸的是网络库,没有使用 const ptr ......无论如何,我可能会转换它。你能用着色器扩展你的建议吗?你什么意思? @immerhart:如果网络库的 API 不是 const 正确的,应该是,您可以使用const_cast<uchar*>(bits)
,但最好修复库或向其作者投诉(并大声抱怨!)。
@immerhart:GPU 编程超出了这个答案的范围,并且不能在堆栈溢出答案中真正教授。如今,GPU 是相当通用的计算机,可以运行类似 C 的代码。所述代码可以获取渲染帧的内容,调整大小并重新采样,然后在传递到系统内存之前将其转储到其他地方。以上是关于QGLWidget - 更快的grabFrameBuffer的主要内容,如果未能解决你的问题,请参考以下文章
QGLWidget::renderText() 创建一些向下移动的字母