void exposeEvent(QExposeEvent *) { if (!isExposed()) return; if (!gl) { gl = new QOpenGLContext(); gl->setFormat(requestedFormat()); gl->create(); } gl->makeCurrent(this); QOpenGLShaderProgram prog; prog.addShaderFromSourceCode(QOpenGLShader::Vertex, "attribute highp vec4 a_Pos;" "attribute lowp vec4 a_Color;" "varying lowp vec4 v_Color;" "void main() {" " gl_Position = a_Pos;" " v_Color = a_Color;" "}"); prog.addShaderFromSourceCode(QOpenGLShader::Fragment, "varying lowp vec4 v_Color;" "void main() {" " gl_FragColor = v_Color;" "}"); prog.bind(); glClearColor(0, 0, 0, 1); glClear(GL_COLOR_BUFFER_BIT); glViewport(0, 0, width(), height()); prog.enableAttributeArray("a_Pos"); prog.enableAttributeArray("a_Color"); float coords[] = { -0.7f, 0.7f, 0.8f, 0.8f, -0.8f, -0.8f, 0.7f, -0.7f }; float colors[] = { 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0 }; prog.setAttributeArray("a_Pos", GL_FLOAT, coords, 2, 0); prog.setAttributeArray("a_Color", GL_FLOAT, colors, 4, 0); glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); prog.disableAttributeArray("a_Pos"); prog.disableAttributeArray("a_Color"); gl->swapBuffers(this); }
void VideoSurface::paintGL() { mutex.lock(); VideoFrame currFrame = frame; frame.invalidate(); mutex.unlock(); if (currFrame.isValid() && res != currFrame.resolution) { res = currFrame.resolution; // delete old texture if (textureId != 0) glDeleteTextures(1, &textureId); // a texture used to render the pbo (has the match the pixelformat of the source) glGenTextures(1,&textureId); glBindTexture(GL_TEXTURE_2D, textureId); glTexImage2D(GL_TEXTURE_2D,0, GL_RGB, res.width(), res.height(), 0, GL_RGB, GL_UNSIGNED_BYTE, 0); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); } if (currFrame.isValid()) { pboIndex = (pboIndex + 1) % 2; int nextPboIndex = (pboIndex + 1) % 2; if (pboAllocSize != currFrame.frameData.size()) { qDebug() << "VideoSurface: Resize pbo " << currFrame.frameData.size() << "(" << currFrame.resolution << ")" << "bytes (before" << pboAllocSize << ")"; pbo[0]->bind(); pbo[0]->allocate(currFrame.frameData.size()); pbo[0]->release(); pbo[1]->bind(); pbo[1]->allocate(currFrame.frameData.size()); pbo[1]->release(); pboAllocSize = currFrame.frameData.size(); } pbo[pboIndex]->bind(); glBindTexture(GL_TEXTURE_2D, textureId); glTexSubImage2D(GL_TEXTURE_2D,0,0,0, res.width(), res.height(), GL_RGB, GL_UNSIGNED_BYTE, 0); pbo[pboIndex]->unmap(); pbo[pboIndex]->release(); // transfer data pbo[nextPboIndex]->bind(); void* ptr = pbo[nextPboIndex]->map(QOpenGLBuffer::WriteOnly); if (ptr) memcpy(ptr, currFrame.frameData.data(), currFrame.frameData.size()); pbo[nextPboIndex]->unmap(); pbo[nextPboIndex]->release(); } // background glClearColor(0, 0, 0, 1); glClear(GL_COLOR_BUFFER_BIT); // keep aspect ratio float aspectRatio = float(res.width()) / float(res.height()); if (width() < float(height()) * aspectRatio) { float h = float(width()) / aspectRatio; glViewport(0, (height() - h)*0.5f, width(), h); } else { float w = float(height()) * float(aspectRatio); glViewport((width() - w)*0.5f, 0, w, height()); } QOpenGLShaderProgram* programm = nullptr; switch (frame.format) { case VideoFrame::YUV: programm = yuvProgramm; break; case VideoFrame::BGR: programm = bgrProgramm; break; default: break; } if (programm) { // render pbo static float values[] = { -1, -1, 1, -1, -1, 1, 1, 1 }; programm->bind(); programm->setAttributeArray(0, GL_FLOAT, values, 2); programm->enableAttributeArray(0); } glBindTexture(GL_TEXTURE_2D, textureId); //draw fullscreen quad glDrawArrays(GL_TRIANGLE_STRIP, 0, 4); glBindTexture(GL_TEXTURE_2D, 0); if (programm) { programm->disableAttributeArray(0); programm->release(); } }