Plain port of particles example to GLFW 3.
diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index 0199819..7a31f98 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -18,17 +18,21 @@
 
 set(GETOPT ${GLFW_SOURCE_DIR}/deps/getopt.h
            ${GLFW_SOURCE_DIR}/deps/getopt.c)
+set(TINYCTHREAD ${GLFW_SOURCE_DIR}/deps/tinycthread.h
+                ${GLFW_SOURCE_DIR}/deps/tinycthread.c)
 
 if (APPLE)
     # Set fancy names for bundles
     add_executable(Boing MACOSX_BUNDLE boing.c)
     add_executable(Gears MACOSX_BUNDLE gears.c)
+    add_executable(Particles MACOSX_BUNDLE particles.c ${TINYCTHREAD})
     add_executable(Simple MACOSX_BUNDLE simple.c)
     add_executable("Split View" MACOSX_BUNDLE splitview.c)
     add_executable(Wave MACOSX_BUNDLE wave.c)
 
     set_target_properties(Boing PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Boing")
     set_target_properties(Gears PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Gears")
+    set_target_properties(Particles PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Particles")
     set_target_properties(Simple PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Simple")
     set_target_properties("Split View" PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Split View")
     set_target_properties(Wave PROPERTIES MACOSX_BUNDLE_BUNDLE_NAME "Wave")
@@ -37,13 +41,14 @@
     add_executable(boing WIN32 boing.c)
     add_executable(gears WIN32 gears.c)
     add_executable(heightmap WIN32 heightmap.c ${GETOPT})
+    add_executable(particles WIN32 particles.c ${TINYCTHREAD})
     add_executable(simple WIN32 simple.c)
     add_executable(splitview WIN32 splitview.c)
     add_executable(wave WIN32 wave.c)
 endif()
 
 if (MSVC)
-    set(WINDOWS_BINARIES boing gears heightmap simple splitview wave)
+    set(WINDOWS_BINARIES boing gears heightmap particles simple splitview wave)
 
     # Tell MSVC to use main instead of WinMain for Windows subsystem executables
     set_target_properties(${WINDOWS_BINARIES} PROPERTIES
@@ -51,7 +56,7 @@
 endif()
 
 if (APPLE)
-    set(BUNDLE_BINARIES Boing Gears Simple "Split View" Wave)
+    set(BUNDLE_BINARIES Boing Gears Particles Simple "Split View" Wave)
 
     set_target_properties(${BUNDLE_BINARIES} PROPERTIES
                           MACOSX_BUNDLE_SHORT_VERSION_STRING ${GLFW_VERSION}
diff --git a/examples/particles.c b/examples/particles.c
index 403a999..570dbdd 100644
--- a/examples/particles.c
+++ b/examples/particles.c
@@ -41,7 +41,11 @@
 #include <stdio.h>
 #include <string.h>
 #include <math.h>
-#include <GL/glfw.h>
+
+#define GLFW_INCLUDE_GLU
+#include <GLFW/glfw3.h>
+
+#include <tinycthread.h>
 
 // Define tokens for GL_EXT_separate_specular_color if not already defined
 #ifndef GL_EXT_separate_specular_color
@@ -100,9 +104,9 @@
     float     dt;        // Time since last frame (s)
     int       p_frame;   // Particle physics frame number
     int       d_frame;   // Particle draw frame number
-    GLFWcond  p_done;    // Condition: particle physics done
-    GLFWcond  d_done;    // Condition: particle draw done
-    GLFWmutex particles_lock; // Particles data sharing mutex
+    cnd_t     p_done;    // Condition: particle physics done
+    cnd_t     d_done;    // Condition: particle draw done
+    mtx_t     particles_lock; // Particles data sharing mutex
 } thread_sync;
 
 
@@ -456,11 +460,12 @@
     if( multithreading )
     {
         // Wait for particle physics thread to be done
-        glfwLockMutex( thread_sync.particles_lock );
+        mtx_lock( &thread_sync.particles_lock );
         while( running && thread_sync.p_frame <= thread_sync.d_frame )
         {
-            glfwWaitCond( thread_sync.p_done, thread_sync.particles_lock,
-                          0.1 );
+            struct timespec ts = { 0, 100000000 };
+            cnd_timedwait( &thread_sync.p_done, &thread_sync.particles_lock,
+                           &ts );
         }
 
         // Store the frame time and delta time for the physics thread
@@ -563,8 +568,8 @@
     // thread
     if( multithreading )
     {
-        glfwUnlockMutex( thread_sync.particles_lock );
-        glfwSignalCond( thread_sync.d_done );
+        mtx_unlock( &thread_sync.particles_lock );
+        cnd_signal( &thread_sync.d_done );
     }
 
     // Draw final batch of particles (if any)
@@ -897,7 +902,7 @@
 // Resize() - GLFW window resize callback function
 //========================================================================
 
-void GLFWCALL Resize( int x, int y )
+void Resize( GLFWwindow* window, int x, int y )
 {
     width = x;
     height = y > 0 ? y : 1;   // Prevent division by zero in aspect calc.
@@ -908,16 +913,16 @@
 // Input callback functions
 //========================================================================
 
-void GLFWCALL KeyFun( int key, int action )
+void KeyFun( GLFWwindow* window, int key, int scancode, int action, int mods )
 {
     if( action == GLFW_PRESS )
     {
         switch( key )
         {
-        case GLFW_KEY_ESC:
+        case GLFW_KEY_ESCAPE:
             running = 0;
             break;
-        case 'W':
+        case GLFW_KEY_W:
             wireframe = !wireframe;
             glPolygonMode( GL_FRONT_AND_BACK,
                            wireframe ? GL_LINE : GL_FILL );
@@ -933,18 +938,19 @@
 // PhysicsThreadFun() - Thread for updating particle physics
 //========================================================================
 
-void GLFWCALL PhysicsThreadFun( void *arg )
+int PhysicsThreadFun( void *arg )
 {
     while( running )
     {
         // Lock mutex
-        glfwLockMutex( thread_sync.particles_lock );
+        mtx_lock( &thread_sync.particles_lock );
 
         // Wait for particle drawing to be done
         while( running && thread_sync.p_frame > thread_sync.d_frame )
         {
-            glfwWaitCond( thread_sync.d_done, thread_sync.particles_lock,
-                          0.1 );
+            struct timespec ts = { 0, 100000000 };
+            cnd_timedwait( &thread_sync.d_done, &thread_sync.particles_lock,
+                           &ts );
         }
 
         // No longer running?
@@ -960,9 +966,11 @@
         thread_sync.p_frame ++;
 
         // Unlock mutex and signal drawing thread
-        glfwUnlockMutex( thread_sync.particles_lock );
-        glfwSignalCond( thread_sync.p_done );
+        mtx_unlock( &thread_sync.particles_lock );
+        cnd_signal( &thread_sync.p_done );
     }
+
+    return 0;
 }
 
 
@@ -974,7 +982,8 @@
 {
     int        i, frames, benchmark;
     double     t0, t;
-    GLFWthread physics_thread = 0;
+    thrd_t     physics_thread = 0;
+    GLFWwindow* window;
 
     // Use multithreading by default, but don't benchmark
     multithreading = 1;
@@ -1028,24 +1037,25 @@
     }
 
     // Open OpenGL fullscreen window
-    if( !glfwOpenWindow( WIDTH, HEIGHT, 0,0,0,0, 16,0, GLFW_FULLSCREEN ) )
+    window = glfwCreateWindow( WIDTH, HEIGHT, "Particle Engine",
+                               glfwGetPrimaryMonitor(), NULL);
+    if( !window )
     {
         fprintf( stderr, "Failed to open GLFW window\n" );
         glfwTerminate();
         exit( EXIT_FAILURE );
     }
 
-    // Set window title
-    glfwSetWindowTitle( "Particle engine" );
+    glfwSetInputMode(window, GLFW_CURSOR, GLFW_CURSOR_DISABLED);
 
-    // Disable VSync (we want to get as high FPS as possible!)
+    glfwMakeContextCurrent(window);
     glfwSwapInterval( 0 );
 
     // Window resize callback function
-    glfwSetWindowSizeCallback( Resize );
+    glfwSetWindowSizeCallback( window, Resize );
 
     // Set keyboard input callback function
-    glfwSetKeyCallback( KeyFun );
+    glfwSetKeyCallback( window, KeyFun );
 
     // Upload particle texture
     glGenTextures( 1, &particle_tex_id );
@@ -1099,10 +1109,15 @@
     {
         thread_sync.p_frame = 0;
         thread_sync.d_frame = 0;
-        thread_sync.particles_lock = glfwCreateMutex();
-        thread_sync.p_done = glfwCreateCond();
-        thread_sync.d_done = glfwCreateCond();
-        physics_thread = glfwCreateThread( PhysicsThreadFun, NULL );
+        mtx_init(&thread_sync.particles_lock, mtx_timed);
+        cnd_init(&thread_sync.p_done);
+        cnd_init(&thread_sync.d_done);
+
+        if (thrd_create( &physics_thread, PhysicsThreadFun, NULL ) != thrd_success)
+        {
+            glfwTerminate();
+            exit(EXIT_FAILURE);
+        }
     }
 
     // Main loop
@@ -1117,10 +1132,11 @@
         Draw( t );
 
         // Swap buffers
-        glfwSwapBuffers();
+        glfwSwapBuffers(window);
+        glfwPollEvents();
 
         // Check if window was closed
-        running = running && glfwGetWindowParam( GLFW_OPENED );
+        running = running && !glfwWindowShouldClose( window );
 
         // Increase frame count
         frames ++;
@@ -1136,7 +1152,7 @@
     // Wait for particle physics thread to die
     if( multithreading )
     {
-        glfwWaitThread( physics_thread, GLFW_WAIT );
+        thrd_join( physics_thread, NULL );
     }
 
     // Display profiling information
@@ -1144,6 +1160,8 @@
             (double)frames / t );
     printf( " (multithreading %s)\n", multithreading ? "on" : "off" );
 
+    glfwDestroyWindow(window);
+
     // Terminate OpenGL
     glfwTerminate();