Skip to content

Commit

Permalink
gl: use glTexSubImage2D
Browse files Browse the repository at this point in the history
TODO: always has gl error
  • Loading branch information
wang-bin committed Feb 13, 2014
1 parent 0a038c2 commit ae797b6
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 24 deletions.
88 changes: 67 additions & 21 deletions src/GLWidgetRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,9 +175,12 @@ GLuint GLWidgetRendererPrivate::createProgram(const char* pVertexSource, const c
return program;
}

bool GLWidgetRendererPrivate::releaseShaderProgram()
bool GLWidgetRendererPrivate::releaseResource()
{
pixel_fmt = VideoFormat::Format_Invalid;
texture0Size = QSize();
glDeleteTextures(textures.size(), textures.data());
qDebug("delete %d textures", textures.size());
textures.clear();
if (vert) {
if (program)
Expand All @@ -196,16 +199,51 @@ bool GLWidgetRendererPrivate::releaseShaderProgram()
return true;
}

bool GLWidgetRendererPrivate::prepareShaderProgram(const VideoFormat &fmt)
bool GLWidgetRendererPrivate::initTexture(GLuint tex, GLint internalFormat, GLenum format, int width, int height)
{
glBindTexture(GL_TEXTURE_2D, tex);
//glUniform1i(u_Texture[i], i);
setupQuality();
// This is necessary for non-power-of-two textures
glTexParameteri(tex, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(tex, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D
, 0 //level
, internalFormat //internal format. 4? why GL_RGBA? GL_RGB?
, width
, height
, 0 //border, ES not support
, format //format, must the same as internal format?
, GL_UNSIGNED_BYTE
, NULL);
glBindTexture(GL_TEXTURE_2D, 0);

}

bool GLWidgetRendererPrivate::prepareShaderProgram(const VideoFormat &fmt, int width, int height)
{
// isSupported(pixfmt)
if (!fmt.isValid())
return false;
releaseResource();
pixel_fmt = fmt.pixelFormat();
texture0Size = QSize(width, height);

textures.resize(fmt.planeCount());
glGenTextures(textures.size(), textures.data());

GLint internalFormat = GL_LUMINANCE;
GLenum format = GL_LUMINANCE;
if (fmt.isRGB()) {
internalFormat = FMT_INTERNAL;
format = FMT;
}

if (!hasGLSL) {
initTexture(textures[0], internalFormat, format, width, height);
qWarning("Does not support GLSL!");
return false;
}
// isSupported(pixfmt)
if (!fmt.isValid())
return false;
releaseShaderProgram();
// FIXME
if (fmt.isRGB()) {
program = createProgram(kVertexShader, kFragmentShader);
Expand Down Expand Up @@ -243,14 +281,17 @@ bool GLWidgetRendererPrivate::prepareShaderProgram(const VideoFormat &fmt)
qDebug("glGetUniformLocation(\"u_MVP_matrix\") = %d\n", u_matrix);

// fragment shader
textures.resize(fmt.planeCount());
u_Texture.resize(fmt.planeCount());
glGenTextures(textures.size(), textures.data());
for (int i = 0; i < textures.size(); ++i) {
QString tex_var = QString("u_Texture%1").arg(i);
u_Texture[i] = glGetUniformLocation(program, tex_var.toUtf8().constData());
checkGlError("glGetUniformLocation");
qDebug("glGetUniformLocation(\"%s\") = %d\n", tex_var.toUtf8().constData(), u_Texture[i]);
if (i == 0) {
width = fmt.chromaWidth(width);
height = fmt.chromaHeight(height);
}
initTexture(textures[i], internalFormat, format, width, height);
}

glUseProgram(program);
Expand All @@ -267,10 +308,18 @@ void GLWidgetRendererPrivate::upload(const QRect &roi)
{
GLint internalFormat = GL_LUMINANCE;
GLenum format = GL_LUMINANCE;
if (video_frame.format().isRGB()) {
const VideoFormat fmt = video_frame.format();
if (fmt.isRGB()) {
internalFormat = FMT_INTERNAL;
format = FMT;
}
if (fmt != pixel_fmt || video_frame.size() != texture0Size) {
qDebug("pixel format changed: %s", video_frame.format().name().toUtf8().constData());
if (!prepareShaderProgram(fmt, video_frame.width(), video_frame.height())) {
qWarning("shader program create error...");
return;
}
}
for (int i = 0; i < video_frame.planeCount(); ++i) {
uploadPlane(i, internalFormat, format, roi);
}
Expand All @@ -282,7 +331,7 @@ void GLWidgetRendererPrivate::uploadPlane(int p, GLint internalFormat, GLenum fo
glActiveTexture(GL_TEXTURE0 + p); //TODO: can remove??
}
glBindTexture(GL_TEXTURE_2D, textures[p]);
glUniform1i(u_Texture[p], p);
glUniform1i(u_Texture[p], p); // for GLSL
setupQuality();
// This is necessary for non-power-of-two textures
glTexParameteri(textures[p], GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
Expand All @@ -297,12 +346,12 @@ void GLWidgetRendererPrivate::uploadPlane(int p, GLint internalFormat, GLenum fo
* TODO: glTexSubImage to update data.
* glEGLImageTargetTexture2DOES:http://software.intel.com/en-us/articles/using-opengl-es-to-accelerate-apps-with-legacy-2d-guis
*/
glTexImage2D(GL_TEXTURE_2D
glTexSubImage2D(GL_TEXTURE_2D
, 0 //level
, internalFormat //internal format. 4? why GL_RGBA? GL_RGB?
, 0 // xoffset
, 0 // yoffset
, video_frame.planeWidth(p)
, video_frame.planeHeight(p)
, 0 //border, ES not support
, format //format, must the same as internal format?
, GL_UNSIGNED_BYTE
, video_frame.bits(p));
Expand Down Expand Up @@ -385,11 +434,13 @@ void GLWidgetRenderer::drawBackground()
void GLWidgetRenderer::drawFrame()
{
DPTR_D(GLWidgetRenderer);
QRect roi = realROI();
d.upload(roi);

// shader program may not ready before upload
if (d.hasGLSL) {
glUseProgram(d.program); //qpainter need
}
QRect roi = realROI();
d.upload(roi);
//TODO: compute kTexCoords only if roi changed
#if ROI_TEXCOORDS
const GLfloat kTexCoords[] = {
Expand Down Expand Up @@ -458,12 +509,7 @@ void GLWidgetRenderer::initializeGL()

glEnable(GL_TEXTURE_2D);
checkGlError("glEnable");
qDebug("initializeGL textures");
if (d.hasGLSL) {
if (!d.prepareShaderProgram(VideoFormat(VideoFormat::Format_RGB32))) {
return;
}
}

#ifndef QT_OPENGL_ES_2
if (!d.hasGLSL) {
glShadeModel(GL_SMOOTH); //setupQuality?
Expand Down
8 changes: 5 additions & 3 deletions src/QtAV/private/GLWidgetRenderer_p.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,13 @@ class Q_AV_EXPORT GLWidgetRendererPrivate : public VideoRendererPrivate, public
}
}
~GLWidgetRendererPrivate() {
releaseShaderProgram();
releaseResource();
}
GLuint loadShader(GLenum shaderType, const char* pSource);
GLuint createProgram(const char* pVertexSource, const char* pFragmentSource);
bool releaseShaderProgram();
bool prepareShaderProgram(const VideoFormat& fmt);
bool releaseResource();
bool initTexture(GLuint tex, GLint internalFormat, GLenum format, int width, int height);
bool prepareShaderProgram(const VideoFormat& fmt, int width, int height);
void upload(const QRect& roi);
void uploadPlane(int p, GLint internalFormat, GLenum format, const QRect& roi);
//GL 4.x: GL_FRAGMENT_SHADER_DERIVATIVE_HINT,GL_TEXTURE_COMPRESSION_HINT
Expand Down Expand Up @@ -140,6 +141,7 @@ class Q_AV_EXPORT GLWidgetRendererPrivate : public VideoRendererPrivate, public
QPainter *painter;

VideoFormat::PixelFormat pixel_fmt;
QSize texture0Size;
};

} //namespace QtAV
Expand Down

0 comments on commit ae797b6

Please sign in to comment.