CudaImageDisplayGL.C

Go to the documentation of this file.
00001 /*!@file CUDA/CudaImageDisplayGL.C  Displays Images from CUDA Memory using OpenGL*/
00002 
00003 // //////////////////////////////////////////////////////////////////// //
00004 // The iLab Neuromorphic Vision C++ Toolkit - Copyright (C) 2000-2005   //
00005 // by the University of Southern California (USC) and the iLab at USC.  //
00006 // See http://iLab.usc.edu for information about this project.          //
00007 // //////////////////////////////////////////////////////////////////// //
00008 // Major portions of the iLab Neuromorphic Vision Toolkit are protected //
00009 // under the U.S. patent ``Computation of Intrinsic Perceptual Saliency //
00010 // in Visual Environments, and Applications'' by Christof Koch and      //
00011 // Laurent Itti, California Institute of Technology, 2001 (patent       //
00012 // pending; application number 09/912,225 filed July 23, 2001; see      //
00013 // http://pair.uspto.gov/cgi-bin/final/home.pl for current status).     //
00014 // //////////////////////////////////////////////////////////////////// //
00015 // This file is part of the iLab Neuromorphic Vision C++ Toolkit.       //
00016 //                                                                      //
00017 // The iLab Neuromorphic Vision C++ Toolkit is free software; you can   //
00018 // redistribute it and/or modify it under the terms of the GNU General  //
00019 // Public License as published by the Free Software Foundation; either  //
00020 // version 2 of the License, or (at your option) any later version.     //
00021 //                                                                      //
00022 // The iLab Neuromorphic Vision C++ Toolkit is distributed in the hope  //
00023 // that it will be useful, but WITHOUT ANY WARRANTY; without even the   //
00024 // implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR      //
00025 // PURPOSE.  See the GNU General Public License for more details.       //
00026 //                                                                      //
00027 // You should have received a copy of the GNU General Public License    //
00028 // along with the iLab Neuromorphic Vision C++ Toolkit; if not, write   //
00029 // to the Free Software Foundation, Inc., 59 Temple Place, Suite 330,   //
00030 // Boston, MA 02111-1307 USA.                                           //
00031 // //////////////////////////////////////////////////////////////////// //
00032 //
00033 // Primary maintainer for this file:
00034 // $HeadURL: svn://isvn.usc.edu/software/invt/trunk/saliency/src/CUDA/CudaImageDisplayGL.C $
00035 // $Id: CudaImageDisplayGL.C 14165 2010-10-23 07:00:08Z rand $
00036 //
00037 
00038 
00039 #include <stdio.h>
00040 #include <stdlib.h>
00041 #include <string.h>
00042 #include <pthread.h>
00043 #include <errno.h>
00044 #include "CUDA/CudaImageDisplayGL.H"
00045 #include "CUDA/CudaImage.H"
00046 #include "CUDA/CudaImageSet.H"
00047 #include "Image/Pixels.H"
00048 #include "Image/MathOps.H"
00049 
00050 #include "CudaImageDisplay.h"
00051 #include <unistd.h>
00052 
00053 #include "CUDA/CudaCutPaste.H"
00054 #include "CUDA/CudaSaliency.H"
00055 #include "CUDA/CudaMathOps.H"
00056 
00057 
00058 
00059 #define BUFFER_DATA(i) ((char *)0 + i)
00060 
00061 static const char *shader_code =
00062   "!!ARBfp1.0\n"
00063   "TEX result.color, fragment.texcoord, texture[0], 2D; \n"
00064   "END";
00065 
00066 CudaImageDisplayGL *CudaImageDisplayGL::instance = NULL;
00067 
00068 CudaImageDisplayGL::CudaImageDisplayGL()
00069 {
00070   bufferIndex=0;
00071   count_buffer_runs=0;
00072   g_Kernel = 0;
00073   g_FPS = false;
00074   g_Diag = false;
00075   frameN = 24;
00076   frameCounter = 0;
00077   shutdown = false;
00078 }
00079 
00080 // ######################################################################
00081 void CudaImageDisplayGL::runImageFilters(unsigned int *d_dst)
00082 {
00083   cuda_Copy(d_dst, mWinW, mWinH);
00084   CUT_CHECK_ERROR("Filtering kernel execution failed.\n");
00085 }
00086 // ######################################################################
00087 void CudaImageDisplayGL::displayFunction()
00088 {
00089   if(getShutdown())
00090     return;
00091   unsigned int *d_dst = NULL;
00092 
00093   CUDA_SAFE_CALL( cudaGLMapBufferObject((void**)&d_dst, gl_PBO ) );
00094   CUDA_SAFE_CALL( CUDA_Bind2TextureArray(bufferIndex));
00095   runImageFilters(d_dst);
00096   CUDA_SAFE_CALL(CUDA_UnbindTexture(bufferIndex));
00097   CUDA_SAFE_CALL(cudaGLUnmapBufferObject(gl_PBO));
00098 
00099 
00100   // Common display code path
00101   {
00102     glClear(GL_COLOR_BUFFER_BIT);
00103     //glBindTexture(GL_TEXTURE_2D, gl_Tex);
00104     glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, mWinW, mWinH, GL_RGBA, GL_UNSIGNED_BYTE,BUFFER_DATA(0) );
00105 
00106     glBegin(GL_QUADS);
00107     glTexCoord2f(0,1); glVertex2f(-1, +1);
00108     glTexCoord2f(1,1); glVertex2f(1, +1);
00109     glTexCoord2f(1, 0); glVertex2f(+1, -1);
00110     glTexCoord2f(0, 0); glVertex2f(-1, -1);
00111     glEnd();
00112 
00113     glFinish();
00114   }
00115 
00116   if(frameCounter == frameN){
00117     frameCounter = 0;
00118     if(g_FPS){
00119 
00120       g_FPS = false;
00121     }
00122   }
00123 
00124   glutSwapBuffers();
00125   glutPostRedisplay();
00126 
00127 }
00128 
00129 
00130 // ######################################################################
00131 void CudaImageDisplayGL::shutDown()
00132 {
00133   CUDA_SAFE_CALL( cudaGLUnregisterBufferObject(gl_PBO) );
00134   glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
00135   glDeleteBuffers(1, &(gl_PBO));
00136   glDeleteTextures(1, &(gl_Tex));
00137   free(h_Src);
00138   CUDA_SAFE_CALL( CUDA_FreeArray() );
00139   framework.setMutexDestroy();
00140   printf("Shutdown done.\n");
00141   cudaThreadExit();
00142 }
00143 
00144 // ######################################################################
00145 int CudaImageDisplayGL::initGL(int x_size,int y_size)
00146 {
00147 
00148   printf("Initializing GLUT...\n");
00149   int tmpImageW = x_size;
00150   int tmpImageH = y_size;
00151   int argc = 1;
00152   char **argv = new char*[2];
00153   argv[0] = new char[50];
00154   sprintf(argv[0],"INVALID COMMAND LINE OPTIONS");
00155   argv[1]=NULL;
00156   glutInit(&argc, argv);
00157   delete argv[0];
00158   delete[] argv;
00159   printf("%s %d\n",__FILE__,__LINE__);
00160   glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE);printf("%s %d\n",__FILE__,__LINE__);
00161   glutInitWindowSize(tmpImageW,tmpImageH);printf("%s %d\n",__FILE__,__LINE__);
00162   glutInitWindowPosition(-1,-1); printf("%s %d\n",__FILE__,__LINE__);
00163 
00164   main_window = glutCreateWindow("Main Display");
00165   glutDisplayFunc(displayWrapper);
00166 
00167 
00168   printf("OpenGL window created.\n");
00169 
00170   glewInit();
00171   printf("Loading extensions: %s\n", glewGetErrorString(glewInit()));
00172 
00173     if (!glewIsSupported( "GL_VERSION_1_5 GL_ARB_vertex_buffer_object GL_ARB_pixel_buffer_object" )) {
00174       fprintf(stderr, "Error: failed to get minimal extensions for demo\n");
00175       fprintf(stderr, "This sample requires:\n");
00176       fprintf(stderr, "  OpenGL version 1.5\n");
00177       fprintf(stderr, "  GL_ARB_vertex_buffer_object\n");
00178       fprintf(stderr, "  GL_ARB_pixel_buffer_object\n");
00179       fflush(stderr);
00180       return -1;
00181   }
00182 
00183   return 0;
00184 }
00185 
00186 // ######################################################################
00187 //Compile the Assembly share code
00188 GLuint CudaImageDisplayGL::compileASMShader(GLenum program_type, const char *code)
00189 {
00190   GLuint program_id;
00191   glGenProgramsARB(1, &program_id);
00192   glBindProgramARB(program_type, program_id);
00193   glProgramStringARB(program_type, GL_PROGRAM_FORMAT_ASCII_ARB, (GLsizei) strlen(code), (GLubyte *) code);
00194 
00195   GLint error_pos;
00196   glGetIntegerv(GL_PROGRAM_ERROR_POSITION_ARB, &error_pos);
00197   if (error_pos != -1) {
00198     const GLubyte *error_string;
00199     error_string = glGetString(GL_PROGRAM_ERROR_STRING_ARB);
00200     fprintf(stderr, "Program error at position: %d\n%s\n", (int)error_pos, error_string);
00201     return 0;
00202   }
00203   return program_id;
00204 }
00205 
00206 
00207 // ######################################################################
00208 void CudaImageDisplayGL::initAllTex()
00209 {
00210   glEnable(GL_TEXTURE_2D);
00211   glGenTextures(MAX_SIZE, &gl_Tex);
00212   glGenBuffers(MAX_SIZE,&gl_PBO);
00213 
00214 }
00215 
00216 
00217 // ######################################################################
00218 void CudaImageDisplayGL::initOpenGLBuffers()
00219 {
00220   glEnable(GL_TEXTURE_2D);
00221   printf("Creating GL texture...\n");
00222   //Generating Texture
00223   glGenTextures(1, &(gl_Tex));
00224   //Binding Texture to GL_TEXTURE_2D
00225   glBindTexture(GL_TEXTURE_2D, gl_Tex);
00226   //Setting up paramters for the texture
00227   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
00228   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
00229   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00230   glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00231   //Allocating data from the Texture to h_Src {Texture->h_Src}
00232   if(count_buffer_runs == 0)
00233     glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8,mWinW,mWinH,0, GL_RGBA, GL_UNSIGNED_BYTE, h_Src);
00234 
00235   printf("Creating PBO...\n");
00236   //Generating Pixel Buffer Object
00237   glGenBuffers(1, &(gl_PBO));
00238   //Binding Pixel Buffer Object to Unpack buffer
00239   glBindBuffer(GL_PIXEL_UNPACK_BUFFER_ARB, gl_PBO);
00240   //Buffering Unpacked Buffer with h_Src data
00241   glBufferData(GL_PIXEL_UNPACK_BUFFER_ARB, mWinW * mWinH * 4, h_Src, GL_STREAM_COPY);
00242   //Register the PBO with CUDA
00243   CUDA_SAFE_CALL( cudaGLRegisterBufferObject(gl_PBO) );
00244   //CUT_CHECK_ERROR_GL();
00245   printf("PBO created.\n");
00246   //2 rotations for proper display
00247   glRotatef(180, 0, 0, 1);
00248   glRotatef(180, 0 ,1, 0);
00249   //load shader program
00250   shader = compileASMShader(GL_FRAGMENT_PROGRAM_ARB,shader_code);
00251   count_buffer_runs++;
00252 
00253 }
00254 
00255 // ######################################################################
00256 void CudaImageDisplayGL::cleanup()
00257 {
00258   glDeleteProgramsARB(1, &shader);
00259 }
00260 
00261 
00262 // ######################################################################
00263 void CudaImageDisplayGL::initMainWindow()
00264 {
00265   initGL(mWinW,mWinH);
00266 }
00267 
00268 
00269 // ######################################################################
00270 void CudaImageDisplayGL::initDispGL(CudaImage<PixRGB<float> > &src)
00271 {
00272   const int dev = src.getMemoryDevice();
00273   const Dims tile = CudaDevices::getDeviceTileSize1D(dev);
00274 
00275   CudaImage<unsigned int> dst = CudaImage<unsigned int>(src.getDims(),NO_INIT, src.getMemoryPolicy(), dev);
00276 
00277   CUDA_convert_float_uint((float3_t *) src.getCudaArrayPtr(),(unsigned int *) dst.getCudaArrayPtr(),tile.sz(),src.size());
00278   CUDA_MallocArray((unsigned int *)dst.getCudaArrayPtr(),src.getWidth(),src.getHeight(),0);
00279   CUDA_MallocArray((unsigned int *)dst.getCudaArrayPtr(),src.getWidth(),src.getHeight(),1);
00280   initOpenGLBuffers();
00281 }
00282 
00283 void CudaImageDisplayGL::idleFunction()
00284 {
00285   // Does nothing, subclasses might want to override
00286 }
00287 
00288 // ######################################################################
00289 void CudaImageDisplayGL::updateDispGL()
00290 {
00291 
00292   // Get the buffer that is not currently being used
00293   int newBufferIndex = (bufferIndex+1)%2;
00294   int w = framework.getCanvasW();
00295   int h = framework.getCanvasH();
00296   const Dims tile = CudaDevices::getDeviceTileSize1D(framework.getDev());
00297   CudaImage<unsigned int> dst = CudaImage<unsigned int>(Dims(w,h),NO_INIT, framework.getMP(), framework.getDev());
00298   // Critical section
00299 
00300   int lockAtt = framework.getLockAtt();
00301   switch(lockAtt)
00302     {
00303     case EINVAL:
00304     case EAGAIN:
00305     case EDEADLK:
00306       fprintf(stderr,"Canvas Lock is BROKEN!\n");
00307       exit(0);
00308       break;
00309     case EBUSY:
00310       // Ok, no updating this time
00311       break;
00312     default:
00313       // Copy new frame to the unused buffer
00314       //Get image handle
00315       CUDA_convert_float_uint((float3_t *)(framework.getCanvas()).getCudaArrayPtr(),(unsigned int *) dst.getCudaArrayPtr(),tile.sz(),w*h);
00316       framework.setCanvasModified(false);
00317       framework.setMutexUnlock();
00318       CUDA_UpdateArray((unsigned int *)dst.getCudaArrayPtr(),w,h,newBufferIndex) ;
00319       // Update buffer index so callback will now use this new buffer
00320       bufferIndex = newBufferIndex;
00321       glutPostRedisplay();
00322     }
00323 }
00324 
00325 
00326 bool CudaImageDisplayGL::getShutdown()
00327 {
00328     return shutdown;
00329 }
00330 
00331 void CudaImageDisplayGL::setShutdown(bool isShutdown)
00332 {
00333     shutdown = isShutdown;
00334 }
00335 
00336 // ######################################################################
00337 void CudaImageDisplayGL::timerFunction(int index)
00338 {
00339   if(getShutdown())
00340     return;
00341   if(framework.getCanvasModified())
00342     {
00343       //printf("Updating modified canvas\n");
00344       updateDispGL();
00345     }
00346   glutTimerFunc(1,timerWrapper,0);
00347 }
00348 // #####################################################################
00349 float CudaImageDisplayGL::getFPS()
00350 {
00351   return float(frameCounter)/float(tim.getSecs());
00352 }
00353 
00354 // ######################################################################
00355 void CudaImageDisplayGL::createDisplay(int w, int h)
00356 {
00357   mWinW = w;
00358   mWinH = h;
00359 
00360   initMainWindow();
00361   initDispGL(framework.getCanvas());
00362   glutTimerFunc(1,timerWrapper,0);
00363   tim.reset();
00364 }
00365 
00366 
00367 
00368 
Generated on Sun May 8 08:40:36 2011 for iLab Neuromorphic Vision Toolkit by  doxygen 1.6.3