/* Using Texture Subloading As an Alternative For Drawpixels By Jaya Kanajan, SGI H1. Introduction: DCC applications often rely heavily on glDrawPixels in order to transfer their generated images to the screen, such as during the playback of video clips. glDrawPixels performance varies substantially in range across commodity graphics implementations. However, texture download performance is often well optimized due to it's use by many popular games. As a result, it can be preferable for ISVs to use texture subloading to achieve the same effect. By using texture subloading, various effects that were unavailable with glDrawPixels can be achieved. For example, sequence switching effects like fading in and out are made simpler using textures and geometry (think multitexture for fading). The ability to allow the user to dynamically adjust the window size without needing to scale the data is very useful. Being able to dynamically switch back and forth between ranges of frames by using texture objects avoids the overhead of redownloading data that is necessary if using glDrawPixels. H1. Details In the following example, the buffers (to be thought of as generated or decoded image buffers) are subloaded repeatedly to measure texture download performance. Please note that textures widths and heights have to be 2^n and have maximum size restrictions which are not imposed on Drawpixels. If your data is not natively of a 2^n size, it is possible to zero-pad and adjust texcoords appropriately. Or preferably, you could texsubimage the arbitaryly sized image. H1. Conclusion There are tradeoffs and benefits to using texture subloading over Drawpixels. When chosen for the right reasons, texture subloading creates room for lots of creative effects that would have been difficult to achieve with Drawpixels. H1. Example Application texsub.c =============================================================================== /* * jaya * for raw texture subload performance */ #include #include #include #include #include #include #include long long now() { struct timeval tv; struct timezone tz; gettimeofday(&tv, &tz); return ((long long)tv.tv_sec) * 1e9 + ((long long)tv.tv_usec)*1e3; } GLenum texinternalformat,buftype,buformat; GLubyte *buf,*buf2; GLuint x,y,w,h,bsize,numiter,texName; long long before,after; void reshape(int w, int h) { glViewport(0,0,w,h); glMatrixMode(GL_PROJECTION); glLoadIdentity(); glOrtho(0,1,0,1,-1,+1); } static void init(void) { int i; GLubyte *obuf,*obuf2; buf = (GLubyte *) malloc(bsize*sizeof(GLubyte)); buf2 = (GLubyte *) malloc(bsize*sizeof(GLubyte)); obuf=buf;obuf2 =buf2; for (i=0; i < bsize; i++) { *(buf++) = 50; *(buf2++) = 90; } buf=obuf; buf2=obuf2; glClearColor(0,0,0,0); glShadeModel(GL_FLAT); glDisable(GL_DEPTH_TEST); glPixelStorei(GL_UNPACK_ALIGNMENT,1); glGenTextures(1,&texName); glBindTexture(GL_TEXTURE_2D, texName); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexEnvf(GL_TEXTURE_ENV,GL_TEXTURE_ENV_MODE,GL_REPLACE); glTexImage2D(GL_TEXTURE_2D,0,texinternalformat,w,h,0,buformat,buftype,buf); glEnable(GL_TEXTURE_2D); glBindTexture(GL_TEXTURE_2D, texName); glBegin(GL_QUADS); glTexCoord2f(0,0); glVertex3f(-2,-1,0); glTexCoord2f(0,1); glVertex3f(-2,1,0); glTexCoord2f(1,1); glVertex3f(2,1,0); glTexCoord2f(1,0); glVertex3f(2,-1,0); glEnd(); fprintf(stderr,"err=%x\n",glGetError()); } void display(void) { int i; glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, buformat, buftype, buf); glBindTexture(GL_TEXTURE_2D, texName); glBegin(GL_QUADS); glTexCoord2f(0,0); glVertex2f(0,0); glTexCoord2f(0,1); glVertex2f(1,0); glTexCoord2f(1,1); glVertex2f(1,1); glTexCoord2f(1,0); glVertex2f(0,1); glEnd(); glFinish(); glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, w, h, buformat, buftype, buf2); glBindTexture(GL_TEXTURE_2D, texName); glBegin(GL_QUADS); glTexCoord2f(0,0); glVertex2f(0,0); glTexCoord2f(0,1); glVertex2f(1,0); glTexCoord2f(1,1); glVertex2f(1,1); glTexCoord2f(1,0); glVertex2f(0,1); glEnd(); glFinish(); before = now(); for(i=0;i