OpenVideo Documentation

   Main Page       Modules       Class Hierarchy       Alphabetical List       Compound List       File List       Compound Members       Related Pages   

GLUTSink.cxx

Go to the documentation of this file.
00001 /* ========================================================================
00002  * Copyright (C) 2005  Graz University of Technology
00003  *
00004  * This framework is free software; you can redistribute it and/or modify
00005  * it under the terms of the GNU General Public License as published by
00006  * the Free Software Foundation; either version 2 of the License, or
00007  * (at your option) any later version.
00008  *
00009  * This framework is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this framework; if not, write to the Free Software
00016  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
00017  *
00018  * For further information please contact Denis Kalkofen under
00019  * <kalkofen@icg.tu-graz.ac.at> or write to Denis Kalkofen,
00020  * Graz University of Technology, Inffeldgasse 16a, A8010 Graz,
00021  * Austria.
00022  * ========================================================================
00023  * PROJECT: OpenVideo
00024  * ======================================================================== */
00033 #include <openvideo/nodes/GLUTSink.h>
00034 #include <openvideo/openVideo.h>
00035 
00036 #ifdef ENABLE_GLUTSINK
00037 
00038 #include <openvideo/State.h>
00039 #include <openvideo/Manager.h>
00040 
00041 #include <GL/gl.h>
00042 #include <GL/glut.h>
00043 #include <GL/glu.h>
00044 
00045 #if defined(WIN32)&&(_MSC_VER>=1400)
00046 // somehow ::TryEnterCriticalSection() is not declared in release build...
00047 // (needed by ACE)
00048 BOOL TryEnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
00049 #endif //WIN32
00050 
00051 #include <ace/OS.h>
00052 #include <ace/Thread.h>
00053 #include <ace/Condition_Thread_Mutex.h>
00054 #include <ace/Thread_Mutex.h>
00055 #include <ace/Mutex.h>
00056 
00057 #include <iostream>
00058 
00059 #if defined(OV_IS_WINXP) && !defined(_IS_KLIMTES_)
00060 #pragma comment(lib,"opengl32.lib")
00061 #pragma comment(lib,"glu32.lib")
00062 #pragma comment(lib,"glut32.lib")
00063 #endif
00064 
00065 using namespace openvideo;
00066 
00067 bool GLUTSink::isGlutThread=false;
00068 std::vector<GLUTSink*> GLUTSink::glutSinks;
00069 bool GLUTSink::glutRedraw=false;
00070 
00071 
00072 GLUTSink::GLUTSink()
00073 {
00074     name = typeName = "GLUTSink";
00075     state=NULL;
00076     originX=originY=0;
00077     width=height=0;
00078     updateVideo=false;
00079     internalFormat=0;
00080     glContext=NULL;
00081     updateCtr = 0;
00082 #ifdef LINUX
00083     dsp=NULL;    
00084 #endif
00085 
00086 }
00087 
00088 #ifdef WIN32
00089 HGLRC 
00090 GLUTSink::getGLContext()
00091 {
00092     return glContext;
00093 }
00094 
00095 HDC   
00096 GLUTSink::getDeviceHandle()
00097 {
00098     return dc;
00099 }
00100 #endif 
00101 
00102 #ifdef LINUX
00103 GLXContext
00104 GLUTSink::getGLContext()
00105 {
00106     return glContext;
00107 }
00108 
00109 GLXDrawable
00110 GLUTSink::getDeviceHandle()
00111 {
00112     return dc;
00113 }
00114 
00115 Display*
00116 GLUTSink::getDisplay() {
00117     return dsp;
00118 }
00119 #endif 
00120 
00121 void 
00122 GLUTSink::initPixelFormats()
00123 {
00124     //format_r8g8b8 = 0,
00125     //format_b8g8r8 = 1,
00126     //format_r8g8b8x8   = 2,
00127     //format_b8g8r8x8   = 3,
00128     //format_l8     = 5,
00129     this->pixelFormats.push_back(PIXEL_FORMAT(FORMAT_R8G8B8));
00130     this->pixelFormats.push_back(PIXEL_FORMAT(FORMAT_B8G8R8));
00131     this->pixelFormats.push_back(PIXEL_FORMAT(FORMAT_R8G8B8X8));
00132     this->pixelFormats.push_back(PIXEL_FORMAT(FORMAT_B8G8R8X8));
00133     this->pixelFormats.push_back(PIXEL_FORMAT(FORMAT_L8));
00134 }
00135 
00136 GLUTSink::~GLUTSink()
00137 {
00138 }
00139 
00140 
00141 void*
00142 GLUTSink::mainLoop(void *)
00143 {
00144 
00145     glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE );
00146 
00147 
00148     //wait 'till all glutsinks are loaded ='till the process() call happens
00149 
00150     for(int i=0;i<(int)GLUTSink::glutSinks.size();i++)
00151     {
00152         GLUTSink *glutSink=GLUTSink::glutSinks[i];
00153         glutInitWindowPosition (glutSink->originX, glutSink->originY );
00154         int w,h;
00155         if(glutSink->width==0)
00156             w=1;
00157         else
00158             w=glutSink->width;
00159         if( glutSink->height==0)
00160             h=1;
00161         else
00162             h=glutSink->height;
00163         glutInitWindowSize (w,h);
00164         glutSink->winHandle=glutCreateWindow(glutSink->getName());
00165         glutDisplayFunc(GLUTSink::mainDisplayFunc);
00166         glutIdleFunc(GLUTSink::idleFunc);
00168 #ifdef WIN32
00169         glutSink->glContext=wglGetCurrentContext();
00170         glutSink->dc=wglGetCurrentDC();
00171 #endif
00172 #ifdef LINUX
00173         glutSink->dc=glXGetCurrentDrawable();
00174         glutSink->dsp=glXGetCurrentDisplay();
00175         glutSink->glContext=glXGetCurrentContext();
00176 #endif
00177 
00179         //create texture
00180         glEnable(GL_TEXTURE_2D);
00181         long data_size = 4 * sizeof(GLubyte) * TEXTURE_WIDTH * TEXTURE_HEIGHT;
00182         GLubyte *data = (GLubyte*)malloc(data_size);
00183         memset(data, 0xFF, data_size);
00184         glGenTextures(1, &glutSink->video_texture_id);
00185         glBindTexture(GL_TEXTURE_2D, glutSink->video_texture_id);
00186         glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR);
00187         glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR);
00188         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
00189         glTexImage2D(GL_TEXTURE_2D, 0, glutSink->internalFormat, TEXTURE_WIDTH, TEXTURE_HEIGHT, 0,
00190                     glutSink->format, GL_UNSIGNED_BYTE, data);
00191 
00192         glDisable(GL_TEXTURE_2D);
00193         free(data);
00195     }
00196     //save context
00197     //if((int)(GLUTSink::glutSinks.size())>0)
00198     //    Manager::getInstance()->setGLContext(GLUTSink::glutSinks[0]->getGLContext(),GLUTSink::glutSinks[0]->getDeviceHandle());
00199     glutMainLoop();
00200     
00201     return 0;
00202 }
00203 
00204 void 
00205 GLUTSink::init()
00206 {
00207    Manager::getInstance()->getLogger()->logEx("OpenVideo: init GLUTSink '%s' \n",name.c_str());
00208     //glteximage2d supported formats
00209     //glteximage2d supported formats
00211     //gl_color_index    each element is a single value, a color index. it is converted to fixed point (with an unspecified number of 0 bits to the right of the binary point), shifted left or right depending on the value and sign of gl_index_shift, and added to gl_index_offset (see glpixeltransfer). the resulting index is converted to a set of color components using the gl_pixel_map_i_to_r, gl_pixel_map_i_to_g, gl_pixel_map_i_to_b, and gl_pixel_map_i_to_a tables, and clamped to the range [0,1].
00212     //gl_red    each element is a single red component. it is converted to floating point and assembled into an rgba element by attaching 0.0 for green and blue, and 1.0 for alpha. each component is then multiplied by the signed scale factor gl_c_scale, added to the signed bias gl_c_bias, and clamped to the range [0,1] (see glpixeltransfer).
00213     //gl_green  each element is a single green component. it is converted to floating point and assembled into an rgba element by attaching 0.0 for red and blue, and 1.0 for alpha. each component is then multiplied by the signed scale factor gl_c_scale, added to the signed bias gl_c_bias, and clamped to the range [0,1] (see glpixeltransfer).
00214     //gl_blue   each element is a single blue component. it is converted to floating point and assembled into an rgba element by attaching 0.0 for red and green, and 1.0 for alpha. each component is then multiplied by the signed scale factor gl_c_scale, added to the signed bias gl_c_bias, and clamped to the range [0,1] (see glpixeltransfer).
00215     //gl_alpha  each element is a single red component. it is converted to floating point and assembled into an rgba element by attaching 0.0 for red, green, and blue. each component is then multiplied by the signed scale factor gl_c_scale, added to the signed bias gl_c_bias, and clamped to the range [0,1] (see glpixeltransfer).
00216     //gl_rgb    each element is an rgb triple. it is converted to floating point and assembled into an rgba element by attaching 1.0 for alpha. each component is then multiplied by the signed scale factor gl_c_scale, added to the signed bias gl_c_bias, and clamped to the range [0,1] (see glpixeltransfer).
00217     //gl_rgba   each element is a complete rgba element. it is converted to floating point. each component is then multiplied by the signed scale factor gl_c_scale, added to the signed bias gl_c_bias, and clamped to the range [0,1] (see glpixeltransfer).
00218     //gl_luminance  each element is a single luminance value. it is converted to floating point, and then assembled into an rgba element by replicating the luminance value three times for red, green, and blue, and attaching 1.0 for alpha. each component is then multiplied by the signed scale factor gl_c_scale, added to the signed bias gl_c_bias, and clamped to the range [0,1] (see glpixeltransfer).
00219     //gl_luminance_alpha    each element is a luminance/alpha pair. it is converted to floating point, and then assembled into an rgba element by replicating the luminance value three times for red, green, and blue. each component is then multiplied by the signed scale factor gl_c_scale, added to the signed bias gl_c_bias, and clamped to the range [0,1] (see glpixeltransfer).
00220 
00221     //windows extension
00222     //gl_bgr_ext    each pixel is a group of three components in this order: blue, green, red. gl_bgr_ext provides a format that matches the memory layout of windows device-independent bitmaps (dibs). thus your applications can use the same data with win32 function calls and opengl pixel function calls.
00223     //gl_bgra_ext   each pixel is a group of four components in this order: blue, green, red, alpha. gl_bgra_ext provides a format that matches the memory layout of windows device-independent bitmaps (dibs). thus your applications can use the same data with win32 function calls and opengl pixel function calls.
00224 
00225     //
00226     //enum pixel_format {
00227     //format_r8g8b8 = 0,
00228     //format_b8g8r8 = 1,
00229     //format_r8g8b8x8   = 2,
00230     //format_b8g8r8x8   = 3,
00231     //format_r5g6b5 = 4,
00232     //format_l8     = 5,
00233 
00234     //format_unknown    = 6
00235     //};
00236     
00237     // map ov to gl pixel format and set gl_texture_2d_sink's format
00238     switch(curPixelFormat)
00239     {
00240         case FORMAT_R8G8B8:
00241             format=GL_RGB;
00242             internalFormat=3;
00243             break;
00244 
00245         case FORMAT_B8G8R8:
00246             format=GL_BGR_EXT;
00247             internalFormat=3;
00248             break;
00249         
00250         case FORMAT_R8G8B8X8:
00251             format=GL_RGBA;
00252             internalFormat=4;
00253             break;
00254 
00255         case FORMAT_B8G8R8X8:
00256             format=GL_BGRA_EXT;
00257             internalFormat=4;
00258             break;
00259 
00260 
00261 //      case FORMAT_R5G6B5:
00262 //          format=;
00263 //          internalFormat=;
00264 //          break;
00265 
00266         case FORMAT_L8:
00267             format=GL_LUMINANCE;
00268             internalFormat=GL_LUMINANCE8;
00269             break;
00270 
00271         default:
00272             Manager::getInstance()->getLogger()->logEx("GL_TEXTURE_2D_Sink does not suppport the current pixel format %s\n",
00273                 (PixelFormat::FormatToString(curPixelFormat)).c_str());
00274             exit(-1);
00275 
00276     }
00277     //get the first state 
00278     
00279     //states this sink 'lives' in
00280     if(inputs.size()<=0)
00281         return;
00282     state=this->inputs[0]->getState();
00283     if(state)
00284     {
00285         this->width=state->width;
00286         this->height=state->height;
00287 
00288         flip_h = false; 
00289         flip_v = true;
00290         
00291         float u_rt = (float)width / TEXTURE_WIDTH;
00292         float v_rt = (float)height / TEXTURE_HEIGHT;
00293         
00294         t_u0 = (flip_h ? u_rt : 0   );
00295         t_u1 = (flip_h ?    0 : u_rt);
00296         t_v0 = (flip_v ? v_rt : 0   );
00297         t_v1 = (flip_v ?    0 : v_rt);
00298         //
00299         GLUTSink::glutSinks.push_back(this);
00300     }// if(state)
00301 }
00302 
00303 void
00304 GLUTSink::start()
00305 {
00306     Manager::getInstance()->getLogger()->log("GLUTSink::start()\n");
00307     if(!GLUTSink::isGlutThread){
00308         //start glut in a new thread
00309         GLUTSink::isGlutThread=true;
00310         ACE_hthread_t* threadHandle = new ACE_hthread_t();
00311         if(ACE_Thread::spawn((ACE_THR_FUNC)GLUTSink::mainLoop,
00312                 0,  
00313                 THR_NEW_LWP|THR_JOINABLE,   
00314                 0,  
00315                 threadHandle,
00316                 0,  
00317                 0,  
00318                 0
00319         )==-1)
00320         { 
00321             Manager::getInstance()->getLogger()->log("Error in spawning thread\n"); 
00322         }
00323     }
00324 }
00325 
00326 
00327 void
00328 GLUTSink::process()
00329 {
00330     if(!state)
00331         return;
00332 
00333     if(Buffer* buffer = state->getCurrentBuffer())
00334         bufferSychronizer.assign(buffer);
00335 }
00336 
00337 
00338 void 
00339 GLUTSink::updateTexture()
00340 {
00341     // bufferSychronizer does all the synchronization work...
00342     //
00343     if(Buffer* buffer = bufferSychronizer.getLocked())
00344     {
00345         // only update if this buffer contains new content!
00346         //
00347         if(updateCtr != buffer->getUpdateCounter())
00348         {
00349             updateCtr = buffer->getUpdateCounter();
00350             glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
00351             glEnable(GL_TEXTURE_2D);
00352             glBindTexture(GL_TEXTURE_2D, video_texture_id);
00353             glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 
00354                             width,height, this->format, GL_UNSIGNED_BYTE,
00355                             (void*)buffer->getPixels());
00356             glDisable(GL_TEXTURE_2D);
00357             //printf("T");
00358         }
00359         else
00360         {
00361             //printf("t");
00362         }
00363 
00364         buffer->unlock();
00365     }
00366 }
00367 
00368 
00369 void 
00370 GLUTSink::redraw()
00371 {
00372     //preGLCalls()
00373     glPushMatrix();
00374     glMatrixMode(GL_PROJECTION);
00375     glPushMatrix();
00376     glLoadIdentity();
00377     glMatrixMode(GL_MODELVIEW);
00378     glLoadIdentity();
00379     glPushAttrib(GL_ALL_ATTRIB_BITS);
00380     glDisable(GL_DEPTH_TEST);
00381     glDepthMask(GL_FALSE);
00382     glDisable(GL_LIGHTING);
00383     glDisable(GL_ALPHA_TEST);
00384     glDisable(GL_BLEND);
00386     
00387     glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
00388     glEnable(GL_TEXTURE_2D);
00389     
00390     // redraw texture
00391     glBindTexture(GL_TEXTURE_2D, video_texture_id);
00392     glBegin(GL_QUADS);
00393     // video backplate
00394     glTexCoord2f(t_u0,t_v0); glVertex3f(-1.0f, -1.0f,  0.0f);
00395     glTexCoord2f(t_u1,t_v0); glVertex3f( 1.0f, -1.0f,  0.0f);
00396     glTexCoord2f(t_u1,t_v1); glVertex3f( 1.0f,  1.0f,  0.0f);
00397     glTexCoord2f(t_u0,t_v1); glVertex3f(-1.0f,  1.0f,  0.0f);
00398     glEnd();
00399     
00400     glDisable(GL_TEXTURE_2D);
00401     
00403     glPopAttrib();
00404     glMatrixMode(GL_PROJECTION);
00405     glPopMatrix();
00406     glMatrixMode(GL_MODELVIEW);
00407     glPopMatrix();
00408 }
00409 
00410 void 
00411 GLUTSink::idleFunc()
00412 {
00413     glutPostRedisplay();
00414 }
00415 
00416 void 
00417 GLUTSink::mainDisplayFunc()
00418 {
00419     if(Manager::getInstance()->glContextChanged)
00420         //if(!wglGetCurrentContext())
00421     {
00422         printf("GLUTSINK::try to set new gl context \n");
00423         if((int)(GLUTSink::glutSinks.size())>0)
00424         {
00425 #ifdef WIN32
00426             bool hasGLContext=wglMakeCurrent(GLUTSink::glutSinks[0]->getDeviceHandle(),GLUTSink::glutSinks[0]->getGLContext());
00427 #endif
00428 #ifdef LINUX
00429             bool hasGLContext=glXMakeCurrent(GLUTSink::glutSinks[0]->getDisplay(),
00430                              GLUTSink::glutSinks[0]->getDeviceHandle(),
00431                              GLUTSink::glutSinks[0]->getGLContext());
00432 #endif
00433 
00434             if(hasGLContext)
00435                 Manager::getInstance()->getLogger()->logEx("OpenVideo: successfully set new glContext in GLUTSink thread\n") ;
00436             else{
00437                 Manager::getInstance()->getLogger()->logEx("OpenVideo: couldn't set new glContext\n");
00438                 return;
00439             }
00440         }
00441         Manager::getInstance()->glContextChanged=false;
00442     }
00443 
00444     int size=(int)GLUTSink::glutSinks.size();
00445     for (int i=0;i<size;i++)
00446     {   
00447         glutSetWindow(glutSinks[i]->winHandle);
00448         glutSinks[i]->updateTexture();
00449         glutSinks[i]->redraw();
00450     }
00451 
00452     glutSwapBuffers();
00453     //Sleep(10);
00454 }
00455 
00456 #endif //ENABLE_GLUTSINK
 This page was generated at Wed May 31 13:04:16 2006 for OpenVideo by Doxygen.
 If you have any comments, please send a message to schmalstieg@icg.tu-graz.ac.at.
www.studierstube.org