├── public-domain-mark.png ├── .gitignore ├── cmake └── gl3w-config.cmake ├── SConstruct ├── UNLICENSE ├── src ├── glut_test.c └── glfw_test.c ├── CMakeLists.txt ├── README.rst └── gl3w_gen.py /public-domain-mark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skaslev/gl3w/HEAD/public-domain-mark.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .* 2 | *.o 3 | *.os 4 | bin 5 | lib 6 | include 7 | src/gl3w.c 8 | *.cmake 9 | CMakeFiles 10 | CMakeCache.txt 11 | *.ninja 12 | *.a -------------------------------------------------------------------------------- /cmake/gl3w-config.cmake: -------------------------------------------------------------------------------- 1 | if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.8.0) 2 | include(CMakeFindDependencyMacro) 3 | find_dependency(OpenGL REQUIRED) 4 | endif() 5 | 6 | include("${CMAKE_CURRENT_LIST_DIR}/gl3w-targets.cmake") 7 | -------------------------------------------------------------------------------- /SConstruct: -------------------------------------------------------------------------------- 1 | import os 2 | import platform 3 | import shutil 4 | 5 | env = Environment() 6 | if env.GetOption('clean'): 7 | for d in ['bin', 'include', 'lib']: 8 | shutil.rmtree(d, True) 9 | try: 10 | os.unlink('src/gl3w.c') 11 | except: 12 | pass 13 | else: 14 | print('Generating gl3w...') 15 | os.system('./gl3w_gen.py') 16 | 17 | libs = [] 18 | if platform.system() == 'Darwin': 19 | env.Append(CFLAGS=['-Wno-deprecated-declarations'], 20 | FRAMEWORKS=['GLUT']) 21 | else: 22 | libs = ['glut', 'dl'] 23 | 24 | env.Append(CFLAGS=['-Wall', '-Wextra', '-pedantic', '-O2']) 25 | env.Append(CPPPATH='include') 26 | env.SharedLibrary('lib/gl3w', 'src/gl3w.c') 27 | o = env.Object('src/glut_test', 'src/glut_test.c') 28 | env.Program('bin/glut_test_static', [o, 'src/gl3w.c'], LIBS=libs) 29 | env.Program('bin/glut_test_shared', o, LIBS=libs + ['gl3w'], 30 | LIBPATH='lib', RPATH=os.path.abspath('lib')) 31 | env.Program('bin/glfw_test_static', ['src/glfw_test.c', 'src/gl3w.c'], LIBS=['dl', 'glfw']) 32 | -------------------------------------------------------------------------------- /UNLICENSE: -------------------------------------------------------------------------------- 1 | This is free and unencumbered software released into the public domain. 2 | 3 | Anyone is free to copy, modify, publish, use, compile, sell, or 4 | distribute this software, either in source code form or as a compiled 5 | binary, for any purpose, commercial or non-commercial, and by any 6 | means. 7 | 8 | In jurisdictions that recognize copyright laws, the author or authors 9 | of this software dedicate any and all copyright interest in the 10 | software to the public domain. We make this dedication for the benefit 11 | of the public at large and to the detriment of our heirs and 12 | successors. We intend this dedication to be an overt act of 13 | relinquishment in perpetuity of all present and future rights to this 14 | software under copyright law. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /src/glut_test.c: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | This file is part of gl3w, hosted at https://github.com/skaslev/gl3w 4 | 5 | This is free and unencumbered software released into the public domain. 6 | 7 | Anyone is free to copy, modify, publish, use, compile, sell, or 8 | distribute this software, either in source code form or as a compiled 9 | binary, for any purpose, commercial or non-commercial, and by any 10 | means. 11 | 12 | In jurisdictions that recognize copyright laws, the author or authors 13 | of this software dedicate any and all copyright interest in the 14 | software to the public domain. We make this dedication for the benefit 15 | of the public at large and to the detriment of our heirs and 16 | successors. We intend this dedication to be an overt act of 17 | relinquishment in perpetuity of all present and future rights to this 18 | software under copyright law. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 23 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 24 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 25 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 | OTHER DEALINGS IN THE SOFTWARE. 27 | 28 | */ 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | #define UNUSED(x) ((void) (x)) 37 | 38 | static int width = 600, height = 600; 39 | static float r, g, b; 40 | 41 | static float randf() 42 | { 43 | return (float) rand() / ((float) RAND_MAX + 1); 44 | } 45 | 46 | static void display(void) 47 | { 48 | glClearColor(r, g, b, 1.0f); 49 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 50 | glutSwapBuffers(); 51 | glutPostRedisplay(); 52 | } 53 | 54 | static void reshape(int w, int h) 55 | { 56 | width = w > 1 ? w : 1; 57 | height = h > 1 ? h : 1; 58 | glViewport(0, 0, width, height); 59 | glClearDepth(1.0); 60 | glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 61 | glEnable(GL_DEPTH_TEST); 62 | } 63 | 64 | static void keyboard(unsigned char key, int x, int y) 65 | { 66 | UNUSED(key), UNUSED(x), UNUSED(y); 67 | exit(0); 68 | } 69 | 70 | int main(int argc, char **argv) 71 | { 72 | unsigned mode = GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE; 73 | 74 | srand(time(NULL)); 75 | r = randf(); 76 | g = randf(); 77 | b = randf(); 78 | 79 | glutInit(&argc, argv); 80 | glutInitContextVersion(3, 2); 81 | glutInitContextProfile(GLUT_CORE_PROFILE); 82 | glutInitDisplayMode(mode); 83 | glutInitWindowSize(width, height); 84 | glutCreateWindow("cookie"); 85 | 86 | glutReshapeFunc(reshape); 87 | glutDisplayFunc(display); 88 | glutKeyboardFunc(keyboard); 89 | 90 | if (gl3wInit()) { 91 | fprintf(stderr, "failed to initialize OpenGL\n"); 92 | return -1; 93 | } 94 | if (!gl3wIsSupported(3, 2)) { 95 | fprintf(stderr, "OpenGL 3.2 not supported\n"); 96 | return -1; 97 | } 98 | printf("OpenGL %s, GLSL %s\n", glGetString(GL_VERSION), 99 | glGetString(GL_SHADING_LANGUAGE_VERSION)); 100 | 101 | glutMainLoop(); 102 | return 0; 103 | } 104 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.10 FATAL_ERROR) 2 | 3 | project(gl3w) 4 | 5 | cmake_policy(SET CMP0072 NEW) 6 | cmake_policy(SET CMP0148 NEW) 7 | 8 | set(CMAKE_VERBOSE_MAKEFILE false) 9 | set(CMAKE_POSITION_INDEPENDENT_CODE ON) # -fPIC 10 | 11 | set(SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/src) 12 | set(HEADER_DIR ${CMAKE_CURRENT_BINARY_DIR}/include) 13 | 14 | set(HEADER_FILES 15 | "${HEADER_DIR}/GL/gl3w.h" 16 | "${HEADER_DIR}/GL/glcorearb.h" 17 | "${HEADER_DIR}/KHR/khrplatform.h" 18 | ) 19 | 20 | set(SOURCE_FILES 21 | "${SOURCE_DIR}/gl3w.c" 22 | ) 23 | 24 | # add and depend on OpenGL 25 | find_package(OpenGL REQUIRED) 26 | 27 | # find python interpreter 28 | find_package(Python COMPONENTS Interpreter REQUIRED) 29 | 30 | if(CMAKE_VERSION VERSION_LESS 3.8.0) 31 | set(EXTERNAL_INCLUDE_DIRS ${EXTERNAL_INCLUDE_DIRS} ${OPENGL_INCLUDE_DIR}) 32 | set(EXTERNAL_LIBRARIES ${EXTERNAL_LIBRARIES} ${OPENGL_LIBRARIES}) 33 | else() 34 | # Since CMake 3.8 the IMPORTED targets available 35 | set(EXTERNAL_LIBRARIES ${EXTERNAL_LIBRARIES} ${OPENGL_LIBRARIES} 36 | ) 37 | endif() 38 | 39 | message(CHECK_START "Generating gl3w sources") 40 | execute_process(COMMAND ${Python_EXECUTABLE} "${CMAKE_CURRENT_SOURCE_DIR}/gl3w_gen.py" 41 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} RESULT_VARIABLE success) 42 | message(CHECK_PASS "Done") 43 | 44 | # create gl3w target 45 | add_library(${PROJECT_NAME} INTERFACE) 46 | 47 | include(GNUInstallDirs) 48 | 49 | # let remote project know about source and header files 50 | foreach(SOURCE_FILE ${SOURCE_FILES}) 51 | get_filename_component(SOURCE_FILENAME ${SOURCE_FILE} NAME) 52 | target_sources(${PROJECT_NAME} INTERFACE 53 | $ 54 | $) 55 | install(FILES "${SOURCE_FILE}" 56 | DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}) 57 | endforeach() 58 | foreach(HEADER_FILE ${HEADER_FILES}) 59 | get_filename_component(HEADER_FILENAME ${HEADER_FILE} NAME) 60 | file(RELATIVE_PATH HEADER_PATH "${HEADER_DIR}" "${HEADER_FILE}") 61 | get_filename_component(HEADER_PATH ${HEADER_PATH} PATH) 62 | install(FILES "${HEADER_FILE}" 63 | DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}/${HEADER_PATH}") 64 | endforeach() 65 | 66 | target_include_directories(${PROJECT_NAME} INTERFACE 67 | $ 68 | $ 69 | ) 70 | if(DEFINED EXTERNAL_INCLUDE_DIRS) 71 | target_include_directories(${PROJECT_NAME} INTERFACE ${EXTERNAL_INCLUDE_DIRS}) 72 | endif() 73 | # let remote project know which libraries need to be linked 74 | target_link_libraries(${PROJECT_NAME} INTERFACE ${EXTERNAL_LIBRARIES} ${CMAKE_DL_LIBS}) 75 | 76 | set(MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") 77 | set(BUILD_CMAKE_DIR "${CMAKE_CURRENT_BINARY_DIR}/cmake") 78 | 79 | # export targets for remote projects (i.e. make find_package(gl3w) work) 80 | configure_file( 81 | "${MODULE_PATH}/${PROJECT_NAME}-config.cmake" 82 | "${BUILD_CMAKE_DIR}/${PROJECT_NAME}-config.cmake" 83 | COPYONLY 84 | ) 85 | 86 | install(TARGETS ${PROJECT_NAME} EXPORT ${PROJECT_NAME}-targets) 87 | 88 | install(FILES "${MODULE_PATH}/${PROJECT_NAME}-config.cmake" 89 | DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}) 90 | install(EXPORT ${PROJECT_NAME}-targets 91 | DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}) 92 | 93 | export( 94 | TARGETS ${PROJECT_NAME} 95 | FILE "${BUILD_CMAKE_DIR}/${PROJECT_NAME}-targets.cmake" 96 | ) 97 | 98 | export(PACKAGE ${PROJECT_NAME}) 99 | -------------------------------------------------------------------------------- /src/glfw_test.c: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | This file is part of gl3w, hosted at https://github.com/skaslev/gl3w 4 | 5 | This is free and unencumbered software released into the public domain. 6 | 7 | Anyone is free to copy, modify, publish, use, compile, sell, or 8 | distribute this software, either in source code form or as a compiled 9 | binary, for any purpose, commercial or non-commercial, and by any 10 | means. 11 | 12 | In jurisdictions that recognize copyright laws, the author or authors 13 | of this software dedicate any and all copyright interest in the 14 | software to the public domain. We make this dedication for the benefit 15 | of the public at large and to the detriment of our heirs and 16 | successors. We intend this dedication to be an overt act of 17 | relinquishment in perpetuity of all present and future rights to this 18 | software under copyright law. 19 | 20 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 23 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 24 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 25 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 | OTHER DEALINGS IN THE SOFTWARE. 27 | 28 | */ 29 | 30 | #include 31 | #include 32 | #include 33 | #include 34 | #include 35 | 36 | #define UNUSED(x) ((void) (x)) 37 | 38 | static int width = 600, height = 600; 39 | static float r, g, b; 40 | 41 | static float randf() 42 | { 43 | return (float) rand() / ((float) RAND_MAX + 1); 44 | } 45 | 46 | static void display(GLFWwindow *window) 47 | { 48 | glClearColor(r, g, b, 1.0f); 49 | glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 50 | glfwSwapBuffers(window); 51 | } 52 | 53 | static void reshape(GLFWwindow *window, int w, int h) 54 | { 55 | UNUSED(window); 56 | width = w > 1 ? w : 1; 57 | height = h > 1 ? h : 1; 58 | glViewport(0, 0, width, height); 59 | glClearDepth(1.0); 60 | glClearColor(0.0f, 0.0f, 0.0f, 0.0f); 61 | glEnable(GL_DEPTH_TEST); 62 | } 63 | 64 | static void keyboard(GLFWwindow* window, int key, int scancode, int action, int mods) 65 | { 66 | UNUSED(window), UNUSED(key), UNUSED(scancode), UNUSED(action), UNUSED(mods); 67 | exit(0); 68 | } 69 | 70 | int main(int argc, char **argv) 71 | { 72 | GLFWwindow *window; 73 | 74 | UNUSED(argc), UNUSED(argv); 75 | srand(time(NULL)); 76 | r = randf(); 77 | g = randf(); 78 | b = randf(); 79 | 80 | glfwInit(); 81 | 82 | glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); 83 | glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); 84 | glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2); 85 | glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE); 86 | window = glfwCreateWindow(width, height, "cookie", NULL, NULL); 87 | 88 | glfwSetFramebufferSizeCallback(window, reshape); 89 | glfwSetWindowRefreshCallback(window, display); 90 | glfwSetKeyCallback(window, keyboard); 91 | 92 | glfwMakeContextCurrent(window); 93 | 94 | if (gl3wInit()) { 95 | fprintf(stderr, "failed to initialize OpenGL\n"); 96 | return -1; 97 | } 98 | if (!gl3wIsSupported(3, 2)) { 99 | fprintf(stderr, "OpenGL 3.2 not supported\n"); 100 | return -1; 101 | } 102 | printf("OpenGL %s, GLSL %s\n", glGetString(GL_VERSION), 103 | glGetString(GL_SHADING_LANGUAGE_VERSION)); 104 | 105 | while (!glfwWindowShouldClose(window)) { 106 | display(window); 107 | glfwPollEvents(); 108 | } 109 | 110 | glfwTerminate(); 111 | return 0; 112 | } 113 | -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | ======================================== 2 | gl3w: Simple OpenGL core profile loading 3 | ======================================== 4 | 5 | Introduction 6 | ------------ 7 | 8 | gl3w_ is the easiest way to get your hands on the functionality offered by the 9 | OpenGL core profile specification. 10 | 11 | Its main part is a simple gl3w_gen.py_ Python script that downloads the 12 | Khronos_ supported glcorearb.h_ header and generates gl3w.h and gl3w.c from it. 13 | Those files can then be added and linked (statically or dynamically) into your 14 | project. 15 | 16 | Requirements 17 | ------------ 18 | 19 | gl3w_gen.py_ requires Python version 2.7 or newer. 20 | It is also compatible with Python 3.x. 21 | 22 | Example 23 | ------- 24 | 25 | Here is a simple example of using gl3w_ with glut. Note that GL/gl3w.h must be 26 | included before any other OpenGL related headers:: 27 | 28 | #include 29 | #include 30 | #include 31 | 32 | // ... 33 | 34 | int main(int argc, char **argv) 35 | { 36 | glutInit(&argc, argv); 37 | glutInitDisplayMode(GLUT_RGBA | GLUT_DEPTH | GLUT_DOUBLE); 38 | glutInitWindowSize(width, height); 39 | glutCreateWindow("cookie"); 40 | 41 | glutReshapeFunc(reshape); 42 | glutDisplayFunc(display); 43 | glutKeyboardFunc(keyboard); 44 | glutSpecialFunc(special); 45 | glutMouseFunc(mouse); 46 | glutMotionFunc(motion); 47 | 48 | if (gl3wInit()) { 49 | fprintf(stderr, "failed to initialize OpenGL\n"); 50 | return -1; 51 | } 52 | if (!gl3wIsSupported(3, 2)) { 53 | fprintf(stderr, "OpenGL 3.2 not supported\n"); 54 | return -1; 55 | } 56 | printf("OpenGL %s, GLSL %s\n", glGetString(GL_VERSION), 57 | glGetString(GL_SHADING_LANGUAGE_VERSION)); 58 | 59 | // ... 60 | 61 | glutMainLoop(); 62 | return 0; 63 | } 64 | 65 | If your Project is using CMake you can import gl3w_ using ``FetchContent``:: 66 | 67 | include(FetchContent) 68 | FetchContent_Declare( 69 | gl3w 70 | GIT_REPOSITORY https://github.com/skaslev/gl3w.git 71 | GIT_TAG master 72 | GIT_SHALLOW TRUE 73 | GIT_PROGRESS TRUE 74 | EXCLUDE_FROM_ALL 75 | ) 76 | FetchContent_MakeAvailable(gl3w) 77 | # Declare your target that needs gl3w here 78 | target_link_libraries( PRIVATE gl3w) 79 | 80 | API Reference 81 | ------------- 82 | 83 | The gl3w_ API consists of just three functions: 84 | 85 | ``int gl3wInit(void)`` 86 | 87 | Initializes the library. Should be called once after an OpenGL context has 88 | been created. Returns ``0`` when gl3w_ was initialized successfully, 89 | ``non-zero`` if there was an error. 90 | 91 | ``int gl3wIsSupported(int major, int minor)`` 92 | 93 | Returns ``1`` when OpenGL core profile version *major.minor* is available 94 | and ``0`` otherwise. 95 | 96 | ``GL3WglProc gl3wGetProcAddress(const char *proc)`` 97 | 98 | Returns the address of an OpenGL extension function. Generally, you won't 99 | need to use it since gl3w_ loads all functions defined in the OpenGL core 100 | profile on initialization. It allows you to load OpenGL extensions outside 101 | of the core profile. 102 | 103 | Options 104 | ------- 105 | 106 | The generator script optionally takes the arguments: 107 | 108 | ``--ext`` to include the GL Extensions in output header. 109 | 110 | ``--root=outputdir`` to set the location for the output to something else than current working directory. 111 | 112 | License 113 | ------- 114 | 115 | .. image:: public-domain-mark.png 116 | 117 | gl3w_ is in the public domain. See the file UNLICENSE for more information. 118 | 119 | Credits 120 | ------- 121 | 122 | Slavomir Kaslev 123 | Initial implementation 124 | 125 | Kelvin McDowell 126 | Mac OS X support 127 | 128 | Sjors Gielen 129 | Mac OS X support 130 | 131 | Travis Gesslein 132 | Patches regarding glcorearb.h 133 | 134 | Arthur Tombs 135 | Port to Python 3 136 | 137 | Daniel Cousens [https://github.com/dcousens] 138 | Code contributions 139 | 140 | Copyright 141 | --------- 142 | 143 | OpenGL_ is a registered trademark of SGI_. 144 | 145 | .. _gl3w: https://github.com/skaslev/gl3w 146 | .. _gl3w_gen.py: https://github.com/skaslev/gl3w/blob/master/gl3w_gen.py 147 | .. _glcorearb.h: https://www.opengl.org/registry/api/GL/glcorearb.h 148 | .. _OpenGL: http://www.opengl.org/ 149 | .. _Khronos: http://www.khronos.org/ 150 | .. _SGI: http://www.sgi.com/ 151 | -------------------------------------------------------------------------------- /gl3w_gen.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | # This file is part of gl3w, hosted at https://github.com/skaslev/gl3w 4 | # 5 | # This is free and unencumbered software released into the public domain. 6 | # 7 | # Anyone is free to copy, modify, publish, use, compile, sell, or 8 | # distribute this software, either in source code form or as a compiled 9 | # binary, for any purpose, commercial or non-commercial, and by any 10 | # means. 11 | # 12 | # In jurisdictions that recognize copyright laws, the author or authors 13 | # of this software dedicate any and all copyright interest in the 14 | # software to the public domain. We make this dedication for the benefit 15 | # of the public at large and to the detriment of our heirs and 16 | # successors. We intend this dedication to be an overt act of 17 | # relinquishment in perpetuity of all present and future rights to this 18 | # software under copyright law. 19 | # 20 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 21 | # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 22 | # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 23 | # IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 24 | # OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 25 | # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 | # OTHER DEALINGS IN THE SOFTWARE. 27 | 28 | # Allow Python 2.6+ to use the print() function 29 | from __future__ import print_function 30 | 31 | import argparse 32 | import os 33 | import re 34 | 35 | # Try to import Python 3 library urllib.request 36 | # and if it fails, fall back to Python 2 urllib2 37 | try: 38 | import urllib.request as urllib2 39 | except ImportError: 40 | import urllib2 41 | 42 | # UNLICENSE copyright header 43 | UNLICENSE = r'''/* 44 | * This file was generated with gl3w_gen.py, part of gl3w 45 | * (hosted at https://github.com/skaslev/gl3w) 46 | * 47 | * This is free and unencumbered software released into the public domain. 48 | * 49 | * Anyone is free to copy, modify, publish, use, compile, sell, or 50 | * distribute this software, either in source code form or as a compiled 51 | * binary, for any purpose, commercial or non-commercial, and by any 52 | * means. 53 | * 54 | * In jurisdictions that recognize copyright laws, the author or authors 55 | * of this software dedicate any and all copyright interest in the 56 | * software to the public domain. We make this dedication for the benefit 57 | * of the public at large and to the detriment of our heirs and 58 | * successors. We intend this dedication to be an overt act of 59 | * relinquishment in perpetuity of all present and future rights to this 60 | * software under copyright law. 61 | * 62 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 63 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 64 | * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 65 | * IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR 66 | * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 67 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 68 | * OTHER DEALINGS IN THE SOFTWARE. 69 | */ 70 | 71 | ''' 72 | 73 | EXT_SUFFIX = ['ARB', 'EXT', 'KHR', 'OVR', 'NV', 'AMD', 'INTEL'] 74 | 75 | def is_ext(proc): 76 | return any(proc.endswith(suffix) for suffix in EXT_SUFFIX) 77 | 78 | def write(f, s): 79 | f.write(s.encode('utf-8')) 80 | 81 | def touch_dir(path): 82 | if not os.path.exists(path): 83 | os.makedirs(path) 84 | 85 | def download(url, dst): 86 | if os.path.exists(dst): 87 | print('Reusing {0}...'.format(dst)) 88 | return 89 | 90 | print('Downloading {0}...'.format(dst)) 91 | web = urllib2.urlopen(urllib2.Request(url, headers={'User-Agent': 'Mozilla/5.0'})) 92 | with open(dst, 'wb') as f: 93 | f.writelines(web.readlines()) 94 | 95 | parser = argparse.ArgumentParser(description='gl3w generator script') 96 | parser.add_argument('--ext', action='store_true', help='Load extensions') 97 | parser.add_argument('--root', type=str, default='', help='Root directory') 98 | args = parser.parse_args() 99 | 100 | # Create directories 101 | touch_dir(os.path.join(args.root, 'include/GL')) 102 | touch_dir(os.path.join(args.root, 'include/KHR')) 103 | touch_dir(os.path.join(args.root, 'src')) 104 | 105 | # Download glcorearb.h and khrplatform.h 106 | download('https://registry.khronos.org/OpenGL/api/GL/glcorearb.h', 107 | os.path.join(args.root, 'include/GL/glcorearb.h')) 108 | download('https://registry.khronos.org/EGL/api/KHR/khrplatform.h', 109 | os.path.join(args.root, 'include/KHR/khrplatform.h')) 110 | 111 | # Parse function names from glcorearb.h 112 | print('Parsing glcorearb.h header...') 113 | procs = [] 114 | p = re.compile(r'GLAPI.*APIENTRY\s+(\w+)') 115 | with open(os.path.join(args.root, 'include/GL/glcorearb.h'), 'r') as f: 116 | for line in f: 117 | m = p.match(line) 118 | if not m: 119 | continue 120 | proc = m.group(1) 121 | if args.ext or not is_ext(proc): 122 | procs.append(proc) 123 | procs.sort() 124 | 125 | # Generate gl3w.h 126 | print('Generating {0}...'.format(os.path.join(args.root, 'include/GL/gl3w.h'))) 127 | with open(os.path.join(args.root, 'include/GL/gl3w.h'), 'wb') as f: 128 | write(f, UNLICENSE) 129 | write(f, r'''#ifndef __gl3w_h_ 130 | #define __gl3w_h_ 131 | 132 | #include 133 | 134 | #ifndef GL3W_API 135 | #define GL3W_API 136 | #endif 137 | 138 | #ifndef __gl_h_ 139 | #define __gl_h_ 140 | #endif 141 | 142 | #ifdef __cplusplus 143 | extern "C" { 144 | #endif 145 | 146 | #define GL3W_OK 0 147 | #define GL3W_ERROR_INIT -1 148 | #define GL3W_ERROR_LIBRARY_OPEN -2 149 | #define GL3W_ERROR_OPENGL_VERSION -3 150 | 151 | typedef void (*GL3WglProc)(void); 152 | typedef GL3WglProc (*GL3WGetProcAddressProc)(const char *proc); 153 | 154 | /* gl3w api */ 155 | GL3W_API int gl3wInit(void); 156 | GL3W_API int gl3wInit2(GL3WGetProcAddressProc proc); 157 | GL3W_API int gl3wIsSupported(int major, int minor); 158 | GL3W_API GL3WglProc gl3wGetProcAddress(const char *proc); 159 | 160 | /* gl3w internal state */ 161 | ''') 162 | write(f, 'union GL3WProcs {\n') 163 | write(f, '\tGL3WglProc ptr[{0}];\n'.format(len(procs))) 164 | write(f, '\tstruct {\n') 165 | for proc in procs: 166 | write(f, '\t\t{0: <55} {1};\n'.format('PFN{0}PROC'.format(proc.upper()), proc[2:])) 167 | write(f, r''' } gl; 168 | }; 169 | 170 | GL3W_API extern union GL3WProcs gl3wProcs; 171 | 172 | /* OpenGL functions */ 173 | ''') 174 | for proc in procs: 175 | write(f, '#define {0: <48} gl3wProcs.gl.{1}\n'.format(proc, proc[2:])) 176 | write(f, r''' 177 | #ifdef __cplusplus 178 | } 179 | #endif 180 | 181 | #endif 182 | ''') 183 | 184 | # Generate gl3w.c 185 | print('Generating {0}...'.format(os.path.join(args.root, 'src/gl3w.c'))) 186 | with open(os.path.join(args.root, 'src/gl3w.c'), 'wb') as f: 187 | write(f, UNLICENSE) 188 | write(f, r'''#include 189 | #include 190 | 191 | #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) 192 | 193 | #if defined(_WIN32) 194 | #ifndef WIN32_LEAN_AND_MEAN 195 | #define WIN32_LEAN_AND_MEAN 1 196 | #endif 197 | #include 198 | 199 | #if defined(__GNUC__) 200 | #pragma GCC diagnostic push 201 | #pragma GCC diagnostic ignored "-Wcast-function-type" 202 | #endif 203 | 204 | static HMODULE libgl; 205 | typedef PROC(__stdcall* GL3WglGetProcAddr)(LPCSTR); 206 | static GL3WglGetProcAddr wgl_get_proc_address; 207 | 208 | static int open_libgl(void) 209 | { 210 | libgl = LoadLibraryA("opengl32.dll"); 211 | if (!libgl) 212 | return GL3W_ERROR_LIBRARY_OPEN; 213 | 214 | wgl_get_proc_address = (GL3WglGetProcAddr)GetProcAddress(libgl, "wglGetProcAddress"); 215 | return GL3W_OK; 216 | } 217 | 218 | static void close_libgl(void) 219 | { 220 | FreeLibrary(libgl); 221 | } 222 | 223 | static GL3WglProc get_proc(const char *proc) 224 | { 225 | GL3WglProc res; 226 | 227 | res = (GL3WglProc)wgl_get_proc_address(proc); 228 | if (!res) 229 | res = (GL3WglProc)GetProcAddress(libgl, proc); 230 | return res; 231 | } 232 | 233 | #if defined(__GNUC__) 234 | #pragma GCC diagnostic pop 235 | #endif 236 | #elif defined(__APPLE__) 237 | #include 238 | 239 | static void *libgl; 240 | 241 | static int open_libgl(void) 242 | { 243 | libgl = dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LAZY | RTLD_LOCAL); 244 | if (!libgl) 245 | return GL3W_ERROR_LIBRARY_OPEN; 246 | 247 | return GL3W_OK; 248 | } 249 | 250 | static void close_libgl(void) 251 | { 252 | dlclose(libgl); 253 | } 254 | 255 | static GL3WglProc get_proc(const char *proc) 256 | { 257 | GL3WglProc res; 258 | 259 | *(void **)(&res) = dlsym(libgl, proc); 260 | return res; 261 | } 262 | #else 263 | #include 264 | 265 | static void *libgl; /* OpenGL library */ 266 | static void *libglx; /* GLX library */ 267 | static void *libegl; /* EGL library */ 268 | static GL3WGetProcAddressProc gl_get_proc_address; 269 | 270 | static void close_libgl(void) 271 | { 272 | if (libgl) { 273 | dlclose(libgl); 274 | libgl = NULL; 275 | } 276 | if (libegl) { 277 | dlclose(libegl); 278 | libegl = NULL; 279 | } 280 | if (libglx) { 281 | dlclose(libglx); 282 | libglx = NULL; 283 | } 284 | } 285 | 286 | static int is_library_loaded(const char *name, void **lib) 287 | { 288 | #if defined(__HAIKU__) 289 | *lib = NULL; 290 | #else 291 | *lib = dlopen(name, RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD); 292 | #endif 293 | return *lib != NULL; 294 | } 295 | 296 | static int open_libs(void) 297 | { 298 | /* On Linux we have two APIs to get process addresses: EGL and GLX. 299 | * EGL is supported under both X11 and Wayland, whereas GLX is X11-specific. 300 | * First check what's already loaded, the windowing library might have 301 | * already loaded either EGL or GLX and we want to use the same one. 302 | */ 303 | 304 | if (is_library_loaded("libEGL.so.1", &libegl) || 305 | is_library_loaded("libGLX.so.0", &libglx)) { 306 | libgl = dlopen("libOpenGL.so.0", RTLD_LAZY | RTLD_LOCAL); 307 | if (libgl) 308 | return GL3W_OK; 309 | else 310 | close_libgl(); 311 | } 312 | 313 | if (is_library_loaded("libGL.so.1", &libgl)) 314 | return GL3W_OK; 315 | 316 | /* Neither is already loaded, so we have to load one. Try EGL first 317 | * because it is supported under both X11 and Wayland. 318 | */ 319 | 320 | /* Load OpenGL + EGL */ 321 | libgl = dlopen("libOpenGL.so.0", RTLD_LAZY | RTLD_LOCAL); 322 | libegl = dlopen("libEGL.so.1", RTLD_LAZY | RTLD_LOCAL); 323 | if (libgl && libegl) 324 | return GL3W_OK; 325 | 326 | /* Fall back to legacy libGL, which includes GLX */ 327 | close_libgl(); 328 | libgl = dlopen("libGL.so.1", RTLD_LAZY | RTLD_LOCAL); 329 | if (libgl) 330 | return GL3W_OK; 331 | 332 | return GL3W_ERROR_LIBRARY_OPEN; 333 | } 334 | 335 | static int open_libgl(void) 336 | { 337 | int res = open_libs(); 338 | if (res) 339 | return res; 340 | 341 | if (libegl) 342 | *(void **)(&gl_get_proc_address) = dlsym(libegl, "eglGetProcAddress"); 343 | else if (libglx) 344 | *(void **)(&gl_get_proc_address) = dlsym(libglx, "glXGetProcAddressARB"); 345 | else 346 | *(void **)(&gl_get_proc_address) = dlsym(libgl, "glXGetProcAddressARB"); 347 | 348 | if (!gl_get_proc_address) { 349 | close_libgl(); 350 | return GL3W_ERROR_LIBRARY_OPEN; 351 | } 352 | 353 | return GL3W_OK; 354 | } 355 | 356 | static GL3WglProc get_proc(const char *proc) 357 | { 358 | GL3WglProc res = NULL; 359 | 360 | /* Before EGL version 1.5, eglGetProcAddress doesn't support querying core 361 | * functions and may return a dummy function if we try, so try to load the 362 | * function from the GL library directly first. 363 | */ 364 | if (libegl) 365 | *(void **)(&res) = dlsym(libgl, proc); 366 | 367 | if (!res) 368 | res = gl_get_proc_address(proc); 369 | 370 | if (!libegl && !res) 371 | *(void **)(&res) = dlsym(libgl, proc); 372 | 373 | return res; 374 | } 375 | #endif 376 | 377 | static struct { 378 | int major, minor; 379 | } version; 380 | 381 | static int parse_version(void) 382 | { 383 | if (!glGetIntegerv) 384 | return GL3W_ERROR_INIT; 385 | 386 | glGetIntegerv(GL_MAJOR_VERSION, &version.major); 387 | glGetIntegerv(GL_MINOR_VERSION, &version.minor); 388 | 389 | if (version.major < 3) 390 | return GL3W_ERROR_OPENGL_VERSION; 391 | return GL3W_OK; 392 | } 393 | 394 | static void load_procs(GL3WGetProcAddressProc proc); 395 | 396 | int gl3wInit(void) 397 | { 398 | int res; 399 | 400 | res = open_libgl(); 401 | if (res) 402 | return res; 403 | 404 | atexit(close_libgl); 405 | return gl3wInit2(get_proc); 406 | } 407 | 408 | int gl3wInit2(GL3WGetProcAddressProc proc) 409 | { 410 | load_procs(proc); 411 | return parse_version(); 412 | } 413 | 414 | int gl3wIsSupported(int major, int minor) 415 | { 416 | if (major < 3) 417 | return 0; 418 | if (version.major == major) 419 | return version.minor >= minor; 420 | return version.major >= major; 421 | } 422 | 423 | GL3WglProc gl3wGetProcAddress(const char *proc) 424 | { 425 | return get_proc(proc); 426 | } 427 | 428 | static const char *proc_names[] = { 429 | ''') 430 | for proc in procs: 431 | write(f, '\t"{0}",\n'.format(proc)) 432 | write(f, r'''}; 433 | 434 | GL3W_API union GL3WProcs gl3wProcs; 435 | 436 | static void load_procs(GL3WGetProcAddressProc proc) 437 | { 438 | size_t i; 439 | 440 | for (i = 0; i < ARRAY_SIZE(proc_names); i++) 441 | gl3wProcs.ptr[i] = proc(proc_names[i]); 442 | } 443 | ''') 444 | --------------------------------------------------------------------------------