1.4.2. demos/sdl/sdl-1.01.02

Start felix section to demos/sdl/sdl-1.01.02-0.flx[1 /1 ]
     1: #line 2942 "./lpsrc/flx_sdl.pak"
     2: // REQUIRES OpenGL and GLU
     3: /*
     4:  * This code was created by Jeff Molofee '99
     5:  * (ported to Linux/SDL by Ti Leggett '01)
     6:  *
     7:  * If you've found this code useful, please let me know.
     8:  *
     9:  * Visit Jeff at http://nehe.gamedev.net/
    10:  *
    11:  * or for port-specific comments, questions, bugreports etc.
    12:  * email to leggett@eecs.tulane.edu
    13:  */
    14: 
    15: #import <flx.flxh>
    16: include "SDL/SDL";
    17: include "SDL/SDL_keyboard";
    18: include "SDL/SDL_keysym";
    19: include "SDL/SDL_video";
    20: include "SDL/SDL_events";
    21: include "SDL/SDL_timer";
    22: include "SDL/SDL_mutex";
    23: include "SDL/SDL_opengl";
    24: 
    25: include "flx_faio";
    26: include "flx_faio_sdl";
    27: 
    28: 
    29: open C_hack;
    30: open Carray;
    31: open MixedInt;
    32: open Uint32;
    33: open Uint8;
    34: open Float;
    35: 
    36: open SDL_h;
    37: open SDL_video_h;
    38: open SDL_keyboard_h;
    39: open SDL_events_h;
    40: open SDL_keysym_h;
    41: open SDL_timer_h;
    42: open SDL_mutex_h;
    43: 
    44: // This is the Felix asynchronous event source
    45: open SDL_events;
    46: 
    47: open SDL_opengl_h;
    48: 
    49: /* screen width, height, and bit depth */
    50: val SCREEN_WIDTH  = 640;
    51: val SCREEN_HEIGHT = 480;
    52: val SCREEN_BPP = 16;
    53: 
    54: /* function to reset our viewport after a window resize */
    55: proc resizeWindow( wwidth : int, hheight :int)
    56: {
    57:   var height = hheight;
    58:   var width = wwidth;
    59: 
    60:   /* Protect against a divide by zero */
    61:   if height == 0 do height = 1; done;
    62:   var ratio = double_of width / double_of height;
    63: 
    64:   block_sdl_events event_lock;
    65:   /* Setup our viewport. */
    66:   glViewport( 0, 0, width, height );
    67: 
    68:   /* change to the projection matrix and set our viewing volume. */
    69:   glMatrixMode( GL_PROJECTION );
    70:   glLoadIdentity( );
    71: 
    72:   /* Set our perspective */
    73:   gluPerspective( 45.0, ratio, 0.1, 100.0 );
    74: 
    75:   /* Make sure we're chaning the model view and not the projection */
    76:   glMatrixMode( GL_MODELVIEW );
    77: 
    78:   /* Reset The View */
    79:   glLoadIdentity( );
    80:   unblock_sdl_events event_lock;
    81: }
    82: 
    83: /* general OpenGL initialization function */
    84: proc initGL()
    85: {
    86:   /* Enable smooth shading */
    87:   glShadeModel( GL_SMOOTH );
    88: 
    89:   /* Set the background black */
    90:   glClearColor( 0.0f, 0.0f, 0.0f, 0.0f );
    91: 
    92:   /* Depth buffer setup */
    93:   glClearDepth( 1.0 );
    94: 
    95:   /* Enables Depth Testing */
    96:   glEnable( GL_DEPTH_TEST );
    97: 
    98:   /* The Type Of Depth Test To Do */
    99:   glDepthFunc( GL_LEQUAL );
   100: 
   101:   /* Really Nice Perspective Calculations */
   102:   glHint( GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST );
   103: }
   104: 
   105: /* These are to calculate our fps */
   106: var T0     = 0;
   107: var Frames = 0;
   108: 
   109: 
   110: /* Here goes our drawing code */
   111: proc drawGLScene(drawing:1->0)
   112: {
   113:   block_sdl_events event_lock;
   114:   drawing();
   115:   unblock_sdl_events event_lock;
   116: 
   117:   /* Gather our frames per second */
   118:   Frames++;
   119:   {
   120:     var t = SDL_GetTicks();
   121:     if t - T0 >= 5000 do
   122:       val seconds = double_of (t - T0) / 1000.0;
   123:       val fps = double_of Frames / seconds;
   124:       print Frames; print " frames in "; print seconds;
   125:       print " seconds = "; print fps; print " FPS"; endl;
   126:       T0 = t;
   127:       Frames = 0;
   128:     done;
   129:   };
   130: }
   131: 
   132: /* whether or not the window is active */
   133: var isActive = true;
   134: 
   135: if SDL_Init(SDL_INIT_AUDIO \| SDL_INIT_VIDEO) < 0 do
   136:   print "Unable to init SDL"; endl;
   137:   System::exit(1);
   138: done;
   139: 
   140: var event_lock = SDL_CreateMutex();
   141: 
   142: 
   143: proc Quit(n:int)
   144: {
   145:   SDL_Quit;
   146:   System::exit 0;
   147: }
   148: 
   149: /* Fetch the video info */
   150: var videoInfo = SDL_GetVideoInfo();
   151: 
   152: if isNULL videoInfo do
   153:   print "Video query failed"; endl;
   154:   Quit 1;
   155: done;
   156: 
   157: /* the flags to pass to SDL_SetVideoMode */
   158: var
   159:   videoFlags  = SDL_OPENGL;          /* Enable OpenGL in SDL */
   160:   videoFlags |= cast[uint] SDL_GL_DOUBLEBUFFER; /* Enable double buffering */
   161:   videoFlags |= SDL_HWPALETTE;       /* Store the palette in hardware */
   162:   videoFlags |= SDL_RESIZABLE;       /* Enable window resizing */
   163: 
   164: /* This checks to see if surfaces can be stored in memory */
   165: if  videoInfo.->hw_available != 0 do
   166:     videoFlags |= SDL_HWSURFACE;
   167: else
   168:     videoFlags |= SDL_SWSURFACE;
   169: done;
   170: 
   171: /* This checks if hardware blits can be done */
   172: if videoInfo.->blit_hw != 0 do
   173:     videoFlags |= SDL_HWACCEL;
   174: done;
   175: 
   176: /* Sets up OpenGL double buffering */
   177: ignore$ SDL_GL_SetAttribute( cast[SDL_GLattr] SDL_GL_DOUBLEBUFFER, 1 );
   178: 
   179: /* get a SDL surface */
   180: var surface = SDL_SetVideoMode
   181:   (SCREEN_WIDTH, SCREEN_HEIGHT, SCREEN_BPP, videoFlags )
   182: ;
   183: 
   184: /* Verify there is a surface */
   185: if isNULL surface do
   186:   print "Video mode set failed"; endl;
   187:   Quit 1;
   188: done;
   189: 
   190: /* initialize OpenGL */
   191: initGL();
   192: var gl_vendor = str$ glGetString(GL_VENDOR);
   193: var gl_renderer = str$ glGetString(GL_RENDERER);
   194: var gl_version = str$ glGetString(GL_VERSION);
   195: var gl_extensions = str$ glGetString(GL_EXTENSIONS);
   196: 
   197: print$ "GL vendor = " + gl_vendor; endl;
   198: print$ "GL renderer = " + gl_renderer; endl;
   199: print$ "GL version = " + gl_version; endl;
   200: print$ "GL extensions = " + gl_extensions; endl;
   201: 
   202: /* resize the initial window */
   203: resizeWindow( SCREEN_WIDTH, SCREEN_HEIGHT );
   204: 
   205: // SDL Event dispatcher
   206: proc handle_active (e:SDL_ActiveEvent)
   207: {
   208:    isActive = e.gain != 0;
   209: }
   210: 
   211: proc handle_resize(e:SDL_ResizeEvent)
   212: {
   213:   block_sdl_events event_lock;
   214:   surface = SDL_SetVideoMode(
   215:     e.w,
   216:     e.h,
   217:     16, videoFlags
   218:   );
   219:   if isNULL surface do
   220:     print "Could not get a surface after resize"; endl;
   221:   done;
   222:   resizeWindow( e.w, e.h );
   223:   unblock_sdl_events event_lock;
   224: }
   225: 
   226: /* function to handle key press events */
   227: proc handle_key( keysym : SDL_keysym)
   228: {
   229:   match keysym.sym with
   230:   | ?k when k == SDLK_ESCAPE => { Quit 0; }
   231:   | ?k when k ==  SDLK_F1 =>
   232:         {
   233:         block_sdl_events event_lock;
   234:         ignore$ SDL_WM_ToggleFullScreen( surface );
   235:         unblock_sdl_events event_lock;
   236:       }
   237:   | _ => {}
   238:   endmatch;
   239: }
   240: 
   241: /* draw the scene */
   242: proc draw(drawing: 1->0) {
   243:   if isActive call drawGLScene( drawing );
   244: }
   245: 
   246: proc keychan(x:schannel[SDL_keysym])
   247: {
   248:   whilst true do
   249:     var &k : SDL_keysym <- read x;
   250:     handle_key k;
   251:   done;
   252: }
   253: 
   254: proc activechan(x:schannel[SDL_ActiveEvent])
   255: {
   256:   whilst true do
   257:     var &k : SDL_ActiveEvent <- read x;
   258:     handle_active k;
   259:   done;
   260: }
   261: 
   262: proc resizechan(x:schannel[SDL_ResizeEvent])
   263: {
   264:   whilst true do
   265:     var &k : SDL_ResizeEvent <- read x;
   266:     handle_resize k;
   267:   done;
   268: }
   269: 
   270: proc drawchan(x:schannel[int], drawing:1->0)
   271: {
   272:   whilst true do
   273:     var &k : int <- read x;
   274:     draw drawing;
   275:   done;
   276: }
   277: 
   278: val clock = Faio::mk_alarm_clock();
   279: proc poll_event(e: &SDL_Event)
   280: {
   281: tryagain:>
   282:   //print "Polling event"; endl;
   283:   var result = SDL_PollEvent(unref e);
   284:   if result > 0 do
   285:     //print "Got event"; endl;
   286:     return;
   287:   done;
   288:   Faio::sleep$ clock, 0.1;
   289:   goto tryagain;
   290: }
   291: 
   292: proc dispatch_event(
   293:   keyboard:schannel[SDL_keysym],
   294:   active:schannel[SDL_ActiveEvent],
   295:   resize:schannel[SDL_ResizeEvent]
   296: )
   297: {
   298:   whilst true do
   299:     // var &e : SDL_Event <- get_sdl_event event_lock;
   300:     var e : SDL_Event;
   301:     poll_event(&e);
   302: 
   303:     match e.type_ with
   304:     | ?et when et == SDL_ACTIVEEVENT =>
   305:       { write (active, e.active); }
   306: 
   307:     | ?et when et == SDL_VIDEORESIZE =>
   308:       { write (resize, e.resize); }
   309: 
   310:     | ?et when et == SDL_KEYDOWN =>
   311:       { write (keyboard, e.key.keysym); }
   312: 
   313:     | ?et when et == SDL_QUIT =>
   314:       { Quit 0; }
   315: 
   316:     | _ => {}
   317:     endmatch;
   318:   done;
   319: }
   320: 
   321: /* write ticks at the desired framerate */
   322: proc framerate (x:schannel[int], framerate:double)
   323: {
   324:   whilst true do
   325:     Faio::sleep$ clock, framerate;
   326:     write (x,1);
   327:   done;
   328: }
   329: 
   330: /* LINEAR CONTROL MODEL: CANNOT DEADLOCK
   331:   ~~> async/sync connection
   332:   --> sync/sync connection
   333: 
   334:   SDL_event ~~> dispatcher
   335:                 --> resize handler
   336:                 --> active handler
   337:                 --> key handler
   338:   timer ~~> framerate --> draw
   339: */
   340: 
   341: /* make our communication channels */
   342: var keyboard = mk_schannel[SDL_keysym] ();
   343: var active = mk_schannel[SDL_ActiveEvent] ();
   344: var resize = mk_schannel[SDL_ResizeEvent] ();
   345: var clicks = mk_schannel[int] ();
   346: 
   347: /* start up the fthreads and plug them together */
   348: spawn_fthread { dispatch_event (keyboard, active, resize); };
   349: spawn_fthread { resizechan resize; };
   350: spawn_fthread { activechan active; };
   351: spawn_fthread { keychan keyboard; };
   352: 
   353: spawn_fthread { drawchan (clicks, the Drawing); };
   354: spawn_fthread { framerate (clicks, 0.1); };
   355: 
   356: // main thread hangs
   357: 
   358: // THE DRAWING
   359: proc Drawing()
   360: {
   361:   /* Clear The Screen And The Depth Buffer */
   362:   glClear( GL_COLOR_BUFFER_BIT \| GL_DEPTH_BUFFER_BIT );
   363: 
   364:   /* Move Left 1.5 Units And Into The Screen 6.0 */
   365:   glLoadIdentity();
   366:   glTranslatef( -1.5f, 0.0f, -6.0f );
   367: 
   368:   glBegin( GL_TRIANGLES );            /* Drawing Using Triangles */
   369:     glVertex3f(  0.0f,  1.0f, 0.0f ); /* Top */
   370:     glVertex3f( -1.0f, -1.0f, 0.0f ); /* Bottom Left */
   371:     glVertex3f(  1.0f, -1.0f, 0.0f ); /* Bottom Right */
   372:   glEnd( );                           /* Finished Drawing The Triangle */
   373: 
   374:   /* Move Right 3 Units */
   375:   glTranslatef( 3.0f, 0.0f, 0.0f );
   376: 
   377:   glBegin( GL_QUADS );                /* Draw A Quad */
   378:     glVertex3f( -1.0f,  1.0f, 0.0f ); /* Top Left */
   379:     glVertex3f(  1.0f,  1.0f, 0.0f ); /* Top Right */
   380:     glVertex3f(  1.0f, -1.0f, 0.0f ); /* Bottom Right */
   381:     glVertex3f( -1.0f, -1.0f, 0.0f ); /* Bottom Left */
   382:   glEnd( );                           /* Done Drawing The Quad */
   383: 
   384:   /* Draw it to the screen */
   385:   SDL_GL_SwapBuffers( );
   386: }
End felix section to demos/sdl/sdl-1.01.02-0.flx[1]