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&lt;uchar*&gt;(bits),但最好修复库或向其作者投诉(并大声抱怨!)。 @immerhart:GPU 编程超出了这个答案的范围,并且不能在堆栈溢出答案中真正教授。如今,GPU 是相当通用的计算机,可以运行类似 C 的代码。所述代码可以获取渲染帧的内容,调整大小并重新采样,然后在传递到系统内存之前将其转储到其他地方。

以上是关于QGLWidget - 更快的grabFrameBuffer的主要内容,如果未能解决你的问题,请参考以下文章

Qt连接QTableWidget和QGLWidget

ubuntu 上的 QGLWidget 啥也没显示

QGLWidget::renderText 边界框

QGLWidget::renderText() 创建一些向下移动的字母

QMainWindow +QGraphicsView 和多个 QGLWidget 的问题

在 QGLWidget 中将位复制到 QtImage