OpenGl bloqué par une Thread !?

Signaler
Messages postés
16
Date d'inscription
samedi 4 novembre 2000
Statut
Membre
Dernière intervention
21 mars 2009
-
Messages postés
1054
Date d'inscription
samedi 2 octobre 2004
Statut
Membre
Dernière intervention
9 juillet 2013
-
Bonjour 


J'ai une animation (win32) OpenGL à laquelle j'essaie d'intégrer de la synthese sonore avec la lib STK.(...au passage, si vous en connaissez d'autres, tournant sous windows  )


Alors, mon problème vient du fait que le rendu graphique via une fonction glut:



main.cpp :

int main()
{
...
glutReshapeFunc(ReshapeCallback_1);
glutDisplayFunc(RenderCallback_1);
...
}

...est bloqué pendant le calcul du son, lancé par une classe Attack (pouvant avoir de multiples instances):



attack.cpp:

int Attack::tick( void *outputBuffer, void *inputBuffer, unsigned int nBufferFrames,
         double streamTime, RtAudioStreamStatus status, void *dataPointer )
{
  SineWave *sine = (SineWave *) dataPointer;
  register StkFloat *samples = (StkFloat *) outputBuffer;



  for ( unsigned int i=0; i<nBufferFrames; i++ )
    *samples++ = sine->tick();



  return 1;
}
//---------------------------------------------------------
bool Attack::play()
{


   SineWave sine;



  //- Figure out how many bytes in an StkFloat and setup the RtAudio stream.
  RtAudio::StreamParameters p;
  p.deviceId = dac.getDefaultOutputDevice();
  p.nChannels = 1;//_o_->channel;   RtAudioFormat format ( sizeof(StkFloat) 8 ) ? RTAUDIO_FLOAT64 : RTAUDIO_FLOAT32;



  //-The bufferFrames argument is an API-dependent buffering parameter (see RtAudio for further information).
  unsigned int bufferFrames = RT_BUFFER_SIZE;//defined in Stk.h.



//--1) OPEN STREAM
  try {



dac.openStream( &p,            //RtAudio::StreamParameters *outputParameters,
       NULL,           //RtAudio::StreamParameters *inputParameters,
       format,           // RtAudioFormat format, unsigned int sampleRate
       (unsigned int)Stk::sampleRate(), //unsigned int *bufferFrames
       &bufferFrames,       //RtAudioCallback callback, void *userData
       &Attack::tick,        //RtAudio::StreamOptions *options
       (void *)&sine
       );
}
 
  catch ( RtError &error ) {
    error.printMessage();
    goto cleanup;
  }



  sine.setFrequency( _o_->frequency );



  //--2) START STREAM
  try {
    dac.startStream();
}
  catch ( RtError &error ) {
    error.printMessage();
   goto cleanup;
}



// Block waiting here.
/*char keyhit;
  cout << "\nPlaying ... press <enter> to quit.\n";
  cin.get( keyhit );





  -> QUOI METTRE A LA PLACE (ci-dessus) ?? 



****************************************/



 cleanup:



 dac.closeStream();
 //delete dac;
 //_o_->func_killFM(_o_->id); 
}

... qui semble utiliser une thread , concept que je n'avais pas encore abordé


Je suis donc parti d'un exemple de Callback, dont une portion du code est en partie responsable du problème:

  // Block waiting here.
 char keyhit;
  cout << "\nPlaying ... press <enter> to quit.\n";
  cin.get( keyhit );


J'ai remplacé cette partie par

return 1;

... pensant que le son continuerait à jouer mais cela provoque une erreur (error.printMessage() ) -que je n'arrive pas à afficher- puisque

goto cleanup

...est aussitôt appelé !


Auriez-vous une solution 
merci

ps: On m'a suggéré de mettre un
return 1;

juste après startStream() , ou dans tick()
... ou encore de m'intéresser au concept de concurrence !??  mais je n'ai rien trouvé


 

23 réponses

Messages postés
1054
Date d'inscription
samedi 2 octobre 2004
Statut
Membre
Dernière intervention
9 juillet 2013
6
Salut
La solution est simple, il faut créer ta fenêtre open GL dans un autre thread. Pendant le calcul du son, cela ne bloquera plus l'affichage.
Regarde la fonction CreateThread()
A+

