├── .gitignore ├── CMakeLists.txt ├── README.rst ├── SConstruct ├── UNLICENSE ├── cmake └── gl3w-config.cmake ├── gl3w_gen.py ├── public-domain-mark.png └── src ├── glfw_test.c └── glut_test.c /.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 -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.1.3 FATAL_ERROR) 2 | 3 | project(gl3w) 4 | 5 | set(CMAKE_VERBOSE_MAKEFILE false) 6 | set(CMAKE_POSITION_INDEPENDENT_CODE ON) # -fPIC 7 | 8 | set(SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/src) 9 | set(HEADER_DIR ${CMAKE_CURRENT_BINARY_DIR}/include) 10 | 11 | set(HEADER_FILES 12 | "${HEADER_DIR}/GL/gl3w.h" 13 | "${HEADER_DIR}/GL/glcorearb.h" 14 | "${HEADER_DIR}/KHR/khrplatform.h" 15 | ) 16 | 17 | set(SOURCE_FILES 18 | "${SOURCE_DIR}/gl3w.c" 19 | ) 20 | 21 | # add and depend on OpenGL 22 | find_package(OpenGL REQUIRED) 23 | 24 | # find python interpreter 25 | find_package(PythonInterp REQUIRED) 26 | 27 | if(CMAKE_VERSION VERSION_LESS 3.8.0) 28 | set(EXTERNAL_INCLUDE_DIRS ${EXTERNAL_INCLUDE_DIRS} ${OPENGL_INCLUDE_DIR}) 29 | set(EXTERNAL_LIBRARIES ${EXTERNAL_LIBRARIES} ${OPENGL_LIBRARIES}) 30 | else() 31 | # Since CMake 3.8 the IMPORTED targets available 32 | set(EXTERNAL_LIBRARIES ${EXTERNAL_LIBRARIES} OpenGL::GL OpenGL::GLU) 33 | endif() 34 | # add command to create the header and source files 35 | add_custom_command( 36 | OUTPUT 37 | "${SOURCE_DIR}/gl3w.c" 38 | "${HEADER_DIR}/GL/gl3w.h" 39 | "${HEADER_DIR}/GL/glcorearb.h" 40 | "${HEADER_DIR}/KHR/khrplatform.h" 41 | COMMAND "${PYTHON_EXECUTABLE}" ${CMAKE_CURRENT_SOURCE_DIR}/gl3w_gen.py 42 | DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/gl3w_gen.py 43 | WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} 44 | ) 45 | 46 | # add pseudo target that depends on the generated files 47 | add_custom_target( 48 | gl3w_gen ALL 49 | DEPENDS 50 | "${SOURCE_DIR}/gl3w.c" 51 | "${HEADER_DIR}/GL/gl3w.h" 52 | "${HEADER_DIR}/GL/glcorearb.h" 53 | "${HEADER_DIR}/KHR/khrplatform.h" 54 | ) 55 | 56 | # create gl3w target 57 | add_library(${PROJECT_NAME} INTERFACE) 58 | 59 | # make gl3w target depend on the generator target 60 | add_dependencies(${PROJECT_NAME} gl3w_gen) 61 | 62 | include(GNUInstallDirs) 63 | 64 | # let remote project know about source and header files 65 | foreach(SOURCE_FILE ${SOURCE_FILES}) 66 | get_filename_component(SOURCE_FILENAME ${SOURCE_FILE} NAME) 67 | target_sources(${PROJECT_NAME} INTERFACE 68 | $ 69 | $) 70 | install(FILES "${SOURCE_FILE}" 71 | DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}) 72 | endforeach() 73 | foreach(HEADER_FILE ${HEADER_FILES}) 74 | get_filename_component(HEADER_FILENAME ${HEADER_FILE} NAME) 75 | file(RELATIVE_PATH HEADER_PATH "${HEADER_DIR}" "${HEADER_FILE}") 76 | get_filename_component(HEADER_PATH ${HEADER_PATH} PATH) 77 | install(FILES "${HEADER_FILE}" 78 | DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${PROJECT_NAME}/${HEADER_PATH}") 79 | endforeach() 80 | 81 | target_include_directories(${PROJECT_NAME} INTERFACE 82 | $ 83 | $ 84 | ) 85 | if(DEFINED EXTERNAL_INCLUDE_DIRS) 86 | target_include_directories(${PROJECT_NAME} INTERFACE ${EXTERNAL_INCLUDE_DIRS}) 87 | endif() 88 | # let remote project know which libraries need to be linked 89 | target_link_libraries(${PROJECT_NAME} INTERFACE ${EXTERNAL_LIBRARIES} ${CMAKE_DL_LIBS}) 90 | 91 | set(MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake") 92 | set(BUILD_CMAKE_DIR "${CMAKE_CURRENT_BINARY_DIR}/cmake") 93 | 94 | # export targets for remote projects (i.e. make find_package(gl3w) work) 95 | configure_file( 96 | "${MODULE_PATH}/${PROJECT_NAME}-config.cmake" 97 | "${BUILD_CMAKE_DIR}/${PROJECT_NAME}-config.cmake" 98 | COPYONLY 99 | ) 100 | 101 | install(TARGETS ${PROJECT_NAME} EXPORT ${PROJECT_NAME}-targets) 102 | 103 | install(FILES "${MODULE_PATH}/${PROJECT_NAME}-config.cmake" 104 | DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}) 105 | install(EXPORT ${PROJECT_NAME}-targets 106 | DESTINATION ${CMAKE_INSTALL_DATAROOTDIR}/${PROJECT_NAME}) 107 | 108 | export( 109 | TARGETS ${PROJECT_NAME} 110 | FILE "${BUILD_CMAKE_DIR}/${PROJECT_NAME}-targets.cmake" 111 | ) 112 | 113 | export(PACKAGE ${PROJECT_NAME}) 114 | -------------------------------------------------------------------------------- /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 | API Reference 66 | ------------- 67 | 68 | The gl3w_ API consists of just three functions: 69 | 70 | ``int gl3wInit(void)`` 71 | 72 | Initializes the library. Should be called once after an OpenGL context has 73 | been created. Returns ``0`` when gl3w_ was initialized successfully, 74 | ``non-zero`` if there was an error. 75 | 76 | ``int gl3wIsSupported(int major, int minor)`` 77 | 78 | Returns ``1`` when OpenGL core profile version *major.minor* is available 79 | and ``0`` otherwise. 80 | 81 | ``GL3WglProc gl3wGetProcAddress(const char *proc)`` 82 | 83 | Returns the address of an OpenGL extension function. Generally, you won't 84 | need to use it since gl3w_ loads all functions defined in the OpenGL core 85 | profile on initialization. It allows you to load OpenGL extensions outside 86 | of the core profile. 87 | 88 | Options 89 | ------- 90 | 91 | The generator script optionally takes the arguments: 92 | 93 | ``--ext`` to include the GL Extensions in output header. 94 | 95 | ``--root=outputdir`` to set the location for the output to something else than current working directory. 96 | 97 | License 98 | ------- 99 | 100 | .. image:: public-domain-mark.png 101 | 102 | gl3w_ is in the public domain. See the file UNLICENSE for more information. 103 | 104 | Credits 105 | ------- 106 | 107 | Slavomir Kaslev 108 | Initial implementation 109 | 110 | Kelvin McDowell 111 | Mac OS X support 112 | 113 | Sjors Gielen 114 | Mac OS X support 115 | 116 | Travis Gesslein 117 | Patches regarding glcorearb.h 118 | 119 | Arthur Tombs 120 | Port to Python 3 121 | 122 | Daniel Cousens [https://github.com/dcousens] 123 | Code contributions 124 | 125 | Copyright 126 | --------- 127 | 128 | OpenGL_ is a registered trademark of SGI_. 129 | 130 | .. _gl3w: https://github.com/skaslev/gl3w 131 | .. _gl3w_gen.py: https://github.com/skaslev/gl3w/blob/master/gl3w_gen.py 132 | .. _glcorearb.h: https://www.opengl.org/registry/api/GL/glcorearb.h 133 | .. _OpenGL: http://www.opengl.org/ 134 | .. _Khronos: http://www.khronos.org/ 135 | .. _SGI: http://www.sgi.com/ 136 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | static HMODULE libgl; 200 | typedef PROC(__stdcall* GL3WglGetProcAddr)(LPCSTR); 201 | static GL3WglGetProcAddr wgl_get_proc_address; 202 | 203 | static int open_libgl(void) 204 | { 205 | libgl = LoadLibraryA("opengl32.dll"); 206 | if (!libgl) 207 | return GL3W_ERROR_LIBRARY_OPEN; 208 | 209 | wgl_get_proc_address = (GL3WglGetProcAddr)GetProcAddress(libgl, "wglGetProcAddress"); 210 | return GL3W_OK; 211 | } 212 | 213 | static void close_libgl(void) 214 | { 215 | FreeLibrary(libgl); 216 | } 217 | 218 | static GL3WglProc get_proc(const char *proc) 219 | { 220 | GL3WglProc res; 221 | 222 | res = (GL3WglProc)wgl_get_proc_address(proc); 223 | if (!res) 224 | res = (GL3WglProc)GetProcAddress(libgl, proc); 225 | return res; 226 | } 227 | #elif defined(__APPLE__) 228 | #include 229 | 230 | static void *libgl; 231 | 232 | static int open_libgl(void) 233 | { 234 | libgl = dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LAZY | RTLD_LOCAL); 235 | if (!libgl) 236 | return GL3W_ERROR_LIBRARY_OPEN; 237 | 238 | return GL3W_OK; 239 | } 240 | 241 | static void close_libgl(void) 242 | { 243 | dlclose(libgl); 244 | } 245 | 246 | static GL3WglProc get_proc(const char *proc) 247 | { 248 | GL3WglProc res; 249 | 250 | *(void **)(&res) = dlsym(libgl, proc); 251 | return res; 252 | } 253 | #else 254 | #include 255 | 256 | static void *libgl; /* OpenGL library */ 257 | static void *libglx; /* GLX library */ 258 | static void *libegl; /* EGL library */ 259 | static GL3WGetProcAddressProc gl_get_proc_address; 260 | 261 | static void close_libgl(void) 262 | { 263 | if (libgl) { 264 | dlclose(libgl); 265 | libgl = NULL; 266 | } 267 | if (libegl) { 268 | dlclose(libegl); 269 | libegl = NULL; 270 | } 271 | if (libglx) { 272 | dlclose(libglx); 273 | libglx = NULL; 274 | } 275 | } 276 | 277 | static int is_library_loaded(const char *name, void **lib) 278 | { 279 | *lib = dlopen(name, RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD); 280 | return *lib != NULL; 281 | } 282 | 283 | static int open_libs(void) 284 | { 285 | /* On Linux we have two APIs to get process addresses: EGL and GLX. 286 | * EGL is supported under both X11 and Wayland, whereas GLX is X11-specific. 287 | * First check what's already loaded, the windowing library might have 288 | * already loaded either EGL or GLX and we want to use the same one. 289 | */ 290 | 291 | if (is_library_loaded("libEGL.so.1", &libegl) || 292 | is_library_loaded("libGLX.so.0", &libglx)) { 293 | libgl = dlopen("libOpenGL.so.0", RTLD_LAZY | RTLD_LOCAL); 294 | if (libgl) 295 | return GL3W_OK; 296 | else 297 | close_libgl(); 298 | } 299 | 300 | if (is_library_loaded("libGL.so.1", &libgl)) 301 | return GL3W_OK; 302 | 303 | /* Neither is already loaded, so we have to load one. Try EGL first 304 | * because it is supported under both X11 and Wayland. 305 | */ 306 | 307 | /* Load OpenGL + EGL */ 308 | libgl = dlopen("libOpenGL.so.0", RTLD_LAZY | RTLD_LOCAL); 309 | libegl = dlopen("libEGL.so.1", RTLD_LAZY | RTLD_LOCAL); 310 | if (libgl && libegl) 311 | return GL3W_OK; 312 | 313 | /* Fall back to legacy libGL, which includes GLX */ 314 | close_libgl(); 315 | libgl = dlopen("libGL.so.1", RTLD_LAZY | RTLD_LOCAL); 316 | if (libgl) 317 | return GL3W_OK; 318 | 319 | return GL3W_ERROR_LIBRARY_OPEN; 320 | } 321 | 322 | static int open_libgl(void) 323 | { 324 | int res = open_libs(); 325 | if (res) 326 | return res; 327 | 328 | if (libegl) 329 | *(void **)(&gl_get_proc_address) = dlsym(libegl, "eglGetProcAddress"); 330 | else if (libglx) 331 | *(void **)(&gl_get_proc_address) = dlsym(libglx, "glXGetProcAddressARB"); 332 | else 333 | *(void **)(&gl_get_proc_address) = dlsym(libgl, "glXGetProcAddressARB"); 334 | 335 | if (!gl_get_proc_address) { 336 | close_libgl(); 337 | return GL3W_ERROR_LIBRARY_OPEN; 338 | } 339 | 340 | return GL3W_OK; 341 | } 342 | 343 | static GL3WglProc get_proc(const char *proc) 344 | { 345 | GL3WglProc res = NULL; 346 | 347 | /* Before EGL version 1.5, eglGetProcAddress doesn't support querying core 348 | * functions and may return a dummy function if we try, so try to load the 349 | * function from the GL library directly first. 350 | */ 351 | if (libegl) 352 | *(void **)(&res) = dlsym(libgl, proc); 353 | 354 | if (!res) 355 | res = gl_get_proc_address(proc); 356 | 357 | if (!libegl && !res) 358 | *(void **)(&res) = dlsym(libgl, proc); 359 | 360 | return res; 361 | } 362 | #endif 363 | 364 | static struct { 365 | int major, minor; 366 | } version; 367 | 368 | static int parse_version(void) 369 | { 370 | if (!glGetIntegerv) 371 | return GL3W_ERROR_INIT; 372 | 373 | glGetIntegerv(GL_MAJOR_VERSION, &version.major); 374 | glGetIntegerv(GL_MINOR_VERSION, &version.minor); 375 | 376 | if (version.major < 3) 377 | return GL3W_ERROR_OPENGL_VERSION; 378 | return GL3W_OK; 379 | } 380 | 381 | static void load_procs(GL3WGetProcAddressProc proc); 382 | 383 | int gl3wInit(void) 384 | { 385 | int res; 386 | 387 | res = open_libgl(); 388 | if (res) 389 | return res; 390 | 391 | atexit(close_libgl); 392 | return gl3wInit2(get_proc); 393 | } 394 | 395 | int gl3wInit2(GL3WGetProcAddressProc proc) 396 | { 397 | load_procs(proc); 398 | return parse_version(); 399 | } 400 | 401 | int gl3wIsSupported(int major, int minor) 402 | { 403 | if (major < 3) 404 | return 0; 405 | if (version.major == major) 406 | return version.minor >= minor; 407 | return version.major >= major; 408 | } 409 | 410 | GL3WglProc gl3wGetProcAddress(const char *proc) 411 | { 412 | return get_proc(proc); 413 | } 414 | 415 | static const char *proc_names[] = { 416 | ''') 417 | for proc in procs: 418 | write(f, '\t"{0}",\n'.format(proc)) 419 | write(f, r'''}; 420 | 421 | GL3W_API union GL3WProcs gl3wProcs; 422 | 423 | static void load_procs(GL3WGetProcAddressProc proc) 424 | { 425 | size_t i; 426 | 427 | for (i = 0; i < ARRAY_SIZE(proc_names); i++) 428 | gl3wProcs.ptr[i] = proc(proc_names[i]); 429 | } 430 | ''') 431 | -------------------------------------------------------------------------------- /public-domain-mark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/skaslev/gl3w/1528d8918447a61e97fe669d7b3e280a60b9a161/public-domain-mark.png -------------------------------------------------------------------------------- /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 | -------------------------------------------------------------------------------- /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 | --------------------------------------------------------------------------------