I have code in OpenGL to display a YUV image in an OpenGL viewport. The program works without problems when working on nvidia cards, but when an error occurs when working with Intel HD 3000, unfortunately, this is the target machine. The point where the error is generated is marked in the code.
Shader programs
// Vertex Shader #version 120 void main() { gl_TexCoord[0] = gl_MultiTexCoord0; gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; } // fragment shader #version 120 uniform sampler2D texY; uniform sampler2D texU; uniform sampler2D texV; void main() { vec4 color; float y = texture2D(texY, gl_TexCoord[0].st).r; float u = texture2D(texU, gl_TexCoord[0].st).r; float v = texture2D(texV, gl_TexCoord[0].st).r; color.r = (1.164 * (y - 0.0625)) + (1.596 * (v - 0.5)); color.g = (1.164 * (y - 0.0625)) - (0.391 * (u - 0.5)) - (0.813 * (v - 0.5)); color.b = (1.164 * (y - 0.0625)) + (2.018 * (u - 0.5)); color.a = 1.0; gl_FragColor = color; };
Then I run the program as follows:
GLuint textures[3]; glGenTextures(3, textures); glBindTexture(GL_TEXTURE_2D, textures[YTEX]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glBindTexture(GL_TEXTURE_2D, textures[UTEX]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glBindTexture(GL_TEXTURE_2D, textures[VTEX]); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glBindTexture(GL_TEXTURE_2D, 0); GLsizei size = width * height; GLvoid *y = yuv_buffer; GLvoid *u = (GLubyte *)y + size; GLvoid *v = (GLubyte *)u + (size >> 2); glUseProgram(program_id); glActiveTexture(GL_TEXTURE0); glBindTexture(GL_TEXTURE_2D, textures[0]); glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, y); glUniform1i(glGetUniformLocation(program_id, "texY"), 0); glActiveTexture(GL_TEXTURE1); glBindTexture(GL_TEXTURE_2D, textures[1]); glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width >> 1, height >> 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, u); glUniform1i(glGetUniformLocation(program_id, "texU"), 1); glActiveTexture(GL_TEXTURE2); glBindTexture(GL_TEXTURE_2D, textures[2]); glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width >> 1, height >> 1, 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, u); glUniform1i(glGetUniformLocation(program_id, "texV"), 2); glBegin(GL_QUADS); glTexCoord2f(texLeft, texTop); glVertex2i(left, top); glTexCoord2f(texLeft, texBottom); glVertex2i(left, bottom); glTexCoord2f(texRight, texBottom); glVertex2i(right, bottom); glTexCoord2f(texRight, texTop); glVertex2i(right, top); glEnd(); // glError() returns 0x506 here glBindTexture(GL_TEXTURE_2D, 0); glActiveTexture(GL_TEXTURE0); glUseProgram(0);
update , because the error occurs with frame buffers, I found that they are used as follows: when the program starts, a frame buffer is created as follows:
glViewport(0, 0, (GLint)width, (GLint)height); glGenFramebuffers(1, &fbo_id); glGenTextures(1, &fbo_texture); glGenRenderbuffers(1, &rbo_id); glBindTexture(GL_TEXTURE_2D, fbo_texture); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); glTexParameteri(GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE); glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0); glBindTexture(GL_TEXTURE_2D, 0); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, rbo_id); glRenderbufferStorageEXT(GL_RENDERBUFFER_EXT, GL_DEPTH_COMPONENT, width, height); glBindRenderbufferEXT(GL_RENDERBUFFER_EXT, 0); glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, fbo_id); glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, fbo_texture, 0); glFramebufferRenderbufferEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_ATTACHMENT_EXT, GL_RENDERBUFFER_EXT, rbo_id); GLenum status = glCheckFramebufferStatusEXT(GL_FRAMEBUFFER_EXT); glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); glPushAttrib(GL_TEXTURE_BIT); glBindTexture(GL_TEXTURE_2D, m_frameTexture->texture()); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); glPopAttrib();
The YUV image comes in the form of tiles that are going to be rendered in this fbo. Whenever a frame starts, this is done:
glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); glDrawBuffer(GL_BACK); glViewport(0, 0, (GLint)width, (GLint)height); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0.0, (double)width, 0.0, (double)height, -1.0, 1.0); glMatrixMode(GL_MODELVIEW); glLoadIdentity(); glBindFramebuffer(GL_FRAMEBUFFER_EXT, fbo_id);
Then the code above is executed, and after all the tiles have been assembled together
glBindFramebuffer(GL_FRAMEBUFFER_EXT, 0); glPushAttrib(GL_VIEWPORT_BIT | GL_TEXTURE_BIT | GL_ENABLE_BIT); glViewport(0, 0, width, height); glClearColor(0.0f, 0.0f, 0.0f, 0.0f); glClear(GL_COLOR_BUFFER_BIT); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); glOrtho(0.0, (double)width, 0.0, (double)height, -1.0, 1.0); glMatrixMode(GL_MODELVIEW); glPushMatrix(); glLoadIdentity(); glEnable(GL_TEXTURE_2D); glDisable(GL_DEPTH_TEST); glBindTexture(GL_TEXTURE_2D, fbo_texture); glBegin(GL_QUADS); glTexCoord2i(0, 0); glVertex2f(renderLeft, renderTop); glTexCoord2i(0, 1); glVertex2f(renderLeft, renderTop + renderHeight); glTexCoord2i(1, 1); glVertex2f(renderLeft + renderWidth, renderTop + renderHeight); glTexCoord2i(1, 0); glVertex2f(renderLeft + renderWidth, renderTop); glEnd(); glPopMatrix(); glMatrixMode(GL_PROJECTION); glPopMatrix(); glPopAttrib();