____________________________________________________________________________
Mon site internet :  
http://ImAnalyse.free.fr
Messages postés
16
Date d'inscription
samedi 4 novembre 2000
Statut
Membre
Dernière intervention
21 mars 2009

Super Pistol !

Merci du conseil, je regrade ça de suite ...

Une petite objection qd même, j'ai entendu dire :

"Keep all openGL code in single thread.
 The main thread - ie. the one which created the render context - is best"

que ça pourrait nuire aux peformances du programme, qu'en penses-tu ?
Messages postés
1054
Date d'inscription
samedi 2 octobre 2004
Statut
Membre
Dernière intervention
9 juillet 2013
6
En fait, ils disent qu'il faut que tous les appels aux fonctions d'OpenGL ne se fasse que dans un seul thread. Cela signifie que tu peux sans problème créer un thread pour OpenGL et un thread pour pour le son...
A+
____________________________________________________________________________
Mon site internet :  
http://ImAnalyse.free.fr
Messages postés
16
Date d'inscription
samedi 4 novembre 2000
Statut
Membre
Dernière intervention
21 mars 2009

Je pense avoir bien formulé la thread :




void RunPhysics()
{
 // Update the time step
 NxReal deltaTime = UpdateTime();
 deltaTime = 0.02f; 
 //gScene->simulate(deltaTime);
 gScene->simulate(1.0f/60.0f)
 gScene->flushStream();
 gFrameCounter++;
}
//------------------------------------------------------------------------------------
void RenderCallback_1()
{
 if (gScene && !bPause)

 RunPhysics();
 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

 PhysicCORE::updateCAMERA();
 RenderScene(bShadows);
 
 gPerfRenderer.render(gScene->readProfileData(true), glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT));

glutSwapBuffers();
}
//------------------------------------------------------------------------------------
void setThread_RENDER()

 DWORD dwID;
     HANDLE threadHandle = CreateThread(NULL,
                 NULL,
                   (LPTHREAD_START_ROUTINE)RenderCallback_1,
                   NULL,//(LPVOID)this,
                   NULL,
                   &dwID);
}



void init()
{
 ...
 glutReshapeFunc(ReshapeCallback_1);
 glutDisplayFunc(setThread_RENDER);
 ...
}

...mais un autre problème se pose, que j'aurais sans doute du préciser :
RenderCallback_1()  fait aussi appel aux fonctions d'un moteur de physique, dont son timer RunPhysic() ...

 J'obtiens alors cette erreur :

f:\scvista\experimental\PhysX_2.8.1\novodex...etc
invlid paramter: Scene::simulation is still processing last simulate call, you should call fetchResults() !

Il me propose d'apeller une fonction fetchResults() mais peut être qu'il faut revoir l'approche de la thread ?
Messages postés
1054
Date d'inscription
samedi 2 octobre 2004
Statut
Membre
Dernière intervention
9 juillet 2013
6
Je n'aurai pas fait du tout comme ca: la, a chaque fois que tu veux afficher qqchose avec OpenGL, tu va créer un thread...

dans ton main, tu devrais faire;
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInst, LPSTR lpCmdLine, int show)
{
   CreateThread(0,0,StartOpenGL,0,0,&ThreadId);
   ....

Regarde ma source elle pourra d'aider. Elle fait fonctionner OpenGL et une application en win32:
http://www.cppfrance.com/codes/SYNTHESE-IMAGE-BRUIT-PERLIN-TEXTURES-MARBRE-BOIS_47220.aspx

____________________________________________________________________________
Mon site internet :  
http://ImAnalyse.free.fr
Messages postés
16
Date d'inscription
samedi 4 novembre 2000
Statut
Membre
Dernière intervention
21 mars 2009

"a chaque fois que tu veux afficher qqchose avec OpenGL, tu va créer un thread..."

Bon sang que c'est idiot, j'avais pas compris ;-)

Un peu de repos et je regarde ta source...

merci
Messages postés
16
Date d'inscription
samedi 4 novembre 2000
Statut
Membre
Dernière intervention
21 mars 2009

Salut Pistol

