У меня есть своего рода потоковое приложение, которое должно захватывать содержимое окна. В окне QGLWidget рисует материал. В настоящий момент я использую widget.grabFrameBuffer
в каждом цикле розыгрыша (должно быть в реальном времени). Приложение использует 100% процессор и без widget.grabFrameBuffer
оно падает до 10-20%. Я понял, что вызов image.bits()
(что мне нужно для отправки данных QImage) создает копию (не очень хороший способ решения проблемы). Кто-нибудь знает, как я могу получить указатель на буфер кадра или данные изображения, или мне нужно использовать команды opengl?QGLWidget - быстрее grabFrameBuffer
ответ
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.
правильный, но, к сожалению, сеть lib, не использует const ptr ... во всяком случае, я могу ее отбросить. не могли бы вы расширить свое предложение с помощью шейдера? что вы имеете в виду? – immerhart
@immerhart: Если API сетевой библиотеки не является константным, как это и должно быть, вы можете использовать 'const_cast
@immerhart: программирование на GPU выходит за рамки этого ответа и не может быть преподано в ответ на переполнение стека. В наши дни графические процессоры являются достаточно универсальными компьютерами и могут запускать код C-like. Указанный код может принимать содержимое визуализированного фрейма, изменять его размер и изменять его, а затем выгружать его где-то еще до того, как он будет передан в системную память. –
Обычно вы не можете получить «указатель» на буфер кадра, поскольку он хранится в VRAM графического процессора. И здесь проблема, вам нужно синхронизировать конвейер, чтобы читать фреймбуфер, если вы не используете что-то вроде PBO и не нуждаетесь в результатах немедленно. –
ОК, но есть ли способ избежать копирования в qt? но спасибо! – immerhart