diff --git a/CMakeLists.txt b/CMakeLists.txt index e990b85b8..56df00a09 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -489,6 +489,18 @@ write_basic_package_version_file("${GLFW_BINARY_DIR}/src/glfw3ConfigVersion.cmak VERSION ${GLFW_VERSION_FULL} COMPATIBILITY SameMajorVersion) +OPTION(GLFW_USE_GL3W "Use Internal OpenGL loader" ON) +if(GLFW_USE_GL3W) + FIND_PACKAGE(PythonInterp 2.6 REQUIRED) + EXECUTE_PROCESS(COMMAND ${PYTHON_EXECUTABLE} ${CMAKE_CURRENT_SOURCE_DIR}/gl3w_gen.py + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) + INCLUDE_DIRECTORIES(${CMAKE_CURRENT_BINARY_DIR}/include) + ADD_LIBRARY(gl3w ${CMAKE_CURRENT_BINARY_DIR}/src/gl3w.c) + IF(UNIX) + TARGET_LINK_LIBRARIES(gl3w dl) + ENDIF() +endif() + if (GLFW_BUILD_DOCS) configure_file("${GLFW_SOURCE_DIR}/docs/Doxyfile.in" "${GLFW_BINARY_DIR}/docs/Doxyfile" @ONLY) diff --git a/gl3w_gen.py b/gl3w_gen.py new file mode 100644 index 000000000..714dde348 --- /dev/null +++ b/gl3w_gen.py @@ -0,0 +1,284 @@ +#!/usr/bin/env python + +# This file is part of gl3w, hosted at https://github.com/skaslev/gl3w +# +# This is free and unencumbered software released into the public domain. +# +# Anyone is free to copy, modify, publish, use, compile, sell, or +# distribute this software, either in source code form or as a compiled +# binary, for any purpose, commercial or non-commercial, and by any +# means. +# +# In jurisdictions that recognize copyright laws, the author or authors +# of this software dedicate any and all copyright interest in the +# software to the public domain. We make this dedication for the benefit +# of the public at large and to the detriment of our heirs and +# successors. We intend this dedication to be an overt act of +# relinquishment in perpetuity of all present and future rights to this +# software under copyright law. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +# IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR +# OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +# ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +# OTHER DEALINGS IN THE SOFTWARE. + +# Allow Python 2.6+ to use the print() function +from __future__ import print_function + +import re +import os + +# Try to import Python 3 library urllib.request +# and if it fails, fall back to Python 2 urllib2 +try: + import urllib.request as urllib2 +except ImportError: + import urllib2 + +# UNLICENSE copyright header +UNLICENSE = br'''/* + + This file was generated with gl3w_gen.py, part of gl3w + (hosted at https://github.com/skaslev/gl3w) + + This is free and unencumbered software released into the public domain. + + Anyone is free to copy, modify, publish, use, compile, sell, or + distribute this software, either in source code form or as a compiled + binary, for any purpose, commercial or non-commercial, and by any + means. + + In jurisdictions that recognize copyright laws, the author or authors + of this software dedicate any and all copyright interest in the + software to the public domain. We make this dedication for the benefit + of the public at large and to the detriment of our heirs and + successors. We intend this dedication to be an overt act of + relinquishment in perpetuity of all present and future rights to this + software under copyright law. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. + IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR + OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR + OTHER DEALINGS IN THE SOFTWARE. + +*/ + +''' + +# Create directories +if not os.path.exists('include/GL'): + os.makedirs('include/GL') +if not os.path.exists('src'): + os.makedirs('src') + +# Download glcorearb.h +if not os.path.exists('include/GL/glcorearb.h'): + print('-- Downloading glcorearb.h to include/GL...') + web = urllib2.urlopen('https://www.opengl.org/registry/api/GL/glcorearb.h') + with open('include/GL/glcorearb.h', 'wb') as f: + f.writelines(web.readlines()) +else: + print('-- Reusing glcorearb.h from include/GL...') + +# Parse function names from glcorearb.h +print('-- Parsing glcorearb.h header...') +procs = [] +p = re.compile(r'GLAPI.*APIENTRY\s+(\w+)') +with open('include/GL/glcorearb.h', 'r') as f: + for line in f: + m = p.match(line) + if m: + procs.append(m.group(1)) +procs.sort() + +def proc_t(proc): + return { 'p': proc, + 'p_s': 'gl3w' + proc[2:], + 'p_t': 'PFN' + proc.upper() + 'PROC' } + +# Generate gl3w.h +print('-- Generating gl3w.h in include/GL...') +with open('include/GL/gl3w.h', 'wb') as f: + f.write(UNLICENSE) + f.write(br'''#ifndef __gl3w_h_ +#define __gl3w_h_ + +#include + +#ifndef __gl_h_ +#define __gl_h_ +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef void (*GL3WglProc)(void); + +/* gl3w api */ +int gl3wInit(void); +int gl3wIsSupported(int major, int minor); +GL3WglProc gl3wGetProcAddress(const char *proc); + +/* OpenGL functions */ +''') + for proc in procs: + f.write('extern {0[p_t]: <52} {0[p_s]};\n'.format(proc_t(proc)).encode("utf-8")) + f.write(b'\n') + for proc in procs: + f.write('#define {0[p]: <45} {0[p_s]}\n'.format(proc_t(proc)).encode("utf-8")) + f.write(br''' +#ifdef __cplusplus +} +#endif + +#endif +''') + +# Generate gl3w.c +print('-- Generating gl3w.c in src...') +with open('src/gl3w.c', 'wb') as f: + f.write(UNLICENSE) + f.write(br'''#include + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN 1 +#include + +static HMODULE libgl; + +static void open_libgl(void) +{ + libgl = LoadLibraryA("opengl32.dll"); +} + +static void close_libgl(void) +{ + FreeLibrary(libgl); +} + +static GL3WglProc get_proc(const char *proc) +{ + GL3WglProc res; + + res = (GL3WglProc) wglGetProcAddress(proc); + if (!res) + res = (GL3WglProc) GetProcAddress(libgl, proc); + return res; +} +#elif defined(__APPLE__) || defined(__APPLE_CC__) +#include + +CFBundleRef bundle; +CFURLRef bundleURL; + +static void open_libgl(void) +{ + bundleURL = CFURLCreateWithFileSystemPath(kCFAllocatorDefault, + CFSTR("/System/Library/Frameworks/OpenGL.framework"), + kCFURLPOSIXPathStyle, true); + + bundle = CFBundleCreate(kCFAllocatorDefault, bundleURL); + assert(bundle != NULL); +} + +static void close_libgl(void) +{ + CFRelease(bundle); + CFRelease(bundleURL); +} + +static GL3WglProc get_proc(const char *proc) +{ + GL3WglProc res; + + CFStringRef procname = CFStringCreateWithCString(kCFAllocatorDefault, proc, + kCFStringEncodingASCII); + res = (GL3WglProc) CFBundleGetFunctionPointerForName(bundle, procname); + CFRelease(procname); + return res; +} +#else +#include +#include + +static void *libgl; + +static void open_libgl(void) +{ + libgl = dlopen("libGL.so.1", RTLD_LAZY | RTLD_GLOBAL); +} + +static void close_libgl(void) +{ + dlclose(libgl); +} + +static GL3WglProc get_proc(const char *proc) +{ + GL3WglProc res; + + res = (GL3WglProc) glXGetProcAddress((const GLubyte *) proc); + if (!res) + res = (GL3WglProc) dlsym(libgl, proc); + return res; +} +#endif + +static struct { + int major, minor; +} version; + +static int parse_version(void) +{ + if (!glGetIntegerv) + return -1; + + glGetIntegerv(GL_MAJOR_VERSION, &version.major); + glGetIntegerv(GL_MINOR_VERSION, &version.minor); + + if (version.major < 3) + return -1; + return 0; +} + +static void load_procs(void); + +int gl3wInit(void) +{ + open_libgl(); + load_procs(); + close_libgl(); + return parse_version(); +} + +int gl3wIsSupported(int major, int minor) +{ + if (major < 3) + return 0; + if (version.major == major) + return version.minor >= minor; + return version.major >= major; +} + +GL3WglProc gl3wGetProcAddress(const char *proc) +{ + return get_proc(proc); +} + +''') + for proc in procs: + f.write('{0[p_t]: <52} {0[p_s]};\n'.format(proc_t(proc)).encode("utf-8")) + f.write(br''' +static void load_procs(void) +{ +''') + for proc in procs: + f.write('\t{0[p_s]} = ({0[p_t]}) get_proc("{0[p]}");\n'.format(proc_t(proc)).encode("utf-8")) + f.write(b'}\n') diff --git a/include/GLFW/glfw3.h b/include/GLFW/glfw3.h index 9a7ca1764..1123cae58 100644 --- a/include/GLFW/glfw3.h +++ b/include/GLFW/glfw3.h @@ -127,7 +127,9 @@ extern "C" { #include #endif #else - #if defined(GLFW_INCLUDE_GLCOREARB) + #if defined(GLFW_INCLUDE_GL3W) + #include + #elif defined(GLFW_INCLUDE_GLCOREARB) #include #elif defined(GLFW_INCLUDE_ES1) #include