diff --git a/CMakeLists.txt b/CMakeLists.txt index 74e26556..d37146ae 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -8,6 +8,7 @@ set(GLFW_VERSION_PATCH "0") set(GLFW_VERSION_EXTRA "") set(GLFW_VERSION "${GLFW_VERSION_MAJOR}.${GLFW_VERSION_MINOR}") set(GLFW_VERSION_FULL "${GLFW_VERSION}.${GLFW_VERSION_PATCH}${GLFW_VERSION_EXTRA}") +set(LIB_SUFFIX "" CACHE STRING "Takes an empty string or 64. Directory where lib will be installed: lib or lib64") option(GLFW_BUILD_EXAMPLES "Build the GLFW example programs" ON) option(GLFW_BUILD_TESTS "Build the GLFW test programs" ON) @@ -334,11 +335,11 @@ install(FILES COPYING.txt readme.html # Create and install pkg-config file on supported platforms #-------------------------------------------------------------------- if (_GLFW_X11_GLX OR _GLFW_COCOA_NSGL) - configure_file(${GLFW_SOURCE_DIR}/src/libglfw3.pc.in - ${GLFW_BINARY_DIR}/src/libglfw3.pc @ONLY) + configure_file(${GLFW_SOURCE_DIR}/src/glfw3.pc.in + ${GLFW_BINARY_DIR}/src/glfw3.pc @ONLY) - install(FILES ${GLFW_BINARY_DIR}/src/libglfw3.pc - DESTINATION lib/pkgconfig) + install(FILES ${GLFW_BINARY_DIR}/src/glfw3.pc + DESTINATION lib${LIB_SUFFIX}/pkgconfig) endif() #-------------------------------------------------------------------- diff --git a/cmake_uninstall.cmake.in b/cmake_uninstall.cmake.in index 17376d2e..4ea57b1c 100644 --- a/cmake_uninstall.cmake.in +++ b/cmake_uninstall.cmake.in @@ -1,22 +1,29 @@ -IF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") - MESSAGE(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"") -ENDIF(NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") -FILE(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) -STRING(REGEX REPLACE "\n" ";" files "${files}") -FOREACH(file ${files}) - MESSAGE(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"") - IF(EXISTS "$ENV{DESTDIR}${file}") - EXEC_PROGRAM( - "@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" - OUTPUT_VARIABLE rm_out - RETURN_VALUE rm_retval - ) - IF(NOT "${rm_retval}" STREQUAL 0) +if (NOT EXISTS "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt") + message(FATAL_ERROR "Cannot find install manifest: \"@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt\"") +endif() + +file(READ "@CMAKE_CURRENT_BINARY_DIR@/install_manifest.txt" files) +string(REGEX REPLACE "\n" ";" files "${files}") + +foreach (file ${files}) + message(STATUS "Uninstalling \"$ENV{DESTDIR}${file}\"") + if (EXISTS "$ENV{DESTDIR}${file}") + exec_program("@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" + OUTPUT_VARIABLE rm_out + RETURN_VALUE rm_retval) + if (NOT "${rm_retval}" STREQUAL 0) MESSAGE(FATAL_ERROR "Problem when removing \"$ENV{DESTDIR}${file}\"") - ENDIF(NOT "${rm_retval}" STREQUAL 0) - ELSE(EXISTS "$ENV{DESTDIR}${file}") - MESSAGE(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.") - ENDIF(EXISTS "$ENV{DESTDIR}${file}") -ENDFOREACH(file) + endif() + elseif (IS_SYMLINK "$ENV{DESTDIR}${file}") + EXEC_PROGRAM("@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\"" + OUTPUT_VARIABLE rm_out + RETURN_VALUE rm_retval) + if (NOT "${rm_retval}" STREQUAL 0) + message(FATAL_ERROR "Problem when removing symlink \"$ENV{DESTDIR}${file}\"") + endif() + else() + message(STATUS "File \"$ENV{DESTDIR}${file}\" does not exist.") + endif() +endforeach() diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt index 3e7065c6..a3c26beb 100644 --- a/examples/CMakeLists.txt +++ b/examples/CMakeLists.txt @@ -12,6 +12,9 @@ include_directories(${GLFW_SOURCE_DIR}/include ${GLFW_SOURCE_DIR}/support ${OPENGL_INCLUDE_DIR}) +set(GETOPT ${GLFW_SOURCE_DIR}/support/getopt.h + ${GLFW_SOURCE_DIR}/support/getopt.c) + if (APPLE) # Set fancy names for bundles add_executable(Boing MACOSX_BUNDLE boing.c) @@ -29,7 +32,7 @@ else() # Set boring names for executables add_executable(boing WIN32 boing.c) add_executable(gears WIN32 gears.c) - add_executable(heightmap WIN32 heightmap.c getopt.c) + add_executable(heightmap WIN32 heightmap.c ${GETOPT}) add_executable(splitview WIN32 splitview.c) add_executable(triangle WIN32 triangle.c) add_executable(wave WIN32 wave.c) diff --git a/examples/boing.c b/examples/boing.c index 49d602ca..a2094c5f 100644 --- a/examples/boing.c +++ b/examples/boing.c @@ -330,7 +330,7 @@ void DrawBoingBall( void ) /***************************************************************************** * Bounce the ball. *****************************************************************************/ -void BounceBall( double dt ) +void BounceBall( double delta_t ) { GLfloat sign; GLfloat deg; @@ -358,8 +358,8 @@ void BounceBall( double dt ) } /* Update ball position */ - ball_x += ball_x_inc * ((float)dt*ANIMATION_SPEED); - ball_y += ball_y_inc * ((float)dt*ANIMATION_SPEED); + ball_x += ball_x_inc * ((float)delta_t*ANIMATION_SPEED); + ball_y += ball_y_inc * ((float)delta_t*ANIMATION_SPEED); /* * Simulate the effects of gravity on Y movement. @@ -567,8 +567,8 @@ void DrawGrid( void ) int main( void ) { - int running; GLFWwindow window; + int width, height; /* Init GLFW */ if( !glfwInit() ) @@ -577,9 +577,11 @@ int main( void ) exit( EXIT_FAILURE ); } - glfwOpenWindowHint(GLFW_DEPTH_BITS, 16); + glfwSetWindowSizeCallback( reshape ); - window = glfwOpenWindow( 400, 400, GLFW_WINDOWED, "Boing (classic Amiga demo)", NULL ); + glfwWindowHint(GLFW_DEPTH_BITS, 16); + + window = glfwCreateWindow( 400, 400, GLFW_WINDOWED, "Boing (classic Amiga demo)", NULL ); if (!window) { fprintf( stderr, "Failed to open GLFW window\n" ); @@ -587,15 +589,19 @@ int main( void ) exit( EXIT_FAILURE ); } - glfwSetWindowSizeCallback( reshape ); - glfwSetInputMode( window, GLFW_STICKY_KEYS, GL_TRUE ); + glfwMakeContextCurrent(window); glfwSwapInterval( 1 ); + + glfwGetWindowSize(window, &width, &height); + reshape(window, width, height); + + glfwSetInputMode( window, GLFW_STICKY_KEYS, GL_TRUE ); glfwSetTime( 0.0 ); init(); /* Main loop */ - do + for (;;) { /* Timing */ t = glfwGetTime(); @@ -606,13 +612,15 @@ int main( void ) display(); /* Swap buffers */ - glfwSwapBuffers(); + glfwSwapBuffers(window); glfwPollEvents(); /* Check if we are still running */ - running = glfwIsWindow(window) && !glfwGetKey( window, GLFW_KEY_ESCAPE ); + if (glfwGetKey( window, GLFW_KEY_ESCAPE )) + break; + if (glfwGetWindowParam(window, GLFW_CLOSE_REQUESTED)) + break; } - while( running ); glfwTerminate(); exit( EXIT_SUCCESS ); diff --git a/examples/gears.c b/examples/gears.c index 53d601f3..cd3cdbb1 100644 --- a/examples/gears.c +++ b/examples/gears.c @@ -267,6 +267,14 @@ void reshape( GLFWwindow window, int width, int height ) } +/* close callback */ +static int window_close_callback(GLFWwindow window) +{ + running = 0; + return GL_TRUE; +} + + /* program & OpenGL initialization */ static void init(int argc, char *argv[]) { @@ -322,6 +330,7 @@ static void init(int argc, char *argv[]) int main(int argc, char *argv[]) { GLFWwindow window; + int width, height; if( !glfwInit() ) { @@ -329,9 +338,14 @@ int main(int argc, char *argv[]) exit( EXIT_FAILURE ); } - glfwOpenWindowHint(GLFW_DEPTH_BITS, 16); + // Set callback functions + glfwSetWindowCloseCallback(window_close_callback); + glfwSetWindowSizeCallback( reshape ); + glfwSetKeyCallback( key ); - window = glfwOpenWindow( 300, 300, GLFW_WINDOWED, "Gears", NULL ); + glfwWindowHint(GLFW_DEPTH_BITS, 16); + + window = glfwCreateWindow( 300, 300, GLFW_WINDOWED, "Gears", NULL ); if (!window) { fprintf( stderr, "Failed to open GLFW window\n" ); @@ -339,16 +353,17 @@ int main(int argc, char *argv[]) exit( EXIT_FAILURE ); } - glfwSetInputMode( window, GLFW_KEY_REPEAT, GL_TRUE ); + glfwMakeContextCurrent(window); glfwSwapInterval( 1 ); + glfwGetWindowSize(window, &width, &height); + reshape(window, width, height); + + glfwSetInputMode( window, GLFW_KEY_REPEAT, GL_TRUE ); + // Parse command-line options init(argc, argv); - // Set callback functions - glfwSetWindowSizeCallback( reshape ); - glfwSetKeyCallback( key ); - // Main loop while( running ) { @@ -359,14 +374,8 @@ int main(int argc, char *argv[]) animate(); // Swap buffers - glfwSwapBuffers(); + glfwSwapBuffers(window); glfwPollEvents(); - - // Was the window closed? - if( !glfwIsWindow( window ) ) - { - running = 0; - } } // Terminate GLFW diff --git a/examples/getopt.h b/examples/getopt.h deleted file mode 100644 index 0b78650a..00000000 --- a/examples/getopt.h +++ /dev/null @@ -1,63 +0,0 @@ -/***************************************************************************** -* getopt.h - competent and free getopt library. -* $Header: /cvsroot/freegetopt/freegetopt/getopt.h,v 1.2 2003/10/26 03:10:20 vindaci Exp $ -* -* Copyright (c)2002-2003 Mark K. Kim -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in -* the documentation and/or other materials provided with the -* distribution. -* -* * Neither the original author of this software nor the names of its -* contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS -* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED -* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -* DAMAGE. -*/ -#ifndef GETOPT_H_ -#define GETOPT_H_ - - -#ifdef __cplusplus -extern "C" { -#endif - - -extern char* optarg; -extern int optind; -extern int opterr; -extern int optopt; - -int getopt(int argc, char** argv, char* optstr); - - -#ifdef __cplusplus -} -#endif - - -#endif /* GETOPT_H_ */ - - -/* vim:ts=3 -*/ diff --git a/examples/heightmap.c b/examples/heightmap.c index e926581a..fce8b8de 100644 --- a/examples/heightmap.c +++ b/examples/heightmap.c @@ -581,13 +581,13 @@ int main(int argc, char** argv) exit(EXIT_FAILURE); } - glfwOpenWindowHint(GLFW_WINDOW_RESIZABLE, GL_FALSE); - glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, 3); - glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, 2); - glfwOpenWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); - glfwOpenWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_FALSE); + glfwWindowHint(GLFW_WINDOW_RESIZABLE, GL_FALSE); + glfwWindowHint(GLFW_OPENGL_VERSION_MAJOR, 3); + glfwWindowHint(GLFW_OPENGL_VERSION_MINOR, 2); + glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); + glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_FALSE); - window = glfwOpenWindow(800, 600, GLFW_WINDOWED, "GLFW OpenGL3 Heightmap demo", NULL); + window = glfwCreateWindow(800, 600, GLFW_WINDOWED, "GLFW OpenGL3 Heightmap demo", NULL); if (! window ) { fprintf(stderr, "ERROR: Unable to create the OpenGL context and associated window\n"); @@ -597,10 +597,12 @@ int main(int argc, char** argv) free(fragment_shader_src); exit(EXIT_FAILURE); } + + /* Register events callback */ glfwSetWindowCloseCallback(window_close_callback); glfwSetKeyCallback(key_callback); - /* Register events callback */ + glfwMakeContextCurrent(window); if (GL_TRUE != init_opengl()) { fprintf(stderr, "ERROR: unable to resolve OpenGL function pointers\n"); @@ -663,7 +665,7 @@ int main(int argc, char** argv) glDrawElements(GL_LINES, 2* MAP_NUM_LINES , GL_UNSIGNED_INT, 0); /* display and process events through callbacks */ - glfwSwapBuffers(); + glfwSwapBuffers(window); glfwPollEvents(); /* Check the frame rate and update the heightmap if needed */ dt = glfwGetTime(); diff --git a/examples/particles.c b/examples/particles.c deleted file mode 100644 index 403a9997..00000000 --- a/examples/particles.c +++ /dev/null @@ -1,1152 +0,0 @@ -//======================================================================== -// This is a simple, but cool particle engine (buzz-word meaning many -// small objects that are treated as points and drawn as textures -// projected on simple geometry). -// -// This demonstration generates a colorful fountain-like animation. It -// uses several advanced OpenGL teqhniques: -// -// 1) Lighting (per vertex) -// 2) Alpha blending -// 3) Fog -// 4) Texturing -// 5) Display lists (for drawing the static environment geometry) -// 6) Vertex arrays (for drawing the particles) -// 7) GL_EXT_separate_specular_color is used (if available) -// -// Even more so, this program uses multi threading. The program is -// essentialy divided into a main rendering thread and a particle physics -// calculation thread. My benchmarks under Windows 2000 on a single -// processor system show that running this program as two threads instead -// of a single thread means no difference (there may be a very marginal -// advantage for the multi threaded case). On dual processor systems I -// have had reports of 5-25% of speed increase when running this program -// as two threads instead of one thread. -// -// The default behaviour of this program is to use two threads. To force -// a single thread to be used, use the command line switch -s. -// -// To run a fixed length benchmark (60 s), use the command line switch -b. -// -// Benchmark results (640x480x16, best of three tests): -// -// CPU GFX 1 thread 2 threads -// Athlon XP 2700+ GeForce Ti4200 (oc) 757 FPS 759 FPS -// P4 2.8 GHz (SMT) GeForce FX5600 548 FPS 550 FPS -// -// One more thing: Press 'w' during the demo to toggle wireframe mode. -//======================================================================== - -#include -#include -#include -#include -#include - -// Define tokens for GL_EXT_separate_specular_color if not already defined -#ifndef GL_EXT_separate_specular_color -#define GL_LIGHT_MODEL_COLOR_CONTROL_EXT 0x81F8 -#define GL_SINGLE_COLOR_EXT 0x81F9 -#define GL_SEPARATE_SPECULAR_COLOR_EXT 0x81FA -#endif // GL_EXT_separate_specular_color - -// Some 's do not define M_PI -#ifndef M_PI -#define M_PI 3.141592654 -#endif - -// Desired fullscreen resolution -#define WIDTH 640 -#define HEIGHT 480 - - -//======================================================================== -// Type definitions -//======================================================================== - -typedef struct { float x,y,z; } VEC; - -// This structure is used for interleaved vertex arrays (see the -// DrawParticles function) - Note: This structure SHOULD be packed on most -// systems. It uses 32-bit fields on 32-bit boundaries, and is a multiple -// of 64 bits in total (6x32=3x64). If it does not work, try using pragmas -// or whatever to force the structure to be packed. -typedef struct { - GLfloat s, t; // Texture coordinates - GLuint rgba; // Color (four ubytes packed into an uint) - GLfloat x, y, z; // Vertex coordinates -} VERTEX; - - -//======================================================================== -// Program control global variables -//======================================================================== - -// "Running" flag (true if program shall continue to run) -int running; - -// Window dimensions -int width, height; - -// "wireframe" flag (true if we use wireframe view) -int wireframe; - -// "multithreading" flag (true if we use multithreading) -int multithreading; - -// Thread synchronization -struct { - double t; // Time (s) - 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 -} thread_sync; - - -//======================================================================== -// Texture declarations (we hard-code them into the source code, since -// they are so simple) -//======================================================================== - -#define P_TEX_WIDTH 8 // Particle texture dimensions -#define P_TEX_HEIGHT 8 -#define F_TEX_WIDTH 16 // Floor texture dimensions -#define F_TEX_HEIGHT 16 - -// Texture object IDs -GLuint particle_tex_id, floor_tex_id; - -// Particle texture (a simple spot) -const unsigned char particle_texture[ P_TEX_WIDTH * P_TEX_HEIGHT ] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x11, 0x22, 0x22, 0x11, 0x00, 0x00, - 0x00, 0x11, 0x33, 0x88, 0x77, 0x33, 0x11, 0x00, - 0x00, 0x22, 0x88, 0xff, 0xee, 0x77, 0x22, 0x00, - 0x00, 0x22, 0x77, 0xee, 0xff, 0x88, 0x22, 0x00, - 0x00, 0x11, 0x33, 0x77, 0x88, 0x33, 0x11, 0x00, - 0x00, 0x00, 0x11, 0x33, 0x22, 0x11, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -// Floor texture (your basic checkered floor) -const unsigned char floor_texture[ F_TEX_WIDTH * F_TEX_HEIGHT ] = { - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, - 0xff, 0xf0, 0xcc, 0xf0, 0xf0, 0xf0, 0xff, 0xf0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, - 0xf0, 0xcc, 0xee, 0xff, 0xf0, 0xf0, 0xf0, 0xf0, 0x30, 0x66, 0x30, 0x30, 0x30, 0x20, 0x30, 0x30, - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xee, 0xf0, 0xf0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, - 0xf0, 0xf0, 0xf0, 0xf0, 0xcc, 0xf0, 0xf0, 0xf0, 0x30, 0x30, 0x55, 0x30, 0x30, 0x44, 0x30, 0x30, - 0xf0, 0xdd, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xff, 0xf0, 0xf0, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x60, 0x30, - 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0x33, 0x33, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, - 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x33, 0x30, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0x30, 0x30, 0x30, 0x30, 0x30, 0x20, 0x30, 0x30, 0xf0, 0xff, 0xf0, 0xf0, 0xdd, 0xf0, 0xf0, 0xff, - 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x55, 0x33, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xff, 0xf0, 0xf0, - 0x30, 0x44, 0x66, 0x30, 0x30, 0x30, 0x30, 0x30, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xf0, 0xf0, 0xf0, 0xaa, 0xf0, 0xf0, 0xcc, 0xf0, - 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xff, 0xf0, 0xf0, 0xf0, 0xff, 0xf0, 0xdd, 0xf0, - 0x30, 0x30, 0x30, 0x77, 0x30, 0x30, 0x30, 0x30, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, - 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, -}; - - -//======================================================================== -// These are fixed constants that control the particle engine. In a -// modular world, these values should be variables... -//======================================================================== - -// Maximum number of particles -#define MAX_PARTICLES 3000 - -// Life span of a particle (in seconds) -#define LIFE_SPAN 8.0f - -// A new particle is born every [BIRTH_INTERVAL] second -#define BIRTH_INTERVAL (LIFE_SPAN/(float)MAX_PARTICLES) - -// Particle size (meters) -#define PARTICLE_SIZE 0.7f - -// Gravitational constant (m/s^2) -#define GRAVITY 9.8f - -// Base initial velocity (m/s) -#define VELOCITY 8.0f - -// Bounce friction (1.0 = no friction, 0.0 = maximum friction) -#define FRICTION 0.75f - -// "Fountain" height (m) -#define FOUNTAIN_HEIGHT 3.0f - -// Fountain radius (m) -#define FOUNTAIN_RADIUS 1.6f - -// Minimum delta-time for particle phisics (s) -#define MIN_DELTA_T (BIRTH_INTERVAL * 0.5f) - - -//======================================================================== -// Particle system global variables -//======================================================================== - -// This structure holds all state for a single particle -typedef struct { - float x,y,z; // Position in space - float vx,vy,vz; // Velocity vector - float r,g,b; // Color of particle - float life; // Life of particle (1.0 = newborn, < 0.0 = dead) - int active; // Tells if this particle is active -} PARTICLE; - -// Global vectors holding all particles. We use two vectors for double -// buffering. -static PARTICLE particles[ MAX_PARTICLES ]; - -// Global variable holding the age of the youngest particle -static float min_age; - -// Color of latest born particle (used for fountain lighting) -static float glow_color[4]; - -// Position of latest born particle (used for fountain lighting) -static float glow_pos[4]; - - -//======================================================================== -// Object material and fog configuration constants -//======================================================================== - -const GLfloat fountain_diffuse[4] = {0.7f,1.0f,1.0f,1.0f}; -const GLfloat fountain_specular[4] = {1.0f,1.0f,1.0f,1.0f}; -const GLfloat fountain_shininess = 12.0f; -const GLfloat floor_diffuse[4] = {1.0f,0.6f,0.6f,1.0f}; -const GLfloat floor_specular[4] = {0.6f,0.6f,0.6f,1.0f}; -const GLfloat floor_shininess = 18.0f; -const GLfloat fog_color[4] = {0.1f, 0.1f, 0.1f, 1.0f}; - - -//======================================================================== -// InitParticle() - Initialize a new particle -//======================================================================== - -void InitParticle( PARTICLE *p, double t ) -{ - float xy_angle, velocity; - - // Start position of particle is at the fountain blow-out - p->x = 0.0f; - p->y = 0.0f; - p->z = FOUNTAIN_HEIGHT; - - // Start velocity is up (Z)... - p->vz = 0.7f + (0.3f/4096.f) * (float) (rand() & 4095); - - // ...and a randomly chosen X/Y direction - xy_angle = (2.f * (float)M_PI / 4096.f) * (float) (rand() & 4095); - p->vx = 0.4f * (float) cos( xy_angle ); - p->vy = 0.4f * (float) sin( xy_angle ); - - // Scale velocity vector according to a time-varying velocity - velocity = VELOCITY*(0.8f + 0.1f*(float)(sin( 0.5*t )+sin( 1.31*t ))); - p->vx *= velocity; - p->vy *= velocity; - p->vz *= velocity; - - // Color is time-varying - p->r = 0.7f + 0.3f * (float) sin( 0.34*t + 0.1 ); - p->g = 0.6f + 0.4f * (float) sin( 0.63*t + 1.1 ); - p->b = 0.6f + 0.4f * (float) sin( 0.91*t + 2.1 ); - - // Store settings for fountain glow lighting - glow_pos[0] = 0.4f * (float) sin( 1.34*t ); - glow_pos[1] = 0.4f * (float) sin( 3.11*t ); - glow_pos[2] = FOUNTAIN_HEIGHT + 1.0f; - glow_pos[3] = 1.0f; - glow_color[0] = p->r; - glow_color[1] = p->g; - glow_color[2] = p->b; - glow_color[3] = 1.0f; - - // The particle is new-born and active - p->life = 1.0f; - p->active = 1; -} - - -//======================================================================== -// UpdateParticle() - Update a particle -//======================================================================== - -#define FOUNTAIN_R2 (FOUNTAIN_RADIUS+PARTICLE_SIZE/2)*(FOUNTAIN_RADIUS+PARTICLE_SIZE/2) - -void UpdateParticle( PARTICLE *p, float dt ) -{ - // If the particle is not active, we need not do anything - if( !p->active ) - { - return; - } - - // The particle is getting older... - p->life = p->life - dt * (1.0f / LIFE_SPAN); - - // Did the particle die? - if( p->life <= 0.0f ) - { - p->active = 0; - return; - } - - // Update particle velocity (apply gravity) - p->vz = p->vz - GRAVITY * dt; - - // Update particle position - p->x = p->x + p->vx * dt; - p->y = p->y + p->vy * dt; - p->z = p->z + p->vz * dt; - - // Simple collision detection + response - if( p->vz < 0.0f ) - { - // Particles should bounce on the fountain (with friction) - if( (p->x*p->x + p->y*p->y) < FOUNTAIN_R2 && - p->z < (FOUNTAIN_HEIGHT + PARTICLE_SIZE/2) ) - { - p->vz = -FRICTION * p->vz; - p->z = FOUNTAIN_HEIGHT + PARTICLE_SIZE/2 + - FRICTION * (FOUNTAIN_HEIGHT + - PARTICLE_SIZE/2 - p->z); - } - - // Particles should bounce on the floor (with friction) - else if( p->z < PARTICLE_SIZE/2 ) - { - p->vz = -FRICTION * p->vz; - p->z = PARTICLE_SIZE/2 + - FRICTION * (PARTICLE_SIZE/2 - p->z); - } - - } -} - - -//======================================================================== -// ParticleEngine() - The main frame for the particle engine. Called once -// per frame. -//======================================================================== - -void ParticleEngine( double t, float dt ) -{ - int i; - float dt2; - - // Update particles (iterated several times per frame if dt is too - // large) - while( dt > 0.0f ) - { - // Calculate delta time for this iteration - dt2 = dt < MIN_DELTA_T ? dt : MIN_DELTA_T; - - // Update particles - for( i = 0; i < MAX_PARTICLES; i ++ ) - { - UpdateParticle( &particles[ i ], dt2 ); - } - - // Increase minimum age - min_age += dt2; - - // Should we create any new particle(s)? - while( min_age >= BIRTH_INTERVAL ) - { - min_age -= BIRTH_INTERVAL; - - // Find a dead particle to replace with a new one - for( i = 0; i < MAX_PARTICLES; i ++ ) - { - if( !particles[ i ].active ) - { - InitParticle( &particles[ i ], t + min_age ); - UpdateParticle( &particles[ i ], min_age ); - break; - } - } - } - - // Decrease frame delta time - dt -= dt2; - } -} - - -//======================================================================== -// DrawParticles() - Draw all active particles. We use OpenGL 1.1 vertex -// arrays for this in order to accelerate the drawing. -//======================================================================== - -#define BATCH_PARTICLES 70 // Number of particles to draw in each batch - // (70 corresponds to 7.5 KB = will not blow - // the L1 data cache on most CPUs) -#define PARTICLE_VERTS 4 // Number of vertices per particle - -void DrawParticles( double t, float dt ) -{ - int i, particle_count; - VERTEX vertex_array[ BATCH_PARTICLES * PARTICLE_VERTS ], *vptr; - float alpha; - GLuint rgba; - VEC quad_lower_left, quad_lower_right; - GLfloat mat[ 16 ]; - PARTICLE *pptr; - - // Here comes the real trick with flat single primitive objects (s.c. - // "billboards"): We must rotate the textured primitive so that it - // always faces the viewer (is coplanar with the view-plane). - // We: - // 1) Create the primitive around origo (0,0,0) - // 2) Rotate it so that it is coplanar with the view plane - // 3) Translate it according to the particle position - // Note that 1) and 2) is the same for all particles (done only once). - - // Get modelview matrix. We will only use the upper left 3x3 part of - // the matrix, which represents the rotation. - glGetFloatv( GL_MODELVIEW_MATRIX, mat ); - - // 1) & 2) We do it in one swift step: - // Although not obvious, the following six lines represent two matrix/ - // vector multiplications. The matrix is the inverse 3x3 rotation - // matrix (i.e. the transpose of the same matrix), and the two vectors - // represent the lower left corner of the quad, PARTICLE_SIZE/2 * - // (-1,-1,0), and the lower right corner, PARTICLE_SIZE/2 * (1,-1,0). - // The upper left/right corners of the quad is always the negative of - // the opposite corners (regardless of rotation). - quad_lower_left.x = (-PARTICLE_SIZE/2) * (mat[0] + mat[1]); - quad_lower_left.y = (-PARTICLE_SIZE/2) * (mat[4] + mat[5]); - quad_lower_left.z = (-PARTICLE_SIZE/2) * (mat[8] + mat[9]); - quad_lower_right.x = (PARTICLE_SIZE/2) * (mat[0] - mat[1]); - quad_lower_right.y = (PARTICLE_SIZE/2) * (mat[4] - mat[5]); - quad_lower_right.z = (PARTICLE_SIZE/2) * (mat[8] - mat[9]); - - // Don't update z-buffer, since all particles are transparent! - glDepthMask( GL_FALSE ); - - // Enable blending - glEnable( GL_BLEND ); - glBlendFunc( GL_SRC_ALPHA, GL_ONE ); - - // Select particle texture - if( !wireframe ) - { - glEnable( GL_TEXTURE_2D ); - glBindTexture( GL_TEXTURE_2D, particle_tex_id ); - } - - // Set up vertex arrays. We use interleaved arrays, which is easier to - // handle (in most situations) and it gives a linear memeory access - // access pattern (which may give better performance in some - // situations). GL_T2F_C4UB_V3F means: 2 floats for texture coords, - // 4 ubytes for color and 3 floats for vertex coord (in that order). - // Most OpenGL cards / drivers are optimized for this format. - glInterleavedArrays( GL_T2F_C4UB_V3F, 0, vertex_array ); - - // Is particle physics carried out in a separate thread? - if( multithreading ) - { - // Wait for particle physics thread to be done - glfwLockMutex( 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 ); - } - - // Store the frame time and delta time for the physics thread - thread_sync.t = t; - thread_sync.dt = dt; - - // Update frame counter - thread_sync.d_frame ++; - } - else - { - // Perform particle physics in this thread - ParticleEngine( t, dt ); - } - - // Loop through all particles and build vertex arrays. - particle_count = 0; - vptr = vertex_array; - pptr = particles; - for( i = 0; i < MAX_PARTICLES; i ++ ) - { - if( pptr->active ) - { - // Calculate particle intensity (we set it to max during 75% - // of its life, then it fades out) - alpha = 4.0f * pptr->life; - if( alpha > 1.0f ) - { - alpha = 1.0f; - } - - // Convert color from float to 8-bit (store it in a 32-bit - // integer using endian independent type casting) - ((GLubyte *)&rgba)[0] = (GLubyte)(pptr->r * 255.0f); - ((GLubyte *)&rgba)[1] = (GLubyte)(pptr->g * 255.0f); - ((GLubyte *)&rgba)[2] = (GLubyte)(pptr->b * 255.0f); - ((GLubyte *)&rgba)[3] = (GLubyte)(alpha * 255.0f); - - // 3) Translate the quad to the correct position in modelview - // space and store its parameters in vertex arrays (we also - // store texture coord and color information for each vertex). - - // Lower left corner - vptr->s = 0.0f; - vptr->t = 0.0f; - vptr->rgba = rgba; - vptr->x = pptr->x + quad_lower_left.x; - vptr->y = pptr->y + quad_lower_left.y; - vptr->z = pptr->z + quad_lower_left.z; - vptr ++; - - // Lower right corner - vptr->s = 1.0f; - vptr->t = 0.0f; - vptr->rgba = rgba; - vptr->x = pptr->x + quad_lower_right.x; - vptr->y = pptr->y + quad_lower_right.y; - vptr->z = pptr->z + quad_lower_right.z; - vptr ++; - - // Upper right corner - vptr->s = 1.0f; - vptr->t = 1.0f; - vptr->rgba = rgba; - vptr->x = pptr->x - quad_lower_left.x; - vptr->y = pptr->y - quad_lower_left.y; - vptr->z = pptr->z - quad_lower_left.z; - vptr ++; - - // Upper left corner - vptr->s = 0.0f; - vptr->t = 1.0f; - vptr->rgba = rgba; - vptr->x = pptr->x - quad_lower_right.x; - vptr->y = pptr->y - quad_lower_right.y; - vptr->z = pptr->z - quad_lower_right.z; - vptr ++; - - // Increase count of drawable particles - particle_count ++; - } - - // If we have filled up one batch of particles, draw it as a set - // of quads using glDrawArrays. - if( particle_count >= BATCH_PARTICLES ) - { - // The first argument tells which primitive type we use (QUAD) - // The second argument tells the index of the first vertex (0) - // The last argument is the vertex count - glDrawArrays( GL_QUADS, 0, PARTICLE_VERTS * particle_count ); - particle_count = 0; - vptr = vertex_array; - } - - // Next particle - pptr ++; - } - - // We are done with the particle data: Unlock mutex and signal physics - // thread - if( multithreading ) - { - glfwUnlockMutex( thread_sync.particles_lock ); - glfwSignalCond( thread_sync.d_done ); - } - - // Draw final batch of particles (if any) - glDrawArrays( GL_QUADS, 0, PARTICLE_VERTS * particle_count ); - - // Disable vertex arrays (Note: glInterleavedArrays implicitly called - // glEnableClientState for vertex, texture coord and color arrays) - glDisableClientState( GL_VERTEX_ARRAY ); - glDisableClientState( GL_TEXTURE_COORD_ARRAY ); - glDisableClientState( GL_COLOR_ARRAY ); - - // Disable texturing and blending - glDisable( GL_TEXTURE_2D ); - glDisable( GL_BLEND ); - - // Allow Z-buffer updates again - glDepthMask( GL_TRUE ); -} - - -//======================================================================== -// Fountain geometry specification -//======================================================================== - -#define FOUNTAIN_SIDE_POINTS 14 -#define FOUNTAIN_SWEEP_STEPS 32 - -static const float fountain_side[ FOUNTAIN_SIDE_POINTS*2 ] = { - 1.2f, 0.0f, 1.0f, 0.2f, 0.41f, 0.3f, 0.4f, 0.35f, - 0.4f, 1.95f, 0.41f, 2.0f, 0.8f, 2.2f, 1.2f, 2.4f, - 1.5f, 2.7f, 1.55f,2.95f, 1.6f, 3.0f, 1.0f, 3.0f, - 0.5f, 3.0f, 0.0f, 3.0f -}; - -static const float fountain_normal[ FOUNTAIN_SIDE_POINTS*2 ] = { - 1.0000f, 0.0000f, 0.6428f, 0.7660f, 0.3420f, 0.9397f, 1.0000f, 0.0000f, - 1.0000f, 0.0000f, 0.3420f,-0.9397f, 0.4226f,-0.9063f, 0.5000f,-0.8660f, - 0.7660f,-0.6428f, 0.9063f,-0.4226f, 0.0000f,1.00000f, 0.0000f,1.00000f, - 0.0000f,1.00000f, 0.0000f,1.00000f -}; - - -//======================================================================== -// DrawFountain() - Draw a fountain -//======================================================================== - -void DrawFountain( void ) -{ - static GLuint fountain_list = 0; - double angle; - float x, y; - int m, n; - - // The first time, we build the fountain display list - if( !fountain_list ) - { - // Start recording of a new display list - fountain_list = glGenLists( 1 ); - glNewList( fountain_list, GL_COMPILE_AND_EXECUTE ); - - // Set fountain material - glMaterialfv( GL_FRONT, GL_DIFFUSE, fountain_diffuse ); - glMaterialfv( GL_FRONT, GL_SPECULAR, fountain_specular ); - glMaterialf( GL_FRONT, GL_SHININESS, fountain_shininess ); - - // Build fountain using triangle strips - for( n = 0; n < FOUNTAIN_SIDE_POINTS-1; n ++ ) - { - glBegin( GL_TRIANGLE_STRIP ); - for( m = 0; m <= FOUNTAIN_SWEEP_STEPS; m ++ ) - { - angle = (double) m * (2.0*M_PI/(double)FOUNTAIN_SWEEP_STEPS); - x = (float) cos( angle ); - y = (float) sin( angle ); - - // Draw triangle strip - glNormal3f( x * fountain_normal[ n*2+2 ], - y * fountain_normal[ n*2+2 ], - fountain_normal[ n*2+3 ] ); - glVertex3f( x * fountain_side[ n*2+2 ], - y * fountain_side[ n*2+2 ], - fountain_side[ n*2+3 ] ); - glNormal3f( x * fountain_normal[ n*2 ], - y * fountain_normal[ n*2 ], - fountain_normal[ n*2+1 ] ); - glVertex3f( x * fountain_side[ n*2 ], - y * fountain_side[ n*2 ], - fountain_side[ n*2+1 ] ); - } - glEnd(); - } - - // End recording of display list - glEndList(); - } - else - { - // Playback display list - glCallList( fountain_list ); - } -} - - -//======================================================================== -// TesselateFloor() - Recursive function for building variable tesselated -// floor -//======================================================================== - -void TesselateFloor( float x1, float y1, float x2, float y2, - int recursion ) -{ - float delta, x, y; - - // Last recursion? - if( recursion >= 5 ) - { - delta = 999999.0f; - } - else - { - x = (float) (fabs(x1) < fabs(x2) ? fabs(x1) : fabs(x2)); - y = (float) (fabs(y1) < fabs(y2) ? fabs(y1) : fabs(y2)); - delta = x*x + y*y; - } - - // Recurse further? - if( delta < 0.1f ) - { - x = (x1+x2) * 0.5f; - y = (y1+y2) * 0.5f; - TesselateFloor( x1,y1, x, y, recursion + 1 ); - TesselateFloor( x,y1, x2, y, recursion + 1 ); - TesselateFloor( x1, y, x,y2, recursion + 1 ); - TesselateFloor( x, y, x2,y2, recursion + 1 ); - } - else - { - glTexCoord2f( x1*30.0f, y1*30.0f ); - glVertex3f( x1*80.0f, y1*80.0f , 0.0f ); - glTexCoord2f( x2*30.0f, y1*30.0f ); - glVertex3f( x2*80.0f, y1*80.0f , 0.0f ); - glTexCoord2f( x2*30.0f, y2*30.0f ); - glVertex3f( x2*80.0f, y2*80.0f , 0.0f ); - glTexCoord2f( x1*30.0f, y2*30.0f ); - glVertex3f( x1*80.0f, y2*80.0f , 0.0f ); - } -} - - -//======================================================================== -// DrawFloor() - Draw floor. We builde the floor recursively, and let the -// tesselation in the centre (near x,y=0,0) be high, while the selleation -// around the edges be low. -//======================================================================== - -void DrawFloor( void ) -{ - static GLuint floor_list = 0; - - // Select floor texture - if( !wireframe ) - { - glEnable( GL_TEXTURE_2D ); - glBindTexture( GL_TEXTURE_2D, floor_tex_id ); - } - - // The first time, we build the floor display list - if( !floor_list ) - { - // Start recording of a new display list - floor_list = glGenLists( 1 ); - glNewList( floor_list, GL_COMPILE_AND_EXECUTE ); - - // Set floor material - glMaterialfv( GL_FRONT, GL_DIFFUSE, floor_diffuse ); - glMaterialfv( GL_FRONT, GL_SPECULAR, floor_specular ); - glMaterialf( GL_FRONT, GL_SHININESS, floor_shininess ); - - // Draw floor as a bunch of triangle strips (high tesselation - // improves lighting) - glNormal3f( 0.0f, 0.0f, 1.0f ); - glBegin( GL_QUADS ); - TesselateFloor( -1.0f,-1.0f, 0.0f,0.0f, 0 ); - TesselateFloor( 0.0f,-1.0f, 1.0f,0.0f, 0 ); - TesselateFloor( 0.0f, 0.0f, 1.0f,1.0f, 0 ); - TesselateFloor( -1.0f, 0.0f, 0.0f,1.0f, 0 ); - glEnd(); - - // End recording of display list - glEndList(); - } - else - { - // Playback display list - glCallList( floor_list ); - } - - glDisable( GL_TEXTURE_2D ); - -} - - -//======================================================================== -// SetupLights() - Position and configure light sources -//======================================================================== - -void SetupLights( void ) -{ - float l1pos[4], l1amb[4], l1dif[4], l1spec[4]; - float l2pos[4], l2amb[4], l2dif[4], l2spec[4]; - - // Set light source 1 parameters - l1pos[0] = 0.0f; l1pos[1] = -9.0f; l1pos[2] = 8.0f; l1pos[3] = 1.0f; - l1amb[0] = 0.2f; l1amb[1] = 0.2f; l1amb[2] = 0.2f; l1amb[3] = 1.0f; - l1dif[0] = 0.8f; l1dif[1] = 0.4f; l1dif[2] = 0.2f; l1dif[3] = 1.0f; - l1spec[0] = 1.0f; l1spec[1] = 0.6f; l1spec[2] = 0.2f; l1spec[3] = 0.0f; - - // Set light source 2 parameters - l2pos[0] = -15.0f; l2pos[1] = 12.0f; l2pos[2] = 1.5f; l2pos[3] = 1.0f; - l2amb[0] = 0.0f; l2amb[1] = 0.0f; l2amb[2] = 0.0f; l2amb[3] = 1.0f; - l2dif[0] = 0.2f; l2dif[1] = 0.4f; l2dif[2] = 0.8f; l2dif[3] = 1.0f; - l2spec[0] = 0.2f; l2spec[1] = 0.6f; l2spec[2] = 1.0f; l2spec[3] = 0.0f; - - // Configure light sources in OpenGL - glLightfv( GL_LIGHT1, GL_POSITION, l1pos ); - glLightfv( GL_LIGHT1, GL_AMBIENT, l1amb ); - glLightfv( GL_LIGHT1, GL_DIFFUSE, l1dif ); - glLightfv( GL_LIGHT1, GL_SPECULAR, l1spec ); - glLightfv( GL_LIGHT2, GL_POSITION, l2pos ); - glLightfv( GL_LIGHT2, GL_AMBIENT, l2amb ); - glLightfv( GL_LIGHT2, GL_DIFFUSE, l2dif ); - glLightfv( GL_LIGHT2, GL_SPECULAR, l2spec ); - glLightfv( GL_LIGHT3, GL_POSITION, glow_pos ); - glLightfv( GL_LIGHT3, GL_DIFFUSE, glow_color ); - glLightfv( GL_LIGHT3, GL_SPECULAR, glow_color ); - - // Enable light sources - glEnable( GL_LIGHT1 ); - glEnable( GL_LIGHT2 ); - glEnable( GL_LIGHT3 ); -} - - -//======================================================================== -// Draw() - Main rendering function -//======================================================================== - -void Draw( double t ) -{ - double xpos, ypos, zpos, angle_x, angle_y, angle_z; - static double t_old = 0.0; - float dt; - - // Calculate frame-to-frame delta time - dt = (float)(t-t_old); - t_old = t; - - // Setup viewport - glViewport( 0, 0, width, height ); - - // Clear color and Z-buffer - glClearColor( 0.1f, 0.1f, 0.1f, 1.0f ); - glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); - - // Setup projection - glMatrixMode( GL_PROJECTION ); - glLoadIdentity(); - gluPerspective( 65.0, (double)width/(double)height, 1.0, 60.0 ); - - // Setup camera - glMatrixMode( GL_MODELVIEW ); - glLoadIdentity(); - - // Rotate camera - angle_x = 90.0 - 10.0; - angle_y = 10.0 * sin( 0.3 * t ); - angle_z = 10.0 * t; - glRotated( -angle_x, 1.0, 0.0, 0.0 ); - glRotated( -angle_y, 0.0, 1.0, 0.0 ); - glRotated( -angle_z, 0.0, 0.0, 1.0 ); - - // Translate camera - xpos = 15.0 * sin( (M_PI/180.0) * angle_z ) + - 2.0 * sin( (M_PI/180.0) * 3.1 * t ); - ypos = -15.0 * cos( (M_PI/180.0) * angle_z ) + - 2.0 * cos( (M_PI/180.0) * 2.9 * t ); - zpos = 4.0 + 2.0 * cos( (M_PI/180.0) * 4.9 * t ); - glTranslated( -xpos, -ypos, -zpos ); - - // Enable face culling - glFrontFace( GL_CCW ); - glCullFace( GL_BACK ); - glEnable( GL_CULL_FACE ); - - // Enable lighting - SetupLights(); - glEnable( GL_LIGHTING ); - - // Enable fog (dim details far away) - glEnable( GL_FOG ); - glFogi( GL_FOG_MODE, GL_EXP ); - glFogf( GL_FOG_DENSITY, 0.05f ); - glFogfv( GL_FOG_COLOR, fog_color ); - - // Draw floor - DrawFloor(); - - // Enable Z-buffering - glEnable( GL_DEPTH_TEST ); - glDepthFunc( GL_LEQUAL ); - glDepthMask( GL_TRUE ); - - // Draw fountain - DrawFountain(); - - // Disable fog & lighting - glDisable( GL_LIGHTING ); - glDisable( GL_FOG ); - - // Draw all particles (must be drawn after all solid objects have been - // drawn!) - DrawParticles( t, dt ); - - // Z-buffer not needed anymore - glDisable( GL_DEPTH_TEST ); -} - - -//======================================================================== -// Resize() - GLFW window resize callback function -//======================================================================== - -void GLFWCALL Resize( int x, int y ) -{ - width = x; - height = y > 0 ? y : 1; // Prevent division by zero in aspect calc. -} - - -//======================================================================== -// Input callback functions -//======================================================================== - -void GLFWCALL KeyFun( int key, int action ) -{ - if( action == GLFW_PRESS ) - { - switch( key ) - { - case GLFW_KEY_ESC: - running = 0; - break; - case 'W': - wireframe = !wireframe; - glPolygonMode( GL_FRONT_AND_BACK, - wireframe ? GL_LINE : GL_FILL ); - break; - default: - break; - } - } -} - - -//======================================================================== -// PhysicsThreadFun() - Thread for updating particle physics -//======================================================================== - -void GLFWCALL PhysicsThreadFun( void *arg ) -{ - while( running ) - { - // Lock mutex - glfwLockMutex( 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 ); - } - - // No longer running? - if( !running ) - { - break; - } - - // Update particles - ParticleEngine( thread_sync.t, thread_sync.dt ); - - // Update frame counter - thread_sync.p_frame ++; - - // Unlock mutex and signal drawing thread - glfwUnlockMutex( thread_sync.particles_lock ); - glfwSignalCond( thread_sync.p_done ); - } -} - - -//======================================================================== -// main() -//======================================================================== - -int main( int argc, char **argv ) -{ - int i, frames, benchmark; - double t0, t; - GLFWthread physics_thread = 0; - - // Use multithreading by default, but don't benchmark - multithreading = 1; - benchmark = 0; - - // Check command line arguments - for( i = 1; i < argc; i ++ ) - { - // Use benchmarking? - if( strcmp( argv[i], "-b" ) == 0 ) - { - benchmark = 1; - } - - // Force multithreading off? - else if( strcmp( argv[i], "-s" ) == 0 ) - { - multithreading = 0; - } - - // With a Finder launch on Mac OS X we get a bogus -psn_0_46268417 - // kind of argument (actual numbers vary). Ignore it. - else if( strncmp( argv[i], "-psn_", 5) == 0 ); - - // Usage - else - { - if( strcmp( argv[i], "-?" ) != 0 ) - { - printf( "Unknonwn option %s\n\n", argv[ i ] ); - } - printf( "Usage: %s [options]\n", argv[ 0 ] ); - printf( "\n"); - printf( "Options:\n" ); - printf( " -b Benchmark (run program for 60 s)\n" ); - printf( " -s Run program as single thread (default is to use two threads)\n" ); - printf( " -? Display this text\n" ); - printf( "\n"); - printf( "Program runtime controls:\n" ); - printf( " w Toggle wireframe mode\n" ); - printf( " ESC Exit program\n" ); - exit( 0 ); - } - } - - // Initialize GLFW - if( !glfwInit() ) - { - fprintf( stderr, "Failed to initialize GLFW\n" ); - exit( EXIT_FAILURE ); - } - - // Open OpenGL fullscreen window - if( !glfwOpenWindow( WIDTH, HEIGHT, 0,0,0,0, 16,0, GLFW_FULLSCREEN ) ) - { - fprintf( stderr, "Failed to open GLFW window\n" ); - glfwTerminate(); - exit( EXIT_FAILURE ); - } - - // Set window title - glfwSetWindowTitle( "Particle engine" ); - - // Disable VSync (we want to get as high FPS as possible!) - glfwSwapInterval( 0 ); - - // Window resize callback function - glfwSetWindowSizeCallback( Resize ); - - // Set keyboard input callback function - glfwSetKeyCallback( KeyFun ); - - // Upload particle texture - glGenTextures( 1, &particle_tex_id ); - glBindTexture( GL_TEXTURE_2D, particle_tex_id ); - glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); - glTexImage2D( GL_TEXTURE_2D, 0, GL_LUMINANCE, P_TEX_WIDTH, P_TEX_HEIGHT, - 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, particle_texture ); - - // Upload floor texture - glGenTextures( 1, &floor_tex_id ); - glBindTexture( GL_TEXTURE_2D, floor_tex_id ); - glPixelStorei( GL_UNPACK_ALIGNMENT, 1 ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); - glTexImage2D( GL_TEXTURE_2D, 0, GL_LUMINANCE, F_TEX_WIDTH, F_TEX_HEIGHT, - 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, floor_texture ); - - // Check if we have GL_EXT_separate_specular_color, and if so use it - if( glfwExtensionSupported( "GL_EXT_separate_specular_color" ) ) - { - glLightModeli( GL_LIGHT_MODEL_COLOR_CONTROL_EXT, - GL_SEPARATE_SPECULAR_COLOR_EXT ); - } - - // Set filled polygon mode as default (not wireframe) - glPolygonMode( GL_FRONT_AND_BACK, GL_FILL ); - wireframe = 0; - - // Clear particle system - for( i = 0; i < MAX_PARTICLES; i ++ ) - { - particles[ i ].active = 0; - } - min_age = 0.0f; - - // Set "running" flag - running = 1; - - // Set initial times - thread_sync.t = 0.0; - thread_sync.dt = 0.001f; - - // Init threading - if( multithreading ) - { - 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 ); - } - - // Main loop - t0 = glfwGetTime(); - frames = 0; - while( running ) - { - // Get frame time - t = glfwGetTime() - t0; - - // Draw... - Draw( t ); - - // Swap buffers - glfwSwapBuffers(); - - // Check if window was closed - running = running && glfwGetWindowParam( GLFW_OPENED ); - - // Increase frame count - frames ++; - - // End of benchmark? - if( benchmark && t >= 60.0 ) - { - running = 0; - } - } - t = glfwGetTime() - t0; - - // Wait for particle physics thread to die - if( multithreading ) - { - glfwWaitThread( physics_thread, GLFW_WAIT ); - } - - // Display profiling information - printf( "%d frames in %.2f seconds = %.1f FPS", frames, t, - (double)frames / t ); - printf( " (multithreading %s)\n", multithreading ? "on" : "off" ); - - // Terminate OpenGL - glfwTerminate(); - - exit( EXIT_SUCCESS ); -} - diff --git a/examples/pong3d.c b/examples/pong3d.c deleted file mode 100644 index 1d1afd1f..00000000 --- a/examples/pong3d.c +++ /dev/null @@ -1,854 +0,0 @@ -//======================================================================== -// This is a small test application for GLFW. -// This is an OpenGL port of the famous "PONG" game (the first computer -// game ever?). It is very simple, and could be improved alot. It was -// created in order to show off the gaming capabilities of GLFW. -//======================================================================== - -#include -#include -#include -#include - - -//======================================================================== -// Constants -//======================================================================== - -// Screen resolution -#define WIDTH 640 -#define HEIGHT 480 - -// Player size (units) -#define PLAYER_XSIZE 0.05f -#define PLAYER_YSIZE 0.15f - -// Ball size (units) -#define BALL_SIZE 0.02f - -// Maximum player movement speed (units / second) -#define MAX_SPEED 1.5f - -// Player movement acceleration (units / seconds^2) -#define ACCELERATION 4.0f - -// Player movement deceleration (units / seconds^2) -#define DECELERATION 2.0f - -// Ball movement speed (units / second) -#define BALL_SPEED 0.4f - -// Menu options -#define MENU_NONE 0 -#define MENU_PLAY 1 -#define MENU_QUIT 2 - -// Game events -#define NOBODY_WINS 0 -#define PLAYER1_WINS 1 -#define PLAYER2_WINS 2 - -// Winner ID -#define NOBODY 0 -#define PLAYER1 1 -#define PLAYER2 2 - -// Camera positions -#define CAMERA_CLASSIC 0 -#define CAMERA_ABOVE 1 -#define CAMERA_SPECTATOR 2 -#define CAMERA_DEFAULT CAMERA_CLASSIC - - -//======================================================================== -// Textures -//======================================================================== - -#define TEX_TITLE 0 -#define TEX_MENU 1 -#define TEX_INSTR 2 -#define TEX_WINNER1 3 -#define TEX_WINNER2 4 -#define TEX_FIELD 5 -#define NUM_TEXTURES 6 - -// Texture names -char * tex_name[ NUM_TEXTURES ] = { - "pong3d_title.tga", - "pong3d_menu.tga", - "pong3d_instr.tga", - "pong3d_winner1.tga", - "pong3d_winner2.tga", - "pong3d_field.tga" -}; - -// OpenGL texture object IDs -GLuint tex_id[ NUM_TEXTURES ]; - - -//======================================================================== -// Global variables -//======================================================================== - -// Display information -int width, height; - -// Frame information -double thistime, oldtime, dt, starttime; - -// Camera information -int camerapos; - -// Player information -struct { - double ypos; // -1.0 to +1.0 - double yspeed; // -MAX_SPEED to +MAX_SPEED -} player1, player2; - -// Ball information -struct { - double xpos, ypos; - double xspeed, yspeed; -} ball; - -// And the winner is... -int winner; - -// Lighting configuration -const GLfloat env_ambient[4] = {1.0f,1.0f,1.0f,1.0f}; -const GLfloat light1_position[4] = {-3.0f,3.0f,2.0f,1.0f}; -const GLfloat light1_diffuse[4] = {1.0f,1.0f,1.0f,0.0f}; -const GLfloat light1_ambient[4] = {0.0f,0.0f,0.0f,0.0f}; - -// Object material properties -const GLfloat player1_diffuse[4] = {1.0f,0.3f,0.3f,1.0f}; -const GLfloat player1_ambient[4] = {0.3f,0.1f,0.0f,1.0f}; -const GLfloat player2_diffuse[4] = {0.3f,1.0f,0.3f,1.0f}; -const GLfloat player2_ambient[4] = {0.1f,0.3f,0.1f,1.0f}; -const GLfloat ball_diffuse[4] = {1.0f,1.0f,0.5f,1.0f}; -const GLfloat ball_ambient[4] = {0.3f,0.3f,0.1f,1.0f}; -const GLfloat border_diffuse[4] = {0.3f,0.3f,1.0f,1.0f}; -const GLfloat border_ambient[4] = {0.1f,0.1f,0.3f,1.0f}; -const GLfloat floor_diffuse[4] = {1.0f,1.0f,1.0f,1.0f}; -const GLfloat floor_ambient[4] = {0.3f,0.3f,0.3f,1.0f}; - - -//======================================================================== -// LoadTextures() - Load textures from disk and upload to OpenGL card -//======================================================================== - -GLboolean LoadTextures( void ) -{ - int i; - - // Generate texture objects - glGenTextures( NUM_TEXTURES, tex_id ); - - // Load textures - for( i = 0; i < NUM_TEXTURES; i ++ ) - { - // Select texture object - glBindTexture( GL_TEXTURE_2D, tex_id[ i ] ); - - // Set texture parameters - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR ); - glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR ); - - // Upload texture from file to texture memory - if( !glfwLoadTexture2D( tex_name[ i ], 0 ) ) - { - fprintf( stderr, "Failed to load texture %s\n", tex_name[ i ] ); - return GL_FALSE; - } - } - - return GL_TRUE; -} - - -//======================================================================== -// DrawImage() - Draw a 2D image as a texture -//======================================================================== - -void DrawImage( int texnum, float x1, float x2, float y1, float y2 ) -{ - glEnable( GL_TEXTURE_2D ); - glBindTexture( GL_TEXTURE_2D, tex_id[ texnum ] ); - glBegin( GL_QUADS ); - glTexCoord2f( 0.0f, 1.0f ); - glVertex2f( x1, y1 ); - glTexCoord2f( 1.0f, 1.0f ); - glVertex2f( x2, y1 ); - glTexCoord2f( 1.0f, 0.0f ); - glVertex2f( x2, y2 ); - glTexCoord2f( 0.0f, 0.0f ); - glVertex2f( x1, y2 ); - glEnd(); - glDisable( GL_TEXTURE_2D ); -} - - -//======================================================================== -// GameMenu() - Game menu (returns menu option) -//======================================================================== - -int GameMenu( void ) -{ - int option; - - // Enable sticky keys - glfwEnable( GLFW_STICKY_KEYS ); - - // Wait for a game menu key to be pressed - do - { - // Get window size - glfwGetWindowSize( &width, &height ); - - // Set viewport - glViewport( 0, 0, width, height ); - - // Clear display - glClearColor( 0.0f, 0.0f, 0.0f, 0.0f ); - glClear( GL_COLOR_BUFFER_BIT ); - - // Setup projection matrix - glMatrixMode( GL_PROJECTION ); - glLoadIdentity(); - glOrtho( 0.0f, 1.0f, 1.0f, 0.0f, -1.0f, 1.0f ); - - // Setup modelview matrix - glMatrixMode( GL_MODELVIEW ); - glLoadIdentity(); - - // Display title - glColor3f( 1.0f, 1.0f, 1.0f ); - DrawImage( TEX_TITLE, 0.1f, 0.9f, 0.0f, 0.3f ); - - // Display menu - glColor3f( 1.0f, 1.0f, 0.0f ); - DrawImage( TEX_MENU, 0.38f, 0.62f, 0.35f, 0.5f ); - - // Display instructions - glColor3f( 0.0f, 1.0f, 1.0f ); - DrawImage( TEX_INSTR, 0.32f, 0.68f, 0.65f, 0.85f ); - - // Swap buffers - glfwSwapBuffers(); - - // Check for keys - if( glfwGetKey( 'Q' ) || !glfwGetWindowParam( GLFW_OPENED ) ) - { - option = MENU_QUIT; - } - else if( glfwGetKey( GLFW_KEY_F1 ) ) - { - option = MENU_PLAY; - } - else - { - option = MENU_NONE; - } - - // To avoid horrible busy waiting, sleep for at least 20 ms - glfwSleep( 0.02 ); - } - while( option == MENU_NONE ); - - // Disable sticky keys - glfwDisable( GLFW_STICKY_KEYS ); - - return option; -} - - -//======================================================================== -// NewGame() - Initialize a new game -//======================================================================== - -void NewGame( void ) -{ - // Frame information - starttime = thistime = glfwGetTime(); - - // Camera information - camerapos = CAMERA_DEFAULT; - - // Player 1 information - player1.ypos = 0.0; - player1.yspeed = 0.0; - - // Player 2 information - player2.ypos = 0.0; - player2.yspeed = 0.0; - - // Ball information - ball.xpos = -1.0 + PLAYER_XSIZE; - ball.ypos = player1.ypos; - ball.xspeed = 1.0; - ball.yspeed = 1.0; -} - - -//======================================================================== -// PlayerControl() - Player control -//======================================================================== - -void PlayerControl( void ) -{ - float joy1pos[ 2 ], joy2pos[ 2 ]; - - // Get joystick X & Y axis positions - glfwGetJoystickPos( GLFW_JOYSTICK_1, joy1pos, 2 ); - glfwGetJoystickPos( GLFW_JOYSTICK_2, joy2pos, 2 ); - - // Player 1 control - if( glfwGetKey( 'A' ) || joy1pos[ 1 ] > 0.2f ) - { - player1.yspeed += dt * ACCELERATION; - if( player1.yspeed > MAX_SPEED ) - { - player1.yspeed = MAX_SPEED; - } - } - else if( glfwGetKey( 'Z' ) || joy1pos[ 1 ] < -0.2f ) - { - player1.yspeed -= dt * ACCELERATION; - if( player1.yspeed < -MAX_SPEED ) - { - player1.yspeed = -MAX_SPEED; - } - } - else - { - player1.yspeed /= exp( DECELERATION * dt ); - } - - // Player 2 control - if( glfwGetKey( 'K' ) || joy2pos[ 1 ] > 0.2f ) - { - player2.yspeed += dt * ACCELERATION; - if( player2.yspeed > MAX_SPEED ) - { - player2.yspeed = MAX_SPEED; - } - } - else if( glfwGetKey( 'M' ) || joy2pos[ 1 ] < -0.2f ) - { - player2.yspeed -= dt * ACCELERATION; - if( player2.yspeed < -MAX_SPEED ) - { - player2.yspeed = -MAX_SPEED; - } - } - else - { - player2.yspeed /= exp( DECELERATION * dt ); - } - - // Update player 1 position - player1.ypos += dt * player1.yspeed; - if( player1.ypos > 1.0 - PLAYER_YSIZE ) - { - player1.ypos = 1.0 - PLAYER_YSIZE; - player1.yspeed = 0.0; - } - else if( player1.ypos < -1.0 + PLAYER_YSIZE ) - { - player1.ypos = -1.0 + PLAYER_YSIZE; - player1.yspeed = 0.0; - } - - // Update player 2 position - player2.ypos += dt * player2.yspeed; - if( player2.ypos > 1.0 - PLAYER_YSIZE ) - { - player2.ypos = 1.0 - PLAYER_YSIZE; - player2.yspeed = 0.0; - } - else if( player2.ypos < -1.0 + PLAYER_YSIZE ) - { - player2.ypos = -1.0 + PLAYER_YSIZE; - player2.yspeed = 0.0; - } -} - - -//======================================================================== -// BallControl() - Ball control -//======================================================================== - -int BallControl( void ) -{ - int event; - double ballspeed; - - // Calculate new ball speed - ballspeed = BALL_SPEED * (1.0 + 0.02*(thistime-starttime)); - ball.xspeed = ball.xspeed > 0 ? ballspeed : -ballspeed; - ball.yspeed = ball.yspeed > 0 ? ballspeed : -ballspeed; - ball.yspeed *= 0.74321; - - // Update ball position - ball.xpos += dt * ball.xspeed; - ball.ypos += dt * ball.yspeed; - - // Did the ball hit a top/bottom wall? - if( ball.ypos >= 1.0 ) - { - ball.ypos = 2.0 - ball.ypos; - ball.yspeed = -ball.yspeed; - } - else if( ball.ypos <= -1.0 ) - { - ball.ypos = -2.0 - ball.ypos; - ball.yspeed = -ball.yspeed; - } - - // Did the ball hit/miss a player? - event = NOBODY_WINS; - - // Is the ball entering the player 1 goal? - if( ball.xpos < -1.0 + PLAYER_XSIZE ) - { - // Did player 1 catch the ball? - if( ball.ypos > (player1.ypos-PLAYER_YSIZE) && - ball.ypos < (player1.ypos+PLAYER_YSIZE) ) - { - ball.xpos = -2.0 + 2.0*PLAYER_XSIZE - ball.xpos; - ball.xspeed = -ball.xspeed; - } - else - { - event = PLAYER2_WINS; - } - } - - // Is the ball entering the player 2 goal? - if( ball.xpos > 1.0 - PLAYER_XSIZE ) - { - // Did player 2 catch the ball? - if( ball.ypos > (player2.ypos-PLAYER_YSIZE) && - ball.ypos < (player2.ypos+PLAYER_YSIZE) ) - { - ball.xpos = 2.0 - 2.0*PLAYER_XSIZE - ball.xpos; - ball.xspeed = -ball.xspeed; - } - else - { - event = PLAYER1_WINS; - } - } - - return event; -} - - -//======================================================================== -// DrawBox() - Draw a 3D box -//======================================================================== - -#define TEX_SCALE 4.0f - - -void DrawBox( float x1, float y1, float z1, float x2, float y2, float z2 ) -{ - // Draw six sides of a cube - glBegin( GL_QUADS ); - // Side 1 (down) - glNormal3f( 0.0f, 0.0f, -1.0f ); - glTexCoord2f( 0.0f, 0.0f ); - glVertex3f( x1,y2,z1 ); - glTexCoord2f( TEX_SCALE, 0.0f ); - glVertex3f( x2,y2,z1 ); - glTexCoord2f( TEX_SCALE, TEX_SCALE ); - glVertex3f( x2,y1,z1 ); - glTexCoord2f( 0.0f, TEX_SCALE ); - glVertex3f( x1,y1,z1 ); - // Side 2 (up) - glNormal3f( 0.0f, 0.0f, 1.0f ); - glTexCoord2f( 0.0f, 0.0f ); - glVertex3f( x1,y1,z2 ); - glTexCoord2f( TEX_SCALE, 0.0f ); - glVertex3f( x2,y1,z2 ); - glTexCoord2f( TEX_SCALE, TEX_SCALE ); - glVertex3f( x2,y2,z2 ); - glTexCoord2f( 0.0f, TEX_SCALE ); - glVertex3f( x1,y2,z2 ); - // Side 3 (backward) - glNormal3f( 0.0f, -1.0f, 0.0f ); - glTexCoord2f( 0.0f, 0.0f ); - glVertex3f( x1,y1,z1 ); - glTexCoord2f( TEX_SCALE, 0.0f ); - glVertex3f( x2,y1,z1 ); - glTexCoord2f( TEX_SCALE, TEX_SCALE ); - glVertex3f( x2,y1,z2 ); - glTexCoord2f( 0.0f, TEX_SCALE ); - glVertex3f( x1,y1,z2 ); - // Side 4 (forward) - glNormal3f( 0.0f, 1.0f, 0.0f ); - glTexCoord2f( 0.0f, 0.0f ); - glVertex3f( x1,y2,z2 ); - glTexCoord2f( TEX_SCALE, 0.0f ); - glVertex3f( x2,y2,z2 ); - glTexCoord2f( TEX_SCALE, TEX_SCALE ); - glVertex3f( x2,y2,z1 ); - glTexCoord2f( 0.0f, TEX_SCALE ); - glVertex3f( x1,y2,z1 ); - // Side 5 (left) - glNormal3f( -1.0f, 0.0f, 0.0f ); - glTexCoord2f( 0.0f, 0.0f ); - glVertex3f( x1,y1,z2 ); - glTexCoord2f( TEX_SCALE, 0.0f ); - glVertex3f( x1,y2,z2 ); - glTexCoord2f( TEX_SCALE, TEX_SCALE ); - glVertex3f( x1,y2,z1 ); - glTexCoord2f( 0.0f, TEX_SCALE ); - glVertex3f( x1,y1,z1 ); - // Side 6 (right) - glNormal3f( 1.0f, 0.0f, 0.0f ); - glTexCoord2f( 0.0f, 0.0f ); - glVertex3f( x2,y1,z1 ); - glTexCoord2f( TEX_SCALE, 0.0f ); - glVertex3f( x2,y2,z1 ); - glTexCoord2f( TEX_SCALE, TEX_SCALE ); - glVertex3f( x2,y2,z2 ); - glTexCoord2f( 0.0f, TEX_SCALE ); - glVertex3f( x2,y1,z2 ); - glEnd(); -} - - -//======================================================================== -// UpdateDisplay() - Draw graphics (all game related OpenGL stuff goes -// here) -//======================================================================== - -void UpdateDisplay( void ) -{ - // Get window size - glfwGetWindowSize( &width, &height ); - - // Set viewport - glViewport( 0, 0, width, height ); - - // Clear display - glClearColor( 0.02f, 0.02f, 0.02f, 0.0f ); - glClearDepth( 1.0f ); - glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ); - - // Setup projection matrix - glMatrixMode( GL_PROJECTION ); - glLoadIdentity(); - gluPerspective( - 55.0f, // Angle of view - (GLfloat)width/(GLfloat)height, // Aspect - 1.0f, // Near Z - 100.0f // Far Z - ); - - // Setup modelview matrix - glMatrixMode( GL_MODELVIEW ); - glLoadIdentity(); - switch( camerapos ) - { - default: - case CAMERA_CLASSIC: - gluLookAt( - 0.0f, 0.0f, 2.5f, - 0.0f, 0.0f, 0.0f, - 0.0f, 1.0f, 0.0f - ); - break; - case CAMERA_ABOVE: - gluLookAt( - 0.0f, 0.0f, 2.5f, - (float)ball.xpos, (float)ball.ypos, 0.0f, - 0.0f, 1.0f, 0.0f - ); - break; - case CAMERA_SPECTATOR: - gluLookAt( - 0.0f, -2.0, 1.2f, - (float)ball.xpos, (float)ball.ypos, 0.0f, - 0.0f, 0.0f, 1.0f - ); - break; - } - - // Enable depth testing - glEnable( GL_DEPTH_TEST ); - glDepthFunc( GL_LEQUAL ); - - // Enable lighting - glEnable( GL_LIGHTING ); - glLightModelfv( GL_LIGHT_MODEL_AMBIENT, env_ambient ); - glLightModeli( GL_LIGHT_MODEL_LOCAL_VIEWER, GL_TRUE ); - glLightModeli( GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE ); - glLightfv( GL_LIGHT1, GL_POSITION, light1_position ); - glLightfv( GL_LIGHT1, GL_DIFFUSE, light1_diffuse ); - glLightfv( GL_LIGHT1, GL_AMBIENT, light1_ambient ); - glEnable( GL_LIGHT1 ); - - // Front face is counter-clock-wise - glFrontFace( GL_CCW ); - - // Enable face culling (not necessary, but speeds up rendering) - glCullFace( GL_BACK ); - glEnable( GL_CULL_FACE ); - - // Draw Player 1 - glMaterialfv( GL_FRONT, GL_DIFFUSE, player1_diffuse ); - glMaterialfv( GL_FRONT, GL_AMBIENT, player1_ambient ); - DrawBox( -1.f, (GLfloat)player1.ypos-PLAYER_YSIZE, 0.f, - -1.f+PLAYER_XSIZE, (GLfloat)player1.ypos+PLAYER_YSIZE, 0.1f ); - - // Draw Player 2 - glMaterialfv( GL_FRONT, GL_DIFFUSE, player2_diffuse ); - glMaterialfv( GL_FRONT, GL_AMBIENT, player2_ambient ); - DrawBox( 1.f-PLAYER_XSIZE, (GLfloat)player2.ypos-PLAYER_YSIZE, 0.f, - 1.f, (GLfloat)player2.ypos+PLAYER_YSIZE, 0.1f ); - - // Draw Ball - glMaterialfv( GL_FRONT, GL_DIFFUSE, ball_diffuse ); - glMaterialfv( GL_FRONT, GL_AMBIENT, ball_ambient ); - DrawBox( (GLfloat)ball.xpos-BALL_SIZE, (GLfloat)ball.ypos-BALL_SIZE, 0.f, - (GLfloat)ball.xpos+BALL_SIZE, (GLfloat)ball.ypos+BALL_SIZE, BALL_SIZE*2 ); - - // Top game field border - glMaterialfv( GL_FRONT, GL_DIFFUSE, border_diffuse ); - glMaterialfv( GL_FRONT, GL_AMBIENT, border_ambient ); - DrawBox( -1.1f, 1.0f, 0.0f, 1.1f, 1.1f, 0.1f ); - // Bottom game field border - glColor3f( 0.0f, 0.0f, 0.7f ); - DrawBox( -1.1f, -1.1f, 0.0f, 1.1f, -1.0f, 0.1f ); - // Left game field border - DrawBox( -1.1f, -1.0f, 0.0f, -1.0f, 1.0f, 0.1f ); - // Left game field border - DrawBox( 1.0f, -1.0f, 0.0f, 1.1f, 1.0f, 0.1f ); - - // Enable texturing - glEnable( GL_TEXTURE_2D ); - glBindTexture( GL_TEXTURE_2D, tex_id[ TEX_FIELD ] ); - - // Game field floor - glMaterialfv( GL_FRONT, GL_DIFFUSE, floor_diffuse ); - glMaterialfv( GL_FRONT, GL_AMBIENT, floor_ambient ); - DrawBox( -1.01f, -1.01f, -0.01f, 1.01f, 1.01f, 0.0f ); - - // Disable texturing - glDisable( GL_TEXTURE_2D ); - - // Disable face culling - glDisable( GL_CULL_FACE ); - - // Disable lighting - glDisable( GL_LIGHTING ); - - // Disable depth testing - glDisable( GL_DEPTH_TEST ); -} - - -//======================================================================== -// GameOver() -//======================================================================== - -void GameOver( void ) -{ - // Enable sticky keys - glfwEnable( GLFW_STICKY_KEYS ); - - // Until the user presses ESC or SPACE - while( !glfwGetKey( GLFW_KEY_ESC ) && !glfwGetKey( ' ' ) && - glfwGetWindowParam( GLFW_OPENED ) ) - { - // Draw display - UpdateDisplay(); - - // Setup projection matrix - glMatrixMode( GL_PROJECTION ); - glLoadIdentity(); - glOrtho( 0.0f, 1.0f, 1.0f, 0.0f, -1.0f, 1.0f ); - - // Setup modelview matrix - glMatrixMode( GL_MODELVIEW ); - glLoadIdentity(); - - // Enable blending - glEnable( GL_BLEND ); - - // Dim background - glBlendFunc( GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA ); - glColor4f( 0.3f, 0.3f, 0.3f, 0.3f ); - glBegin( GL_QUADS ); - glVertex2f( 0.0f, 0.0f ); - glVertex2f( 1.0f, 0.0f ); - glVertex2f( 1.0f, 1.0f ); - glVertex2f( 0.0f, 1.0f ); - glEnd(); - - // Display winner text - glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_COLOR ); - if( winner == PLAYER1 ) - { - glColor4f( 1.0f, 0.5f, 0.5f, 1.0f ); - DrawImage( TEX_WINNER1, 0.35f, 0.65f, 0.46f, 0.54f ); - } - else if( winner == PLAYER2 ) - { - glColor4f( 0.5f, 1.0f, 0.5f, 1.0f ); - DrawImage( TEX_WINNER2, 0.35f, 0.65f, 0.46f, 0.54f ); - } - - // Disable blending - glDisable( GL_BLEND ); - - // Swap buffers - glfwSwapBuffers(); - } - - // Disable sticky keys - glfwDisable( GLFW_STICKY_KEYS ); -} - - -//======================================================================== -// GameLoop() - Game loop -//======================================================================== - -void GameLoop( void ) -{ - int playing, event; - - // Initialize a new game - NewGame(); - - // Enable sticky keys - glfwEnable( GLFW_STICKY_KEYS ); - - // Loop until the game ends - playing = GL_TRUE; - while( playing && glfwGetWindowParam( GLFW_OPENED ) ) - { - // Frame timer - oldtime = thistime; - thistime = glfwGetTime(); - dt = thistime - oldtime; - - // Get user input and update player positions - PlayerControl(); - - // Move the ball, and check if a player hits/misses the ball - event = BallControl(); - - // Did we have a winner? - switch( event ) - { - case PLAYER1_WINS: - winner = PLAYER1; - playing = GL_FALSE; - break; - case PLAYER2_WINS: - winner = PLAYER2; - playing = GL_FALSE; - break; - default: - break; - } - - // Did the user press ESC? - if( glfwGetKey( GLFW_KEY_ESC ) ) - { - playing = GL_FALSE; - } - - // Did the user change camera view? - if( glfwGetKey( '1' ) ) - { - camerapos = CAMERA_CLASSIC; - } - else if( glfwGetKey( '2' ) ) - { - camerapos = CAMERA_ABOVE; - } - else if( glfwGetKey( '3' ) ) - { - camerapos = CAMERA_SPECTATOR; - } - - // Draw display - UpdateDisplay(); - - // Swap buffers - glfwSwapBuffers(); - } - - // Disable sticky keys - glfwDisable( GLFW_STICKY_KEYS ); - - // Show winner - GameOver(); -} - - -//======================================================================== -// main() - Program entry point -//======================================================================== - -int main( void ) -{ - int menuoption; - - // Initialize GLFW - if( !glfwInit() ) - { - fprintf( stderr, "Failed to initialize GLFW\n" ); - exit( EXIT_FAILURE ); - } - - // Open OpenGL window - if( !glfwOpenWindow( WIDTH, HEIGHT, 0,0,0,0, 16,0, GLFW_FULLSCREEN ) ) - { - fprintf( stderr, "Failed to open GLFW window\n" ); - glfwTerminate(); - exit( EXIT_FAILURE ); - } - - glfwSwapInterval( 1 ); - - // Load all textures - if( !LoadTextures() ) - { - glfwTerminate(); - exit( EXIT_FAILURE ); - } - - // Main loop - do - { - // Get menu option - menuoption = GameMenu(); - - // If the user wants to play, let him... - if( menuoption == MENU_PLAY ) - { - GameLoop(); - } - } - while( menuoption != MENU_QUIT ); - - // Unload all textures - if( glfwGetWindowParam( GLFW_OPENED ) ) - { - glDeleteTextures( NUM_TEXTURES, tex_id ); - } - - // Terminate GLFW - glfwTerminate(); - - exit( EXIT_SUCCESS ); -} - diff --git a/examples/pong3d_field.tga b/examples/pong3d_field.tga deleted file mode 100644 index cc20bbdb..00000000 Binary files a/examples/pong3d_field.tga and /dev/null differ diff --git a/examples/pong3d_instr.tga b/examples/pong3d_instr.tga deleted file mode 100644 index 758eb447..00000000 Binary files a/examples/pong3d_instr.tga and /dev/null differ diff --git a/examples/pong3d_menu.tga b/examples/pong3d_menu.tga deleted file mode 100644 index d0d6c5a4..00000000 Binary files a/examples/pong3d_menu.tga and /dev/null differ diff --git a/examples/pong3d_title.tga b/examples/pong3d_title.tga deleted file mode 100644 index d0d8e36d..00000000 Binary files a/examples/pong3d_title.tga and /dev/null differ diff --git a/examples/pong3d_winner1.tga b/examples/pong3d_winner1.tga deleted file mode 100644 index f963720c..00000000 Binary files a/examples/pong3d_winner1.tga and /dev/null differ diff --git a/examples/pong3d_winner2.tga b/examples/pong3d_winner2.tga deleted file mode 100644 index ea8266de..00000000 Binary files a/examples/pong3d_winner2.tga and /dev/null differ diff --git a/examples/splitview.c b/examples/splitview.c index c584f9af..4a48a383 100644 --- a/examples/splitview.c +++ b/examples/splitview.c @@ -450,10 +450,16 @@ int main(void) exit(EXIT_FAILURE); } - glfwOpenWindowHint(GLFW_DEPTH_BITS, 16); + // Set callback functions + glfwSetWindowSizeCallback(windowSizeFun); + glfwSetWindowRefreshCallback(windowRefreshFun); + glfwSetCursorPosCallback(cursorPosFun); + glfwSetMouseButtonCallback(mouseButtonFun); + + glfwWindowHint(GLFW_DEPTH_BITS, 16); // Open OpenGL window - window = glfwOpenWindow(500, 500, GLFW_WINDOWED, "Split view demo", NULL); + window = glfwCreateWindow(500, 500, GLFW_WINDOWED, "Split view demo", NULL); if (!window) { fprintf(stderr, "Failed to open GLFW window\n"); @@ -461,22 +467,20 @@ int main(void) } // Enable vsync + glfwMakeContextCurrent(window); glfwSwapInterval(1); + glfwGetWindowSize(window, &width, &height); + windowSizeFun(window, width, height); + // Enable sticky keys glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE); // Enable mouse cursor (only needed for fullscreen mode) glfwSetInputMode(window, GLFW_CURSOR_MODE, GLFW_CURSOR_NORMAL); - // Set callback functions - glfwSetWindowSizeCallback(windowSizeFun); - glfwSetWindowRefreshCallback(windowRefreshFun); - glfwSetCursorPosCallback(cursorPosFun); - glfwSetMouseButtonCallback(mouseButtonFun); - // Main loop - do + for (;;) { // Only redraw if we need to if (do_redraw) @@ -485,7 +489,7 @@ int main(void) drawAllViews(); // Swap buffers - glfwSwapBuffers(); + glfwSwapBuffers(window); do_redraw = 0; } @@ -493,9 +497,12 @@ int main(void) // Wait for new events glfwWaitEvents(); - } // Check if the ESC key was pressed or the window was closed - while (glfwIsWindow(window) && - glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS); + // Check if the ESC key was pressed or the window should be closed + if (glfwGetKey(window, GLFW_KEY_ESCAPE)) + break; + if (glfwGetWindowParam(window, GLFW_CLOSE_REQUESTED)) + break; + } // Close OpenGL window and terminate GLFW glfwTerminate(); diff --git a/examples/triangle.c b/examples/triangle.c index ee340496..615483a9 100644 --- a/examples/triangle.c +++ b/examples/triangle.c @@ -23,20 +23,21 @@ int main(void) } // Open a window and create its OpenGL context - window = glfwOpenWindow(640, 480, GLFW_WINDOWED, "Spinning Triangle", NULL); + window = glfwCreateWindow(640, 480, GLFW_WINDOWED, "Spinning Triangle", NULL); if (!window) { fprintf(stderr, "Failed to open GLFW window\n"); exit(EXIT_FAILURE); } + // Enable vertical sync (on cards that support it) + glfwMakeContextCurrent(window); + glfwSwapInterval(1); + // Ensure we can capture the escape key being pressed below glfwSetInputMode(window, GLFW_STICKY_KEYS, GL_TRUE); - // Enable vertical sync (on cards that support it) - glfwSwapInterval(1); - - do + for (;;) { double t = glfwGetTime(); glfwGetCursorPos(window, &x, NULL); @@ -79,12 +80,15 @@ int main(void) glEnd(); // Swap buffers - glfwSwapBuffers(); + glfwSwapBuffers(window); glfwPollEvents(); - } // Check if the ESC key was pressed or the window was closed - while (glfwIsWindow(window) && - glfwGetKey(window, GLFW_KEY_ESCAPE) != GLFW_PRESS); + // Check if the ESC key was pressed or the window should be closed + if (glfwGetKey(window, GLFW_KEY_ESCAPE)) + break; + if (glfwGetWindowParam(window, GLFW_CLOSE_REQUESTED)) + break; + } // Close OpenGL window and terminate GLFW glfwTerminate(); diff --git a/examples/wave.c b/examples/wave.c index 54574839..668d54bd 100644 --- a/examples/wave.c +++ b/examples/wave.c @@ -145,7 +145,7 @@ void init_grid(void) // Draw scene //======================================================================== -void draw_scene(void) +void draw_scene(GLFWwindow window) { // Clear the color and depth buffers glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); @@ -162,7 +162,7 @@ void draw_scene(void) glDrawElements(GL_QUADS, 4 * QUADNUM, GL_UNSIGNED_INT, quad); - glfwSwapBuffers(); + glfwSwapBuffers(window); } @@ -355,7 +355,7 @@ void scroll_callback(GLFWwindow window, double x, double y) // Callback function for window resize events //======================================================================== -void window_resize_callback(GLFWwindow window, int width, int height) +void window_size_callback(GLFWwindow window, int width, int height) { float ratio = 1.f; @@ -372,6 +372,17 @@ void window_resize_callback(GLFWwindow window, int width, int height) } +//======================================================================== +// Callback function for window close events +//======================================================================== + +static int window_close_callback(GLFWwindow window) +{ + running = GL_FALSE; + return GL_TRUE; +} + + //======================================================================== // main //======================================================================== @@ -380,6 +391,7 @@ int main(int argc, char* argv[]) { GLFWwindow window; double t, dt_total, t_old; + int width, height; if (!glfwInit()) { @@ -387,24 +399,27 @@ int main(int argc, char* argv[]) exit(EXIT_FAILURE); } - window = glfwOpenWindow(640, 480, GLFW_WINDOWED, "Wave Simulation", NULL); + glfwSetKeyCallback(key_callback); + glfwSetWindowCloseCallback(window_close_callback); + glfwSetWindowSizeCallback(window_size_callback); + glfwSetMouseButtonCallback(mouse_button_callback); + glfwSetCursorPosCallback(cursor_position_callback); + glfwSetScrollCallback(scroll_callback); + + window = glfwCreateWindow(640, 480, GLFW_WINDOWED, "Wave Simulation", NULL); if (!window) { fprintf(stderr, "Could not open window\n"); exit(EXIT_FAILURE); } + glfwMakeContextCurrent(window); glfwSwapInterval(1); - // Keyboard handler - glfwSetKeyCallback(key_callback); - glfwSetInputMode(window, GLFW_KEY_REPEAT, GL_TRUE); + glfwGetWindowSize(window, &width, &height); + window_size_callback(window, width, height); - // Window resize handler - glfwSetWindowSizeCallback(window_resize_callback); - glfwSetMouseButtonCallback(mouse_button_callback); - glfwSetCursorPosCallback(cursor_position_callback); - glfwSetScrollCallback(scroll_callback); + glfwSetInputMode(window, GLFW_KEY_REPEAT, GL_TRUE); // Initialize OpenGL init_opengl(); @@ -438,12 +453,9 @@ int main(int argc, char* argv[]) adjust_grid(); // Draw wave grid to OpenGL display - draw_scene(); + draw_scene(window); glfwPollEvents(); - - // Still running? - running = running && glfwIsWindow(window); } exit(EXIT_SUCCESS); diff --git a/include/GL/glfw3.h b/include/GL/glfw3.h index 26c76d41..c0d638bf 100644 --- a/include/GL/glfw3.h +++ b/include/GL/glfw3.h @@ -67,13 +67,6 @@ extern "C" { #endif #endif /* APIENTRY */ -/* TEMPORARY MinGW-w64 hacks. - */ -#if __MINGW64__ - #define WINAPI -#include -#endif - /* The following three defines are here solely to make some Windows-based * files happy. Theoretically we could include , but * it has the major drawback of severely polluting our namespace. @@ -110,11 +103,10 @@ extern "C" { #define GLFW_CALLBACK_DEFINED #endif /* CALLBACK */ -/* Microsoft Visual C++, Borland C++ and Pelles C needs wchar_t */ -#if defined(_WIN32) && (defined(_MSC_VER) || defined(__BORLANDC__) || defined(__POCC__)) && !defined(_WCHAR_T_DEFINED) - typedef unsigned short wchar_t; - #define _WCHAR_T_DEFINED -#endif /* _WCHAR_T_DEFINED */ +/* Most variants on Windows need wchar_t */ +#if defined(_WIN32) + #include +#endif /* ---------------- GLFW related system specific defines ----------------- */ @@ -385,18 +377,17 @@ extern "C" { * Other definitions *************************************************************************/ -/* glfwOpenWindow modes */ +/* glfwCreateWindow modes */ #define GLFW_WINDOWED 0x00010001 #define GLFW_FULLSCREEN 0x00010002 /* glfwGetWindowParam tokens */ #define GLFW_ACTIVE 0x00020001 #define GLFW_ICONIFIED 0x00020002 +#define GLFW_CLOSE_REQUESTED 0x00020003 #define GLFW_OPENGL_REVISION 0x00020004 -/* The following constants are used for both glfwGetWindowParam - * and glfwOpenWindowHint - */ +/* glfwWindowHint tokens */ #define GLFW_RED_BITS 0x00021000 #define GLFW_GREEN_BITS 0x00021001 #define GLFW_BLUE_BITS 0x00021002 @@ -412,6 +403,10 @@ extern "C" { #define GLFW_STEREO 0x0002100C #define GLFW_WINDOW_RESIZABLE 0x0002100D #define GLFW_FSAA_SAMPLES 0x0002100E + +/* The following constants are used with both glfwGetWindowParam + * and glfwWindowHint + */ #define GLFW_CLIENT_API 0x0002100F #define GLFW_OPENGL_VERSION_MAJOR 0x00021010 #define GLFW_OPENGL_VERSION_MINOR 0x00021011 @@ -454,7 +449,7 @@ extern "C" { /* glfwGetError/glfwErrorString tokens */ #define GLFW_NO_ERROR 0 #define GLFW_NOT_INITIALIZED 0x00070001 -#define GLFW_NO_CURRENT_WINDOW 0x00070002 +#define GLFW_NO_CURRENT_CONTEXT 0x00070002 #define GLFW_INVALID_ENUM 0x00070003 #define GLFW_INVALID_VALUE 0x00070004 #define GLFW_OUT_OF_MEMORY 0x00070005 @@ -526,7 +521,7 @@ GLFWAPI const char* glfwErrorString(int error); GLFWAPI void glfwSetErrorCallback(GLFWerrorfun cbfun); /* Video mode functions */ -GLFWAPI int glfwGetVideoModes(GLFWvidmode* list, int maxcount); +GLFWAPI GLFWvidmode* glfwGetVideoModes(int* count); GLFWAPI void glfwGetDesktopMode(GLFWvidmode* mode); /* Gamma ramp functions */ @@ -535,15 +530,14 @@ GLFWAPI void glfwGetGammaRamp(GLFWgammaramp* ramp); GLFWAPI void glfwSetGammaRamp(const GLFWgammaramp* ramp); /* Window handling */ -GLFWAPI GLFWwindow glfwOpenWindow(int width, int height, int mode, const char* title, GLFWwindow share); -GLFWAPI void glfwOpenWindowHint(int target, int hint); -GLFWAPI int glfwIsWindow(GLFWwindow window); -GLFWAPI void glfwCloseWindow(GLFWwindow window); -GLFWAPI void glfwSetWindowTitle(GLFWwindow, const char* title); -GLFWAPI void glfwGetWindowSize(GLFWwindow, int* width, int* height); -GLFWAPI void glfwSetWindowSize(GLFWwindow, int width, int height); -GLFWAPI void glfwGetWindowPos(GLFWwindow, int* xpos, int* ypos); -GLFWAPI void glfwSetWindowPos(GLFWwindow, int xpos, int ypos); +GLFWAPI void glfwWindowHint(int target, int hint); +GLFWAPI GLFWwindow glfwCreateWindow(int width, int height, int mode, const char* title, GLFWwindow share); +GLFWAPI void glfwDestroyWindow(GLFWwindow window); +GLFWAPI void glfwSetWindowTitle(GLFWwindow window, const char* title); +GLFWAPI void glfwGetWindowSize(GLFWwindow window, int* width, int* height); +GLFWAPI void glfwSetWindowSize(GLFWwindow window, int width, int height); +GLFWAPI void glfwGetWindowPos(GLFWwindow window, int* xpos, int* ypos); +GLFWAPI void glfwSetWindowPos(GLFWwindow window, int xpos, int ypos); GLFWAPI void glfwIconifyWindow(GLFWwindow window); GLFWAPI void glfwRestoreWindow(GLFWwindow window); GLFWAPI int glfwGetWindowParam(GLFWwindow window, int param); @@ -576,7 +570,7 @@ GLFWAPI void glfwSetScrollCallback(GLFWscrollfun cbfun); /* Joystick input */ GLFWAPI int glfwGetJoystickParam(int joy, int param); -GLFWAPI int glfwGetJoystickPos(int joy, float* pos, int numaxes); +GLFWAPI int glfwGetJoystickAxes(int joy, float* axes, int numaxes); GLFWAPI int glfwGetJoystickButtons(int joy, unsigned char* buttons, int numbuttons); /* Clipboard */ @@ -590,7 +584,7 @@ GLFWAPI void glfwSetTime(double time); /* OpenGL support */ GLFWAPI void glfwMakeContextCurrent(GLFWwindow window); GLFWAPI GLFWwindow glfwGetCurrentContext(void); -GLFWAPI void glfwSwapBuffers(void); +GLFWAPI void glfwSwapBuffers(GLFWwindow window); GLFWAPI void glfwSwapInterval(int interval); GLFWAPI int glfwExtensionSupported(const char* extension); GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname); diff --git a/readme.html b/readme.html index 5e3799e5..e577891b 100644 --- a/readme.html +++ b/readme.html @@ -268,7 +268,6 @@ version of GLFW.

v3.0

  • Added GLFWwindow window handle type and updated window-related functions and callbacks to take a window handle
  • -
  • Added glfwIsWindow function for verifying that a given window handle is (still) valid
  • Added glfwMakeContextCurrent function for making the context of the specified window current
  • Added glfwGetError and glfwErrorString error reporting functions and a number of error tokens
  • Added glfwSetErrorCallback function and GLFWerrorfun type for receiving more specific and/or nested errors
  • @@ -289,24 +288,28 @@ version of GLFW.

  • Added sharing simple OpenGL object sharing test program
  • Added modes video mode enumeration and setting test program
  • Added glfw3native.h header and platform-specific functions for explicit access to native display, window and context handles
  • -
  • Added a parameter to glfwOpenWindow for specifying a context the new window's context will share objects with
  • -
  • Added initial window title parameter to glfwOpenWindow
  • Added glfwSetGamma, glfwSetGammaRamp and glfwGetGammaRamp functions and GLFWgammaramp type for monitor gamma ramp control
  • +
  • Added window parameter to glfwSwapBuffers
  • Changed buffer bit depth parameters of glfwOpenWindow to window hints
  • Changed glfwOpenWindow and glfwSetWindowTitle to use UTF-8 encoded strings
  • Changed glfwGetProcAddress to return a (generic) function pointer
  • +
  • Changed glfwGetVideoModes to return a dynamic, unlimited number of video modes
  • Renamed glfw.h to glfw3.h to avoid conflicts with 2.x series
  • +
  • Renamed glfwOpenWindowHint to glfwWindowHint
  • Renamed GLFW_WINDOW token to GLFW_WINDOWED
  • Renamed GLFW_WINDOW_NO_RESIZE to GLFW_WINDOW_RESIZABLE
  • Renamed GLFW_BUILD_DLL to _GLFW_BUILD_DLL
  • Renamed version test to glfwinfo
  • Renamed GLFW_NO_GLU to GLFW_INCLUDE_GLU and made it disabled by default
  • +
  • Renamed glfwGetJoystickPos to glfwGetJoystickAxes to match glfwGetJoystickButtons
  • Renamed mouse position functions to cursor position equivalents
  • +
  • Replaced glfwOpenWindow and glfwCloseWindow with glfwCreateWindow and glfwDestroyWindow
  • Replaced ad hoc build system with CMake
  • Replaced layout-dependent key codes with single, platform-independent set based on US layout
  • Replaced mouse wheel interface with two-dimensional, floating point scrolling interface
  • Replaced glfwEnable and glfwDisable with glfwGetInputMode and glfwSetInputMode
  • Replaced joystick test with graphical version
  • +
  • Replaced automatic closing of windows with GLFW_CLOSE_REQUESTED window parameter
  • Made Unicode character input unaffected by GLFW_KEY_REPEAT
  • Removed event auto-polling and the GLFW_AUTO_POLL_EVENTS window enable
  • Removed the Win32 port .def files
  • @@ -320,6 +323,7 @@ version of GLFW.

  • Removed nonsensical key actions for Unicode character input
  • Removed GLFWCALL and GLFWAPIENTRY macros for stdcall calling convention
  • Removed GLFW_ACCELERATED window parameter
  • +
  • Removed default framebuffer attributes from glfwGetWindowParam
  • Bugfix: The default OpenGL version in the glfwinfo test was set to 1.1
  • Bugfix: The OpenGL profile and forward-compatibility window parameters were not saved after context creation
  • Bugfix: The FSAA test did not check for the availability of GL_ARB_multisample
  • @@ -920,6 +924,9 @@ their skills. Special thanks go out to:

    Much of the Windows code of GLFW was originally based on Jeff's code +
  • Arturo J. Pérez, for a bug fix for cursor tracking on Mac OS X 10.6 Snow + Leopard
  • +
  • Douglas C. Schmidt and Irfan Pyarali, for their excellent article Strategies for Implementing POSIX Condition Variables on Win32
  • @@ -945,6 +952,8 @@ their skills. Special thanks go out to:

  • Samuli Tuomola, for support, bug reports and testing
  • +
  • Torsten Walluhn, for fixing various compilation issues on OS X
  • +
  • Frank Wille, for helping with the AmigaOS port and making GLFW compile under IRIX 5.3
  • diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index da1b7bc0..4c31f39e 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -1,10 +1,9 @@ - include_directories(${GLFW_SOURCE_DIR}/src ${GLFW_BINARY_DIR}/src ${glfw_INCLUDE_DIRS}) set(common_HEADERS ${GLFW_SOURCE_DIR}/include/GL/glfw3.h internal.h) -set(common_SOURCES clipboard.c error.c fullscreen.c gamma.c init.c input.c +set(common_SOURCES clipboard.c fullscreen.c gamma.c init.c input.c joystick.c opengl.c time.c window.c) if (_GLFW_COCOA_NSGL) @@ -47,10 +46,13 @@ if (BUILD_SHARED_LIBS) if (_GLFW_WIN32_WGL) # The GLFW DLL needs a special compile-time macro and import library name - set_target_properties(glfw PROPERTIES - PREFIX "" - IMPORT_PREFIX "" - IMPORT_SUFFIX "dll.lib") + set_target_properties(glfw PROPERTIES PREFIX "" IMPORT_PREFIX "") + + if (MINGW) + set_target_properties(glfw PROPERTIES IMPORT_SUFFIX "dll.a") + else() + set_target_properties(glfw PROPERTIES IMPORT_SUFFIX "dll.lib") + endif() elseif (_GLFW_COCOA_NSGL) # Append -fno-common to the compile flags to work around a bug in the Apple GCC get_target_property(glfw_CFLAGS glfw COMPILE_FLAGS) @@ -65,5 +67,5 @@ if (BUILD_SHARED_LIBS) target_link_libraries(glfw LINK_INTERFACE_LIBRARIES) endif() -install(TARGETS glfw DESTINATION lib) +install(TARGETS glfw DESTINATION lib${LIB_SUFFIX} ) diff --git a/src/cocoa_clipboard.m b/src/cocoa_clipboard.m index 56b98437..99918f77 100644 --- a/src/cocoa_clipboard.m +++ b/src/cocoa_clipboard.m @@ -1,6 +1,6 @@ //======================================================================== // GLFW - An OpenGL library -// Platform: Cocoa/NSOpenGL +// Platform: Cocoa // API version: 3.0 // WWW: http://www.glfw.org/ //------------------------------------------------------------------------ @@ -70,7 +70,7 @@ const char* _glfwPlatformGetClipboardString(_GLFWwindow* window) if (!object) { _glfwSetError(GLFW_PLATFORM_ERROR, - "Cocoa/NSGL: Failed to retrieve object from pasteboard"); + "Cocoa: Failed to retrieve object from pasteboard"); return NULL; } diff --git a/src/cocoa_fullscreen.m b/src/cocoa_fullscreen.m index 147913fb..47f86739 100644 --- a/src/cocoa_fullscreen.m +++ b/src/cocoa_fullscreen.m @@ -1,6 +1,6 @@ //======================================================================== // GLFW - An OpenGL library -// Platform: Cocoa/NSOpenGL +// Platform: Cocoa // API Version: 3.0 // WWW: http://www.glfw.org/ //------------------------------------------------------------------------ @@ -197,25 +197,32 @@ void _glfwRestoreVideoMode(void) // Get a list of available video modes //======================================================================== -int _glfwPlatformGetVideoModes(GLFWvidmode* list, int maxcount) +GLFWvidmode* _glfwPlatformGetVideoModes(int* found) { - CGDisplayModeRef mode; CFArrayRef modes; CFIndex count, i; - int stored = 0; + GLFWvidmode* result; modes = CGDisplayCopyAllDisplayModes(CGMainDisplayID(), NULL); count = CFArrayGetCount(modes); - for (i = 0; i < count && stored < maxcount; i++) + result = (GLFWvidmode*) malloc(sizeof(GLFWvidmode) * count); + *found = 0; + + for (i = 0; i < count; i++) { + CGDisplayModeRef mode; + mode = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, i); if (modeIsGood(mode)) - list[stored++] = vidmodeFromCGDisplayMode(mode); + { + result[*found] = vidmodeFromCGDisplayMode(mode); + (*found)++; + } } CFRelease(modes); - return stored; + return result; } diff --git a/src/cocoa_gamma.c b/src/cocoa_gamma.c index 53c47a89..85d1e489 100644 --- a/src/cocoa_gamma.c +++ b/src/cocoa_gamma.c @@ -1,6 +1,6 @@ //======================================================================== // GLFW - An OpenGL library -// Platform: Cocoa/NSOpenGL +// Platform: Cocoa // API version: 3.0 // WWW: http://www.glfw.org/ //------------------------------------------------------------------------ @@ -40,7 +40,7 @@ //************************************************************************ //======================================================================== -// Save the original gamma ramp so that we can restore it later +// Save the original gamma ramp so that it can be restored later //======================================================================== void _glfwPlatformGetGammaRamp(GLFWgammaramp* ramp) diff --git a/src/cocoa_input.m b/src/cocoa_input.m index 869c9cd3..11e1083b 100644 --- a/src/cocoa_input.m +++ b/src/cocoa_input.m @@ -1,6 +1,6 @@ //======================================================================== // GLFW - An OpenGL library -// Platform: Cocoa/NSOpenGL +// Platform: Cocoa // API Version: 3.0 // WWW: http://www.glfw.org/ //------------------------------------------------------------------------ @@ -40,13 +40,14 @@ void _glfwPlatformEnableSystemKeys(_GLFWwindow* window) { - // This is checked in macosx_window.m; we take no action here + // This is checked in cocoa_window.m; no action needed here } void _glfwPlatformDisableSystemKeys(_GLFWwindow* window) { - // This is checked in macosx_window.m; we take no action here - // I don't think it's really possible to disable stuff like Exposé + // This is checked in cocoa_window.m; no action needed here + + // Note that it may not be possible to disable things like Exposé // except in full-screen mode. } diff --git a/src/cocoa_joystick.m b/src/cocoa_joystick.m index 97510fdf..7eac7f91 100644 --- a/src/cocoa_joystick.m +++ b/src/cocoa_joystick.m @@ -1,10 +1,11 @@ //======================================================================== // GLFW - An OpenGL library -// Platform: Cocoa/NSOpenGL +// Platform: Cocoa // API Version: 3.0 // WWW: http://www.glfw.org/ //------------------------------------------------------------------------ // Copyright (c) 2009-2010 Camilla Berglund +// Copyright (c) 2012 Torsten Walluhn // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -46,7 +47,6 @@ //------------------------------------------------------------------------ // Joystick element information //------------------------------------------------------------------------ - typedef struct { IOHIDElementCookie cookie; @@ -65,7 +65,6 @@ typedef struct //------------------------------------------------------------------------ // Joystick information & state //------------------------------------------------------------------------ - typedef struct { int present; @@ -86,7 +85,7 @@ typedef struct static _glfwJoystick _glfwJoysticks[GLFW_JOYSTICK_LAST + 1]; -void GetElementsCFArrayHandler(const void* value, void* parameter); +static void getElementsCFArrayHandler(const void* value, void* parameter); //======================================================================== @@ -112,7 +111,7 @@ static void addJoystickElement(_glfwJoystick* joystick, CFTypeRef refElement) (elementType == kIOHIDElementTypeInput_Button) || (elementType == kIOHIDElementTypeInput_Misc)) { - switch (usagePage) /* only interested in kHIDPage_GenericDesktop and kHIDPage_Button */ + switch (usagePage) { case kHIDPage_GenericDesktop: { @@ -175,10 +174,10 @@ static void addJoystickElement(_glfwJoystick* joystick, CFTypeRef refElement) if (refElementTop) { CFTypeID type = CFGetTypeID (refElementTop); - if (type == CFArrayGetTypeID()) /* if element is an array */ + if (type == CFArrayGetTypeID()) { CFRange range = {0, CFArrayGetCount (refElementTop)}; - CFArrayApplyFunction(refElementTop, range, GetElementsCFArrayHandler, joystick); + CFArrayApplyFunction(refElementTop, range, getElementsCFArrayHandler, joystick); } } } @@ -189,7 +188,7 @@ static void addJoystickElement(_glfwJoystick* joystick, CFTypeRef refElement) // Adds an element to the specified joystick //======================================================================== -void GetElementsCFArrayHandler(const void* value, void* parameter) +static void getElementsCFArrayHandler(const void* value, void* parameter) { if (CFGetTypeID(value) == CFDictionaryGetTypeID()) addJoystickElement((_glfwJoystick*) parameter, (CFTypeRef) value); @@ -213,7 +212,7 @@ static long getElementValue(_glfwJoystick* joystick, _glfwJoystickElement* eleme &hidEvent); if (kIOReturnSuccess == result) { - /* record min and max for auto calibration */ + // Record min and max for auto calibration if (hidEvent.value < element->minReport) element->minReport = hidEvent.value; if (hidEvent.value > element->maxReport) @@ -221,7 +220,7 @@ static long getElementValue(_glfwJoystick* joystick, _glfwJoystickElement* eleme } } - /* auto user scale */ + // Auto user scale return (long) hidEvent.value; } @@ -284,7 +283,7 @@ static void removalCallback(void* target, IOReturn result, void* refcon, void* s //======================================================================== -// Polls for joystick events and updates GFLW state +// Polls for joystick events and updates GLFW state //======================================================================== static void pollJoystickEvents(void) @@ -340,13 +339,15 @@ void _glfwInitJoysticks(void) CFMutableDictionaryRef hidMatchDictionary = NULL; io_object_t ioHIDDeviceObject = 0; + memset(&_glfwJoysticks, 0, sizeof(_glfwJoysticks)); + result = IOMasterPort(bootstrap_port, &masterPort); hidMatchDictionary = IOServiceMatching(kIOHIDDeviceKey); if (kIOReturnSuccess != result || !hidMatchDictionary) { if (hidMatchDictionary) CFRelease(hidMatchDictionary); - + return; } @@ -356,8 +357,11 @@ void _glfwInitJoysticks(void) if (result != kIOReturnSuccess) return; - if (!objectIterator) /* there are no joysticks */ + if (!objectIterator) + { + // There are no joysticks return; + } while ((ioHIDDeviceObject = IOIteratorNext(objectIterator))) { @@ -379,14 +383,14 @@ void _glfwInitJoysticks(void) if (result != kIOReturnSuccess) continue; - /* Check device type */ + // Check device type refCF = CFDictionaryGetValue(hidProperties, CFSTR(kIOHIDPrimaryUsagePageKey)); if (refCF) { CFNumberGetValue(refCF, kCFNumberLongType, &usagePage); if (usagePage != kHIDPage_GenericDesktop) { - /* We are not interested in this device */ + // This device is not relevant to GLFW continue; } } @@ -395,12 +399,12 @@ void _glfwInitJoysticks(void) if (refCF) { CFNumberGetValue(refCF, kCFNumberLongType, &usage); - + if ((usage != kHIDUsage_GD_Joystick && usage != kHIDUsage_GD_GamePad && usage != kHIDUsage_GD_MultiAxisController)) { - /* We are not interested in this device */ + // This device is not relevant to GLFW continue; } } @@ -434,7 +438,7 @@ void _glfwInitJoysticks(void) joystick, joystick); - /* Get product string */ + // Get product string refCF = CFDictionaryGetValue(hidProperties, CFSTR(kIOHIDProductKey)); if (refCF) { @@ -459,7 +463,7 @@ void _glfwInitJoysticks(void) CFRange range = { 0, CFArrayGetCount(refTopElement) }; CFArrayApplyFunction(refTopElement, range, - GetElementsCFArrayHandler, + getElementsCFArrayHandler, (void*) joystick); } @@ -509,7 +513,8 @@ int _glfwPlatformGetJoystickParam(int joy, int param) return (int) CFArrayGetCount(_glfwJoysticks[joy].axes); case GLFW_BUTTONS: - return (int) CFArrayGetCount(_glfwJoysticks[joy].buttons) + ((int) CFArrayGetCount(_glfwJoysticks[joy].hats)) * 4; + return (int) CFArrayGetCount(_glfwJoysticks[joy].buttons) + + (int) CFArrayGetCount(_glfwJoysticks[joy].hats) * 4; default: break; @@ -523,7 +528,7 @@ int _glfwPlatformGetJoystickParam(int joy, int param) // Get joystick axis positions //======================================================================== -int _glfwPlatformGetJoystickPos(int joy, float* pos, int numaxes) +int _glfwPlatformGetJoystickAxes(int joy, float* axes, int numaxes) { int i; @@ -551,14 +556,12 @@ int _glfwPlatformGetJoystickPos(int joy, float* pos, int numaxes) long readScale = axes->maxReport - axes->minReport; if (readScale == 0) - pos[i] = axes->value; + axes[i] = axes->value; else - pos[i] = (2.0f * (axes->value - axes->minReport) / readScale) - 1.0f; - - //printf("%ld, %ld, %ld\n", axes->value, axes->minReport, axes->maxReport); + axes[i] = (2.0f * (axes->value - axes->minReport) / readScale) - 1.0f; if (i & 1) - pos[i] = -pos[i]; + axes[i] = -axes[i]; } return numaxes; @@ -597,19 +600,28 @@ int _glfwPlatformGetJoystickButtons(int joy, unsigned char* buttons, // Virtual buttons - Inject data from hats // Each hat is exposed as 4 buttons which exposes 8 directions with concurrent button presses - const int directions[9] = { 1, 3, 2, 6, 4, 12, 8, 9, 0 }; // Bit fields of button presses for each direction, including nil + // Bit fields of button presses for each direction, including nil + const int directions[9] = { 1, 3, 2, 6, 4, 12, 8, 9, 0 }; for (i = 0; i < joystick.numHats; i++) { _glfwJoystickElement* hat = (_glfwJoystickElement*) CFArrayGetValueAtIndex(joystick.hats, i); - int value = hat->value; - if (value < 0 || value > 8) value = 8; - for (j = 0; j < 4 && button < numbuttons; j++) + int value = hat->value; + if (value < 0 || value > 8) + value = 8; + + for (j = 0; j < 4 && button < numbuttons; j++) { - buttons[button++] = directions[value] & (1 << j) ? GLFW_PRESS : GLFW_RELEASE; + if (directions[value] & (1 << j)) + buttons[button] = GLFW_PRESS; + else + buttons[button] = GLFW_RELEASE; + + button++; } } return button; } + diff --git a/src/cocoa_opengl.m b/src/cocoa_opengl.m index b04efaee..2ffd774c 100644 --- a/src/cocoa_opengl.m +++ b/src/cocoa_opengl.m @@ -51,10 +51,8 @@ void _glfwPlatformMakeContextCurrent(_GLFWwindow* window) // Swap buffers //======================================================================== -void _glfwPlatformSwapBuffers(void) +void _glfwPlatformSwapBuffers(_GLFWwindow* window) { - _GLFWwindow* window = _glfwLibrary.currentWindow; - // ARP appears to be unnecessary, but this is future-proof [window->NSGL.context flushBuffer]; } diff --git a/src/cocoa_time.c b/src/cocoa_time.c index 745b4239..d80dd147 100644 --- a/src/cocoa_time.c +++ b/src/cocoa_time.c @@ -1,6 +1,6 @@ //======================================================================== // GLFW - An OpenGL library -// Platform: Cocoa/NSOpenGL +// Platform: Cocoa // API Version: 3.0 // WWW: http://www.glfw.org/ //------------------------------------------------------------------------ diff --git a/src/cocoa_window.m b/src/cocoa_window.m index 4a06b501..6b192f09 100644 --- a/src/cocoa_window.m +++ b/src/cocoa_window.m @@ -59,8 +59,7 @@ - (BOOL)windowShouldClose:(id)sender { - window->closeRequested = GL_TRUE; - + _glfwInputWindowCloseRequest(window); return NO; } @@ -127,7 +126,7 @@ _GLFWwindow* window; for (window = _glfwLibrary.windowListHead; window; window = window->next) - window->closeRequested = GL_TRUE; + _glfwInputWindowCloseRequest(window); return NSTerminateCancel; } @@ -278,9 +277,6 @@ static int convertMacKeyCode(unsigned int macKeyCode) if (macKeyCode >= 128) return -1; - // This treats keycodes as *positional*; that is, we'll return 'a' - // for the key left of 's', even on an AZERTY keyboard. The charInput - // function should still get 'q' though. return table[macKeyCode]; } @@ -425,6 +421,7 @@ static int convertMacKeyCode(unsigned int macKeyCode) userInfo:nil]; [self addTrackingArea:trackingArea]; + [super updateTrackingAreas]; } - (void)keyDown:(NSEvent *)event @@ -541,7 +538,7 @@ static NSString* findAppName(void) } } - // If we get here, we're unbundled + // If we get here, the application is unbundled ProcessSerialNumber psn = { 0, kCurrentProcess }; TransformProcessType(&psn, kProcessTransformToForegroundApplication); @@ -551,10 +548,7 @@ static NSString* findAppName(void) char** progname = _NSGetProgname(); if (progname && *progname) - { - // TODO: UTF-8? return [NSString stringWithUTF8String:*progname]; - } // Really shouldn't get here return @"GLFW Application"; @@ -680,8 +674,7 @@ static GLboolean createWindow(_GLFWwindow* window, if (window->NS.object == nil) { - _glfwSetError(GLFW_PLATFORM_ERROR, - "Cocoa/NSOpenGL: Failed to create window"); + _glfwSetError(GLFW_PLATFORM_ERROR, "Cocoa: Failed to create window"); return GL_FALSE; } @@ -730,8 +723,8 @@ static GLboolean createContext(_GLFWwindow* window, (wndconfig->glMajor == 3 && wndconfig->glMinor != 2)) { _glfwSetError(GLFW_VERSION_UNAVAILABLE, - "Cocoa/NSOpenGL: The targeted version of Mac OS X does " - "not support any OpenGL version above 2.1 except 3.2"); + "NSOpenGL: The targeted version of Mac OS X does not " + "support any OpenGL version above 2.1 except 3.2"); return GL_FALSE; } @@ -740,8 +733,8 @@ static GLboolean createContext(_GLFWwindow* window, if (!wndconfig->glForward) { _glfwSetError(GLFW_VERSION_UNAVAILABLE, - "Cocoa/NSOpenGL: The targeted version of Mac OS X " - "only supports OpenGL 3.2 contexts if they are " + "NSOpenGL: The targeted version of Mac OS X only " + "supports OpenGL 3.2 contexts if they are " "forward-compatible"); return GL_FALSE; } @@ -749,8 +742,8 @@ static GLboolean createContext(_GLFWwindow* window, if (wndconfig->glProfile != GLFW_OPENGL_CORE_PROFILE) { _glfwSetError(GLFW_VERSION_UNAVAILABLE, - "Cocoa/NSOpenGL: The targeted version of Mac OS X " - "only supports OpenGL 3.2 contexts if they use the " + "NSOpenGL: The targeted version of Mac OS X only " + "supports OpenGL 3.2 contexts if they use the " "core profile"); return GL_FALSE; } @@ -760,8 +753,8 @@ static GLboolean createContext(_GLFWwindow* window, if (wndconfig->glMajor > 2) { _glfwSetError(GLFW_VERSION_UNAVAILABLE, - "Cocoa/NSOpenGL: The targeted version of Mac OS X does " - "not support OpenGL version 3.0 or above"); + "NSOpenGL: The targeted version of Mac OS X does not " + "support OpenGL version 3.0 or above"); return GL_FALSE; } #endif /*MAC_OS_X_VERSION_MAX_ALLOWED*/ @@ -770,8 +763,8 @@ static GLboolean createContext(_GLFWwindow* window, if (wndconfig->glRobustness) { _glfwSetError(GLFW_VERSION_UNAVAILABLE, - "Cocoa/NSOpenGL: Mac OS X does not support OpenGL " - "robustness strategies"); + "NSOpenGL: Mac OS X does not support OpenGL robustness " + "strategies"); return GL_FALSE; } @@ -834,7 +827,7 @@ static GLboolean createContext(_GLFWwindow* window, if (window->NSGL.pixelFormat == nil) { _glfwSetError(GLFW_PLATFORM_ERROR, - "Cocoa/NSOpenGL: Failed to create OpenGL pixel format"); + "NSOpenGL: Failed to create OpenGL pixel format"); return GL_FALSE; } @@ -849,7 +842,7 @@ static GLboolean createContext(_GLFWwindow* window, if (window->NSGL.context == nil) { _glfwSetError(GLFW_PLATFORM_ERROR, - "Cocoa/NSOpenGL: Failed to create OpenGL context"); + "NSOpenGL: Failed to create OpenGL context"); return GL_FALSE; } @@ -866,25 +859,22 @@ static GLboolean createContext(_GLFWwindow* window, // created //======================================================================== -int _glfwPlatformOpenWindow(_GLFWwindow* window, - const _GLFWwndconfig* wndconfig, - const _GLFWfbconfig* fbconfig) +int _glfwPlatformCreateWindow(_GLFWwindow* window, + const _GLFWwndconfig* wndconfig, + const _GLFWfbconfig* fbconfig) { if (!initializeAppKit()) return GL_FALSE; - window->resizable = wndconfig->resizable; - - // We can only have one application delegate, but we only allocate it the - // first time we create a window to keep all window code in this file + // There can only be one application delegate, but we allocate it the + // first time a window is created to keep all window code in this file if (_glfwLibrary.NS.delegate == nil) { _glfwLibrary.NS.delegate = [[GLFWApplicationDelegate alloc] init]; if (_glfwLibrary.NS.delegate == nil) { _glfwSetError(GLFW_PLATFORM_ERROR, - "Cocoa/NSOpenGL: Failed to create application " - "delegate"); + "Cocoa: Failed to create application delegate"); return GL_FALSE; } @@ -895,7 +885,7 @@ int _glfwPlatformOpenWindow(_GLFWwindow* window, if (window->NS.delegate == nil) { _glfwSetError(GLFW_PLATFORM_ERROR, - "Cocoa/NSOpenGL: Failed to create window delegate"); + "Cocoa: Failed to create window delegate"); return GL_FALSE; } @@ -934,14 +924,10 @@ int _glfwPlatformOpenWindow(_GLFWwindow* window, withOptions:nil]; } - glfwMakeContextCurrent(window); - NSPoint point = [[NSCursor currentCursor] hotSpot]; window->cursorPosX = point.x; window->cursorPosY = point.y; - window->resizable = wndconfig->resizable; - return GL_TRUE; } @@ -950,7 +936,7 @@ int _glfwPlatformOpenWindow(_GLFWwindow* window, // Properly kill the window / video display //======================================================================== -void _glfwPlatformCloseWindow(_GLFWwindow* window) +void _glfwPlatformDestroyWindow(_GLFWwindow* window) { [window->NS.object orderOut:nil]; @@ -1047,7 +1033,7 @@ void _glfwPlatformRestoreWindow(_GLFWwindow* window) // Write back window parameters into GLFW window structure //======================================================================== -void _glfwPlatformRefreshWindowParams(void) +void _glfwPlatformRefreshWindowParams(_GLFWwindow* window) { } diff --git a/src/error.c b/src/error.c deleted file mode 100644 index 062fb76a..00000000 --- a/src/error.c +++ /dev/null @@ -1,129 +0,0 @@ -//======================================================================== -// GLFW - An OpenGL library -// Platform: All -// API version: 3.0 -// WWW: http://www.glfw.org/ -//------------------------------------------------------------------------ -// Copyright (c) 2008-2010 Camilla Berglund -// -// This software is provided 'as-is', without any express or implied -// warranty. In no event will the authors be held liable for any damages -// arising from the use of this software. -// -// Permission is granted to anyone to use this software for any purpose, -// including commercial applications, and to alter it and redistribute it -// freely, subject to the following restrictions: -// -// 1. The origin of this software must not be misrepresented; you must not -// claim that you wrote the original software. If you use this software -// in a product, an acknowledgment in the product documentation would -// be appreciated but is not required. -// -// 2. Altered source versions must be plainly marked as such, and must not -// be misrepresented as being the original software. -// -// 3. This notice may not be removed or altered from any source -// distribution. -// -//======================================================================== - -#include "internal.h" - - -////////////////////////////////////////////////////////////////////////// -////// GLFW internal API ////// -////////////////////////////////////////////////////////////////////////// - -//======================================================================== -// The current error value and callback -// These are not in _glfwLibrary since they need to be initialized and -// accessible before glfwInit so it can report errors -//======================================================================== - -static int _glfwError = GLFW_NO_ERROR; -static GLFWerrorfun _glfwErrorCallback = NULL; - - -//======================================================================== -// Sets the current error value -// This function may be called without GLFW having been initialized -//======================================================================== - -void _glfwSetError(int error, const char* description) -{ - if (_glfwErrorCallback) - { - if (!description) - description = glfwErrorString(error); - - _glfwErrorCallback(error, description); - } - else - _glfwError = error; -} - - -////////////////////////////////////////////////////////////////////////// -////// GLFW public API ////// -////////////////////////////////////////////////////////////////////////// - -//======================================================================== -// Returns the current error value -// This function may be called without GLFW having been initialized -//======================================================================== - -GLFWAPI int glfwGetError(void) -{ - int error = _glfwError; - _glfwError = GLFW_NO_ERROR; - return error; -} - - -//======================================================================== -// Returns a string representation of the specified error value -// This function may be called without GLFW having been initialized -//======================================================================== - -GLFWAPI const char* glfwErrorString(int error) -{ - switch (error) - { - case GLFW_NO_ERROR: - return "No error"; - case GLFW_NOT_INITIALIZED: - return "The GLFW library is not initialized"; - case GLFW_NO_CURRENT_WINDOW: - return "There is no current GLFW window"; - case GLFW_INVALID_ENUM: - return "Invalid argument for enum parameter"; - case GLFW_INVALID_VALUE: - return "Invalid value for parameter"; - case GLFW_OUT_OF_MEMORY: - return "Out of memory"; - case GLFW_OPENGL_UNAVAILABLE: - return "OpenGL is not available on this machine"; - case GLFW_VERSION_UNAVAILABLE: - return "The requested OpenGL version is unavailable"; - case GLFW_PLATFORM_ERROR: - return "A platform-specific error occurred"; - case GLFW_WINDOW_NOT_ACTIVE: - return "The specified window is not active"; - case GLFW_FORMAT_UNAVAILABLE: - return "The requested format is unavailable"; - } - - return "ERROR: UNKNOWN ERROR TOKEN PASSED TO glfwErrorString"; -} - - -//======================================================================== -// Sets the callback function for GLFW errors -// This function may be called without GLFW having been initialized -//======================================================================== - -GLFWAPI void glfwSetErrorCallback(GLFWerrorfun cbfun) -{ - _glfwErrorCallback = cbfun; -} - diff --git a/src/fullscreen.c b/src/fullscreen.c index 631f6193..f632749f 100644 --- a/src/fullscreen.c +++ b/src/fullscreen.c @@ -6,6 +6,7 @@ //------------------------------------------------------------------------ // Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2006-2010 Camilla Berglund +// Copyright (c) 2012 Torsten Walluhn // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -31,6 +32,11 @@ #include "internal.h" #include +#ifdef __APPLE__ +#include +#else +#include +#endif //======================================================================== @@ -68,6 +74,16 @@ static int compareVideoModes(const void* firstPtr, const void* secondPtr) ////// GLFW internal API ////// ////////////////////////////////////////////////////////////////////////// +//======================================================================== +// Lexical comparison of GLFW video modes +//======================================================================== + +int _glfwCompareVideoModes(const GLFWvidmode* first, const GLFWvidmode* second) +{ + return compareVideoModes(first, second); +} + + //======================================================================== // Convert BPP to RGB bits based on "best guess" //======================================================================== @@ -76,7 +92,7 @@ void _glfwSplitBPP(int bpp, int* red, int* green, int* blue) { int delta; - // We assume that by 32 they really meant 24 + // We assume that by 32 the user really meant 24 if (bpp == 32) bpp = 24; @@ -100,36 +116,27 @@ void _glfwSplitBPP(int bpp, int* red, int* green, int* blue) // Get a list of available video modes //======================================================================== -GLFWAPI int glfwGetVideoModes(GLFWvidmode* list, int maxcount) +GLFWAPI GLFWvidmode* glfwGetVideoModes(int* count) { - int count; - if (!_glfwInitialized) { _glfwSetError(GLFW_NOT_INITIALIZED, NULL); - return 0; + return NULL; } - if (maxcount <= 0) + if (count == NULL) { - _glfwSetError(GLFW_INVALID_VALUE, - "glfwGetVideoModes: Parameter 'maxcount' must be " - "greater than zero"); - return 0; + _glfwSetError(GLFW_INVALID_VALUE, NULL); + return NULL; } - if (list == NULL) - { - _glfwSetError(GLFW_INVALID_VALUE, - "glfwGetVideoModes: Parameter 'list' cannot be NULL"); - return 0; - } + free(_glfwLibrary.modes); - count = _glfwPlatformGetVideoModes(list, maxcount); - if (count > 0) - qsort(list, count, sizeof(GLFWvidmode), compareVideoModes); + _glfwLibrary.modes = _glfwPlatformGetVideoModes(count); + if (_glfwLibrary.modes) + qsort(_glfwLibrary.modes, *count, sizeof(GLFWvidmode), compareVideoModes); - return count; + return _glfwLibrary.modes; } diff --git a/src/libglfw3.pc.in b/src/glfw3.pc.in similarity index 100% rename from src/libglfw3.pc.in rename to src/glfw3.pc.in diff --git a/src/init.c b/src/init.c index 336cfe25..7e9fe4e7 100644 --- a/src/init.c +++ b/src/init.c @@ -28,11 +28,82 @@ // //======================================================================== -#define _init_c_ #include "internal.h" #include #include +#include +#include + + +//------------------------------------------------------------------------ +// Flag indicating whether GLFW has been successfully initialized +//------------------------------------------------------------------------ +GLboolean _glfwInitialized = GL_FALSE; + + +//------------------------------------------------------------------------ +// All shared and API-specific global data protected by _glfwInitialized +// This should only be touched after a call to glfwInit that has not been +// followed by a call to glfwTerminate +//------------------------------------------------------------------------ +_GLFWlibrary _glfwLibrary; + + +//------------------------------------------------------------------------ +// The current GLFW error code +// This is outside of _glfwLibrary so it can be initialized and usable +// before glfwInit is called, which lets that function report errors +// TODO: Make this thread-local +//------------------------------------------------------------------------ +static int _glfwError = GLFW_NO_ERROR; + + +//------------------------------------------------------------------------ +// The current error callback +// This is outside of _glfwLibrary so it can be initialized and usable +// before glfwInit is called, which lets that function report errors +//------------------------------------------------------------------------ +static GLFWerrorfun _glfwErrorCallback = NULL; + + +////////////////////////////////////////////////////////////////////////// +////// GLFW internal API ////// +////////////////////////////////////////////////////////////////////////// + +//======================================================================== +// Sets the current error value +//======================================================================== + +void _glfwSetError(int error, const char* format, ...) +{ + if (_glfwErrorCallback) + { + char buffer[16384]; + const char* description; + + if (format) + { + int count; + va_list vl; + + va_start(vl, format); + count = vsnprintf(buffer, sizeof(buffer), format, vl); + va_end(vl); + + if (count < 0) + buffer[sizeof(buffer) - 1] = '\0'; + + description = buffer; + } + else + description = glfwErrorString(error); + + _glfwErrorCallback(error, description); + } + else + _glfwError = error; +} ////////////////////////////////////////////////////////////////////////// @@ -50,8 +121,7 @@ GLFWAPI int glfwInit(void) memset(&_glfwLibrary, 0, sizeof(_glfwLibrary)); - // Not all window hints have zero as their default value, so this - // needs to be here despite the memset above + // Not all window hints have zero as their default value _glfwSetDefaultWindowHints(); if (!_glfwPlatformInit()) @@ -79,17 +149,21 @@ GLFWAPI void glfwTerminate(void) // Close all remaining windows while (_glfwLibrary.windowListHead) - glfwCloseWindow(_glfwLibrary.windowListHead); + glfwDestroyWindow(_glfwLibrary.windowListHead); if (!_glfwPlatformTerminate()) return; + if (_glfwLibrary.modes) + free(_glfwLibrary.modes); + _glfwInitialized = GL_FALSE; } //======================================================================== // Get GLFW version +// This function may be called without GLFW having been initialized //======================================================================== GLFWAPI void glfwGetVersion(int* major, int* minor, int* rev) @@ -107,6 +181,7 @@ GLFWAPI void glfwGetVersion(int* major, int* minor, int* rev) //======================================================================== // Get the GLFW version string +// This function may be called without GLFW having been initialized //======================================================================== GLFWAPI const char* glfwGetVersionString(void) @@ -114,3 +189,64 @@ GLFWAPI const char* glfwGetVersionString(void) return _glfwPlatformGetVersionString(); } + +//======================================================================== +// Returns the current error value +// This function may be called without GLFW having been initialized +//======================================================================== + +GLFWAPI int glfwGetError(void) +{ + int error = _glfwError; + _glfwError = GLFW_NO_ERROR; + return error; +} + + +//======================================================================== +// Returns a string representation of the specified error value +// This function may be called without GLFW having been initialized +//======================================================================== + +GLFWAPI const char* glfwErrorString(int error) +{ + switch (error) + { + case GLFW_NO_ERROR: + return "No error"; + case GLFW_NOT_INITIALIZED: + return "The GLFW library is not initialized"; + case GLFW_NO_CURRENT_CONTEXT: + return "There is no current OpenGL context"; + case GLFW_INVALID_ENUM: + return "Invalid argument for enum parameter"; + case GLFW_INVALID_VALUE: + return "Invalid value for parameter"; + case GLFW_OUT_OF_MEMORY: + return "Out of memory"; + case GLFW_OPENGL_UNAVAILABLE: + return "OpenGL is not available on this machine"; + case GLFW_VERSION_UNAVAILABLE: + return "The requested OpenGL version is unavailable"; + case GLFW_PLATFORM_ERROR: + return "A platform-specific error occurred"; + case GLFW_WINDOW_NOT_ACTIVE: + return "The specified window is not active"; + case GLFW_FORMAT_UNAVAILABLE: + return "The requested format is unavailable"; + } + + return "ERROR: UNKNOWN ERROR TOKEN PASSED TO glfwErrorString"; +} + + +//======================================================================== +// Sets the callback function for GLFW errors +// This function may be called without GLFW having been initialized +//======================================================================== + +GLFWAPI void glfwSetErrorCallback(GLFWerrorfun cbfun) +{ + _glfwErrorCallback = cbfun; +} + diff --git a/src/input.c b/src/input.c index 37da571a..52b3b0fb 100644 --- a/src/input.c +++ b/src/input.c @@ -551,16 +551,6 @@ GLFWAPI void glfwSetCursorPosCallback(GLFWcursorposfun cbfun) } _glfwLibrary.cursorPosCallback = cbfun; - - // Call the callback function to let the application know the current - // cursor position - if (cbfun) - { - _GLFWwindow* window; - - for (window = _glfwLibrary.windowListHead; window; window = window->next) - cbfun(window, window->cursorPosX, window->cursorPosY); - } } diff --git a/src/internal.h b/src/internal.h index 6cfcc5cb..99781fbd 100644 --- a/src/internal.h +++ b/src/internal.h @@ -31,17 +31,6 @@ #ifndef _internal_h_ #define _internal_h_ -//======================================================================== -// GLFWGLOBAL is a macro that places all global variables in the init.c -// module (all other modules reference global variables as 'extern') -//======================================================================== - -#if defined(_init_c_) - #define GLFWGLOBAL -#else - #define GLFWGLOBAL extern -#endif - //======================================================================== // Input handling definitions @@ -88,10 +77,10 @@ typedef struct _GLFWlibrary _GLFWlibrary; //------------------------------------------------------------------------ -// Window hints, set by glfwOpenWindowHint and consumed by glfwOpenWindow +// Window hints, set by glfwWindowHint and consumed by glfwCreateWindow // A bucket of semi-random stuff lumped together for historical reasons // This is used only by the platform independent code and only to store -// parameters passed to us by glfwOpenWindowHint +// parameters passed to us by glfwWindowHint //------------------------------------------------------------------------ struct _GLFWhints { @@ -197,21 +186,6 @@ struct _GLFWwindow char mouseButton[GLFW_MOUSE_BUTTON_LAST + 1]; char key[GLFW_KEY_LAST + 1]; - // Framebuffer attributes - GLint redBits; - GLint greenBits; - GLint blueBits; - GLint alphaBits; - GLint depthBits; - GLint stencilBits; - GLint accumRedBits; - GLint accumGreenBits; - GLint accumBlueBits; - GLint accumAlphaBits; - GLint auxBuffers; - GLboolean stereo; - GLint samples; - // OpenGL extensions and context attributes int clientAPI; int glMajor, glMinor, glRevision; @@ -254,104 +228,98 @@ struct _GLFWlibrary int originalRampSize; GLboolean rampChanged; + GLFWvidmode* modes; + // This is defined in the current port's platform.h _GLFW_PLATFORM_LIBRARY_WINDOW_STATE; _GLFW_PLATFORM_LIBRARY_OPENGL_STATE; }; -//======================================================================== -// System independent global variables (GLFW internals) -//======================================================================== - -// Flag indicating if GLFW has been initialized -#if defined(_init_c_) -GLboolean _glfwInitialized = GL_FALSE; -#else -GLFWGLOBAL GLboolean _glfwInitialized; -#endif - -GLFWGLOBAL _GLFWlibrary _glfwLibrary; +//------------------------------------------------------------------------ +// Global state shared between compilation units of GLFW +// These are exported from and documented in init.c +//------------------------------------------------------------------------ +extern GLboolean _glfwInitialized; +extern _GLFWlibrary _glfwLibrary; //======================================================================== -// Prototypes for platform specific implementation functions +// Prototypes for the platform API +// This is the interface exposed by the platform-specific code for each +// platform and is called by the shared code of the public API +// It mirrors the public API except it uses objects instead of handles //======================================================================== -// Init/terminate +// Platform init and version int _glfwPlatformInit(void); int _glfwPlatformTerminate(void); const char* _glfwPlatformGetVersionString(void); -// Input +// Input mode support void _glfwPlatformEnableSystemKeys(_GLFWwindow* window); void _glfwPlatformDisableSystemKeys(_GLFWwindow* window); void _glfwPlatformSetCursorPos(_GLFWwindow* window, int x, int y); void _glfwPlatformSetCursorMode(_GLFWwindow* window, int mode); -// Fullscreen -int _glfwPlatformGetVideoModes(GLFWvidmode* list, int maxcount); +// Video mode support +GLFWvidmode* _glfwPlatformGetVideoModes(int* count); void _glfwPlatformGetDesktopMode(GLFWvidmode* mode); -// Gamma ramp +// Gamma ramp support void _glfwPlatformGetGammaRamp(GLFWgammaramp* ramp); void _glfwPlatformSetGammaRamp(const GLFWgammaramp* ramp); -// Clipboard +// Clipboard support void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string); const char* _glfwPlatformGetClipboardString(_GLFWwindow* window); -// Joystick +// Joystick input int _glfwPlatformGetJoystickParam(int joy, int param); -int _glfwPlatformGetJoystickPos(int joy, float* pos, int numaxes); +int _glfwPlatformGetJoystickAxes(int joy, float* axes, int numaxes); int _glfwPlatformGetJoystickButtons(int joy, unsigned char* buttons, int numbuttons); -// Time +// Time input double _glfwPlatformGetTime(void); void _glfwPlatformSetTime(double time); // Window management -int _glfwPlatformOpenWindow(_GLFWwindow* window, const _GLFWwndconfig* wndconfig, const _GLFWfbconfig* fbconfig); -void _glfwPlatformCloseWindow(_GLFWwindow* window); +int _glfwPlatformCreateWindow(_GLFWwindow* window, const _GLFWwndconfig* wndconfig, const _GLFWfbconfig* fbconfig); +void _glfwPlatformDestroyWindow(_GLFWwindow* window); void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title); void _glfwPlatformSetWindowSize(_GLFWwindow* window, int width, int height); void _glfwPlatformSetWindowPos(_GLFWwindow* window, int x, int y); void _glfwPlatformIconifyWindow(_GLFWwindow* window); void _glfwPlatformRestoreWindow(_GLFWwindow* window); -// Event management +// Event processing void _glfwPlatformPollEvents(void); void _glfwPlatformWaitEvents(void); // OpenGL context management void _glfwPlatformMakeContextCurrent(_GLFWwindow* window); -void _glfwPlatformSwapBuffers(void); +void _glfwPlatformSwapBuffers(_GLFWwindow* window); void _glfwPlatformSwapInterval(int interval); -void _glfwPlatformRefreshWindowParams(void); +void _glfwPlatformRefreshWindowParams(_GLFWwindow* window); int _glfwPlatformExtensionSupported(const char* extension); GLFWglproc _glfwPlatformGetProcAddress(const char* procname); void _glfwPlatformCopyContext(_GLFWwindow* src, _GLFWwindow* dst, unsigned long mask); //======================================================================== -// Prototypes for platform independent internal functions +// Prototypes for the event API +// This is used by the platform-specific code to notify the shared code of +// events that can be translated into state changes and/or callback calls, +// instead of directly calling callbacks or modifying shared state //======================================================================== -// Fullscren management (fullscreen.c) -void _glfwSplitBPP(int bpp, int* red, int* green, int* blue); - -// Error handling (error.c) -void _glfwSetError(int error, const char* description); - -// Window management (window.c) -void _glfwSetDefaultWindowHints(void); - // Window event notification (window.c) void _glfwInputWindowFocus(_GLFWwindow* window, GLboolean activated); void _glfwInputWindowPos(_GLFWwindow* window, int x, int y); void _glfwInputWindowSize(_GLFWwindow* window, int width, int height); void _glfwInputWindowIconify(_GLFWwindow* window, int iconified); void _glfwInputWindowDamage(_GLFWwindow* window); +void _glfwInputWindowCloseRequest(_GLFWwindow* window); // Input event notification (input.c) void _glfwInputKey(_GLFWwindow* window, int key, int action); @@ -361,14 +329,32 @@ void _glfwInputMouseClick(_GLFWwindow* window, int button, int action); void _glfwInputCursorMotion(_GLFWwindow* window, int x, int y); void _glfwInputCursorEnter(_GLFWwindow* window, int entered); + +//======================================================================== +// Prototypes for internal utility functions +// These functions are shared code and may be used by any part of GLFW +// Each platform may add its own utility functions, but those may only be +// called by the platform-specific code +//======================================================================== + +// Fullscren management (fullscreen.c) +int _glfwCompareVideoModes(const GLFWvidmode* first, const GLFWvidmode* second); +void _glfwSplitBPP(int bpp, int* red, int* green, int* blue); + +// Error handling (init.c) +void _glfwSetError(int error, const char* format, ...); + +// Window management (window.c) +void _glfwSetDefaultWindowHints(void); + // OpenGL context helpers (opengl.c) int _glfwStringInExtensionString(const char* string, const GLubyte* extensions); const _GLFWfbconfig* _glfwChooseFBConfig(const _GLFWfbconfig* desired, const _GLFWfbconfig* alternatives, unsigned int count); -void _glfwRefreshContextParams(void); +GLboolean _glfwRefreshContextParams(void); GLboolean _glfwIsValidContextConfig(_GLFWwndconfig* wndconfig); -GLboolean _glfwIsValidContext(_GLFWwindow* window, _GLFWwndconfig* wndconfig); +GLboolean _glfwIsValidContext(_GLFWwndconfig* wndconfig); #endif // _internal_h_ diff --git a/src/joystick.c b/src/joystick.c index 682ba4b0..84763951 100644 --- a/src/joystick.c +++ b/src/joystick.c @@ -47,6 +47,12 @@ GLFWAPI int glfwGetJoystickParam(int joy, int param) return 0; } + if (joy < 0 || joy > GLFW_JOYSTICK_LAST) + { + _glfwSetError(GLFW_INVALID_ENUM, NULL); + return 0; + } + return _glfwPlatformGetJoystickParam(joy, param); } @@ -55,7 +61,7 @@ GLFWAPI int glfwGetJoystickParam(int joy, int param) // Get joystick axis positions //======================================================================== -GLFWAPI int glfwGetJoystickPos(int joy, float* pos, int numaxes) +GLFWAPI int glfwGetJoystickAxes(int joy, float* axes, int numaxes) { int i; @@ -65,11 +71,23 @@ GLFWAPI int glfwGetJoystickPos(int joy, float* pos, int numaxes) return 0; } + if (joy < 0 || joy > GLFW_JOYSTICK_LAST) + { + _glfwSetError(GLFW_INVALID_ENUM, NULL); + return 0; + } + + if (axes == NULL || numaxes < 0) + { + _glfwSetError(GLFW_INVALID_VALUE, NULL); + return 0; + } + // Clear positions for (i = 0; i < numaxes; i++) - pos[i] = 0.0f; + axes[i] = 0.0f; - return _glfwPlatformGetJoystickPos(joy, pos, numaxes); + return _glfwPlatformGetJoystickAxes(joy, axes, numaxes); } @@ -89,6 +107,18 @@ GLFWAPI int glfwGetJoystickButtons(int joy, return 0; } + if (joy < 0 || joy > GLFW_JOYSTICK_LAST) + { + _glfwSetError(GLFW_INVALID_ENUM, NULL); + return 0; + } + + if (buttons == NULL || numbuttons < 0) + { + _glfwSetError(GLFW_INVALID_VALUE, NULL); + return 0; + } + // Clear button states for (i = 0; i < numbuttons; i++) buttons[i] = GLFW_RELEASE; diff --git a/src/opengl.c b/src/opengl.c index 5a292d16..825ccaf6 100644 --- a/src/opengl.c +++ b/src/opengl.c @@ -30,6 +30,7 @@ #include "internal.h" +#include #include #include #include @@ -323,8 +324,8 @@ GLboolean _glfwIsValidContextConfig(_GLFWwndconfig* wndconfig) { // Forward-compatible contexts are only defined for OpenGL version 3.0 and above _glfwSetError(GLFW_INVALID_VALUE, - "glfwOpenWindow: Forward compatibility only exist for " - "OpenGL version 3.0 and above"); + "glfwOpenWindow: Forward compatibility only exist " + "for OpenGL version 3.0 and above"); return GL_FALSE; } } @@ -386,9 +387,10 @@ GLboolean _glfwIsValidContextConfig(_GLFWwndconfig* wndconfig) //======================================================================== // Reads back context properties +// It blames glfwCreateWindow because that's the only caller //======================================================================== -void _glfwRefreshContextParams(void) +GLboolean _glfwRefreshContextParams(void) { _GLFWwindow* window = _glfwLibrary.currentWindow; @@ -397,7 +399,22 @@ void _glfwRefreshContextParams(void) &window->glMinor, &window->glRevision)) { - return; + return GL_FALSE; + } + + if (window->glMajor > 2) + { + // OpenGL 3.0+ uses a different function for extension string retrieval + // We cache it here instead of in glfwExtensionSupported mostly to alert + // users as early as possible that their build may be broken + + window->GetStringi = (PFNGLGETSTRINGIPROC) glfwGetProcAddress("glGetStringi"); + if (!window->GetStringi) + { + _glfwSetError(GLFW_PLATFORM_ERROR, + "glfwCreateWindow: Entry point retrieval is broken"); + return GL_FALSE; + } } // Read back forward-compatibility flag @@ -432,36 +449,19 @@ void _glfwRefreshContextParams(void) } } - glGetIntegerv(GL_RED_BITS, &window->redBits); - glGetIntegerv(GL_GREEN_BITS, &window->greenBits); - glGetIntegerv(GL_BLUE_BITS, &window->blueBits); - - glGetIntegerv(GL_ALPHA_BITS, &window->alphaBits); - glGetIntegerv(GL_DEPTH_BITS, &window->depthBits); - glGetIntegerv(GL_STENCIL_BITS, &window->stencilBits); - - glGetIntegerv(GL_ACCUM_RED_BITS, &window->accumRedBits); - glGetIntegerv(GL_ACCUM_GREEN_BITS, &window->accumGreenBits); - glGetIntegerv(GL_ACCUM_BLUE_BITS, &window->accumBlueBits); - glGetIntegerv(GL_ACCUM_ALPHA_BITS, &window->accumAlphaBits); - - glGetIntegerv(GL_AUX_BUFFERS, &window->auxBuffers); - glGetBooleanv(GL_STEREO, &window->stereo); - - if (_glfwPlatformExtensionSupported("GL_ARB_multisample")) - glGetIntegerv(GL_SAMPLES_ARB, &window->samples); - else - window->samples = 0; + return GL_TRUE; } //======================================================================== -// Checks whether the specified context fulfils the requirements -// It blames glfwOpenWindow because that's the only caller +// Checks whether the current context fulfils the specified requirements +// It blames glfwCreateWindow because that's the only caller //======================================================================== -GLboolean _glfwIsValidContext(_GLFWwindow* window, _GLFWwndconfig* wndconfig) +GLboolean _glfwIsValidContext(_GLFWwndconfig* wndconfig) { + _GLFWwindow* window = _glfwLibrary.currentWindow; + if (window->glMajor < wndconfig->glMajor || (window->glMajor == wndconfig->glMajor && window->glMinor < wndconfig->glMinor)) @@ -474,25 +474,10 @@ GLboolean _glfwIsValidContext(_GLFWwindow* window, _GLFWwndconfig* wndconfig) // {GLX|WGL}_ARB_create_context extension and fail here _glfwSetError(GLFW_VERSION_UNAVAILABLE, - "glfwOpenWindow: The requested OpenGL version is not available"); + "glfwCreateWindow: The requested OpenGL version is not available"); return GL_FALSE; } - if (window->glMajor > 2) - { - // OpenGL 3.0+ uses a different function for extension string retrieval - // We cache it here instead of in glfwExtensionSupported mostly to alert - // users as early as possible that their build may be broken - - window->GetStringi = (PFNGLGETSTRINGIPROC) glfwGetProcAddress("glGetStringi"); - if (!window->GetStringi) - { - _glfwSetError(GLFW_PLATFORM_ERROR, - "glfwOpenWindow: Entry point retrieval is broken"); - return GL_FALSE; - } - } - return GL_TRUE; } @@ -567,7 +552,7 @@ GLFWAPI GLFWwindow glfwGetCurrentContext(void) if (!_glfwInitialized) { _glfwSetError(GLFW_NOT_INITIALIZED, NULL); - return GL_FALSE; + return NULL; } return _glfwLibrary.currentWindow; @@ -578,21 +563,17 @@ GLFWAPI GLFWwindow glfwGetCurrentContext(void) // Swap buffers (double-buffering) //======================================================================== -GLFWAPI void glfwSwapBuffers(void) +GLFWAPI void glfwSwapBuffers(GLFWwindow handle) { + _GLFWwindow* window = (_GLFWwindow*) handle; + if (!_glfwInitialized) { _glfwSetError(GLFW_NOT_INITIALIZED, NULL); return; } - if (!_glfwLibrary.currentWindow) - { - _glfwSetError(GLFW_NO_CURRENT_WINDOW, NULL); - return; - } - - _glfwPlatformSwapBuffers(); + _glfwPlatformSwapBuffers(window); } @@ -610,7 +591,7 @@ GLFWAPI void glfwSwapInterval(int interval) if (!_glfwLibrary.currentWindow) { - _glfwSetError(GLFW_NO_CURRENT_WINDOW, NULL); + _glfwSetError(GLFW_NO_CURRENT_CONTEXT, NULL); return; } @@ -626,9 +607,6 @@ GLFWAPI int glfwExtensionSupported(const char* extension) { const GLubyte* extensions; _GLFWwindow* window; - GLubyte* where; - GLint count; - int i; if (!_glfwInitialized) { @@ -639,14 +617,15 @@ GLFWAPI int glfwExtensionSupported(const char* extension) window = _glfwLibrary.currentWindow; if (!window) { - _glfwSetError(GLFW_NO_CURRENT_WINDOW, NULL); + _glfwSetError(GLFW_NO_CURRENT_CONTEXT, NULL); return GL_FALSE; } - // Extension names should not have spaces - where = (GLubyte*) strchr(extension, ' '); - if (where || *extension == '\0') + if (extension == NULL || *extension == '\0') + { + _glfwSetError(GLFW_INVALID_VALUE, NULL); return GL_FALSE; + } if (window->glMajor < 3) { @@ -661,6 +640,9 @@ GLFWAPI int glfwExtensionSupported(const char* extension) } else { + int i; + GLint count; + // Check if extension is in the modern OpenGL extensions string list glGetIntegerv(GL_NUM_EXTENSIONS, &count); @@ -675,11 +657,8 @@ GLFWAPI int glfwExtensionSupported(const char* extension) } } - // Additional platform specific extension checking (e.g. WGL) - if (_glfwPlatformExtensionSupported(extension)) - return GL_TRUE; - - return GL_FALSE; + // Check if extension is in the platform-specific string + return _glfwPlatformExtensionSupported(extension); } @@ -698,7 +677,7 @@ GLFWAPI GLFWglproc glfwGetProcAddress(const char* procname) if (!_glfwLibrary.currentWindow) { - _glfwSetError(GLFW_NO_CURRENT_WINDOW, NULL); + _glfwSetError(GLFW_NO_CURRENT_CONTEXT, NULL); return NULL; } diff --git a/src/win32_clipboard.c b/src/win32_clipboard.c index 2b8742ce..22cdb8f6 100644 --- a/src/win32_clipboard.c +++ b/src/win32_clipboard.c @@ -1,6 +1,6 @@ //======================================================================== // GLFW - An OpenGL library -// Platform: Win32/WGL +// Platform: Win32 // API version: 3.0 // WWW: http://www.glfw.org/ //------------------------------------------------------------------------ @@ -32,6 +32,7 @@ #include #include #include +#include ////////////////////////////////////////////////////////////////////////// @@ -52,7 +53,7 @@ void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string) if (!wideString) { _glfwSetError(GLFW_PLATFORM_ERROR, - "Win32/WGL: Failed to convert clipboard string to " + "Win32: Failed to convert clipboard string to " "wide string"); return; } @@ -65,7 +66,7 @@ void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string) free(wideString); _glfwSetError(GLFW_PLATFORM_ERROR, - "Win32/WGL: Failed to allocate global handle for clipboard"); + "Win32: Failed to allocate global handle for clipboard"); return; } @@ -78,7 +79,7 @@ void _glfwPlatformSetClipboardString(_GLFWwindow* window, const char* string) free(wideString); _glfwSetError(GLFW_PLATFORM_ERROR, - "Win32/WGL: Failed to open clipboard"); + "Win32: Failed to open clipboard"); return; } @@ -107,7 +108,7 @@ const char* _glfwPlatformGetClipboardString(_GLFWwindow* window) if (!OpenClipboard(window->Win32.handle)) { _glfwSetError(GLFW_PLATFORM_ERROR, - "Win32/WGL: Failed to open clipboard"); + "Win32: Failed to open clipboard"); return NULL; } @@ -117,7 +118,7 @@ const char* _glfwPlatformGetClipboardString(_GLFWwindow* window) CloseClipboard(); _glfwSetError(GLFW_PLATFORM_ERROR, - "Win32/WGL: Failed to retrieve clipboard data"); + "Win32: Failed to retrieve clipboard data"); return NULL; } @@ -131,7 +132,7 @@ const char* _glfwPlatformGetClipboardString(_GLFWwindow* window) if (!_glfwLibrary.Win32.clipboardString) { _glfwSetError(GLFW_PLATFORM_ERROR, - "Win32/WGL: Failed to convert wide string to UTF-8"); + "Win32: Failed to convert wide string to UTF-8"); return NULL; } diff --git a/src/win32_dllmain.c b/src/win32_dllmain.c index 95258ccc..98f9ab2a 100644 --- a/src/win32_dllmain.c +++ b/src/win32_dllmain.c @@ -1,6 +1,6 @@ //======================================================================== // GLFW - An OpenGL library -// Platform: Win32/WGL +// Platform: Win32 // API version: 3.0 // WWW: http://www.glfw.org/ //------------------------------------------------------------------------ diff --git a/src/win32_fullscreen.c b/src/win32_fullscreen.c index de3d898b..35d75054 100644 --- a/src/win32_fullscreen.c +++ b/src/win32_fullscreen.c @@ -1,6 +1,6 @@ //======================================================================== // GLFW - An OpenGL library -// Platform: Win32/WGL +// Platform: Win32 // API version: 3.0 // WWW: http://www.glfw.org/ //------------------------------------------------------------------------ @@ -32,6 +32,7 @@ #include #include +#include //======================================================================== @@ -182,71 +183,78 @@ void _glfwRestoreVideoMode(void) // Get a list of available video modes //======================================================================== -int _glfwPlatformGetVideoModes(GLFWvidmode* list, int maxcount) +GLFWvidmode* _glfwPlatformGetVideoModes(int* found) { - int count, success, mode, i, j; - int m1, m2, bpp, r, g, b; - DEVMODE dm; + int dmIndex = 0, count = 0; + GLFWvidmode* result = NULL; - // Loop through all video modes and extract all the UNIQUE modes - count = 0; - mode = 0; + *found = 0; - do + for (;;) { - // Get video mode properties + int i; + GLFWvidmode mode; + DEVMODE dm; + + ZeroMemory(&dm, sizeof(DEVMODE)); dm.dmSize = sizeof(DEVMODE); - success = EnumDisplaySettings(NULL, mode, &dm); - // Is it a valid mode? (only list depths >= 15 bpp) - if (success && dm.dmBitsPerPel >= 15) + if (!EnumDisplaySettings(NULL, dmIndex, &dm)) + break; + + dmIndex++; + + if (dm.dmBitsPerPel < 15) { - // Convert to RGB, and back to bpp ("mask out" alpha bits etc) - _glfwSplitBPP(dm.dmBitsPerPel, &r, &g, &b); - bpp = r + g + b; - - // Mode "code" for this mode - m1 = (bpp << 25) | (dm.dmPelsWidth * dm.dmPelsHeight); - - // Insert mode in list (sorted), and avoid duplicates - for (i = 0; i < count; i++) - { - // Mode "code" for already listed mode - bpp = list[i].redBits + list[i].greenBits + list[i].blueBits; - m2 = (bpp << 25) | (list[i].width * list[i].height); - if (m1 <= m2) - break; - } - - // New entry at the end of the list? - if (i >= count) - { - list[count].width = dm.dmPelsWidth; - list[count].height = dm.dmPelsHeight; - list[count].redBits = r; - list[count].greenBits = g; - list[count].blueBits = b; - count ++; - } - // Insert new entry in the list? - else if (m1 < m2) - { - for (j = count; j > i; j--) - list[j] = list[j - 1]; - - list[i].width = dm.dmPelsWidth; - list[i].height = dm.dmPelsHeight; - list[i].redBits = r; - list[i].greenBits = g; - list[i].blueBits = b; - count++; - } + // Skip modes with less than 15 BPP + continue; } - mode++; - } - while (success && (count < maxcount)); - return count; + mode.width = dm.dmPelsWidth; + mode.height = dm.dmPelsHeight; + _glfwSplitBPP(dm.dmBitsPerPel, + &mode.redBits, + &mode.greenBits, + &mode.blueBits); + + for (i = 0; i < *found; i++) + { + if (_glfwCompareVideoModes(result + i, &mode) == 0) + break; + } + + if (i < *found) + { + // This is a duplicate, so skip it + continue; + } + + if (*found == count) + { + void* larger; + + if (count) + count *= 2; + else + count = 128; + + larger = realloc(result, count * sizeof(GLFWvidmode)); + if (!larger) + { + free(result); + + _glfwSetError(GLFW_OUT_OF_MEMORY, NULL); + return NULL; + } + + result = (GLFWvidmode*) larger; + } + + result[*found] = mode; + (*found)++; + } + + return result; } diff --git a/src/win32_gamma.c b/src/win32_gamma.c index 36fbd3a4..74958191 100644 --- a/src/win32_gamma.c +++ b/src/win32_gamma.c @@ -1,6 +1,6 @@ //======================================================================== // GLFW - An OpenGL library -// Platform: Win32/WGL +// Platform: Win32 // API version: 3.0 // WWW: http://www.glfw.org/ //------------------------------------------------------------------------ diff --git a/src/win32_init.c b/src/win32_init.c index 5bcbb310..41444b97 100644 --- a/src/win32_init.c +++ b/src/win32_init.c @@ -31,6 +31,7 @@ #include "internal.h" #include +#include #ifdef __BORLANDC__ // With the Borland C++ compiler, we want to disable FPU exceptions diff --git a/src/win32_input.c b/src/win32_input.c index d3785aa3..a9195838 100644 --- a/src/win32_input.c +++ b/src/win32_input.c @@ -1,6 +1,6 @@ //======================================================================== // GLFW - An OpenGL library -// Platform: Win32/WGL +// Platform: Win32 // API version: 3.0 // WWW: http://www.glfw.org/ //------------------------------------------------------------------------ diff --git a/src/win32_joystick.c b/src/win32_joystick.c index c27218db..a51773d3 100644 --- a/src/win32_joystick.c +++ b/src/win32_joystick.c @@ -1,6 +1,6 @@ //======================================================================== // GLFW - An OpenGL library -// Platform: Win32/WGL +// Platform: Win32 // API version: 3.0 // WWW: http://www.glfw.org/ //------------------------------------------------------------------------ @@ -116,7 +116,7 @@ int _glfwPlatformGetJoystickParam(int joy, int param) // Get joystick axis positions //======================================================================== -int _glfwPlatformGetJoystickPos(int joy, float* pos, int numaxes) +int _glfwPlatformGetJoystickAxes(int joy, float* axes, int numaxes) { JOYCAPS jc; JOYINFOEX ji; @@ -137,22 +137,22 @@ int _glfwPlatformGetJoystickPos(int joy, float* pos, int numaxes) // Get position values for all axes axis = 0; if (axis < numaxes) - pos[axis++] = calcJoystickPos(ji.dwXpos, jc.wXmin, jc.wXmax); + axes[axis++] = calcJoystickPos(ji.dwXpos, jc.wXmin, jc.wXmax); if (axis < numaxes) - pos[axis++] = -calcJoystickPos(ji.dwYpos, jc.wYmin, jc.wYmax); + axes[axis++] = -calcJoystickPos(ji.dwYpos, jc.wYmin, jc.wYmax); if (axis < numaxes && jc.wCaps & JOYCAPS_HASZ) - pos[axis++] = calcJoystickPos(ji.dwZpos, jc.wZmin, jc.wZmax); + axes[axis++] = calcJoystickPos(ji.dwZpos, jc.wZmin, jc.wZmax); if (axis < numaxes && jc.wCaps & JOYCAPS_HASR) - pos[axis++] = calcJoystickPos(ji.dwRpos, jc.wRmin, jc.wRmax); + axes[axis++] = calcJoystickPos(ji.dwRpos, jc.wRmin, jc.wRmax); if (axis < numaxes && jc.wCaps & JOYCAPS_HASU) - pos[axis++] = calcJoystickPos(ji.dwUpos, jc.wUmin, jc.wUmax); + axes[axis++] = calcJoystickPos(ji.dwUpos, jc.wUmin, jc.wUmax); if (axis < numaxes && jc.wCaps & JOYCAPS_HASV) - pos[axis++] = -calcJoystickPos(ji.dwVpos, jc.wVmin, jc.wVmax); + axes[axis++] = -calcJoystickPos(ji.dwVpos, jc.wVmin, jc.wVmax); return axis; } diff --git a/src/win32_opengl.c b/src/win32_opengl.c index 5adf041c..fcca019f 100644 --- a/src/win32_opengl.c +++ b/src/win32_opengl.c @@ -30,6 +30,9 @@ #include "internal.h" +#include +#include + //======================================================================== // Initialize WGL-specific extensions @@ -168,15 +171,14 @@ static _GLFWfbconfig* getFBConfigs(_GLFWwindow* window, unsigned int* found) if (!available) { - _glfwSetError(GLFW_OPENGL_UNAVAILABLE, "Win32/WGL: No pixel formats found"); + _glfwSetError(GLFW_OPENGL_UNAVAILABLE, "WGL: No pixel formats found"); return NULL; } fbconfigs = (_GLFWfbconfig*) malloc(sizeof(_GLFWfbconfig) * available); if (!fbconfigs) { - _glfwSetError(GLFW_OUT_OF_MEMORY, - "Win32/WGL: Failed to allocate _GLFWfbconfig array"); + _glfwSetError(GLFW_OUT_OF_MEMORY, NULL); return NULL; } @@ -282,6 +284,9 @@ static _GLFWfbconfig* getFBConfigs(_GLFWwindow* window, unsigned int* found) if (*found == 0) { + _glfwSetError(GLFW_PLATFORM_ERROR, + "Win32/WGL: No usable pixel formats found"); + free(fbconfigs); return NULL; } @@ -307,15 +312,15 @@ static GLboolean createContext(_GLFWwindow* window, if (!DescribePixelFormat(window->WGL.DC, pixelFormat, sizeof(pfd), &pfd)) { - _glfwSetError(GLFW_OPENGL_UNAVAILABLE, - "Win32/WGL: Failed to retrieve PFD for selected pixel format"); + _glfwSetError(GLFW_PLATFORM_ERROR, + "Win32: Failed to retrieve PFD for selected pixel format"); return GL_FALSE; } if (!SetPixelFormat(window->WGL.DC, pixelFormat, &pfd)) { - _glfwSetError(GLFW_OPENGL_UNAVAILABLE, - "Win32/WGL: Failed to set selected pixel format"); + _glfwSetError(GLFW_PLATFORM_ERROR, + "Win32: Failed to set selected pixel format"); return GL_FALSE; } @@ -372,7 +377,7 @@ static GLboolean createContext(_GLFWwindow* window, if (!window->WGL.ARB_create_context_profile) { _glfwSetError(GLFW_VERSION_UNAVAILABLE, - "Win32/WGL: OpenGL profile requested but " + "WGL: OpenGL profile requested but " "WGL_ARB_create_context_profile is unavailable"); return GL_FALSE; } @@ -393,7 +398,7 @@ static GLboolean createContext(_GLFWwindow* window, if (!window->WGL.ARB_create_context_robustness) { _glfwSetError(GLFW_VERSION_UNAVAILABLE, - "Win32/WGL: An OpenGL robustness strategy was " + "WGL: An OpenGL robustness strategy was " "requested but WGL_ARB_create_context_robustness " "is unavailable"); return GL_FALSE; @@ -416,7 +421,7 @@ static GLboolean createContext(_GLFWwindow* window, if (!window->WGL.context) { _glfwSetError(GLFW_VERSION_UNAVAILABLE, - "Win32/WGL: Failed to create OpenGL context"); + "WGL: Failed to create OpenGL context"); return GL_FALSE; } } @@ -426,7 +431,7 @@ static GLboolean createContext(_GLFWwindow* window, if (!window->WGL.context) { _glfwSetError(GLFW_PLATFORM_ERROR, - "Win32/WGL: Failed to create OpenGL context"); + "WGL: Failed to create OpenGL context"); return GL_FALSE; } @@ -435,8 +440,8 @@ static GLboolean createContext(_GLFWwindow* window, if (!wglShareLists(share, window->WGL.context)) { _glfwSetError(GLFW_PLATFORM_ERROR, - "Win32/WGL: Failed to enable sharing with " - "specified OpenGL context"); + "WGL: Failed to enable sharing with specified " + "OpenGL context"); return GL_FALSE; } } @@ -467,7 +472,7 @@ int _glfwCreateContext(_GLFWwindow* window, if (!window->WGL.DC) { _glfwSetError(GLFW_PLATFORM_ERROR, - "Win32/WGL: Failed to retrieve DC for window"); + "Win32: Failed to retrieve DC for window"); return GL_FALSE; } @@ -479,16 +484,12 @@ int _glfwCreateContext(_GLFWwindow* window, fbconfigs = getFBConfigs(window, &fbcount); if (!fbconfigs) - { - _glfwSetError(GLFW_PLATFORM_ERROR, - "Win32/WGL: No usable pixel formats found"); return GL_FALSE; - } result = _glfwChooseFBConfig(fbconfig, fbconfigs, fbcount); if (!result) { - _glfwSetError(GLFW_PLATFORM_ERROR, + _glfwSetError(GLFW_FORMAT_UNAVAILABLE, "Win32/WGL: No pixel format matched the criteria"); free(fbconfigs); @@ -509,7 +510,7 @@ int _glfwCreateContext(_GLFWwindow* window, void _glfwDestroyContext(_GLFWwindow* window) { - // This is duplicated from glfwCloseWindow + // This is duplicated from glfwDestroyWindow // TODO: Stop duplicating code if (window == _glfwLibrary.currentWindow) glfwMakeContextCurrent(NULL); @@ -549,10 +550,8 @@ void _glfwPlatformMakeContextCurrent(_GLFWwindow* window) // Swap buffers (double-buffering) //======================================================================== -void _glfwPlatformSwapBuffers(void) +void _glfwPlatformSwapBuffers(_GLFWwindow* window) { - _GLFWwindow* window = _glfwLibrary.currentWindow; - SwapBuffers(window->WGL.DC); } @@ -623,7 +622,7 @@ void _glfwPlatformCopyContext(_GLFWwindow* src, _GLFWwindow* dst, unsigned long if (!wglCopyContext(src->WGL.context, dst->WGL.context, mask)) { _glfwSetError(GLFW_PLATFORM_ERROR, - "Win32/WGL: Failed to copy OpenGL context attributes"); + "WGL: Failed to copy OpenGL context attributes"); } } diff --git a/src/win32_platform.h b/src/win32_platform.h index 79bbbb94..ba10039e 100644 --- a/src/win32_platform.h +++ b/src/win32_platform.h @@ -191,7 +191,7 @@ typedef struct _GLFWlibraryWin32 // Timer data struct { - GLboolean hasPerformanceCounter; + GLboolean hasPC; double resolution; unsigned int t0_32; __int64 t0_64; diff --git a/src/win32_time.c b/src/win32_time.c index f3bd173a..96f7b454 100644 --- a/src/win32_time.c +++ b/src/win32_time.c @@ -1,6 +1,6 @@ //======================================================================== // GLFW - An OpenGL library -// Platform: Win32/WGL +// Platform: Win32 // API version: 3.0 // WWW: http://www.glfw.org/ //------------------------------------------------------------------------ @@ -45,13 +45,13 @@ void _glfwInitTimer(void) if (QueryPerformanceFrequency((LARGE_INTEGER*) &freq)) { - _glfwLibrary.Win32.timer.hasPerformanceCounter = GL_TRUE; + _glfwLibrary.Win32.timer.hasPC = GL_TRUE; _glfwLibrary.Win32.timer.resolution = 1.0 / (double) freq; QueryPerformanceCounter((LARGE_INTEGER*) &_glfwLibrary.Win32.timer.t0_64); } else { - _glfwLibrary.Win32.timer.hasPerformanceCounter = GL_FALSE; + _glfwLibrary.Win32.timer.hasPC = GL_FALSE; _glfwLibrary.Win32.timer.resolution = 0.001; // winmm resolution is 1 ms _glfwLibrary.Win32.timer.t0_32 = _glfw_timeGetTime(); } @@ -71,7 +71,7 @@ double _glfwPlatformGetTime(void) double t; __int64 t_64; - if (_glfwLibrary.Win32.timer.hasPerformanceCounter) + if (_glfwLibrary.Win32.timer.hasPC) { QueryPerformanceCounter((LARGE_INTEGER*) &t_64); t = (double)(t_64 - _glfwLibrary.Win32.timer.t0_64); @@ -91,7 +91,7 @@ void _glfwPlatformSetTime(double t) { __int64 t_64; - if (_glfwLibrary.Win32.timer.hasPerformanceCounter) + if (_glfwLibrary.Win32.timer.hasPC) { QueryPerformanceCounter((LARGE_INTEGER*) &t_64); _glfwLibrary.Win32.timer.t0_64 = t_64 - (__int64) (t / _glfwLibrary.Win32.timer.resolution); diff --git a/src/win32_window.c b/src/win32_window.c index fff50ea2..feccb833 100644 --- a/src/win32_window.c +++ b/src/win32_window.c @@ -32,6 +32,7 @@ #include #include +#include //======================================================================== @@ -532,8 +533,7 @@ static LRESULT CALLBACK windowProc(HWND hWnd, UINT uMsg, case WM_CLOSE: { - // Flag this window for closing (handled in glfwPollEvents) - window->closeRequested = GL_TRUE; + _glfwInputWindowCloseRequest(window); return 0; } @@ -813,7 +813,7 @@ static ATOM registerWindowClass(void) if (!classAtom) { _glfwSetError(GLFW_PLATFORM_ERROR, - "Win32/WGL: Failed to register window class"); + "Win32: Failed to register window class"); return 0; } @@ -886,7 +886,7 @@ static int createWindow(_GLFWwindow* window, if (!wideTitle) { _glfwSetError(GLFW_PLATFORM_ERROR, - "glfwOpenWindow: Failed to convert title to wide string"); + "Win32: Failed to convert title to wide string"); return GL_FALSE; } @@ -904,7 +904,7 @@ static int createWindow(_GLFWwindow* window, if (!window->Win32.handle) { - _glfwSetError(GLFW_PLATFORM_ERROR, "Win32/WGL: Failed to create window"); + _glfwSetError(GLFW_PLATFORM_ERROR, "Win32: Failed to create window"); return GL_FALSE; } @@ -931,7 +931,7 @@ static void destroyWindow(_GLFWwindow* window) { _glfwDestroyContext(window); - // This is duplicated from glfwCloseWindow + // This is duplicated from glfwDestroyWindow // TODO: Stop duplicating code if (window == _glfwLibrary.activeWindow) _glfwLibrary.activeWindow = NULL; @@ -953,14 +953,13 @@ static void destroyWindow(_GLFWwindow* window) // created //======================================================================== -int _glfwPlatformOpenWindow(_GLFWwindow* window, - const _GLFWwndconfig* wndconfig, - const _GLFWfbconfig* fbconfig) +int _glfwPlatformCreateWindow(_GLFWwindow* window, + const _GLFWwndconfig* wndconfig, + const _GLFWfbconfig* fbconfig) { GLboolean recreateContext = GL_FALSE; window->Win32.desiredRefreshRate = wndconfig->refreshRate; - window->resizable = wndconfig->resizable; if (!_glfwLibrary.Win32.classAtom) { @@ -1009,8 +1008,8 @@ int _glfwPlatformOpenWindow(_GLFWwindow* window, if (!window->WGL.ARB_create_context) { _glfwSetError(GLFW_VERSION_UNAVAILABLE, - "Win32/WGL: A forward compatible OpenGL context " - "requested but WGL_ARB_create_context is unavailable"); + "WGL: A forward compatible OpenGL context requested " + "but WGL_ARB_create_context is unavailable"); return GL_FALSE; } @@ -1022,7 +1021,7 @@ int _glfwPlatformOpenWindow(_GLFWwindow* window, if (!window->WGL.ARB_create_context_profile) { _glfwSetError(GLFW_VERSION_UNAVAILABLE, - "Win32/WGL: OpenGL profile requested but " + "WGL: OpenGL profile requested but " "WGL_ARB_create_context_profile is unavailable"); return GL_FALSE; } @@ -1083,7 +1082,7 @@ int _glfwPlatformOpenWindow(_GLFWwindow* window, // Properly kill the window / video display //======================================================================== -void _glfwPlatformCloseWindow(_GLFWwindow* window) +void _glfwPlatformDestroyWindow(_GLFWwindow* window) { destroyWindow(window); @@ -1108,7 +1107,7 @@ void _glfwPlatformSetWindowTitle(_GLFWwindow* window, const char* title) if (!wideTitle) { _glfwSetError(GLFW_PLATFORM_ERROR, - "glfwSetWindowTitle: Failed to convert title to wide string"); + "Win32: Failed to convert title to wide string"); return; } @@ -1198,10 +1197,9 @@ void _glfwPlatformRestoreWindow(_GLFWwindow* window) // Write back window parameters into GLFW window structure //======================================================================== -void _glfwPlatformRefreshWindowParams(void) +void _glfwPlatformRefreshWindowParams(_GLFWwindow* window) { DEVMODE dm; - _GLFWwindow* window = _glfwLibrary.currentWindow; ZeroMemory(&dm, sizeof(DEVMODE)); dm.dmSize = sizeof(DEVMODE); @@ -1250,7 +1248,7 @@ void _glfwPlatformPollEvents(void) window = _glfwLibrary.windowListHead; while (window) { - window->closeRequested = GL_TRUE; + _glfwInputWindowCloseRequest(window); window = window->next; } diff --git a/src/window.c b/src/window.c index d2f8d2cd..aea54603 100644 --- a/src/window.c +++ b/src/window.c @@ -6,6 +6,7 @@ //------------------------------------------------------------------------ // Copyright (c) 2002-2006 Marcus Geelnard // Copyright (c) 2006-2010 Camilla Berglund +// Copyright (c) 2012 Torsten Walluhn // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages @@ -32,6 +33,11 @@ #include #include +#ifdef __APPLE__ +#include +#else +#include +#endif //======================================================================== @@ -44,31 +50,6 @@ static int Max(int a, int b) } -//======================================================================== -// Close all GLFW windows with the closed flag set -//======================================================================== - -static void closeFlaggedWindows(void) -{ - _GLFWwindow* window; - - for (window = _glfwLibrary.windowListHead; window; ) - { - if (window->closeRequested && _glfwLibrary.windowCloseCallback) - window->closeRequested = _glfwLibrary.windowCloseCallback(window); - - if (window->closeRequested) - { - _GLFWwindow* next = window->next; - glfwCloseWindow(window); - window = next; - } - else - window = window->next; - } -} - - //======================================================================== // Clear scroll offsets for all windows //======================================================================== @@ -104,6 +85,12 @@ void _glfwSetDefaultWindowHints(void) // The default is to allow window resizing _glfwLibrary.hints.resizable = GL_TRUE; + + // The default is 24 bits of depth, 8 bits of color + _glfwLibrary.hints.depthBits = 24; + _glfwLibrary.hints.redBits = 8; + _glfwLibrary.hints.greenBits = 8; + _glfwLibrary.hints.blueBits = 8; } @@ -207,6 +194,19 @@ void _glfwInputWindowDamage(_GLFWwindow* window) } +//======================================================================== +// Register window close request events +//======================================================================== + +void _glfwInputWindowCloseRequest(_GLFWwindow* window) +{ + if (_glfwLibrary.windowCloseCallback) + window->closeRequested = _glfwLibrary.windowCloseCallback(window); + else + window->closeRequested = GL_TRUE; +} + + ////////////////////////////////////////////////////////////////////////// ////// GLFW public API ////// ////////////////////////////////////////////////////////////////////////// @@ -215,13 +215,14 @@ void _glfwInputWindowDamage(_GLFWwindow* window) // Create the GLFW window and its associated context //======================================================================== -GLFWAPI GLFWwindow glfwOpenWindow(int width, int height, - int mode, const char* title, - GLFWwindow share) +GLFWAPI GLFWwindow glfwCreateWindow(int width, int height, + int mode, const char* title, + GLFWwindow share) { _GLFWfbconfig fbconfig; _GLFWwndconfig wndconfig; _GLFWwindow* window; + _GLFWwindow* previous; if (!_glfwInitialized) { @@ -268,10 +269,13 @@ GLFWAPI GLFWwindow glfwOpenWindow(int width, int height, if (!_glfwIsValidContextConfig(&wndconfig)) return GL_FALSE; + // Save the currently current context so it can be restored later + previous = glfwGetCurrentContext(); + if (mode != GLFW_WINDOWED && mode != GLFW_FULLSCREEN) { _glfwSetError(GLFW_INVALID_ENUM, - "glfwOpenWindow: Invalid enum for 'mode' parameter"); + "glfwCreateWindow: Invalid window mode"); return GL_FALSE; } @@ -296,8 +300,7 @@ GLFWAPI GLFWwindow glfwOpenWindow(int width, int height, window = (_GLFWwindow*) malloc(sizeof(_GLFWwindow)); if (!window) { - _glfwSetError(GLFW_OUT_OF_MEMORY, - "glfwOpenWindow: Failed to allocate window structure"); + _glfwSetError(GLFW_OUT_OF_MEMORY, NULL); return NULL; } @@ -310,27 +313,41 @@ GLFWAPI GLFWwindow glfwOpenWindow(int width, int height, window->width = width; window->height = height; window->mode = mode; + window->resizable = wndconfig.resizable; window->cursorMode = GLFW_CURSOR_NORMAL; window->systemKeys = GL_TRUE; // Open the actual window and create its context - if (!_glfwPlatformOpenWindow(window, &wndconfig, &fbconfig)) + if (!_glfwPlatformCreateWindow(window, &wndconfig, &fbconfig)) { - glfwCloseWindow(window); + glfwDestroyWindow(window); + glfwMakeContextCurrent(previous); return GL_FALSE; } - // Cache the actual (as opposed to desired) window parameters + // Cache the actual (as opposed to requested) window parameters + _glfwPlatformRefreshWindowParams(window); + + // Cache the actual (as opposed to requested) context parameters glfwMakeContextCurrent(window); - _glfwRefreshContextParams(); - _glfwPlatformRefreshWindowParams(); - - if (!_glfwIsValidContext(window, &wndconfig)) + if (!_glfwRefreshContextParams()) { - glfwCloseWindow(window); + glfwDestroyWindow(window); + glfwMakeContextCurrent(previous); return GL_FALSE; } + // Verify the context against the requested parameters + if (!_glfwIsValidContext(&wndconfig)) + { + glfwDestroyWindow(window); + glfwMakeContextCurrent(previous); + return GL_FALSE; + } + + // Restore the previously current context (or NULL) + glfwMakeContextCurrent(previous); + // The GLFW specification states that fullscreen windows have the cursor // captured by default if (mode == GLFW_FULLSCREEN) @@ -339,45 +356,17 @@ GLFWAPI GLFWwindow glfwOpenWindow(int width, int height, // Clearing the front buffer to black to avoid garbage pixels left over // from previous uses of our bit of VRAM glClear(GL_COLOR_BUFFER_BIT); - _glfwPlatformSwapBuffers(); + _glfwPlatformSwapBuffers(window); return window; } //======================================================================== -// Returns GL_TRUE if the specified window handle is an actual window +// Set hints for creating the window //======================================================================== -GLFWAPI int glfwIsWindow(GLFWwindow handle) -{ - _GLFWwindow* entry; - _GLFWwindow* window = (_GLFWwindow*) handle; - - if (!_glfwInitialized) - { - _glfwSetError(GLFW_NOT_INITIALIZED, NULL); - return GL_FALSE; - } - - if (window == NULL) - return GL_FALSE; - - for (entry = _glfwLibrary.windowListHead; entry; entry = entry->next) - { - if (entry == window) - return GL_TRUE; - } - - return GL_FALSE; -} - - -//======================================================================== -// Set hints for opening the window -//======================================================================== - -GLFWAPI void glfwOpenWindowHint(int target, int hint) +GLFWAPI void glfwWindowHint(int target, int hint) { if (!_glfwInitialized) { @@ -464,7 +453,7 @@ GLFWAPI void glfwOpenWindowHint(int target, int hint) // Properly kill the window / video display //======================================================================== -GLFWAPI void glfwCloseWindow(GLFWwindow handle) +GLFWAPI void glfwDestroyWindow(GLFWwindow handle) { _GLFWwindow* window = (_GLFWwindow*) handle; @@ -486,7 +475,7 @@ GLFWAPI void glfwCloseWindow(GLFWwindow handle) if (window == _glfwLibrary.activeWindow) _glfwLibrary.activeWindow = NULL; - _glfwPlatformCloseWindow(window); + _glfwPlatformDestroyWindow(window); // Unlink window from global linked list { @@ -572,7 +561,7 @@ GLFWAPI void glfwSetWindowSize(GLFWwindow handle, int width, int height) { // Refresh window parameters (may have changed due to changed video // modes) - _glfwPlatformRefreshWindowParams(); + _glfwPlatformRefreshWindowParams(window); } } @@ -664,7 +653,7 @@ GLFWAPI void glfwRestoreWindow(GLFWwindow handle) _glfwPlatformRestoreWindow(window); if (window->mode == GLFW_FULLSCREEN) - _glfwPlatformRefreshWindowParams(); + _glfwPlatformRefreshWindowParams(window); } @@ -688,36 +677,12 @@ GLFWAPI int glfwGetWindowParam(GLFWwindow handle, int param) return window == _glfwLibrary.activeWindow; case GLFW_ICONIFIED: return window->iconified; - case GLFW_RED_BITS: - return window->redBits; - case GLFW_GREEN_BITS: - return window->greenBits; - case GLFW_BLUE_BITS: - return window->blueBits; - case GLFW_ALPHA_BITS: - return window->alphaBits; - case GLFW_DEPTH_BITS: - return window->depthBits; - case GLFW_STENCIL_BITS: - return window->stencilBits; - case GLFW_ACCUM_RED_BITS: - return window->accumRedBits; - case GLFW_ACCUM_GREEN_BITS: - return window->accumGreenBits; - case GLFW_ACCUM_BLUE_BITS: - return window->accumBlueBits; - case GLFW_ACCUM_ALPHA_BITS: - return window->accumAlphaBits; - case GLFW_AUX_BUFFERS: - return window->auxBuffers; - case GLFW_STEREO: - return window->stereo; + case GLFW_CLOSE_REQUESTED: + return window->closeRequested; case GLFW_REFRESH_RATE: return window->refreshRate; case GLFW_WINDOW_RESIZABLE: return window->resizable; - case GLFW_FSAA_SAMPLES: - return window->samples; case GLFW_CLIENT_API: return window->clientAPI; case GLFW_OPENGL_VERSION_MAJOR: @@ -790,16 +755,6 @@ GLFWAPI void glfwSetWindowSizeCallback(GLFWwindowsizefun cbfun) } _glfwLibrary.windowSizeCallback = cbfun; - - // Call the callback function to let the application know the current - // window size - if (cbfun) - { - _GLFWwindow* window; - - for (window = _glfwLibrary.windowListHead; window; window = window->next) - cbfun(window, window->width, window->height); - } } @@ -882,8 +837,6 @@ GLFWAPI void glfwPollEvents(void) clearScrollOffsets(); _glfwPlatformPollEvents(); - - closeFlaggedWindows(); } @@ -902,7 +855,5 @@ GLFWAPI void glfwWaitEvents(void) clearScrollOffsets(); _glfwPlatformWaitEvents(); - - closeFlaggedWindows(); } diff --git a/src/x11_egl_opengl.c b/src/x11_egl_opengl.c index f8d317db..5e79a611 100644 --- a/src/x11_egl_opengl.c +++ b/src/x11_egl_opengl.c @@ -519,10 +519,9 @@ void _glfwPlatformMakeContextCurrent(_GLFWwindow* window) // Swap OpenGL buffers //======================================================================== -void _glfwPlatformSwapBuffers(void) +void _glfwPlatformSwapBuffers(_GLFWwindow* window) { - eglSwapBuffers(_glfwLibrary.EGL.display, - _glfwLibrary.currentWindow->EGL.surface); + eglSwapBuffers(_glfwLibrary.EGL.display, window->EGL.surface); } diff --git a/src/x11_fullscreen.c b/src/x11_fullscreen.c index e718951f..06b161e4 100644 --- a/src/x11_fullscreen.c +++ b/src/x11_fullscreen.c @@ -32,6 +32,105 @@ #include #include +#include + + +//------------------------------------------------------------------------ +// Display resolution +//------------------------------------------------------------------------ + +typedef struct +{ + int width; + int height; +} _GLFWvidsize; + + +//======================================================================== +// List available resolutions +//======================================================================== + +static _GLFWvidsize* getResolutions(int* found) +{ + int i, j; + _GLFWvidsize* result = NULL; + + *found = 0; + + // Build array of available resolutions + + if (_glfwLibrary.X11.RandR.available) + { +#if defined(_GLFW_HAS_XRANDR) + XRRScreenConfiguration* sc; + XRRScreenSize* sizes; + + sc = XRRGetScreenInfo(_glfwLibrary.X11.display, _glfwLibrary.X11.root); + sizes = XRRConfigSizes(sc, found); + + result = (_GLFWvidsize*) malloc(sizeof(_GLFWvidsize) * *found); + + for (i = 0; i < *found; i++) + { + result[i].width = sizes[i].width; + result[i].height = sizes[i].height; + } + + XRRFreeScreenConfigInfo(sc); +#endif /*_GLFW_HAS_XRANDR*/ + } + else if (_glfwLibrary.X11.VidMode.available) + { +#if defined(_GLFW_HAS_XF86VIDMODE) + XF86VidModeModeInfo** modes; + int modeCount; + + XF86VidModeGetAllModeLines(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen, + &modeCount, &modes); + + result = (_GLFWvidsize*) malloc(sizeof(_GLFWvidsize) * modeCount); + + for (i = 0; i < modeCount; i++) + { + _GLFWvidsize size; + size.width = modes[i]->hdisplay; + size.height = modes[i]->vdisplay; + + for (j = 0; j < *found; j++) + { + if (memcmp(result + j, &size, sizeof(_GLFWvidsize)) == 0) + break; + } + + if (j < *found) + { + // This size is a duplicate, so skip it + continue; + } + + result[*found] = size; + (*found)++; + } + + XFree(modes); +#endif /*_GLFW_HAS_XF86VIDMODE*/ + } + + if (result == NULL) + { + *found = 1; + result = (_GLFWvidsize*) malloc(sizeof(_GLFWvidsize)); + + result[0].width = DisplayWidth(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen); + result[0].height = DisplayHeight(_glfwLibrary.X11.display, + _glfwLibrary.X11.screen); + } + + return result; +} + ////////////////////////////////////////////////////////////////////////// @@ -325,166 +424,93 @@ void _glfwRestoreVideoMode(void) ////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// -struct _glfwResolution -{ - int width; - int height; -}; //======================================================================== // List available video modes //======================================================================== -int _glfwPlatformGetVideoModes(GLFWvidmode* list, int maxcount) +GLFWvidmode* _glfwPlatformGetVideoModes(int* found) { - int count, k, l, r, g, b, rgba, gl; - int depth; - XVisualInfo* vislist; + XVisualInfo* visuals; XVisualInfo dummy; - int viscount, rgbcount, rescount; - int* rgbarray; - struct _glfwResolution* resarray; + int i, j, visualCount, sizeCount, rgbCount; + int* rgbs; + _GLFWvidsize* sizes; + GLFWvidmode* result; - // Get list of visuals - vislist = XGetVisualInfo(_glfwLibrary.X11.display, 0, &dummy, &viscount); - if (vislist == NULL) + visuals = XGetVisualInfo(_glfwLibrary.X11.display, 0, &dummy, &visualCount); + if (visuals == NULL) { _glfwSetError(GLFW_PLATFORM_ERROR, "X11: Failed to retrieve the available visuals"); return 0; } - rgbarray = (int*) malloc(sizeof(int) * viscount); - rgbcount = 0; + rgbs = (int*) malloc(sizeof(int) * visualCount); + rgbCount = 0; - // Temporary solution #if !defined(_GLFW_X11_EGL) - // Build RGB array - for (k = 0; k < viscount; k++) + for (i = 0; i < visualCount; i++) { - // Does the visual support OpenGL & true color? - glXGetConfig(_glfwLibrary.X11.display, &vislist[k], GLX_USE_GL, &gl); - glXGetConfig(_glfwLibrary.X11.display, &vislist[k], GLX_RGBA, &rgba); - if (gl && rgba) + int gl, rgba, rgb, r, g, b; + + glXGetConfig(_glfwLibrary.X11.display, &visuals[i], GLX_USE_GL, &gl); + glXGetConfig(_glfwLibrary.X11.display, &visuals[i], GLX_RGBA, &rgba); + + if (!gl || !rgba) { - // Get color depth for this visual - depth = vislist[k].depth; - - // Convert to RGB - _glfwSplitBPP(depth, &r, &g, &b); - depth = (r << 16) | (g << 8) | b; - - // Is this mode unique? - for (l = 0; l < rgbcount; l++) - { - if (depth == rgbarray[l]) - break; - } - - if (l >= rgbcount) - { - rgbarray[rgbcount] = depth; - rgbcount++; - } + // The visual lacks OpenGL or true color, so skip it + continue; } + + // Convert to RGB channel depths and encode + _glfwSplitBPP(visuals[i].depth, &r, &g, &b); + rgb = (r << 16) | (g << 8) | b; + + for (j = 0; j < rgbCount; j++) + { + if (rgbs[j] == rgb) + break; + } + + if (j < rgbCount) + { + // This channel depth is a duplicate, so skip it + continue; + } + + rgbs[rgbCount] = rgb; + rgbCount++; } + + XFree(visuals); #endif - XFree(vislist); + // Build all permutations of channel depths and resolutions - rescount = 0; - resarray = NULL; + sizes = getResolutions(&sizeCount); - // Build resolution array + result = (GLFWvidmode*) malloc(sizeof(GLFWvidmode) * rgbCount * sizeCount); + *found = 0; - if (_glfwLibrary.X11.RandR.available) + for (i = 0; i < rgbCount; i++) { -#if defined(_GLFW_HAS_XRANDR) - XRRScreenConfiguration* sc; - XRRScreenSize* sizelist; - int sizecount; - - sc = XRRGetScreenInfo(_glfwLibrary.X11.display, _glfwLibrary.X11.root); - sizelist = XRRConfigSizes(sc, &sizecount); - - resarray = (struct _glfwResolution*) malloc(sizeof(struct _glfwResolution) * sizecount); - - for (k = 0; k < sizecount; k++) + for (j = 0; j < sizeCount; j++) { - resarray[rescount].width = sizelist[k].width; - resarray[rescount].height = sizelist[k].height; - rescount++; - } + result[*found].width = sizes[j].width; + result[*found].height = sizes[j].height; + result[*found].redBits = (rgbs[i] >> 16) & 255; + result[*found].greenBits = (rgbs[i] >> 8) & 255; + result[*found].blueBits = rgbs[i] & 255; - XRRFreeScreenConfigInfo(sc); -#endif /*_GLFW_HAS_XRANDR*/ - } - else if (_glfwLibrary.X11.VidMode.available) - { -#if defined(_GLFW_HAS_XF86VIDMODE) - XF86VidModeModeInfo** modelist; - int modecount, width, height; - - XF86VidModeGetAllModeLines(_glfwLibrary.X11.display, - _glfwLibrary.X11.screen, - &modecount, &modelist); - - resarray = (struct _glfwResolution*) malloc(sizeof(struct _glfwResolution) * modecount); - - for (k = 0; k < modecount; k++) - { - width = modelist[k]->hdisplay; - height = modelist[k]->vdisplay; - - // Is this mode unique? - for (l = 0; l < rescount; l++) - { - if (width == resarray[l].width && height == resarray[l].height) - break; - } - - if (l >= rescount) - { - resarray[rescount].width = width; - resarray[rescount].height = height; - rescount++; - } - } - - XFree(modelist); -#endif /*_GLFW_HAS_XF86VIDMODE*/ - } - - if (!resarray) - { - rescount = 1; - resarray = (struct _glfwResolution*) malloc(sizeof(struct _glfwResolution) * rescount); - - resarray[0].width = DisplayWidth(_glfwLibrary.X11.display, - _glfwLibrary.X11.screen); - resarray[0].height = DisplayHeight(_glfwLibrary.X11.display, - _glfwLibrary.X11.screen); - } - - // Build permutations of colors and resolutions - count = 0; - for (k = 0; k < rgbcount && count < maxcount; k++) - { - for (l = 0; l < rescount && count < maxcount; l++) - { - list[count].width = resarray[l].width; - list[count].height = resarray[l].height; - list[count].redBits = (rgbarray[k] >> 16) & 255; - list[count].greenBits = (rgbarray[k] >> 8) & 255; - list[count].blueBits = rgbarray[k] & 255; - count++; + (*found)++; } } - free(resarray); - free(rgbarray); + free(sizes); + free(rgbs); - return count; + return result; } diff --git a/src/x11_glx_opengl.c b/src/x11_glx_opengl.c index 3649dbe5..ac5dd12c 100644 --- a/src/x11_glx_opengl.c +++ b/src/x11_glx_opengl.c @@ -78,7 +78,7 @@ static _GLFWfbconfig* getFBConfigs(_GLFWwindow* window, unsigned int* found) if (!_glfwLibrary.GLX.SGIX_fbconfig) { _glfwSetError(GLFW_OPENGL_UNAVAILABLE, - "X11/GLX: GLXFBConfig support not found"); + "GLX: GLXFBConfig support not found"); return NULL; } } @@ -101,7 +101,7 @@ static _GLFWfbconfig* getFBConfigs(_GLFWwindow* window, unsigned int* found) if (!count) { _glfwSetError(GLFW_OPENGL_UNAVAILABLE, - "X11/GLX: No GLXFBConfigs returned"); + "GLX: No GLXFBConfigs returned"); return NULL; } } @@ -113,7 +113,7 @@ static _GLFWfbconfig* getFBConfigs(_GLFWwindow* window, unsigned int* found) if (!count) { _glfwSetError(GLFW_OPENGL_UNAVAILABLE, - "X11/GLX: No GLXFBConfigs returned"); + "GLX: No GLXFBConfigs returned"); return NULL; } } @@ -121,8 +121,7 @@ static _GLFWfbconfig* getFBConfigs(_GLFWwindow* window, unsigned int* found) result = (_GLFWfbconfig*) malloc(sizeof(_GLFWfbconfig) * count); if (!result) { - _glfwSetError(GLFW_OUT_OF_MEMORY, - "X11/GLX: Failed to allocate _GLFWfbconfig array"); + _glfwSetError(GLFW_OUT_OF_MEMORY, NULL); return NULL; } @@ -242,7 +241,7 @@ static int createContext(_GLFWwindow* window, if (fbconfig == NULL) { _glfwSetError(GLFW_PLATFORM_ERROR, - "X11/GLX: Failed to retrieve the selected GLXFBConfig"); + "GLX: Failed to retrieve the selected GLXFBConfig"); return GL_FALSE; } } @@ -264,7 +263,7 @@ static int createContext(_GLFWwindow* window, XFree(fbconfig); _glfwSetError(GLFW_PLATFORM_ERROR, - "X11/GLX: Failed to retrieve visual for GLXFBConfig"); + "GLX: Failed to retrieve visual for GLXFBConfig"); return GL_FALSE; } @@ -319,7 +318,7 @@ static int createContext(_GLFWwindow* window, if (!_glfwLibrary.GLX.ARB_create_context_profile) { _glfwSetError(GLFW_VERSION_UNAVAILABLE, - "X11/GLX: An OpenGL profile requested but " + "GLX: An OpenGL profile requested but " "GLX_ARB_create_context_profile is unavailable"); return GL_FALSE; } @@ -339,7 +338,7 @@ static int createContext(_GLFWwindow* window, if (!_glfwLibrary.GLX.ARB_create_context_robustness) { _glfwSetError(GLFW_VERSION_UNAVAILABLE, - "X11/GLX: An OpenGL robustness strategy was " + "GLX: An OpenGL robustness strategy was " "requested but GLX_ARB_create_context_robustness " "is unavailable"); return GL_FALSE; @@ -402,7 +401,7 @@ static int createContext(_GLFWwindow* window, // TODO: Handle all the various error codes here _glfwSetError(GLFW_PLATFORM_ERROR, - "X11/GLX: Failed to create OpenGL context"); + "GLX: Failed to create OpenGL context"); return GL_FALSE; } @@ -442,7 +441,7 @@ int _glfwInitOpenGL(void) if (!_glfwLibrary.GLX.libGL) { - _glfwSetError(GLFW_PLATFORM_ERROR, "X11/GLX: Failed to find libGL"); + _glfwSetError(GLFW_PLATFORM_ERROR, "GLX: Failed to find libGL"); return GL_FALSE; } #endif @@ -450,7 +449,7 @@ int _glfwInitOpenGL(void) // Check if GLX is supported on this display if (!glXQueryExtension(_glfwLibrary.X11.display, NULL, NULL)) { - _glfwSetError(GLFW_OPENGL_UNAVAILABLE, "X11/GLX: GLX supported not found"); + _glfwSetError(GLFW_OPENGL_UNAVAILABLE, "GLX: GLX support not found"); return GL_FALSE; } @@ -459,7 +458,7 @@ int _glfwInitOpenGL(void) &_glfwLibrary.GLX.minorVersion)) { _glfwSetError(GLFW_OPENGL_UNAVAILABLE, - "X11/GLX: Failed to query GLX version"); + "GLX: Failed to query GLX version"); return GL_FALSE; } @@ -570,17 +569,13 @@ int _glfwCreateContext(_GLFWwindow* window, fbconfigs = getFBConfigs(window, &fbcount); if (!fbconfigs) - { - _glfwSetError(GLFW_PLATFORM_ERROR, - "X11/GLX: No usable GLXFBConfigs found"); return GL_FALSE; - } result = _glfwChooseFBConfig(fbconfig, fbconfigs, fbcount); if (!result) { _glfwSetError(GLFW_PLATFORM_ERROR, - "X11/GLX: No GLXFBConfig matched the criteria"); + "GLX: No GLXFBConfig matched the criteria"); free(fbconfigs); return GL_FALSE; @@ -647,10 +642,9 @@ void _glfwPlatformMakeContextCurrent(_GLFWwindow* window) // Swap OpenGL buffers //======================================================================== -void _glfwPlatformSwapBuffers(void) +void _glfwPlatformSwapBuffers(_GLFWwindow* window) { - glXSwapBuffers(_glfwLibrary.X11.display, - _glfwLibrary.currentWindow->X11.handle); + glXSwapBuffers(_glfwLibrary.X11.display, window->X11.handle); } diff --git a/src/x11_joystick.c b/src/x11_joystick.c index 35dad02b..a5700c68 100644 --- a/src/x11_joystick.c +++ b/src/x11_joystick.c @@ -30,47 +30,139 @@ #include "internal.h" - -//======================================================================== -// Note: Only Linux joystick input is supported at the moment. Other -// systems will behave as if there are no joysticks connected. -//======================================================================== - - #ifdef _GLFW_USE_LINUX_JOYSTICKS +#include -//------------------------------------------------------------------------ -// Here are the Linux joystick driver v1.x interface definitions that we -// use (we do not want to rely on ): -//------------------------------------------------------------------------ - -#include +#include +#include #include #include + #include #include - -// Joystick event types -#define JS_EVENT_BUTTON 0x01 /* button pressed/released */ -#define JS_EVENT_AXIS 0x02 /* joystick moved */ -#define JS_EVENT_INIT 0x80 /* initial state of device */ - -// Joystick event structure -struct js_event { - unsigned int time; /* (u32) event timestamp in milliseconds */ - signed short value; /* (s16) value */ - unsigned char type; /* (u8) event type */ - unsigned char number; /* (u8) axis/button number */ -}; - -// Joystick IOCTL commands -#define JSIOCGVERSION _IOR('j', 0x01, int) /* get driver version (u32) */ -#define JSIOCGAXES _IOR('j', 0x11, char) /* get number of axes (u8) */ -#define JSIOCGBUTTONS _IOR('j', 0x12, char) /* get number of buttons (u8) */ - #endif // _GLFW_USE_LINUX_JOYSTICKS +//======================================================================== +// Attempt to open the specified joystick device +//======================================================================== + +static int openJoystickDevice(int joy, const char* path) +{ +#ifdef _GLFW_USE_LINUX_JOYSTICKS + char numAxes, numButtons; + int fd, version; + + fd = open(path, O_NONBLOCK); + if (fd == -1) + return GL_FALSE; + + _glfwLibrary.X11.joystick[joy].fd = fd; + + // Verify that the joystick driver version is at least 1.0 + ioctl(fd, JSIOCGVERSION, &version); + if (version < 0x010000) + { + // It's an old 0.x interface (we don't support it) + close(fd); + return GL_FALSE; + } + + ioctl(fd, JSIOCGAXES, &numAxes); + _glfwLibrary.X11.joystick[joy].numAxes = (int) numAxes; + + ioctl(fd, JSIOCGBUTTONS, &numButtons); + _glfwLibrary.X11.joystick[joy].numButtons = (int) numButtons; + + _glfwLibrary.X11.joystick[joy].axis = + (float*) malloc(sizeof(float) * numAxes); + if (_glfwLibrary.X11.joystick[joy].axis == NULL) + { + close(fd); + + _glfwSetError(GLFW_OUT_OF_MEMORY, NULL); + return GL_FALSE; + } + + _glfwLibrary.X11.joystick[joy].button = + (unsigned char*) malloc(sizeof(char) * numButtons); + if (_glfwLibrary.X11.joystick[joy].button == NULL) + { + free(_glfwLibrary.X11.joystick[joy].axis); + close(fd); + + _glfwSetError(GLFW_OUT_OF_MEMORY, NULL); + return GL_FALSE; + } + + _glfwLibrary.X11.joystick[joy].present = GL_TRUE; +#endif // _GLFW_USE_LINUX_JOYSTICKS + + return GL_TRUE; +} + + +//======================================================================== +// Polls for and processes events for all present joysticks +//======================================================================== + +static void pollJoystickEvents(void) +{ +#ifdef _GLFW_USE_LINUX_JOYSTICKS + int i; + ssize_t result; + struct js_event e; + + for (i = 0; i <= GLFW_JOYSTICK_LAST; i++) + { + if (!_glfwLibrary.X11.joystick[i].present) + continue; + + // Read all queued events (non-blocking) + for (;;) + { + errno = 0; + result = read(_glfwLibrary.X11.joystick[i].fd, &e, sizeof(e)); + + if (errno == ENODEV) + _glfwLibrary.X11.joystick[i].present = GL_FALSE; + + if (result < sizeof(e)) + break; + + // We don't care if it's an init event or not + e.type &= ~JS_EVENT_INIT; + + switch (e.type) + { + case JS_EVENT_AXIS: + _glfwLibrary.X11.joystick[i].axis[e.number] = + (float) e.value / 32767.0f; + + // We need to change the sign for the Y axes, so that + // positive = up/forward, according to the GLFW spec. + if (e.number & 1) + { + _glfwLibrary.X11.joystick[i].axis[e.number] = + -_glfwLibrary.X11.joystick[i].axis[e.number]; + } + + break; + + case JS_EVENT_BUTTON: + _glfwLibrary.X11.joystick[i].button[e.number] = + e.value ? GLFW_PRESS : GLFW_RELEASE; + break; + + default: + break; + } + } + } +#endif // _GLFW_USE_LINUX_JOYSTICKS +} + + ////////////////////////////////////////////////////////////////////////// ////// GLFW internal API ////// ////////////////////////////////////////////////////////////////////////// @@ -82,97 +174,24 @@ struct js_event { void _glfwInitJoysticks(void) { #ifdef _GLFW_USE_LINUX_JOYSTICKS - int k, n, fd, joy_count; - char* joy_base_name; - char joy_dev_name[20]; - int driver_version = 0x000800; - char ret_data; -#endif // _GLFW_USE_LINUX_JOYSTICKS - int i; - - // Start by saying that there are no sticks - for (i = 0; i <= GLFW_JOYSTICK_LAST; i++) - _glfwJoy[i].Present = GL_FALSE; - -#ifdef _GLFW_USE_LINUX_JOYSTICKS - - // Try to open joysticks (nonblocking) - joy_count = 0; - for (k = 0; k <= 1 && joy_count <= GLFW_JOYSTICK_LAST; k++) + int i, j, joy = 0; + char path[20]; + const char* bases[] = { - // Pick joystick base name - switch (k) + "/dev/input/js", + "/dev/js" + }; + + for (i = 0; i < sizeof(bases) / sizeof(bases[0]); i++) + { + for (j = 0; j < 50; j++) { - case 0: - // USB joysticks - joy_base_name = "/dev/input/js"; + if (joy > GLFW_JOYSTICK_LAST) break; - case 1: - // "Legacy" joysticks - joy_base_name = "/dev/js"; - break; - default: - // This should never happen - continue; - } - // Try to open a few of these sticks - for (i = 0; i <= 50 && joy_count <= GLFW_JOYSTICK_LAST; i++) - { - sprintf(joy_dev_name, "%s%d", joy_base_name, i); - fd = open(joy_dev_name, O_NONBLOCK); - if (fd != -1) - { - // Remember fd - _glfwJoy[joy_count].fd = fd; - - // Check that the joystick driver version is 1.0+ - ioctl(fd, JSIOCGVERSION, &driver_version); - if (driver_version < 0x010000) - { - // It's an old 0.x interface (we don't support it) - close(fd); - continue; - } - - // Get number of joystick axes - ioctl(fd, JSIOCGAXES, &ret_data); - _glfwJoy[joy_count].NumAxes = (int) ret_data; - - // Get number of joystick buttons - ioctl(fd, JSIOCGBUTTONS, &ret_data); - _glfwJoy[joy_count].NumButtons = (int) ret_data; - - // Allocate memory for joystick state - _glfwJoy[joy_count].Axis = - (float*) malloc(sizeof(float) * - _glfwJoy[joy_count].NumAxes); - if (_glfwJoy[joy_count].Axis == NULL) - { - close(fd); - continue; - } - _glfwJoy[joy_count].Button = - (unsigned char*) malloc(sizeof(char) * - _glfwJoy[joy_count].NumButtons); - if (_glfwJoy[joy_count].Button == NULL) - { - free(_glfwJoy[joy_count].Axis); - close(fd); - continue; - } - - // Clear joystick state - for (n = 0; n < _glfwJoy[joy_count].NumAxes; n++) - _glfwJoy[joy_count].Axis[n] = 0.0f; - - for (n = 0; n < _glfwJoy[joy_count].NumButtons; n++) - _glfwJoy[joy_count].Button[n] = GLFW_RELEASE; - - // The joystick is supported and connected - _glfwJoy[joy_count].Present = GL_TRUE; - joy_count++; - } + sprintf(path, "%s%i", bases[i], j); + if (openJoystickDevice(joy, path)) + joy++; } } #endif // _GLFW_USE_LINUX_JOYSTICKS @@ -185,72 +204,18 @@ void _glfwInitJoysticks(void) void _glfwTerminateJoysticks(void) { - #ifdef _GLFW_USE_LINUX_JOYSTICKS - int i; - // Close any opened joysticks for (i = 0; i <= GLFW_JOYSTICK_LAST; i++) { - if (_glfwJoy[i].Present) + if (_glfwLibrary.X11.joystick[i].present) { - close(_glfwJoy[i].fd); - free(_glfwJoy[i].Axis); - free(_glfwJoy[i].Button); + close(_glfwLibrary.X11.joystick[i].fd); + free(_glfwLibrary.X11.joystick[i].axis); + free(_glfwLibrary.X11.joystick[i].button); - _glfwJoy[i].Present = GL_FALSE; - } - } - -#endif // _GLFW_USE_LINUX_JOYSTICKS - -} - - -//======================================================================== -// Empty joystick event queue -//======================================================================== - -static void pollJoystickEvents(void) -{ -#ifdef _GLFW_USE_LINUX_JOYSTICKS - - struct js_event e; - int i; - - // Get joystick events for all GLFW joysticks - for (i = 0; i <= GLFW_JOYSTICK_LAST; i++) - { - // Is the stick present? - if (_glfwJoy[i].Present) - { - // Read all queued events (non-blocking) - while (read(_glfwJoy[i].fd, &e, sizeof(struct js_event)) > 0) - { - // We don't care if it's an init event or not - e.type &= ~JS_EVENT_INIT; - - // Check event type - switch (e.type) - { - case JS_EVENT_AXIS: - _glfwJoy[i].Axis[e.number] = (float) e.value / 32767.0f; - // We need to change the sign for the Y axes, so that - // positive = up/forward, according to the GLFW spec. - if (e.number & 1) - _glfwJoy[i].Axis[e.number] = -_glfwJoy[i].Axis[e.number]; - break; - - case JS_EVENT_BUTTON: - _glfwJoy[i].Button[e.number] = - e.value ? GLFW_PRESS : GLFW_RELEASE; - break; - - default: - break; - } - } + _glfwLibrary.X11.joystick[i].present = GL_FALSE; } } #endif // _GLFW_USE_LINUX_JOYSTICKS @@ -267,11 +232,10 @@ static void pollJoystickEvents(void) int _glfwPlatformGetJoystickParam(int joy, int param) { - if (!_glfwJoy[joy].Present) - { - // TODO: Figure out if this is an error + pollJoystickEvents(); + + if (!_glfwLibrary.X11.joystick[joy].present) return 0; - } switch (param) { @@ -279,13 +243,13 @@ int _glfwPlatformGetJoystickParam(int joy, int param) return GL_TRUE; case GLFW_AXES: - return _glfwJoy[joy].NumAxes; + return _glfwLibrary.X11.joystick[joy].numAxes; case GLFW_BUTTONS: - return _glfwJoy[joy].NumButtons; + return _glfwLibrary.X11.joystick[joy].numButtons; default: - break; + _glfwSetError(GLFW_INVALID_ENUM, NULL); } return 0; @@ -296,28 +260,22 @@ int _glfwPlatformGetJoystickParam(int joy, int param) // Get joystick axis positions //======================================================================== -int _glfwPlatformGetJoystickPos(int joy, float* pos, int numaxes) +int _glfwPlatformGetJoystickAxes(int joy, float* axes, int numAxes) { int i; - if (!_glfwJoy[joy].Present) - { - // TODO: Figure out if this is an error - return 0; - } - - // Update joystick state pollJoystickEvents(); - // Does the joystick support less axes than requested? - if (_glfwJoy[joy].NumAxes < numaxes) - numaxes = _glfwJoy[joy].NumAxes; + if (!_glfwLibrary.X11.joystick[joy].present) + return 0; - // Copy axis positions from internal state - for (i = 0; i < numaxes; i++) - pos[i] = _glfwJoy[joy].Axis[i]; + if (_glfwLibrary.X11.joystick[joy].numAxes < numAxes) + numAxes = _glfwLibrary.X11.joystick[joy].numAxes; - return numaxes; + for (i = 0; i < numAxes; i++) + axes[i] = _glfwLibrary.X11.joystick[joy].axis[i]; + + return numAxes; } @@ -326,27 +284,21 @@ int _glfwPlatformGetJoystickPos(int joy, float* pos, int numaxes) //======================================================================== int _glfwPlatformGetJoystickButtons(int joy, unsigned char* buttons, - int numbuttons) + int numButtons) { int i; - if (!_glfwJoy[joy].Present) - { - // TODO: Figure out if this is an error - return 0; - } - - // Update joystick state pollJoystickEvents(); - // Does the joystick support less buttons than requested? - if (_glfwJoy[joy].NumButtons < numbuttons) - numbuttons = _glfwJoy[joy].NumButtons; + if (!_glfwLibrary.X11.joystick[joy].present) + return 0; - // Copy button states from internal state - for (i = 0; i < numbuttons; i++) - buttons[i] = _glfwJoy[joy].Button[i]; + if (_glfwLibrary.X11.joystick[joy].numButtons < numButtons) + numButtons = _glfwLibrary.X11.joystick[joy].numButtons; - return numbuttons; + for (i = 0; i < numButtons; i++) + buttons[i] = _glfwLibrary.X11.joystick[joy].button[i]; + + return numButtons; } diff --git a/src/x11_platform.h b/src/x11_platform.h index 6089f4cb..00ad40b8 100644 --- a/src/x11_platform.h +++ b/src/x11_platform.h @@ -43,6 +43,7 @@ #include #endif +// The XRandR extension provides mode setting and gamma control #if defined(_GLFW_HAS_XRANDR) #include #endif @@ -192,22 +193,18 @@ typedef struct _GLFWlibraryX11 int status; } selection; + struct { + int present; + int fd; + int numAxes; + int numButtons; + float* axis; + unsigned char* button; + } joystick[GLFW_JOYSTICK_LAST + 1]; + } _GLFWlibraryX11; -//------------------------------------------------------------------------ -// Joystick information & state -//------------------------------------------------------------------------ -GLFWGLOBAL struct { - int Present; - int fd; - int NumAxes; - int NumButtons; - float* Axis; - unsigned char* Button; -} _glfwJoy[GLFW_JOYSTICK_LAST + 1]; - - //======================================================================== // Prototypes for platform specific internal functions //======================================================================== diff --git a/src/x11_window.c b/src/x11_window.c index 7637fa19..3c8d39e9 100644 --- a/src/x11_window.c +++ b/src/x11_window.c @@ -43,15 +43,6 @@ #define Button6 6 #define Button7 7 -//======================================================================== -// Checks whether the event is a MapNotify for the specified window -//======================================================================== - -static Bool isMapNotify(Display* d, XEvent* e, char* arg) -{ - return (e->type == MapNotify) && (e->xmap.window == (Window)arg); -} - //======================================================================== // Translates an X Window key to internal coding @@ -59,15 +50,11 @@ static Bool isMapNotify(Display* d, XEvent* e, char* arg) static int translateKey(int keycode) { - // Use the pre-filled LUT (see updateKeyCodeLUT() ). + // Use the pre-filled LUT (see updateKeyCodeLUT() in x11_init.c) if ((keycode >= 0) && (keycode < 256)) - { return _glfwLibrary.X11.keyCodeLUT[keycode]; - } else - { return -1; - } } @@ -94,13 +81,13 @@ static int translateChar(XKeyEvent* event) static GLboolean createWindow(_GLFWwindow* window, const _GLFWwndconfig* wndconfig) { - XEvent event; unsigned long wamask; XSetWindowAttributes wa; XVisualInfo* visual = _glfwGetContextVisual(window); // Every window needs a colormap // Create one based on the visual used by the current context + // TODO: Decouple this from context creation window->X11.colormap = XCreateColormap(_glfwLibrary.X11.display, _glfwLibrary.X11.root, @@ -120,33 +107,31 @@ static GLboolean createWindow(_GLFWwindow* window, if (wndconfig->mode == GLFW_WINDOWED) { - // The /only/ reason we are setting the background pixel here is - // that otherwise our window wont get any decorations on systems - // using Compiz on Intel hardware + // The /only/ reason for setting the background pixel here is that + // otherwise our window won't get any decorations on systems using + // certain versions of Compiz on Intel hardware wa.background_pixel = BlackPixel(_glfwLibrary.X11.display, _glfwLibrary.X11.screen); wamask |= CWBackPixel; } - window->X11.handle = XCreateWindow( - _glfwLibrary.X11.display, - _glfwLibrary.X11.root, - 0, 0, // Upper left corner of this window on root - window->width, window->height, - 0, // Border width - visual->depth, // Color depth - InputOutput, - visual->visual, - wamask, - &wa - ); + window->X11.handle = XCreateWindow(_glfwLibrary.X11.display, + _glfwLibrary.X11.root, + 0, 0, // Position + window->width, window->height, + 0, // Border width + visual->depth, // Color depth + InputOutput, + visual->visual, + wamask, + &wa); if (!window->X11.handle) { - // TODO: Handle all the various error codes here + // TODO: Handle all the various error codes here and translate them + // to GLFW errors - _glfwSetError(GLFW_PLATFORM_ERROR, - "X11: Failed to create window"); + _glfwSetError(GLFW_PLATFORM_ERROR, "X11: Failed to create window"); return GL_FALSE; } } @@ -158,8 +143,8 @@ static GLboolean createWindow(_GLFWwindow* window, // manager ignore the window completely (ICCCM, section 4) // The good thing is that this makes undecorated fullscreen windows // easy to do; the bad thing is that we have to do everything manually - // and some things (like iconify/restore) won't work at all, as they're - // usually performed by the window manager + // and some things (like iconify/restore) won't work at all, as those + // are tasks usually performed by the window manager XSetWindowAttributes attributes; attributes.override_redirect = True; @@ -176,7 +161,7 @@ static GLboolean createWindow(_GLFWwindow* window, "WM_DELETE_WINDOW", False); - // Declare the WM protocols we support + // Declare the WM protocols supported by GLFW { int count = 0; Atom protocols[2]; @@ -187,8 +172,8 @@ static GLboolean createWindow(_GLFWwindow* window, protocols[count++] = _glfwLibrary.X11.wmDeleteWindow; // The _NET_WM_PING EWMH protocol - // Tells the WM to ping our window and flag us as unresponsive if we - // don't reply within a few seconds + // Tells the WM to ping the GLFW window and flag the application as + // unresponsive if the WM doesn't get a reply within a few seconds if (_glfwLibrary.X11.wmPing != None) protocols[count++] = _glfwLibrary.X11.wmPing; @@ -243,8 +228,7 @@ static GLboolean createWindow(_GLFWwindow* window, // Make sure the window is mapped before proceeding XMapWindow(_glfwLibrary.X11.display, window->X11.handle); - XPeekIfEvent(_glfwLibrary.X11.display, &event, isMapNotify, - (char*) window->X11.handle); + XFlush(_glfwLibrary.X11.display); return GL_TRUE; } @@ -295,7 +279,7 @@ static void captureCursor(_GLFWwindow* window) static void showCursor(_GLFWwindow* window) { - // Un-grab cursor (only in windowed mode: in fullscreen mode we still + // Un-grab cursor (in windowed mode only; in fullscreen mode we still // want the cursor grabbed in order to confine the cursor to the window // area) if (window->X11.cursorGrabbed) @@ -389,7 +373,7 @@ static void enterFullscreenMode(_GLFWwindow* window) } else if (window->X11.overrideRedirect) { - // In override-redirect mode, we have divorced ourselves from the + // In override-redirect mode we have divorced ourselves from the // window manager, so we need to do everything manually XRaiseWindow(_glfwLibrary.X11.display, window->X11.handle); @@ -417,7 +401,6 @@ static void leaveFullscreenMode(_GLFWwindow* window) { _glfwRestoreVideoMode(); - // Did we change the screen saver setting? if (_glfwLibrary.X11.saver.changed) { // Restore old screen saver settings @@ -494,17 +477,10 @@ static void processSingleEvent(void) // A keyboard key was pressed window = findWindow(event.xkey.window); if (window == NULL) - { - fprintf(stderr, "Cannot find GLFW window structure for KeyPress event\n"); return; - } - // Translate and report key press _glfwInputKey(window, translateKey(event.xkey.keycode), GLFW_PRESS); - - // Translate and report character input _glfwInputChar(window, translateChar(&event.xkey)); - break; } @@ -513,10 +489,7 @@ static void processSingleEvent(void) // A keyboard key was released window = findWindow(event.xkey.window); if (window == NULL) - { - fprintf(stderr, "Cannot find GLFW window structure for KeyRelease event\n"); return; - } // Do not report key releases for key repeats. For key repeats we // will get KeyRelease/KeyPress pairs with similar or identical @@ -544,9 +517,7 @@ static void processSingleEvent(void) } } - // Translate and report key release _glfwInputKey(window, translateKey(event.xkey.keycode), GLFW_RELEASE); - break; } @@ -555,10 +526,7 @@ static void processSingleEvent(void) // A mouse button was pressed or a scrolling event occurred window = findWindow(event.xbutton.window); if (window == NULL) - { - fprintf(stderr, "Cannot find GLFW window structure for ButtonPress event\n"); return; - } if (event.xbutton.button == Button1) _glfwInputMouseClick(window, GLFW_MOUSE_BUTTON_LEFT, GLFW_PRESS); @@ -587,10 +555,7 @@ static void processSingleEvent(void) // A mouse button was released window = findWindow(event.xbutton.window); if (window == NULL) - { - fprintf(stderr, "Cannot find GLFW window structure for ButtonRelease event\n"); return; - } if (event.xbutton.button == Button1) { @@ -618,10 +583,7 @@ static void processSingleEvent(void) // The cursor entered the window window = findWindow(event.xcrossing.window); if (window == NULL) - { - fprintf(stderr, "Cannot find GLFW window structure for EnterNotify event\n"); return; - } if (window->cursorMode == GLFW_CURSOR_HIDDEN) hideCursor(window); @@ -635,10 +597,7 @@ static void processSingleEvent(void) // The cursor left the window window = findWindow(event.xcrossing.window); if (window == NULL) - { - fprintf(stderr, "Cannot find GLFW window structure for LeaveNotify event\n"); return; - } if (window->cursorMode == GLFW_CURSOR_HIDDEN) showCursor(window); @@ -652,15 +611,13 @@ static void processSingleEvent(void) // The cursor was moved window = findWindow(event.xmotion.window); if (window == NULL) - { - fprintf(stderr, "Cannot find GLFW window structure for MotionNotify event\n"); return; - } if (event.xmotion.x != window->X11.cursorPosX || event.xmotion.y != window->X11.cursorPosY) { - // The cursor was moved and we didn't do it + // The cursor was moved by something other than GLFW + int x, y; if (window->cursorMode == GLFW_CURSOR_CAPTURED) @@ -692,10 +649,7 @@ static void processSingleEvent(void) // The window configuration changed somehow window = findWindow(event.xconfigure.window); if (window == NULL) - { - fprintf(stderr, "Cannot find GLFW window structure for ConfigureNotify event\n"); return; - } _glfwInputWindowSize(window, event.xconfigure.width, @@ -713,23 +667,20 @@ static void processSingleEvent(void) // Custom client message, probably from the window manager window = findWindow(event.xclient.window); if (window == NULL) - { - fprintf(stderr, "Cannot find GLFW window structure for ClientMessage event\n"); return; - } if ((Atom) event.xclient.data.l[0] == _glfwLibrary.X11.wmDeleteWindow) { // The window manager was asked to close the window, for example by // the user pressing a 'close' window decoration button - window->closeRequested = GL_TRUE; + _glfwInputWindowCloseRequest(window); } else if (_glfwLibrary.X11.wmPing != None && (Atom) event.xclient.data.l[0] == _glfwLibrary.X11.wmPing) { - // The window manager is pinging us to make sure we are still - // responding to events + // The window manager is pinging the application to ensure it's + // still responding to events event.xclient.window = _glfwLibrary.X11.root; XSendEvent(_glfwLibrary.X11.display, @@ -747,10 +698,7 @@ static void processSingleEvent(void) // The window was mapped window = findWindow(event.xmap.window); if (window == NULL) - { - fprintf(stderr, "Cannot find GLFW window structure for MapNotify event\n"); return; - } _glfwInputWindowIconify(window, GL_FALSE); break; @@ -761,10 +709,7 @@ static void processSingleEvent(void) // The window was unmapped window = findWindow(event.xmap.window); if (window == NULL) - { - fprintf(stderr, "Cannot find GLFW window structure for UnmapNotify event\n"); return; - } _glfwInputWindowIconify(window, GL_TRUE); break; @@ -775,10 +720,7 @@ static void processSingleEvent(void) // The window gained focus window = findWindow(event.xfocus.window); if (window == NULL) - { - fprintf(stderr, "Cannot find GLFW window structure for FocusIn event\n"); return; - } _glfwInputWindowFocus(window, GL_TRUE); @@ -793,10 +735,7 @@ static void processSingleEvent(void) // The window lost focus window = findWindow(event.xfocus.window); if (window == NULL) - { - fprintf(stderr, "Cannot find GLFW window structure for FocusOut event\n"); return; - } _glfwInputWindowFocus(window, GL_FALSE); @@ -811,10 +750,7 @@ static void processSingleEvent(void) // The window's contents was damaged window = findWindow(event.xexpose.window); if (window == NULL) - { - fprintf(stderr, "Cannot find GLFW window structure for Expose event\n"); return; - } _glfwInputWindowDamage(window); break; @@ -876,7 +812,6 @@ static void processSingleEvent(void) { case RRScreenChangeNotify: { - // Show XRandR that we really care XRRUpdateConfiguration(&event); break; } @@ -887,24 +822,6 @@ static void processSingleEvent(void) } } - -////////////////////////////////////////////////////////////////////////// -////// GLFW internal API ////// -////////////////////////////////////////////////////////////////////////// - -//======================================================================== -// Processes all pending events -//======================================================================== - -void _glfwProcessPendingEvents(void) -{ - int i, count = XPending(_glfwLibrary.X11.display); - - for (i = 0; i < count; i++) - processSingleEvent(); -} - - ////////////////////////////////////////////////////////////////////////// ////// GLFW platform API ////// ////////////////////////////////////////////////////////////////////////// @@ -914,12 +831,11 @@ void _glfwProcessPendingEvents(void) // the OpenGL rendering context is created //======================================================================== -int _glfwPlatformOpenWindow(_GLFWwindow* window, - const _GLFWwndconfig* wndconfig, - const _GLFWfbconfig* fbconfig) +int _glfwPlatformCreateWindow(_GLFWwindow* window, + const _GLFWwndconfig* wndconfig, + const _GLFWfbconfig* fbconfig) { window->refreshRate = wndconfig->refreshRate; - window->resizable = wndconfig->resizable; if (!_glfwCreateContext(window, wndconfig, fbconfig)) return GL_FALSE; @@ -942,9 +858,6 @@ int _glfwPlatformOpenWindow(_GLFWwindow* window, enterFullscreenMode(window); } - // Process the window map event and any other that may have arrived - _glfwProcessPendingEvents(); - // Retrieve and set initial cursor position { Window cursorWindow, cursorRoot; @@ -973,7 +886,7 @@ int _glfwPlatformOpenWindow(_GLFWwindow* window, // Properly kill the window/video display //======================================================================== -void _glfwPlatformCloseWindow(_GLFWwindow* window) +void _glfwPlatformDestroyWindow(_GLFWwindow* window) { if (window->mode == GLFW_FULLSCREEN) leaveFullscreenMode(window); @@ -1105,8 +1018,8 @@ void _glfwPlatformIconifyWindow(_GLFWwindow* window) { if (window->X11.overrideRedirect) { - // We can't iconify/restore override-redirect windows, as that's - // performed by the window manager + // Override-redirect windows cannot be iconified or restored, as those + // tasks are performed by the window manager return; } @@ -1124,8 +1037,8 @@ void _glfwPlatformRestoreWindow(_GLFWwindow* window) { if (window->X11.overrideRedirect) { - // We can't iconify/restore override-redirect windows, as that's - // performed by the window manager + // Override-redirect windows cannot be iconified or restored, as those + // tasks are performed by the window manager return; } @@ -1137,10 +1050,8 @@ void _glfwPlatformRestoreWindow(_GLFWwindow* window) // Read back framebuffer parameters from the context //======================================================================== -void _glfwPlatformRefreshWindowParams(void) +void _glfwPlatformRefreshWindowParams(_GLFWwindow* window) { - _GLFWwindow* window = _glfwLibrary.currentWindow; - // Retrieve refresh rate if possible if (_glfwLibrary.X11.RandR.available) { @@ -1231,7 +1142,7 @@ void _glfwPlatformWaitEvents(void) void _glfwPlatformSetCursorPos(_GLFWwindow* window, int x, int y) { - // Store the new position so we can recognise it later + // Store the new position so it can be recognized later window->X11.cursorPosX = x; window->X11.cursorPosY = y; diff --git a/examples/getopt.c b/support/getopt.c similarity index 97% rename from examples/getopt.c rename to support/getopt.c index 9d79b9a7..6ff6ef99 100644 --- a/examples/getopt.c +++ b/support/getopt.c @@ -41,7 +41,10 @@ #include #include "getopt.h" - +/* 2012-08-12 Lambert Clara + * + * Constify third argument of getopt. + */ /* 2011-07-27 Camilla Berglund * * Added _CRT_SECURE_NO_WARNINGS macro. @@ -51,7 +54,6 @@ * Removed unused global static variable 'ID'. */ - char* optarg = NULL; int optind = 0; int opterr = 1; @@ -103,7 +105,7 @@ static int permute_argv_once() } -int getopt(int argc, char** argv, char* optstr) +int getopt(int argc, char** argv, const char* optstr) { int c = 0; diff --git a/tests/getopt.h b/support/getopt.h similarity index 97% rename from tests/getopt.h rename to support/getopt.h index 0b78650a..6d2e4afe 100644 --- a/tests/getopt.h +++ b/support/getopt.h @@ -48,7 +48,7 @@ extern int optind; extern int opterr; extern int optopt; -int getopt(int argc, char** argv, char* optstr); +int getopt(int argc, char** argv, const char* optstr); #ifdef __cplusplus diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 55862fac..bcad7ef5 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -12,16 +12,19 @@ include_directories(${GLFW_SOURCE_DIR}/include ${GLFW_SOURCE_DIR}/support ${OPENGL_INCLUDE_DIR}) -add_executable(clipboard clipboard.c getopt.c) +set(GETOPT ${GLFW_SOURCE_DIR}/support/getopt.h + ${GLFW_SOURCE_DIR}/support/getopt.c) + +add_executable(clipboard clipboard.c ${GETOPT}) add_executable(defaults defaults.c) add_executable(events events.c) -add_executable(fsaa fsaa.c getopt.c) +add_executable(fsaa fsaa.c ${GETOPT}) add_executable(fsfocus fsfocus.c) -add_executable(gamma gamma.c getopt.c) -add_executable(glfwinfo glfwinfo.c getopt.c) -add_executable(iconify iconify.c getopt.c) +add_executable(gamma gamma.c ${GETOPT}) +add_executable(glfwinfo glfwinfo.c ${GETOPT}) +add_executable(iconify iconify.c ${GETOPT}) add_executable(joysticks joysticks.c) -add_executable(modes modes.c getopt.c) +add_executable(modes modes.c ${GETOPT}) add_executable(peter peter.c) add_executable(reopen reopen.c) diff --git a/tests/accuracy.c b/tests/accuracy.c index cfb70271..f3fb752b 100644 --- a/tests/accuracy.c +++ b/tests/accuracy.c @@ -37,6 +37,19 @@ static int cursor_x = 0, cursor_y = 0; static int window_width = 640, window_height = 480; +static int swap_interval = 1; + +static void set_swap_interval(GLFWwindow window, int interval) +{ + char title[256]; + + swap_interval = interval; + glfwSwapInterval(swap_interval); + + sprintf(title, "Cursor Inaccuracy Detector (interval %i)", swap_interval); + + glfwSetWindowTitle(window, title); +} static void window_size_callback(GLFWwindow window, int width, int height) { @@ -56,9 +69,16 @@ static void cursor_position_callback(GLFWwindow window, int x, int y) cursor_y = y; } +static void key_callback(GLFWwindow window, int key, int action) +{ + if (key == GLFW_KEY_SPACE && action == GLFW_PRESS) + set_swap_interval(window, 1 - swap_interval); +} + int main(void) { GLFWwindow window; + int width, height; if (!glfwInit()) { @@ -66,7 +86,11 @@ int main(void) exit(EXIT_FAILURE); } - window = glfwOpenWindow(window_width, window_height, GLFW_WINDOWED, "Cursor Inaccuracy Detector", NULL); + glfwSetCursorPosCallback(cursor_position_callback); + glfwSetWindowSizeCallback(window_size_callback); + glfwSetKeyCallback(key_callback); + + window = glfwCreateWindow(window_width, window_height, GLFW_WINDOWED, "", NULL); if (!window) { glfwTerminate(); @@ -75,11 +99,14 @@ int main(void) exit(EXIT_FAILURE); } - glfwSetCursorPosCallback(cursor_position_callback); - glfwSetWindowSizeCallback(window_size_callback); - glfwSwapInterval(1); + glfwMakeContextCurrent(window); - while (glfwIsWindow(window)) + glfwGetWindowSize(window, &width, &height); + window_size_callback(window, width, height); + + set_swap_interval(window, swap_interval); + + while (!glfwGetWindowParam(window, GLFW_CLOSE_REQUESTED)) { glClear(GL_COLOR_BUFFER_BIT); @@ -90,7 +117,7 @@ int main(void) glVertex2f((GLfloat) cursor_x, (GLfloat) window_height); glEnd(); - glfwSwapBuffers(); + glfwSwapBuffers(window); glfwPollEvents(); } diff --git a/tests/clipboard.c b/tests/clipboard.c index 3b732290..fcd1c307 100644 --- a/tests/clipboard.c +++ b/tests/clipboard.c @@ -53,7 +53,7 @@ static void key_callback(GLFWwindow window, int key, int action) switch (key) { case GLFW_KEY_ESCAPE: - glfwCloseWindow(window); + glfwDestroyWindow(window); break; case GLFW_KEY_V: @@ -117,7 +117,7 @@ int main(int argc, char** argv) exit(EXIT_FAILURE); } - window = glfwOpenWindow(0, 0, GLFW_WINDOWED, "Clipboard Test", NULL); + window = glfwCreateWindow(0, 0, GLFW_WINDOWED, "Clipboard Test", NULL); if (!window) { glfwTerminate(); @@ -126,7 +126,9 @@ int main(int argc, char** argv) exit(EXIT_FAILURE); } + glfwMakeContextCurrent(window); glfwSwapInterval(1); + glfwSetKeyCallback(key_callback); glfwSetWindowSizeCallback(size_callback); @@ -136,14 +138,14 @@ int main(int argc, char** argv) glClearColor(0.5f, 0.5f, 0.5f, 0); - while (glfwIsWindow(window)) + while (!glfwGetWindowParam(window, GLFW_CLOSE_REQUESTED)) { glClear(GL_COLOR_BUFFER_BIT); glColor3f(0.8f, 0.2f, 0.4f); glRectf(-0.5f, -0.5f, 0.5f, 0.5f); - glfwSwapBuffers(); + glfwSwapBuffers(window); glfwWaitEvents(); } diff --git a/tests/defaults.c b/tests/defaults.c index 16c62723..391b4984 100644 --- a/tests/defaults.c +++ b/tests/defaults.c @@ -30,6 +30,7 @@ //======================================================================== #include +#include #include #include @@ -37,30 +38,38 @@ typedef struct { int param; - char* name; -} Param; + const char* ext; + const char* name; +} ParamGL; -static Param parameters[] = +typedef struct +{ + int param; + const char* name; +} ParamGLFW; + +static ParamGL gl_params[] = +{ + { GL_RED_BITS, NULL, "red bits" }, + { GL_GREEN_BITS, NULL, "green bits" }, + { GL_BLUE_BITS, NULL, "blue bits" }, + { GL_ALPHA_BITS, NULL, "alpha bits" }, + { GL_DEPTH_BITS, NULL, "depth bits" }, + { GL_STENCIL_BITS, NULL, "stencil bits" }, + { GL_STEREO, NULL, "stereo" }, + { GL_SAMPLES_ARB, "GL_ARB_multisample", "FSAA samples" }, + { 0, NULL, NULL } +}; + +static ParamGLFW glfw_params[] = { - { GLFW_RED_BITS, "red bits" }, - { GLFW_GREEN_BITS, "green bits" }, - { GLFW_BLUE_BITS, "blue bits" }, - { GLFW_ALPHA_BITS, "alpha bits" }, - { GLFW_DEPTH_BITS, "depth bits" }, - { GLFW_STENCIL_BITS, "stencil bits" }, { GLFW_REFRESH_RATE, "refresh rate" }, - { GLFW_ACCUM_RED_BITS, "accum red bits" }, - { GLFW_ACCUM_GREEN_BITS, "accum green bits" }, - { GLFW_ACCUM_BLUE_BITS, "accum blue bits" }, - { GLFW_ACCUM_ALPHA_BITS, "accum alpha bits" }, - { GLFW_AUX_BUFFERS, "aux buffers" }, - { GLFW_STEREO, "stereo" }, - { GLFW_FSAA_SAMPLES, "FSAA samples" }, { GLFW_OPENGL_VERSION_MAJOR, "OpenGL major" }, { GLFW_OPENGL_VERSION_MINOR, "OpenGL minor" }, { GLFW_OPENGL_FORWARD_COMPAT, "OpenGL forward compatible" }, { GLFW_OPENGL_DEBUG_CONTEXT, "OpenGL debug context" }, { GLFW_OPENGL_PROFILE, "OpenGL profile" }, + { 0, NULL } }; int main(void) @@ -74,7 +83,7 @@ int main(void) exit(EXIT_FAILURE); } - window = glfwOpenWindow(0, 0, GLFW_WINDOWED, "Defaults", NULL); + window = glfwCreateWindow(0, 0, GLFW_WINDOWED, "Defaults", NULL); if (!window) { glfwTerminate(); @@ -83,18 +92,34 @@ int main(void) exit(EXIT_FAILURE); } + glfwMakeContextCurrent(window); glfwGetWindowSize(window, &width, &height); printf("window size: %ix%i\n", width, height); - for (i = 0; (size_t) i < sizeof(parameters) / sizeof(parameters[0]); i++) + for (i = 0; glfw_params[i].name; i++) { printf("%s: %i\n", - parameters[i].name, - glfwGetWindowParam(window, parameters[i].param)); + glfw_params[i].name, + glfwGetWindowParam(window, glfw_params[i].param)); } - glfwCloseWindow(window); + for (i = 0; gl_params[i].name; i++) + { + GLint value = 0; + + if (gl_params[i].ext) + { + if (!glfwExtensionSupported(gl_params[i].ext)) + continue; + } + + glGetIntegerv(gl_params[i].param, &value); + + printf("%s: %i\n", gl_params[i].name, value); + } + + glfwDestroyWindow(window); window = NULL; glfwTerminate(); diff --git a/tests/events.c b/tests/events.c index 8ab54266..809da473 100644 --- a/tests/events.c +++ b/tests/events.c @@ -40,9 +40,12 @@ #include #include +// These must match the input mode defaults static GLboolean keyrepeat = GL_FALSE; static GLboolean systemkeys = GL_TRUE; static GLboolean closeable = GL_TRUE; + +// Event index static unsigned int counter = 0; static const char* get_key_name(int key) @@ -231,6 +234,7 @@ static void window_size_callback(GLFWwindow window, int width, int height) static int window_close_callback(GLFWwindow window) { printf("%08x at %0.3f: Window close\n", counter++, glfwGetTime()); + return closeable; } @@ -238,8 +242,11 @@ static void window_refresh_callback(GLFWwindow window) { printf("%08x at %0.3f: Window refresh\n", counter++, glfwGetTime()); - glClear(GL_COLOR_BUFFER_BIT); - glfwSwapBuffers(); + if (glfwGetCurrentContext()) + { + glClear(GL_COLOR_BUFFER_BIT); + glfwSwapBuffers(window); + } } static void window_focus_callback(GLFWwindow window, int activated) @@ -344,6 +351,7 @@ static void char_callback(GLFWwindow window, int character) int main(void) { GLFWwindow window; + int width, height; setlocale(LC_ALL, ""); @@ -367,7 +375,7 @@ int main(void) glfwSetKeyCallback(key_callback); glfwSetCharCallback(char_callback); - window = glfwOpenWindow(0, 0, GLFW_WINDOWED, "Event Linter", NULL); + window = glfwCreateWindow(0, 0, GLFW_WINDOWED, "Event Linter", NULL); if (!window) { glfwTerminate(); @@ -378,14 +386,18 @@ int main(void) printf("Window opened\n"); + glfwMakeContextCurrent(window); glfwSwapInterval(1); + glfwGetWindowSize(window, &width, &height); + printf("Window size should be %ix%i\n", width, height); + printf("Key repeat should be %s\n", keyrepeat ? "enabled" : "disabled"); printf("System keys should be %s\n", systemkeys ? "enabled" : "disabled"); printf("Main loop starting\n"); - while (glfwIsWindow(window) == GL_TRUE) + while (!glfwGetWindowParam(window, GLFW_CLOSE_REQUESTED)) glfwWaitEvents(); glfwTerminate(); diff --git a/tests/fsaa.c b/tests/fsaa.c index 9c45ddcc..8fc8b60a 100644 --- a/tests/fsaa.c +++ b/tests/fsaa.c @@ -96,9 +96,9 @@ int main(int argc, char** argv) glfwSetKeyCallback(key_callback); glfwSetWindowSizeCallback(window_size_callback); - glfwOpenWindowHint(GLFW_FSAA_SAMPLES, samples); + glfwWindowHint(GLFW_FSAA_SAMPLES, samples); - window = glfwOpenWindow(800, 400, GLFW_WINDOWED, "Aliasing Detector", NULL); + window = glfwCreateWindow(800, 400, GLFW_WINDOWED, "Aliasing Detector", NULL); if (!window) { glfwTerminate(); @@ -107,6 +107,9 @@ int main(int argc, char** argv) exit(EXIT_FAILURE); } + glfwMakeContextCurrent(window); + glfwSwapInterval(1); + if (!glfwExtensionSupported("GL_ARB_multisample")) { glfwTerminate(); @@ -115,9 +118,7 @@ int main(int argc, char** argv) exit(EXIT_FAILURE); } - glfwSwapInterval(1); - - samples = glfwGetWindowParam(window, GLFW_FSAA_SAMPLES); + glGetIntegerv(GL_SAMPLES_ARB, &samples); if (samples) printf("Context reports FSAA is available with %i samples\n", samples); else @@ -127,7 +128,7 @@ int main(int argc, char** argv) gluOrtho2D(0.f, 1.f, 0.f, 0.5f); glMatrixMode(GL_MODELVIEW); - while (glfwIsWindow(window)) + while (!glfwGetWindowParam(window, GLFW_CLOSE_REQUESTED)) { GLfloat time = (GLfloat) glfwGetTime(); @@ -147,7 +148,7 @@ int main(int argc, char** argv) glEnable(GL_MULTISAMPLE_ARB); glRectf(-0.15f, -0.15f, 0.15f, 0.15f); - glfwSwapBuffers(); + glfwSwapBuffers(window); glfwPollEvents(); } diff --git a/tests/fsfocus.c b/tests/fsfocus.c index 951409a6..1c46d7af 100644 --- a/tests/fsfocus.c +++ b/tests/fsfocus.c @@ -68,6 +68,7 @@ static void window_key_callback(GLFWwindow window, int key, int action) static int window_close_callback(GLFWwindow window) { printf("%0.3f: User closed window\n", glfwGetTime()); + running = GL_FALSE; return GL_TRUE; } @@ -81,7 +82,7 @@ int main(void) exit(EXIT_FAILURE); } - window = glfwOpenWindow(640, 480, GLFW_FULLSCREEN, "Fullscreen focus", NULL); + window = glfwCreateWindow(640, 480, GLFW_FULLSCREEN, "Fullscreen focus", NULL); if (!window) { glfwTerminate(); @@ -90,17 +91,19 @@ int main(void) exit(EXIT_FAILURE); } + glfwMakeContextCurrent(window); glfwSwapInterval(1); + glfwSetInputMode(window, GLFW_CURSOR_MODE, GLFW_CURSOR_NORMAL); glfwSetWindowFocusCallback(window_focus_callback); glfwSetKeyCallback(window_key_callback); glfwSetWindowCloseCallback(window_close_callback); - while (running && glfwIsWindow(window) == GL_TRUE) + while (running) { glClear(GL_COLOR_BUFFER_BIT); - glfwSwapBuffers(); + glfwSwapBuffers(window); glfwWaitEvents(); } diff --git a/tests/gamma.c b/tests/gamma.c index b8ec6c45..e74d5b43 100644 --- a/tests/gamma.c +++ b/tests/gamma.c @@ -37,7 +37,7 @@ #define STEP_SIZE 0.1f -static GLfloat gamma = 1.0f; +static GLfloat gamma_value = 1.0f; static void usage(void) { @@ -46,9 +46,9 @@ static void usage(void) static void set_gamma(float value) { - gamma = value; - printf("Gamma: %f\n", gamma); - glfwSetGamma(gamma); + gamma_value = value; + printf("Gamma: %f\n", gamma_value); + glfwSetGamma(gamma_value); } static void key_callback(GLFWwindow window, int key, int action) @@ -60,22 +60,22 @@ static void key_callback(GLFWwindow window, int key, int action) { case GLFW_KEY_ESCAPE: { - glfwCloseWindow(window); + glfwDestroyWindow(window); break; } case GLFW_KEY_KP_ADD: case GLFW_KEY_Q: { - set_gamma(gamma + STEP_SIZE); + set_gamma(gamma_value + STEP_SIZE); break; } case GLFW_KEY_KP_SUBTRACT: case GLFW_KEY_W: { - if (gamma - STEP_SIZE > 0.f) - set_gamma(gamma - STEP_SIZE); + if (gamma_value - STEP_SIZE > 0.f) + set_gamma(gamma_value - STEP_SIZE); break; } @@ -119,10 +119,10 @@ int main(int argc, char** argv) if (mode == GLFW_FULLSCREEN) { - GLFWvidmode mode; - glfwGetDesktopMode(&mode); - width = mode.width; - height = mode.height; + GLFWvidmode desktop_mode; + glfwGetDesktopMode(&desktop_mode); + width = desktop_mode.width; + height = desktop_mode.height; } else { @@ -130,7 +130,7 @@ int main(int argc, char** argv) height = 0; } - window = glfwOpenWindow(width, height, mode, "Gamma Test", NULL); + window = glfwCreateWindow(width, height, mode, "Gamma Test", NULL); if (!window) { glfwTerminate(); @@ -141,7 +141,9 @@ int main(int argc, char** argv) set_gamma(1.f); + glfwMakeContextCurrent(window); glfwSwapInterval(1); + glfwSetKeyCallback(key_callback); glfwSetWindowSizeCallback(size_callback); @@ -151,14 +153,14 @@ int main(int argc, char** argv) glClearColor(0.5f, 0.5f, 0.5f, 0); - while (glfwIsWindow(window)) + while (!glfwGetWindowParam(window, GLFW_CLOSE_REQUESTED)) { glClear(GL_COLOR_BUFFER_BIT); glColor3f(0.8f, 0.2f, 0.4f); glRectf(-0.5f, -0.5f, 0.5f, 0.5f); - glfwSwapBuffers(); + glfwSwapBuffers(window); glfwPollEvents(); } diff --git a/tests/getopt.c b/tests/getopt.c deleted file mode 100644 index 712cf28a..00000000 --- a/tests/getopt.c +++ /dev/null @@ -1,258 +0,0 @@ -/***************************************************************************** -* getopt.c - competent and free getopt library. -* $Header: /cvsroot/freegetopt/freegetopt/getopt.c,v 1.2 2003/10/26 03:10:20 vindaci Exp $ -* -* Copyright (c)2002-2003 Mark K. Kim -* All rights reserved. -* -* Redistribution and use in source and binary forms, with or without -* modification, are permitted provided that the following conditions -* are met: -* -* * Redistributions of source code must retain the above copyright -* notice, this list of conditions and the following disclaimer. -* -* * Redistributions in binary form must reproduce the above copyright -* notice, this list of conditions and the following disclaimer in -* the documentation and/or other materials provided with the -* distribution. -* -* * Neither the original author of this software nor the names of its -* contributors may be used to endorse or promote products derived -* from this software without specific prior written permission. -* -* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS -* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED -* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -* THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -* DAMAGE. -*/ -#define _CRT_SECURE_NO_WARNINGS - -#include -#include -#include -#include "getopt.h" - - -/* 2011-07-27 Camilla Berglund - * - * Added _CRT_SECURE_NO_WARNINGS macro. - */ -/* 2009-10-12 Camilla Berglund - * - * Removed unused global static variable 'ID'. - */ - -char* optarg = NULL; -int optind = 0; -int opterr = 1; -int optopt = '?'; - - -static char** prev_argv = NULL; /* Keep a copy of argv and argc to */ -static int prev_argc = 0; /* tell if getopt params change */ -static int argv_index = 0; /* Option we're checking */ -static int argv_index2 = 0; /* Option argument we're checking */ -static int opt_offset = 0; /* Index into compounded "-option" */ -static int dashdash = 0; /* True if "--" option reached */ -static int nonopt = 0; /* How many nonopts we've found */ - -static void increment_index() -{ - /* Move onto the next option */ - if(argv_index < argv_index2) - { - while(prev_argv[++argv_index] && prev_argv[argv_index][0] != '-' - && argv_index < argv_index2+1); - } - else argv_index++; - opt_offset = 1; -} - - -/* -* Permutes argv[] so that the argument currently being processed is moved -* to the end. -*/ -static int permute_argv_once() -{ - /* Movability check */ - if(argv_index + nonopt >= prev_argc) return 1; - /* Move the current option to the end, bring the others to front */ - else - { - char* tmp = prev_argv[argv_index]; - - /* Move the data */ - memmove(&prev_argv[argv_index], &prev_argv[argv_index+1], - sizeof(char**) * (prev_argc - argv_index - 1)); - prev_argv[prev_argc - 1] = tmp; - - nonopt++; - return 0; - } -} - - -int getopt(int argc, char** argv, char* optstr) -{ - int c = 0; - - /* If we have new argv, reinitialize */ - if(prev_argv != argv || prev_argc != argc) - { - /* Initialize variables */ - prev_argv = argv; - prev_argc = argc; - argv_index = 1; - argv_index2 = 1; - opt_offset = 1; - dashdash = 0; - nonopt = 0; - } - - /* Jump point in case we want to ignore the current argv_index */ - getopt_top: - - /* Misc. initializations */ - optarg = NULL; - - /* Dash-dash check */ - if(argv[argv_index] && !strcmp(argv[argv_index], "--")) - { - dashdash = 1; - increment_index(); - } - - /* If we're at the end of argv, that's it. */ - if(argv[argv_index] == NULL) - { - c = -1; - } - /* Are we looking at a string? Single dash is also a string */ - else if(dashdash || argv[argv_index][0] != '-' || !strcmp(argv[argv_index], "-")) - { - /* If we want a string... */ - if(optstr[0] == '-') - { - c = 1; - optarg = argv[argv_index]; - increment_index(); - } - /* If we really don't want it (we're in POSIX mode), we're done */ - else if(optstr[0] == '+' || getenv("POSIXLY_CORRECT")) - { - c = -1; - - /* Everything else is a non-opt argument */ - nonopt = argc - argv_index; - } - /* If we mildly don't want it, then move it back */ - else - { - if(!permute_argv_once()) goto getopt_top; - else c = -1; - } - } - /* Otherwise we're looking at an option */ - else - { - char* opt_ptr = NULL; - - /* Grab the option */ - c = argv[argv_index][opt_offset++]; - - /* Is the option in the optstr? */ - if(optstr[0] == '-') opt_ptr = strchr(optstr+1, c); - else opt_ptr = strchr(optstr, c); - /* Invalid argument */ - if(!opt_ptr) - { - if(opterr) - { - fprintf(stderr, "%s: invalid option -- %c\n", argv[0], c); - } - - optopt = c; - c = '?'; - - /* Move onto the next option */ - increment_index(); - } - /* Option takes argument */ - else if(opt_ptr[1] == ':') - { - /* ie, -oARGUMENT, -xxxoARGUMENT, etc. */ - if(argv[argv_index][opt_offset] != '\0') - { - optarg = &argv[argv_index][opt_offset]; - increment_index(); - } - /* ie, -o ARGUMENT (only if it's a required argument) */ - else if(opt_ptr[2] != ':') - { - /* One of those "you're not expected to understand this" moment */ - if(argv_index2 < argv_index) argv_index2 = argv_index; - while(argv[++argv_index2] && argv[argv_index2][0] == '-'); - optarg = argv[argv_index2]; - - /* Don't cross into the non-option argument list */ - if(argv_index2 + nonopt >= prev_argc) optarg = NULL; - - /* Move onto the next option */ - increment_index(); - } - else - { - /* Move onto the next option */ - increment_index(); - } - - /* In case we got no argument for an option with required argument */ - if(optarg == NULL && opt_ptr[2] != ':') - { - optopt = c; - c = '?'; - - if(opterr) - { - fprintf(stderr,"%s: option requires an argument -- %c\n", - argv[0], optopt); - } - } - } - /* Option does not take argument */ - else - { - /* Next argv_index */ - if(argv[argv_index][opt_offset] == '\0') - { - increment_index(); - } - } - } - - /* Calculate optind */ - if(c == -1) - { - optind = argc - nonopt; - } - else - { - optind = argv_index; - } - - return c; -} - - -/* vim:ts=3 -*/ diff --git a/tests/glfwinfo.c b/tests/glfwinfo.c index 762d855c..b889d9b6 100644 --- a/tests/glfwinfo.c +++ b/tests/glfwinfo.c @@ -120,6 +120,32 @@ static void list_extensions(int api, int major, int minor) putchar('\n'); } +static GLboolean valid_version(void) +{ + int major, minor, revision; + + glfwGetVersion(&major, &minor, &revision); + + printf("GLFW header version: %u.%u.%u\n", + GLFW_VERSION_MAJOR, + GLFW_VERSION_MINOR, + GLFW_VERSION_REVISION); + + printf("GLFW library version: %u.%u.%u\n", major, minor, revision); + + if (major != GLFW_VERSION_MAJOR) + { + printf("*** ERROR: GLFW major version mismatch! ***\n"); + return GL_FALSE; + } + + if (minor != GLFW_VERSION_MINOR || revision != GLFW_VERSION_REVISION) + printf("*** WARNING: GLFW version mismatch! ***\n"); + + printf("GLFW library version string: \"%s\"\n", glfwGetVersionString()); + return GL_TRUE; +} + int main(int argc, char** argv) { int ch, api = 0, profile = 0, strategy = 0, major = 1, minor = 0, revision; @@ -127,6 +153,9 @@ int main(int argc, char** argv) GLint flags, mask; GLFWwindow window; + if (!valid_version()) + exit(EXIT_FAILURE); + while ((ch = getopt(argc, argv, "a:dfhlm:n:p:r:")) != -1) { switch (ch) @@ -190,6 +219,8 @@ int main(int argc, char** argv) argc -= optind; argv += optind; + // Initialize GLFW and create window + glfwSetErrorCallback(error_callback); if (!glfwInit()) @@ -200,51 +231,33 @@ int main(int argc, char** argv) if (major != 1 || minor != 0) { - glfwOpenWindowHint(GLFW_OPENGL_VERSION_MAJOR, major); - glfwOpenWindowHint(GLFW_OPENGL_VERSION_MINOR, minor); + glfwWindowHint(GLFW_OPENGL_VERSION_MAJOR, major); + glfwWindowHint(GLFW_OPENGL_VERSION_MINOR, minor); } if (api != 0) - glfwOpenWindowHint(GLFW_CLIENT_API, api); + glfwWindowHint(GLFW_CLIENT_API, api); if (debug) - glfwOpenWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE); + glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE); if (forward) - glfwOpenWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); + glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); if (profile != 0) - glfwOpenWindowHint(GLFW_OPENGL_PROFILE, profile); + glfwWindowHint(GLFW_OPENGL_PROFILE, profile); if (strategy) - glfwOpenWindowHint(GLFW_OPENGL_ROBUSTNESS, strategy); + glfwWindowHint(GLFW_OPENGL_ROBUSTNESS, strategy); // We assume here that we stand a better chance of success by leaving all // possible details of pixel format selection to GLFW - window = glfwOpenWindow(0, 0, GLFW_WINDOWED, "Version", NULL); + window = glfwCreateWindow(0, 0, GLFW_WINDOWED, "Version", NULL); if (!window) exit(EXIT_FAILURE); - // Report GLFW version - - glfwGetVersion(&major, &minor, &revision); - - printf("GLFW header version: %u.%u.%u\n", - GLFW_VERSION_MAJOR, - GLFW_VERSION_MINOR, - GLFW_VERSION_REVISION); - - printf("GLFW library version: %u.%u.%u\n", major, minor, revision); - - if (major != GLFW_VERSION_MAJOR || - minor != GLFW_VERSION_MINOR || - revision != GLFW_VERSION_REVISION) - { - printf("*** WARNING: GLFW version mismatch! ***\n"); - } - - printf("GLFW library version string: \"%s\"\n", glfwGetVersionString()); + glfwMakeContextCurrent(window); // Report client API version diff --git a/tests/iconify.c b/tests/iconify.c index dbc4d9cf..33b6f058 100644 --- a/tests/iconify.c +++ b/tests/iconify.c @@ -55,7 +55,7 @@ static void key_callback(GLFWwindow window, int key, int action) glfwIconifyWindow(window); break; case GLFW_KEY_ESCAPE: - glfwCloseWindow(window); + glfwDestroyWindow(window); break; } } @@ -100,10 +100,10 @@ int main(int argc, char** argv) if (mode == GLFW_FULLSCREEN) { - GLFWvidmode mode; - glfwGetDesktopMode(&mode); - width = mode.width; - height = mode.height; + GLFWvidmode desktop_mode; + glfwGetDesktopMode(&desktop_mode); + width = desktop_mode.width; + height = desktop_mode.height; } else { @@ -111,7 +111,7 @@ int main(int argc, char** argv) height = 0; } - window = glfwOpenWindow(width, height, mode, "Iconify", NULL); + window = glfwCreateWindow(width, height, mode, "Iconify", NULL); if (!window) { glfwTerminate(); @@ -120,16 +120,16 @@ int main(int argc, char** argv) exit(EXIT_FAILURE); } + glfwMakeContextCurrent(window); glfwSwapInterval(1); + glfwSetKeyCallback(key_callback); glfwSetWindowSizeCallback(size_callback); glEnable(GL_SCISSOR_TEST); - while (glfwIsWindow(window)) + while (!glfwGetWindowParam(window, GLFW_CLOSE_REQUESTED)) { - int width, height; - if (iconified != glfwGetWindowParam(window, GLFW_ICONIFIED) || active != glfwGetWindowParam(window, GLFW_ACTIVE)) { @@ -152,7 +152,7 @@ int main(int argc, char** argv) glClearColor(1, 1, 1, 0); glClear(GL_COLOR_BUFFER_BIT); - glfwSwapBuffers(); + glfwSwapBuffers(window); glfwPollEvents(); } diff --git a/tests/joysticks.c b/tests/joysticks.c index 2f208d2b..40202ce7 100644 --- a/tests/joysticks.c +++ b/tests/joysticks.c @@ -44,7 +44,6 @@ typedef struct Joystick } Joystick; static Joystick joysticks[GLFW_JOYSTICK_LAST - GLFW_JOYSTICK_1 + 1]; - static int joystick_count = 0; static void window_size_callback(GLFWwindow window, int width, int height) @@ -138,7 +137,7 @@ static void refresh_joysticks(void) j->axes = realloc(j->axes, j->axis_count * sizeof(float)); } - glfwGetJoystickPos(GLFW_JOYSTICK_1 + i, j->axes, j->axis_count); + glfwGetJoystickAxes(GLFW_JOYSTICK_1 + i, j->axes, j->axis_count); button_count = glfwGetJoystickParam(GLFW_JOYSTICK_1 + i, GLFW_BUTTONS); if (button_count != j->button_count) @@ -187,7 +186,7 @@ int main(void) exit(EXIT_FAILURE); } - window = glfwOpenWindow(0, 0, GLFW_WINDOWED, "Joystick Test", NULL); + window = glfwCreateWindow(0, 0, GLFW_WINDOWED, "Joystick Test", NULL); if (!window) { glfwTerminate(); @@ -197,16 +196,18 @@ int main(void) } glfwSetWindowSizeCallback(window_size_callback); + + glfwMakeContextCurrent(window); glfwSwapInterval(1); - while (glfwIsWindow(window)) + while (!glfwGetWindowParam(window, GLFW_CLOSE_REQUESTED)) { glClear(GL_COLOR_BUFFER_BIT); refresh_joysticks(); draw_joysticks(); - glfwSwapBuffers(); + glfwSwapBuffers(window); glfwPollEvents(); } diff --git a/tests/modes.c b/tests/modes.c index 3a384003..5ce65abb 100644 --- a/tests/modes.c +++ b/tests/modes.c @@ -53,11 +53,11 @@ static const char* format_mode(GLFWvidmode* mode) { static char buffer[512]; - snprintf(buffer, sizeof(buffer), - "%i x %i x %i (%i %i %i)", - mode->width, mode->height, - mode->redBits + mode->greenBits + mode->blueBits, - mode->redBits, mode->greenBits, mode->blueBits); + sprintf(buffer, + "%i x %i x %i (%i %i %i)", + mode->width, mode->height, + mode->redBits + mode->greenBits + mode->blueBits, + mode->redBits, mode->greenBits, mode->blueBits); buffer[sizeof(buffer) - 1] = '\0'; return buffer; @@ -68,7 +68,7 @@ static void error_callback(int error, const char* description) fprintf(stderr, "Error: %s\n", description); } -static void window_size_callback(GLFWwindow window, int width, int height) +static void window_size_callback(GLFWwindow in_window, int width, int height) { printf("Window resized to %ix%i\n", width, height); @@ -85,34 +85,16 @@ static void key_callback(GLFWwindow dummy, int key, int action) { if (key == GLFW_KEY_ESCAPE) { - glfwCloseWindow(window); + glfwDestroyWindow(window); window = NULL; } } -static GLFWvidmode* get_video_modes(size_t* found) -{ - size_t count = 0; - GLFWvidmode* modes = NULL; - - for (;;) - { - count += 256; - modes = realloc(modes, sizeof(GLFWvidmode) * count); - - *found = glfwGetVideoModes(modes, count); - if (*found < count) - break; - } - - return modes; -} - static void list_modes(void) { - size_t count, i; + int count, i; GLFWvidmode desktop_mode; - GLFWvidmode* modes = get_video_modes(&count); + GLFWvidmode* modes = glfwGetVideoModes(&count); glfwGetDesktopMode(&desktop_mode); printf("Desktop mode: %s\n", format_mode(&desktop_mode)); @@ -128,15 +110,12 @@ static void list_modes(void) putchar('\n'); } - - free(modes); } static void test_modes(void) { - int width, height; - size_t i, count; - GLFWvidmode* modes = get_video_modes(&count); + int i, count; + GLFWvidmode* modes = glfwGetVideoModes(&count); glfwSetWindowSizeCallback(window_size_callback); glfwSetWindowCloseCallback(window_close_callback); @@ -145,16 +124,17 @@ static void test_modes(void) for (i = 0; i < count; i++) { GLFWvidmode* mode = modes + i; + GLFWvidmode current; - glfwOpenWindowHint(GLFW_RED_BITS, mode->redBits); - glfwOpenWindowHint(GLFW_GREEN_BITS, mode->greenBits); - glfwOpenWindowHint(GLFW_BLUE_BITS, mode->blueBits); + glfwWindowHint(GLFW_RED_BITS, mode->redBits); + glfwWindowHint(GLFW_GREEN_BITS, mode->greenBits); + glfwWindowHint(GLFW_BLUE_BITS, mode->blueBits); printf("Testing mode %u: %s", (unsigned int) i, format_mode(mode)); - window = glfwOpenWindow(mode->width, mode->height, - GLFW_FULLSCREEN, "Video Mode Test", - NULL); + window = glfwCreateWindow(mode->width, mode->height, + GLFW_FULLSCREEN, "Video Mode Test", + NULL); if (!window) { printf("Failed to enter mode %u: %s\n", @@ -163,13 +143,15 @@ static void test_modes(void) continue; } - glfwSetTime(0.0); + glfwMakeContextCurrent(window); glfwSwapInterval(1); + glfwSetTime(0.0); + while (glfwGetTime() < 5.0) { glClear(GL_COLOR_BUFFER_BIT); - glfwSwapBuffers(); + glfwSwapBuffers(window); glfwPollEvents(); if (!window) @@ -179,36 +161,34 @@ static void test_modes(void) } } - if (glfwGetWindowParam(window, GLFW_RED_BITS) != mode->redBits || - glfwGetWindowParam(window, GLFW_GREEN_BITS) != mode->greenBits || - glfwGetWindowParam(window, GLFW_BLUE_BITS) != mode->blueBits) + glGetIntegerv(GL_RED_BITS, ¤t.redBits); + glGetIntegerv(GL_GREEN_BITS, ¤t.greenBits); + glGetIntegerv(GL_BLUE_BITS, ¤t.blueBits); + + glfwGetWindowSize(window, ¤t.width, ¤t.height); + + if (current.redBits != mode->redBits || + current.greenBits != mode->greenBits || + current.blueBits != mode->blueBits) { printf("*** Color bit mismatch: (%i %i %i) instead of (%i %i %i)\n", - glfwGetWindowParam(window, GLFW_RED_BITS), - glfwGetWindowParam(window, GLFW_GREEN_BITS), - glfwGetWindowParam(window, GLFW_BLUE_BITS), - mode->redBits, - mode->greenBits, - mode->blueBits); + current.redBits, current.greenBits, current.blueBits, + mode->redBits, mode->greenBits, mode->blueBits); } - glfwGetWindowSize(window, &width, &height); - - if (width != mode->width || height != mode->height) + if (current.width != mode->width || current.height != mode->height) { printf("*** Size mismatch: %ix%i instead of %ix%i\n", - width, height, + current.width, current.height, mode->width, mode->height); } printf("Closing window\n"); - glfwCloseWindow(window); + glfwDestroyWindow(window); glfwPollEvents(); window = NULL; } - - free(modes); } int main(int argc, char** argv) diff --git a/tests/peter.c b/tests/peter.c index b9f21f22..ae6e4b7d 100644 --- a/tests/peter.c +++ b/tests/peter.c @@ -78,7 +78,7 @@ static void key_callback(GLFWwindow window, int key, int action) { if (action == GLFW_PRESS) { - glfwCloseWindow(window); + glfwDestroyWindow(window); open_window(); } @@ -94,17 +94,19 @@ static void window_size_callback(GLFWwindow window, int width, int height) static GLboolean open_window(void) { - window_handle = glfwOpenWindow(0, 0, GLFW_WINDOWED, "Peter Detector", NULL); + window_handle = glfwCreateWindow(0, 0, GLFW_WINDOWED, "Peter Detector", NULL); if (!window_handle) return GL_FALSE; + glfwMakeContextCurrent(window_handle); + glfwSwapInterval(1); + glfwGetCursorPos(window_handle, &cursor_x, &cursor_y); printf("Cursor position: %i %i\n", cursor_x, cursor_y); glfwSetWindowSizeCallback(window_size_callback); glfwSetCursorPosCallback(cursor_position_callback); glfwSetKeyCallback(key_callback); - glfwSwapInterval(1); return GL_TRUE; } @@ -127,11 +129,11 @@ int main(void) glClearColor(0.f, 0.f, 0.f, 0.f); - while (glfwIsWindow(window_handle)) + while (!glfwGetWindowParam(window_handle, GLFW_CLOSE_REQUESTED)) { glClear(GL_COLOR_BUFFER_BIT); - glfwSwapBuffers(); + glfwSwapBuffers(window_handle); glfwWaitEvents(); } diff --git a/tests/reopen.c b/tests/reopen.c index 2922cb84..5d137188 100644 --- a/tests/reopen.c +++ b/tests/reopen.c @@ -92,17 +92,19 @@ static GLboolean open_window(int width, int height, int mode) base = glfwGetTime(); - window_handle = glfwOpenWindow(width, height, mode, "Window Re-opener", NULL); + window_handle = glfwCreateWindow(width, height, mode, "Window Re-opener", NULL); if (!window_handle) { fprintf(stderr, "Failed to open %s mode GLFW window: %s\n", get_mode_name(mode), glfwErrorString(glfwGetError())); return GL_FALSE; } + glfwMakeContextCurrent(window_handle); + glfwSwapInterval(1); + glfwSetWindowSizeCallback(window_size_callback); glfwSetWindowCloseCallback(window_close_callback); glfwSetKeyCallback(key_callback); - glfwSwapInterval(1); printf("Opening %s mode window took %0.3f seconds\n", get_mode_name(mode), @@ -115,7 +117,7 @@ static void close_window(void) { double base = glfwGetTime(); - glfwCloseWindow(window_handle); + glfwDestroyWindow(window_handle); window_handle = NULL; printf("Closing window took %0.3f seconds\n", glfwGetTime() - base); @@ -147,7 +149,7 @@ int main(int argc, char** argv) glRectf(-0.5f, -0.5f, 1.f, 1.f); glPopMatrix(); - glfwSwapBuffers(); + glfwSwapBuffers(window_handle); glfwPollEvents(); if (closed) diff --git a/tests/sharing.c b/tests/sharing.c index 6f1df980..95f21342 100644 --- a/tests/sharing.c +++ b/tests/sharing.c @@ -36,23 +36,44 @@ #define WIDTH 400 #define HEIGHT 400 +static GLFWwindow windows[2]; + static void key_callback(GLFWwindow window, int key, int action) { if (action == GLFW_PRESS && key == GLFW_KEY_ESCAPE) - glfwCloseWindow(window); + glfwDestroyWindow(window); +} + +static int window_close_callback(GLFWwindow window) +{ + int i; + + for (i = 0; i < 2; i++) + { + if (windows[i] == window) + { + windows[i] = NULL; + break; + } + } + + return GL_TRUE; } static GLFWwindow open_window(const char* title, GLFWwindow share) { GLFWwindow window; - window = glfwOpenWindow(WIDTH, HEIGHT, GLFW_WINDOWED, title, share); + window = glfwCreateWindow(WIDTH, HEIGHT, GLFW_WINDOWED, title, share); if (!window) return NULL; - glfwSetKeyCallback(key_callback); + glfwMakeContextCurrent(window); glfwSwapInterval(1); + glfwSetWindowCloseCallback(window_close_callback); + glfwSetKeyCallback(key_callback); + return window; } @@ -112,7 +133,6 @@ static void draw_quad(GLuint texture) int main(int argc, char** argv) { - GLFWwindow windows[2]; GLuint texture; int x, y; @@ -150,15 +170,16 @@ int main(int argc, char** argv) glfwGetWindowPos(windows[0], &x, &y); glfwSetWindowPos(windows[1], x + WIDTH + 50, y); - while (glfwIsWindow(windows[0]) && glfwIsWindow(windows[1])) + while (windows[0] && windows[1]) { glfwMakeContextCurrent(windows[0]); draw_quad(texture); - glfwSwapBuffers(); glfwMakeContextCurrent(windows[1]); draw_quad(texture); - glfwSwapBuffers(); + + glfwSwapBuffers(windows[0]); + glfwSwapBuffers(windows[1]); glfwWaitEvents(); } diff --git a/tests/tearing.c b/tests/tearing.c index 1eab454e..a8d774a4 100644 --- a/tests/tearing.c +++ b/tests/tearing.c @@ -36,15 +36,16 @@ static int swap_interval; -static void set_swap_interval(int value) +static void set_swap_interval(GLFWwindow window, int interval) { char title[256]; - swap_interval = value; + swap_interval = interval; glfwSwapInterval(swap_interval); sprintf(title, "Tearing detector (interval %i)", swap_interval); - glfwSetWindowTitle(glfwGetCurrentContext(), title); + + glfwSetWindowTitle(window, title); } static void window_size_callback(GLFWwindow window, int width, int height) @@ -55,7 +56,7 @@ static void window_size_callback(GLFWwindow window, int width, int height) static void key_callback(GLFWwindow window, int key, int action) { if (key == GLFW_KEY_SPACE && action == GLFW_PRESS) - set_swap_interval(!swap_interval); + set_swap_interval(window, 1 - swap_interval); } int main(void) @@ -69,7 +70,7 @@ int main(void) exit(EXIT_FAILURE); } - window = glfwOpenWindow(0, 0, GLFW_WINDOWED, "", NULL); + window = glfwCreateWindow(0, 0, GLFW_WINDOWED, "", NULL); if (!window) { glfwTerminate(); @@ -78,7 +79,8 @@ int main(void) exit(EXIT_FAILURE); } - set_swap_interval(1); + glfwMakeContextCurrent(window); + set_swap_interval(window, swap_interval); glfwSetWindowSizeCallback(window_size_callback); glfwSetKeyCallback(key_callback); @@ -87,14 +89,14 @@ int main(void) glOrtho(-1.f, 1.f, -1.f, 1.f, 1.f, -1.f); glMatrixMode(GL_MODELVIEW); - while (glfwIsWindow(window) == GL_TRUE) + while (!glfwGetWindowParam(window, GLFW_CLOSE_REQUESTED)) { glClear(GL_COLOR_BUFFER_BIT); position = cosf(glfwGetTime() * 4.f) * 0.75f; glRectf(position - 0.25f, -1.f, position + 0.25f, 1.f); - glfwSwapBuffers(); + glfwSwapBuffers(window); glfwPollEvents(); } diff --git a/tests/title.c b/tests/title.c index 7b342d94..c7539033 100644 --- a/tests/title.c +++ b/tests/title.c @@ -47,21 +47,22 @@ int main(void) exit(EXIT_FAILURE); } - window = glfwOpenWindow(0, 0, GLFW_WINDOWED, "English 日本語 русский язык 官話", NULL); + window = glfwCreateWindow(0, 0, GLFW_WINDOWED, "English 日本語 русский язык 官話", NULL); if (!window) { fprintf(stderr, "Failed to open GLFW window: %s\n", glfwErrorString(glfwGetError())); exit(EXIT_FAILURE); } + glfwMakeContextCurrent(window); glfwSwapInterval(1); glfwSetWindowSizeCallback(window_size_callback); - while (glfwIsWindow(window) == GL_TRUE) + while (!glfwGetWindowParam(window, GLFW_CLOSE_REQUESTED)) { glClear(GL_COLOR_BUFFER_BIT); - glfwSwapBuffers(); + glfwSwapBuffers(window); glfwWaitEvents(); } diff --git a/tests/windows.c b/tests/windows.c index c7ff32b2..894febeb 100644 --- a/tests/windows.c +++ b/tests/windows.c @@ -55,7 +55,7 @@ int main(void) for (i = 0; i < 4; i++) { - windows[i] = glfwOpenWindow(200, 200, GLFW_WINDOWED, titles[i], NULL); + windows[i] = glfwCreateWindow(200, 200, GLFW_WINDOWED, titles[i], NULL); if (!windows[i]) { fprintf(stderr, "Failed to open GLFW window: %s\n", @@ -64,12 +64,13 @@ int main(void) exit(EXIT_FAILURE); } - glfwSetWindowPos(windows[i], 100 + (i & 1) * 300, 100 + (i >> 1) * 300); - + glfwMakeContextCurrent(windows[i]); glClearColor((GLclampf) (i & 1), (GLclampf) (i >> 1), - i ? 0.0 : 1.0, - 0.0); + i ? 0.f : 1.f, + 0.f); + + glfwSetWindowPos(windows[i], 100 + (i & 1) * 300, 100 + (i >> 1) * 300); } while (running) @@ -78,16 +79,13 @@ int main(void) { glfwMakeContextCurrent(windows[i]); glClear(GL_COLOR_BUFFER_BIT); - glfwSwapBuffers(); + glfwSwapBuffers(windows[i]); + + if (glfwGetWindowParam(windows[i], GLFW_CLOSE_REQUESTED)) + running = GL_FALSE; } glfwPollEvents(); - - for (i = 0; i < 4; i++) - { - if (!glfwIsWindow(windows[i])) - running = GL_FALSE; - } } glfwTerminate();