2014-01-16 6 views
0

У меня есть своего рода потоковое приложение, которое должно захватывать содержимое окна. В окне QGLWidget рисует материал. В настоящий момент я использую widget.grabFrameBuffer в каждом цикле розыгрыша (должно быть в реальном времени). Приложение использует 100% процессор и без widget.grabFrameBuffer оно падает до 10-20%. Я понял, что вызов image.bits() (что мне нужно для отправки данных QImage) создает копию (не очень хороший способ решения проблемы). Кто-нибудь знает, как я могу получить указатель на буфер кадра или данные изображения, или мне нужно использовать команды opengl?QGLWidget - быстрее grabFrameBuffer

+1

Обычно вы не можете получить «указатель» на буфер кадра, поскольку он хранится в VRAM графического процессора. И здесь проблема, вам нужно синхронизировать конвейер, чтобы читать фреймбуфер, если вы не используете что-то вроде PBO и не нуждаетесь в результатах немедленно. –

+0

ОК, но есть ли способ избежать копирования в qt? но спасибо! – immerhart

ответ

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() должен скопировать данные из памяти графического процессора к системной памяти, но это не должно быть неприличия дорого. Это должно быть сделано с использованием DMA.

Если вы хотите уменьшить или перемасштабировать данные перед тем, как сбросить их на изображение, вы сохраните пропускную способность процессора и системной памяти, запустив downsampler shader program и получив изображение из FBO.

+0

правильный, но, к сожалению, сеть lib, не использует const ptr ... во всяком случае, я могу ее отбросить. не могли бы вы расширить свое предложение с помощью шейдера? что вы имеете в виду? – immerhart

+0

@immerhart: Если API сетевой библиотеки не является константным, как это и должно быть, вы можете использовать 'const_cast (bits)', но было бы лучше исправить библиотеку или пожаловаться ее авторам (и жаловаться **громко**!). –

+0

@immerhart: программирование на GPU выходит за рамки этого ответа и не может быть преподано в ответ на переполнение стека. В наши дни графические процессоры являются достаточно универсальными компьютерами и могут запускать код C-like. Указанный код может принимать содержимое визуализированного фрейма, изменять его размер и изменять его, а затем выгружать его где-то еще до того, как он будет передан в системную память. –