void glActiveTexture(GLenum texture) { #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) #ifndef QT_OPENGL_ES if (!qtav_glActiveTexture) qtavResolveActiveTexture(); if (!qtav_glActiveTexture) return; qtav_glActiveTexture(texture); #else ::glActiveTexture(texture); #endif //QT_OPENGL_ES #else QOpenGLContext::currentContext()->functions()->glActiveTexture(texture); #endif }
void GLWidgetRenderer::drawFrame() { DPTR_D(GLWidgetRenderer); QRect roi = realROI(); d.upload(roi); // shader program may not ready before upload if (d.hasGLSL) { #if NO_QGL_SHADER glUseProgram(d.program); //for glUniform #else d.shader_program->bind(); #endif //NO_QGL_SHADER } glDisable(GL_DEPTH_TEST); const int nb_planes = d.video_frame.planeCount(); //number of texture id // all texture ids should be binded when renderering even for packed plane! for (int i = 0; i < nb_planes; ++i) { glActiveTexture(GL_TEXTURE0 + i); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, d.textures[i]); //we've bind 0 after upload() // use glUniform1i to swap planes. swap uv: i => (3-i)%3 // TODO: in shader, use uniform sample2D u_Texture[], and use glUniform1iv(u_Texture, 3, {...}) #if NO_QGL_SHADER glUniform1i(d.u_Texture[i], i); #else d.shader_program->setUniformValue(d.u_Texture[i], (GLint)i); #endif } if (nb_planes < d.u_Texture.size()) { for (int i = nb_planes; i < d.u_Texture.size(); ++i) { #if NO_QGL_SHADER glUniform1i(d.u_Texture[i], nb_planes - 1); #else d.shader_program->setUniformValue(d.u_Texture[i], (GLint)(nb_planes - 1)); #endif } } //TODO: compute kTexCoords only if roi changed #if ROI_TEXCOORDS /*! tex coords: ROI/frameRect()*effective_tex_width_ratio */ const GLfloat kTexCoords[] = { (GLfloat)roi.x()*(GLfloat)d.effective_tex_width_ratio/(GLfloat)d.video_frame.width(), (GLfloat)roi.y()/(GLfloat)d.video_frame.height(), (GLfloat)(roi.x() + roi.width())*(GLfloat)d.effective_tex_width_ratio/(GLfloat)d.video_frame.width(), (GLfloat)roi.y()/(GLfloat)d.video_frame.height(), (GLfloat)(roi.x() + roi.width())*(GLfloat)d.effective_tex_width_ratio/(GLfloat)d.video_frame.width(), (GLfloat)(roi.y()+roi.height())/(GLfloat)d.video_frame.height(), (GLfloat)roi.x()*(GLfloat)d.effective_tex_width_ratio/(GLfloat)d.video_frame.width(), (GLfloat)(roi.y()+roi.height())/(GLfloat)d.video_frame.height(), }; /// glVertexAttribPointer(d.a_TexCoords, 2, GL_FLOAT, GL_FALSE, 0, kTexCoords); /// glEnableVertexAttribArray(d.a_TexCoords); #else const GLfloat kTexCoords[] = { 0, 0, 1, 0, 1, 1, 0, 1, }; #endif //ROI_TEXCOORDS #ifndef QT_OPENGL_ES_2 //GL_XXX may not defined in ES2. so macro is required if (!d.hasGLSL) { //qpainter will reset gl state, so need glMatrixMode and clear color(in drawBackground()) //TODO: study what state will be reset glMatrixMode(GL_PROJECTION); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glPushMatrix(); d.setupAspectRatio(); //TODO: can we avoid calling this every time but only in resize event? glVertexPointer(2, GL_FLOAT, 0, kVertices); glEnableClientState(GL_VERTEX_ARRAY); glTexCoordPointer(2, GL_FLOAT, 0, kTexCoords); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glDrawArrays(GL_TRIANGLE_FAN, 0, 4); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_VERTEX_ARRAY); glPopMatrix(); } #endif //QT_OPENGL_ES_2 if (d.hasGLSL) { d.setupAspectRatio(); //TODO: can we avoid calling this every time but only in resize event? //qpainter need. TODO: VBO? #if NO_QGL_SHADER glVertexAttribPointer(d.a_Position, 2, GL_FLOAT, GL_FALSE, 0, kVertices); glEnableVertexAttribArray(d.a_Position); glVertexAttribPointer(d.a_TexCoords, 2, GL_FLOAT, GL_FALSE, 0, kTexCoords); glEnableVertexAttribArray(d.a_TexCoords); #else d.shader_program->setAttributeArray(d.a_Position, GL_FLOAT, kVertices, 2); d.shader_program->enableAttributeArray(d.a_Position); d.shader_program->setAttributeArray(d.a_TexCoords, GL_FLOAT, kTexCoords, 2); d.shader_program->enableAttributeArray(d.a_TexCoords); #endif /* * in Qt4 QMatrix4x4 stores qreal (double), while GLfloat may be float * QShaderProgram deal with this case. But compares sizeof(QMatrix4x4) and (GLfloat)*16 * which seems not correct because QMatrix4x4 has a flag var */ GLfloat *mat = (GLfloat*)d.colorTransform.matrixRef().data(); GLfloat glm[16]; #if QT_VERSION < QT_VERSION_CHECK(5, 0, 0) if (sizeof(qreal) != sizeof(GLfloat)) { #else if (sizeof(float) != sizeof(GLfloat)) { #endif d.colorTransform.matrixData(glm); mat = glm; } //QMatrix4x4 stores value in Column-major order to match OpenGL. so transpose is not required in glUniformMatrix4fv #if NO_QGL_SHADER glUniformMatrix4fv(d.u_colorMatrix, 1, GL_FALSE, mat); #else d.shader_program->setUniformValue(d.u_colorMatrix, d.colorTransform.matrixRef()); #endif glDrawArrays(GL_TRIANGLE_FAN, 0, 4); #if NO_QGL_SHADER glUseProgram(0); glDisableVertexAttribArray(d.a_TexCoords); glDisableVertexAttribArray(d.a_Position); #else d.shader_program->release(); d.shader_program->disableAttributeArray(d.a_TexCoords); d.shader_program->disableAttributeArray(d.a_Position); #endif } for (int i = 0; i < d.textures.size(); ++i) { //glActiveTexture: gl functions apply on texture i glActiveTexture(GL_TEXTURE0 + i); glDisable(GL_TEXTURE_2D); } } void GLWidgetRenderer::initializeGL() { DPTR_D(GLWidgetRenderer); makeCurrent(); //const QByteArray extensions(reinterpret_cast<const char *>(glGetString(GL_EXTENSIONS))); d.hasGLSL = QGLShaderProgram::hasOpenGLShaderPrograms(); qDebug("OpenGL version: %d.%d hasGLSL: %d", format().majorVersion(), format().minorVersion(), d.hasGLSL); #if QTAV_HAVE(QGLFUNCTIONS) initializeGLFunctions(); d.initializeGLFunctions(); #endif //QTAV_HAVE(QGLFUNCTIONS) qtavResolveActiveTexture(); glEnable(GL_TEXTURE_2D); if (!d.hasGLSL) { #ifndef QT_OPENGL_ES_2 glShadeModel(GL_SMOOTH); //setupQuality? glClearDepth(1.0f); #endif //QT_OPENGL_ES_2 } else { d.initWithContext(context()); } glClearColor(0.0, 0.0, 0.0, 0.0); d.setupQuality(); }