En m'inspirant de ta source, mes mofifs donnent :

define.h:

#ifndef DEFINE_H
#define DEFINE_H

#include
#include
#include <sstream>
#include <strstream>
#include <string>
#include <vector>
#include
#include <numeric>



#if _MSC_VER > 1020  
   using namespace std; 
#endif



#include <GL/glut.h>
#include <stdio.h>
#include "NxPhysics.h"
#include "math.h"





main.h:

#ifndef MAIN_H
#define MAIN_H



#include "define.h"
//********************* AJOUTé pour les THREAD
#include <windows.h>
#include <time.h>
//**********************



#include



#include "NxCooking.h"
#include "DebugRenderer.h"
#include "PerfRenderer.h"


...
...
DWORD WINAPI StartOpenGL(LPVOID Param);
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInst, LPSTR lpCmdLine, int show);
#endif

Main.cpp:

#include "Main.h"
//---SDK
#include "ErrorStream.h"
#include "Utilities.h"
#include "SamplesVRDSettings.h"
//---Resource filter
#include "Timing.h"
#include "GLFontRenderer.h"
...
...

void RenderCallback_1()
{
 if (gScene && !bPause)
 RunPhysics();
 
 // Clear buffers
 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);



 engine.gereScene();
 PhysicCORE::updateCAMERA();
 PhysicCORE::updateSHAPES();
 
RenderScene(bShadows);



 ...
 ...



 // Print profile results (if enabled)
 gPerfRenderer.render(gScene->readProfileData(true), glutGet(GLUT_WINDOW_WIDTH), glutGet(GLUT_WINDOW_HEIGHT));
 glutSwapBuffers();
}

void InitGlut_1()
{
 int argc=1;
 char **argv=0;
 argv=new char*[2];
 argv[0]=new char[10];
 argv[1]=new char[10];
 
 strcpy(argv[0],"Name");
 //........................................



 glutInit(&argc, argv);
 glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);





 int x1=1400-wnW;int y1=50;
 glutInitWindowSize(wnW, wnH);
 glutInitWindowPosition(x1,y1);


 //........................................
 delete []argv[0];
 delete []argv[1];
 delete []argv;
 
 //........................................


 f1 = glutCreateWindow("SCENE");
 glutSetWindow(f1);


 InitGlut_0();


 glutReshapeFunc(ReshapeCallback_1);
 glutDisplayFunc(RenderCallback_1);//setThread_RENDER);//


 glutIdleFunc(IdleCallback);
 glutKeyboardFunc(KeyboardCallback);// DOWN
 glutKeyboardUpFunc(KeyboardUpCallback);// UP
 
 glutMouseFunc(MouseCallback);
 glutMotionFunc(MotionCallback);
 MotionCallback(0,0);




 atexit(ExitCallback);
 }
//------------------------------------

DWORD WINAPI StartOpenGL(LPVOID Param)





 InitGlut_1();



 // Initialize physics scene and start the application main loop if scene was created
 if (InitNx())//engine.init())//
 {
  glutMainLoop();
 }
 else
 {
  engine.~Engine(); 
  ReleaseNx();
 }



  return 0;
}
//-------------------------------------------------------------



int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInst, LPSTR lpCmdLine, int show)
{



 PrintControls();
  //---Initialisation du moteur
    if(engine.init())
 {//--passing Function through Struct in arg
       usrIn_o* o = new usrIn_o;
             o->getPhyxTM = *getPhysxTime;//timeGetTime;//
  engine.setPROP_o( o );
 }
 else
 {
        return EXIT_FAILURE;
 }



 #ifdef OPENGL
 CreateThread(0,0,StartOpenGL,0,0,&ThreadId);
 #endif





 //HWND hwnd;
    MSG msg;
 
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }


    return (int)msg.wParam;


}

...j'ai du faire une erreur qlqpart car j'obtiens cette erreur  :

error LNK2019: unresolved external symbol _main referenced in function ___tmainCRTSartup

File: MSVCRT.lib !
Messages postés
1054
Date d'inscription
samedi 2 octobre 2004
Statut
Membre
Dernière intervention
9 juillet 2013
6
Salut
Si tu as créé un projet console, il faut remplacer leWinMain par main.

