I have a set of RGB Frames which i'm displaying using openGL's PBO concept. Below is my code:
#include <stdio.h>
#include <stdlib.h>
#include "glew.h"
#include "glfw.h"
#include "glaux.h"
#include "logodata.h"
PFNGLGENBUFFERSARBPROC pglGenBuffersARB = 0; // VBO Name Generation Procedure
PFNGLBINDBUFFERARBPROC pglBindBufferARB = 0; // VBO Bind Procedure
PFNGLBUFFERDATAARBPROC pglBufferDataARB = 0; // VBO Data Loading Procedure
PFNGLBUFFERSUBDATAARBPROC pglBufferSubDataARB = 0; // VBO Sub Data Loading Procedure
PFNGLDELETEBUFFERSARBPROC pglDeleteBuffersARB = 0; // VBO Deletion Procedure
PFNGLGETBUFFERPARAMETERIVARBPROC pglGetBufferParameterivARB = 0; // return various parameters of VBO
PFNGLMAPBUFFERARBPROC pglMapBufferARB = 0; // map VBO procedure
PFNGLUNMAPBUFFERARBPROC pglUnmapBufferARB = 0; // unmap VBO procedure
#define glGenBuffersARB pglGenBuffersARB
#define glBindBufferARB pglBindBufferARB
#define glBufferDataARB pglBufferDataARB
#define glBufferSubDataARB pglBufferSubDataARB
#define glDeleteBuffersARB pglDeleteBuffersARB
#define glGetBufferParameterivARB pglGetBufferParameterivARB
#define glMapBufferARB pglMapBufferARB
#define glUnmapBufferARB pglUnmapBufferARB
int index;
int pboSupported;
int pboMode;
GLuint pixBuffObjs[2];
HDC hDC = NULL;
GLuint texture;
char *FileName;
unsigned char *guibuffer;
AUX_RGBImageRec texture1;
unsigned long long pos=0;
GLuint myPBO;
GLuint logoPBO;
unsigned char *logoBuff;
void initGL(void)
{
int maxSz;
int maxwidth = 416;
int maxheight = 240;
if( !glfwInit() )
{
exit( EXIT_FAILURE );
}
// if( !glfwOpenWindow(4096, 2118, 0,0,0,0,0,0, GLFW_WINDOW ) )
if( !glfwOpenWindow(maxwidth, maxheight, 0,0,0,0,0,0, GLFW_WINDOW ) ) //GLFW_FULLSCREEN
{
glfwTerminate();
exit( EXIT_FAILURE );
}
glfwSetWindowTitle("sample");
glGenBuffersARB = (PFNGLGENBUFFERSARBPROC)wglGetProcAddress("glGenBuffersARB");
glBindBufferARB = (PFNGLBINDBUFFERARBPROC)wglGetProcAddress("glBindBufferARB");
glBufferDataARB = (PFNGLBUFFERDATAARBPROC)wglGetProcAddress("glBufferDataARB");
glBufferSubDataARB = (PFNGLBUFFERSUBDATAARBPROC)wglGetProcAddress("glBufferSubDataARB");
glDeleteBuffersARB = (PFNGLDELETEBUFFERSARBPROC)wglGetProcAddress("glDeleteBuffersARB");
glGetBufferParameterivARB = (PFNGLGETBUFFERPARAMETERIVARBPROC)wglGetProcAddress("glGetBufferParameterivARB");
glMapBufferARB = (PFNGLMAPBUFFERARBPROC)wglGetProcAddress("glMapBufferARB");
glUnmapBufferARB = (PFNGLUNMAPBUFFERARBPROC)wglGetProcAddress("glUnmapBufferARB");
// check once again PBO extension
if(glGenBuffersARB && glBindBufferARB && glBufferDataARB && glBufferSubDataARB &&
glMapBufferARB && glUnmapBufferARB && glDeleteBuffersARB && glGetBufferParameterivARB)
{
pboSupported = 1;
pboMode = 1; // using 1 PBO
printf( "Video card supports GL_ARB_pixel_buffer_object.");
glGenBuffersARB(1, &pixBuffObjs[0]);
}
else
{
pboSupported = 0;
pboMode = 0; // without PBO
printf("Video card does NOT support GL_ARB_pixel_buffer_object.");
}
glGetIntegerv(GL_MAX_TEXTURE_SIZE,&maxSz);
glClearColor(0.0f, 0.0f, 0.0f, 0.0f); // This Will Clear The Background Color To Black
glClearDepth(1.0); // Enables Clearing Of The Depth Buffer
glDepthFunc(GL_LESS); // The Type Of Depth Test To Do
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glShadeModel(GL_SMOOTH); // Enables Smooth Color Shading
glMatrixMode(GL_PROJECTION);
//glLoadIdentity();
hDC= wglGetCurrentDC();
#if 1
{ // TSS
HWND hCurrentWindow = GetActiveWindow();
char szTitle[256]="sample";
//SetWindowText(hCurrentWindow, );
// SetWindowLongA (hCurrentWindow , GWL_STYLE, (GetWindowLongA (hCurrentWindow , GWL_STYLE) & ~(WS_CAPTION)));
SetWindowLongA (hCurrentWindow, GWL_STYLE, (WS_VISIBLE));
}
#endif
glEnable(GL_TEXTURE_2D);
glGenTextures(1, &texture);
glBindTexture(GL_TEXTURE_2D, texture);
}
int GL_Disply()
{
FILE *fptr=fopen("F:\\myRGBvideo.rgb","rb");
fseek(fptr,pos,SEEK_SET);
fread(guibuffer,sizeof(unsigned char),sizeof(unsigned char)*416*240*3,fptr);
pos+=416*240*3;
texture1.sizeX =416;
texture1.sizeY =240;
texture1.data = guibuffer;
glDepthFunc(GL_ALWAYS);
glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);
glEnable(GL_BLEND);
glDisable(GL_LIGHTING);
//glEnable(GL_TEXTURE_2D);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
#if 0
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texture1.sizeX, texture1.sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, guibuffer);
#else
glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, myPBO);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, texture1.sizeX, texture1.sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, NULL);
#endif
glBegin(GL_QUADS);
//glNormal3f( 0.0f, 0.0f, 0.0f);
glTexCoord2f(0.0f, 1.0f); glVertex3f(-1.0f, -1.0f, 0.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 1.0f, -1.0f, 0.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 1.0f, 1.0f, 0.0f);
glTexCoord2f(0.0f, 0.0f); glVertex3f(-1.0f, 1.0f, 0.0f);
glEnd();
//disp logo
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_MODULATE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, LOGO_WIDTH, LOGO_HEIGHT, 0, GL_RGBA, GL_UNSIGNED_BYTE, logoBuff);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 1.0f); glVertex3f(0.8f, 0.8f, 0.0f);
glTexCoord2f(1.0f, 1.0f); glVertex3f( 0.97f, 0.8f, 0.0f);
glTexCoord2f(1.0f, 0.0f); glVertex3f( 0.97f, 0.97f, 0.0f);
glTexCoord2f(0.0f, 0.0f);glVertex3f(0.8f, 0.97f, 0.0f);
glEnd();
glDisable(GL_BLEND);
glEnable(GL_DEPTH_TEST);
// Swap front and back rendering buffers
glfwSwapBuffers();
//glDeleteTextures(1, &texture);
fclose(fptr);
}
int main(int argc, char *argv[])
{
initGL(); // GL initialization
#if 0
/* CPU memory allocation using C - malloc */
guibuffer=(unsigned char*)malloc(sizeof(unsigned char)*416*240*3);
#else
/*GPU memory allocation using C*/
glGenBuffersARB(1, &myPBO);
glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, myPBO);
glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 416*240*3, NULL, GL_STREAM_DRAW_ARB);
#endif
//Allocating memory for RGBA logo data present in logodata.h
logoBuff=(unsigned char*)malloc(400*312*4*sizeof(unsigned char));
memcpy(logoBuff,TELLogo_RGB,400*312*4);
for(index=0;index<200;index++)
{
guibuffer=(unsigned char*)glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_READ_WRITE_ARB);
glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB);
printf("frame %d displayed\r",index);
GL_Disply();
}
free(logoBuff);
return 0;
}
When the above code is run on a system having graphics card details listed below the display is normal and works fine:
First System:
Graphics card: Nvidia GEForce 580
OpenGL Version: 4.3
Second system:
Graphics card: NVidia GEForce 310
OpenGL Version: 3.3
Third system:
Graphics card: MSI
OpenGL Version: 4.2
However when the same code is run on my laptop with same system configuration but with the graphic cards details as shown below, i get a kind of Jerk (slight stuck) for some streams (some streams are working fine). I have checked same streams on different systems listed above and they seem to work fine.
Graphics card: Intel HD Graphics 4000
openGL Version: 4.0
What might be the problem that is causing this issue?
In your display function you're calling
glTexImage2D. This function performs a full texture object re-/allocation. Depending on the implementation details of the driver this might trigger internal garbage collection, if too many texture objects accumulated over time. Since your intention is display a stream of frames, of identical format and size, you should just replace the texture data usingglTexSubImage2Dinstead.Call
glTexImage2Donly once to initialize the texture object and then useglTexSubImage2Dto upload new data. To make coding easier initialize the texture object by callingglTexImage2Dwith a null pointer for the data parameter while no PBO is bound.