我有一种流应用程序,它应该捕获窗口的内容。在窗口中,QGLWidget绘制了东西。目前,我在每个绘制周期中都使用widget.grabFrameBuffer(必须是实时的)。该应用程序使用100%CPU,没有widget.grabFrameBuffer时,它下降到10-20%。我发现,调用image.bits()(发送QImage数据所需的调用)会创建一个副本(不是解决问题的好方法)。是否有人知道如何获取指向帧缓冲区或图像数据的指针,还是必须使用opengl命令?

最佳答案

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和系统内存带宽。

关于c++ - QGLWidget-更快的handleFrameBuffer,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/21171982/

10-12 23:57