A+
____________________________________________________________________________
Mon site internet :  
http://ImAnalyse.free.fr
Messages postés
16
Date d'inscription
samedi 4 novembre 2000
Statut
Membre
Dernière intervention
21 mars 2009

int WINAPI main( HINSTANCE hInstance, HINSTANCE hPrevInst, LPSTR lpCmdLine, int show);



j'ai tjrs la même erreur !
Messages postés
16
Date d'inscription
samedi 4 novembre 2000
Statut
Membre
Dernière intervention
21 mars 2009

L'erreur est là même mais je viens de voir que j'avais oublié de déclacer:



DWORD ThreadId



qui n'était pas détecter à cause les #ifdef (non utilisé) dans int WINAPI main(...

//#ifdef OPENGL
CreateThread(0,0,StartOpenGL,0,0,&ThreadId);
//#endif




 
Messages postés
1054
Date d'inscription
samedi 2 octobre 2004
Statut
Membre
Dernière intervention
9 juillet 2013
6
C'est juste
int main()
{
...

}
A+

____________________________________________________________________________
Mon site internet :  
http://ImAnalyse.free.fr
Messages postés
16
Date d'inscription
samedi 4 novembre 2000
Statut
Membre
Dernière intervention
21 mars 2009

Ok, mais alors faut-il remplacer

WINAPI
par quelque chose ?








//DWORD WINAPI StartOpenGL(LPVOID Param)








DWORD ??? StartOpenGL(LPVOID Param)

{
...
}
int

main(
int
argc,
char
** argv)
{

CreateThread(0,0,StartOpenGL,0,0,&ThreadId);

return
0;
}

...avec main à la place ça donne rien et sans rien du tout ça me renvoie une erreur:

C2664 'CreateThread' : cannot convert parameter 3 from 'DWORD(... to LPTHREAD_START_ROUTINE)
Messages postés
1054
Date d'inscription
samedi 2 octobre 2004
Statut
Membre
Dernière intervention
9 juillet 2013
6
Ta première erreur etait qu'il ne trouvais pas le point d'entré de ton programme soit la fonction main...
Si tu es en programmation console, il faut mettre :
main(
int
argc,
char
** argv)

Si window:
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInst, LPSTR lpCmdLine, int show)

ca donne:
DWORD WINAPI StartOpenGL(LPVOID Param)

{
...
}
int main(
int
argc,
char
** argv)
{

CreateThread(0,0,StartOpenGL,0,0,&ThreadId);

return
0;
A+
____________________________________________________________________________
Mon site internet :  
http://ImAnalyse.free.fr
Messages postés
16
Date d'inscription
samedi 4 novembre 2000
Statut
Membre
Dernière intervention
21 mars 2009

Je suis bien en mode console et j'ai donc gardé






DWORD WINAPI StartOpenGL(LPVOID Param)

mais alors ça compile mais grosse alerte:

DEBUG ASSERT FAILED
file: dbgdel.cpp
EXPRESSION: _BLOCK_TYPER_IS_VALID(pHEAD->nBlockUse)

ps: ma RunTime Library était réglée sur Multi-threaded Debug (/MTd)
avant d'être sur Multi-threaded Debug DLL (/MDd), comme dans ton exemple.
Messages postés
1054
Date d'inscription
samedi 2 octobre 2004
Statut
Membre
Dernière intervention
9 juillet 2013
6
Je laisse toujours les options de debug par default, je ne touche que les options du compilo pour le mode release.

Pour ton erreur essaie de localiser précisément de quelle ligne provient l'erreur. Regarde la pile des appelants en mode debug. Tu dois écrire dans un emplacement mémoire invalide.  
A+
____________________________________________________________________________
Mon site internet :  
http://ImAnalyse.free.fr
Messages postés
16
Date d'inscription
samedi 4 novembre 2000
Statut
Membre
Dernière intervention
21 mars 2009

...apparement ça venait de la classe Engine (

Engine engine; déclarée hors des fonctions, comme ThreadId). Je ne sais si ça a son importance... je précise qd même

Maintenant, je n'ai plus d'erreur mais le programme de ferme aussitôt !!?
ps: z'suis presque
Messages postés
1054
Date d'inscription
samedi 2 octobre 2004
Statut
Membre
Dernière intervention
9 juillet 2013
6
Je suis pas sure que ce soit mieux comme erreur...
Met des break point un peu partout dans ton prog et essaie de savoir à quel moment ton programme s'arrète. Quand tu auras localisé la ligne ce sera facile de corriger l'erreur.
A+
____________________________________________________________________________
Mon site internet :  
http://ImAnalyse.free.fr
Messages postés
16
Date d'inscription
samedi 4 novembre 2000
Statut
Membre
Dernière intervention
21 mars 2009

Effectivement, je trifouille depuis tout à l'heure mais l'obscurité demeure....
Allumons les breakpoints ***
Messages postés
16
Date d'inscription
samedi 4 novembre 2000
Statut
Membre
Dernière intervention
21 mars 2009

Le BreakPoint saute à partir d'ici (->):












void





InitGlut_1()





{



glutInitWindowSize(wnW, wnH);

glutInitWindowPosition(50,50);




//x1,y1);





delete






[]argv[0];





delete






[]argv[1];





delete






[]argv;






f1 = glutCreateWindow(




"SCENE"






);



->
glutSetWindow(f1);


...f1 renvoie 0 !?
Messages postés
16
Date d'inscription
samedi 4 novembre 2000
Statut
Membre
Dernière intervention
21 mars 2009

J'ai recréé un projet simplifié n'affichant qu'un cube, tjrs en mode console et ...
Paf ! pareil, fermeture instantanée !
Et les breakpoints ne fonctionnent pas tjrs
Alors ça vient soi de l'écriture de la thread soi de mon prog !!?

La src complète:

define.h:



#ifndef DEFINE_H
#define DEFINE_H

//.....................
#include <windows.h>
#include <time.h>
//.....................
#include
#include <vector>
#include
#include <numeric>

#if _MSC_VER > 1020
   using namespace std;
#endif
//..............

#define OPENGL
#ifdef OPENGL
#include <GL/glut.h>//#include "glut.h"
//#pragma comment(lib,"glut32.lib")
#endif

#include <stdio.h>
#include "math.h"

#endif







main.h

:



#ifndef MAINL_H
#define MAIN_H



#include "define.h"



int wnW=800;
int wnH=700;
float gX;
float gY;
float gZ;
//-----------------
void updateCAMERA();
void DRAW();
void RenderCallback();
void ReshapeCallback(int w, int h);
void update(int value);
void InitGlut(void);
DWORD WINAPI StartOpenGL(LPVOID Param);
int main(int argc, char** argv);
#endif




main.cpp:



#include "Main.h"



int  f1;
int gViewWidth = 0;
int gViewHeight = 0;
int gCameraFov = 40.0f;
static float gEye[3] = {0,0,15};//50.0f, 10.0f, 50.0f);
static float gDir[3] = {0,0,-1};//-0.6f,-0.2f,-0.7f);
static float gViewY[3] = {1,0,0};



//...............
#ifdef OPENGL
DWORD ThreadId;       
#endif
//...............


//-----------------------------------------------------
void updateCAMERA()
{
 glMatrixMode(GL_PROJECTION);
 glLoadIdentity();
 gluPerspective(gCameraFov, ((float)glutGet(GLUT_WINDOW_WIDTH)/(float)glutGet(GLUT_WINDOW_HEIGHT)), 1.0f, 10000.0f);
 gluLookAt(gEye[0],gEye[1],gEye[2],  gEye[0]+gDir[0], gEye[1]+gDir[1], gEye[2] + gDir[2], 0.0f, 1.0f, 0.0f);
 glMatrixMode(GL_MODELVIEW);
 glLoadIdentity();
}
//-------------------------------------------------------------
void DRAW()
{
 gX += .001;
 gZ += .001;
  glTranslated(gX,gY,gZ);//glTranslatef(X,Y,Z);
   glPushMatrix();



     for (int i = 0; i < 4; i++)
     {
         glColor3f(0.9f,0.0f,0.3f); 


         glBegin(GL_QUADS);
         glTexCoord2d(0,3); glVertex3d(1,1,1);   //glVertex3f(-1.0f, 1.0f, 0.0f);
         glTexCoord2d(0,0); glVertex3d(1,1,-1);  //glVertex3f( 1.0f, 1.0f, 0.0f);
         glTexCoord2d(3,0); glVertex3d(-1,1,-1);  //glVertex3f( 1.0f,-1.0f, 0.0f);
         glTexCoord2d(3,3); glVertex3d(-1,1,1);  //glVertex3f(-1.0f,-1.0f, 0.0f);
         glEnd();
         glRotated(90,0,0,1);
     }
      glBegin(GL_QUADS);
      glTexCoord2d(0,0); glVertex3d(1,-1,1);
      glTexCoord2d(1,0); glVertex3d(1,1,1);
      glTexCoord2d(1,1); glVertex3d(-1,1,1);
      glTexCoord2d(0,1); glVertex3d(-1,-1,1);
      glEnd();
      glPopMatrix();
}



// ------------------------------------------------------
void RenderCallback()
{
 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
 updateCAMERA();
 DRAW();
 glutSwapBuffers(); 
}
// ------------------------------------------------------
void ReshapeCallback(int w, int h)
{
 gViewWidth = w;
 gViewHeight = h;
 glViewport(0, 0, w, h);
 glMatrixMode(GL_PROJECTION);
    glLoadIdentity();
    gluOrtho2D (0, (float)glutGet(GLUT_WINDOW_WIDTH), 0, (float)glutGet(GLUT_WINDOW_HEIGHT));        glMatrixMode(GL_MODELVIEW);
   glLoadIdentity();
}



//--------------------------------------------------------
void update(int value)
{
 glutPostRedisplay();
 glutTimerFunc(25, update, 0);
}
//--------------------------------------------------------
void InitGlut()
{
 //........................................
 int argc=1;
 char **argv=0;
 argv=new char*[2];
 argv[0]=new char[10];
 argv[1]=new char[10]; 
 strcpy(argv[0],"Name");
 //........................................



 glutInit(&argc, argv);
 glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
 
//---WINDOW

glutInitWindowSize(wnW, wnH);
glutInitWindowPosition(50,50);

//........................................
 delete []argv[0];
 delete []argv[1];
 delete []argv;
 //........................................
 f1 = glutCreateWindow("SCENE");
 glutSetWindow(f1);

//---------------
 glClearColor(0.52f, 0.60f, 0.71f, 1.0f); 
 glEnable(GL_DEPTH_TEST);
 glEnable(GL_COLOR_MATERIAL);
 glShadeModel(GL_SMOOTH);

glEnable(GL_LIGHTING);
    float AmbientColor[]    = { 0.0f, 0.1f, 0.2f, 0.0f };         glLightfv(GL_LIGHT0, GL_AMBIENT, AmbientColor);
    float DiffuseColor[]    = { 0.8f, 0.8f, 0.8f, 0.0f };         glLightfv(GL_LIGHT0, GL_DIFFUSE, DiffuseColor);
    float SpecularColor[]   = { 0.7f, 0.7f, 0.7f, 0.0f };         glLightfv(GL_LIGHT0, GL_SPECULAR, SpecularColor);
 float Position[]        = { 10.0f, 10.0f, 10.0f, 0.0f };  glLightfv(GL_LIGHT0, GL_POSITION, Position);
    glEnable(GL_LIGHT0);



  glEnable(GL_AUTO_NORMAL);
  glEnable(GL_NORMALIZE);
  glDepthFunc(GL_LESS);
  glEnable(GL_ALPHA_TEST);
  glEnable(GL_BLEND);
  glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA);

 //-------------

 glutReshapeFunc(ReshapeCallback);
 glutDisplayFunc(RenderCallback);
 glutTimerFunc(25, update, 0);



}
//------------------------------------------------------
DWORD WINAPI StartOpenGL(LPVOID Param)
{
 InitGlut_1();
 glutMainLoop(); 
 return 0;
}
//-----------------------------------------------------
int main(int argc, char** argv)
{
 #ifdef OPENGL
  CreateThread(0,0,StartOpenGL,0,0,&ThreadId);
 #endif
 return 0;
}


... si tu ne vois pas d'incohérences,
peux-tu compiler ce code pour voir ?