mirror of
https://github.com/GayPizzaSpecifications/padlab.git
synced 2025-09-23 18:51:31 +00:00
Core profile renderer skeleton
This commit is contained in:
@ -1,9 +1,18 @@
|
|||||||
cmake_minimum_required(VERSION 3.8 FATAL_ERROR)
|
cmake_minimum_required(VERSION 3.3 FATAL_ERROR)
|
||||||
project(padlab C)
|
project(padlab C)
|
||||||
set(TARGET padlab)
|
set(TARGET padlab)
|
||||||
|
|
||||||
option(USE_OPENGL "Use legacy OpenGL for drawing" ON)
|
option(USE_OPENGL "Use OpenGL for drawing (WIP)" OFF)
|
||||||
|
if (USE_OPENGL)
|
||||||
|
option(USE_OPENGL_LEGACY "Use legacy OpenGL for drawing" OFF)
|
||||||
|
if (USE_OPENGL_LEGACY)
|
||||||
|
message(FATAL_ERROR "USE_OPENGL and USE_OPENGL_LEGACY are both ON but only one backend can be used at a time, turn one OFF and regenerate. (or delete cache and try again)")
|
||||||
|
endif()
|
||||||
|
else()
|
||||||
|
option(USE_OPENGL_LEGACY "Use legacy OpenGL for drawing" ON)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
|
||||||
set(CMAKE_C_STANDARD 99)
|
set(CMAKE_C_STANDARD 99)
|
||||||
set(GNU_COMPILERS GNU Clang AppleClang)
|
set(GNU_COMPILERS GNU Clang AppleClang)
|
||||||
if (CMAKE_C_COMPILER_ID IN_LIST GNU_COMPILERS)
|
if (CMAKE_C_COMPILER_ID IN_LIST GNU_COMPILERS)
|
||||||
@ -13,26 +22,11 @@ elseif (MSVC)
|
|||||||
endif()
|
endif()
|
||||||
|
|
||||||
find_package(SDL2 REQUIRED)
|
find_package(SDL2 REQUIRED)
|
||||||
if (USE_OPENGL)
|
if (USE_OPENGL OR USE_OPENGL_LEGACY)
|
||||||
if (NOT DEFINED OpenGL_GL_PREFERENCE)
|
if (NOT DEFINED OpenGL_GL_PREFERENCE)
|
||||||
set(OpenGL_GL_PREFERENCE "GLVND")
|
set(OpenGL_GL_PREFERENCE "GLVND")
|
||||||
endif()
|
endif()
|
||||||
find_package(OpenGL REQUIRED)
|
find_package(OpenGL REQUIRED)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
set(SOURCES
|
add_subdirectory(src)
|
||||||
src/maths.h
|
|
||||||
src/draw.h src/$<IF:$<BOOL:${USE_OPENGL}>,draw_opengl.c,draw.c>
|
|
||||||
src/stick.c src/stick.h
|
|
||||||
src/analogue.c)
|
|
||||||
|
|
||||||
add_executable(${TARGET} ${SOURCES})
|
|
||||||
target_link_libraries(${TARGET}
|
|
||||||
$<$<PLATFORM_ID:Windows>:SDL2::SDL2main>
|
|
||||||
SDL2::SDL2
|
|
||||||
$<$<BOOL:${USE_OPENGL}>:OpenGL::GL>
|
|
||||||
$<$<BOOL:${GNU}>:m>)
|
|
||||||
target_compile_options(${TARGET} PRIVATE
|
|
||||||
$<$<BOOL:${GNU}>:-Wall -Wextra -pedantic -Wno-unused-parameter>)
|
|
||||||
target_compile_definitions(${TARGET} PRIVATE
|
|
||||||
$<$<BOOL:${USE_OPENGL}>:USE_OPENGL>)
|
|
||||||
|
22
cmake/GL3WHelper.cmake
Normal file
22
cmake/GL3WHelper.cmake
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
find_package(Python REQUIRED COMPONENTS Interpreter)
|
||||||
|
|
||||||
|
function (add_gl3w _GL3W_TARGET)
|
||||||
|
find_file(GL3W_GEN_EXECUTABLE gl3w_gen.py PATHS ${CMAKE_SOURCE_DIR}/tools)
|
||||||
|
|
||||||
|
set(GL3W_ROOT ${CMAKE_CURRENT_BINARY_DIR}/gl3w)
|
||||||
|
set(GL3W_INCLUDE_DIR ${GL3W_ROOT}/include)
|
||||||
|
set(GL3W_SOURCES
|
||||||
|
${GL3W_INCLUDE_DIR}/GL/gl3w.h
|
||||||
|
${GL3W_INCLUDE_DIR}/GL/glcorearb.h
|
||||||
|
${GL3W_INCLUDE_DIR}/KHR/khrplatform.h
|
||||||
|
${GL3W_ROOT}/src/gl3w.c)
|
||||||
|
|
||||||
|
add_custom_command(
|
||||||
|
COMMAND Python::Interpreter
|
||||||
|
ARGS ${GL3W_GEN_EXECUTABLE} --root=${GL3W_ROOT}
|
||||||
|
DEPENDS Python::Interpreter ${GL3W_GEN_EXECUTABLE}
|
||||||
|
OUTPUT ${GL3W_SOURCES})
|
||||||
|
|
||||||
|
add_library(${_GL3W_TARGET} ${GL3W_SOURCES})
|
||||||
|
target_include_directories(${_GL3W_TARGET} PUBLIC ${GL3W_INCLUDE_DIR})
|
||||||
|
endfunction()
|
27
src/CMakeLists.txt
Normal file
27
src/CMakeLists.txt
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
set(SOURCES
|
||||||
|
maths.h
|
||||||
|
draw.h
|
||||||
|
draw_common.c
|
||||||
|
$<$<NOT:$<OR:$<BOOL:${USE_OPENGL}>,$<BOOL:${USE_OPENGL_LEGACY}>>>:draw.c>
|
||||||
|
$<$<BOOL:${USE_OPENGL}>:draw_opengl_core.c>
|
||||||
|
$<$<BOOL:${USE_OPENGL_LEGACY}>:draw_opengl.c>
|
||||||
|
stick.h
|
||||||
|
stick.c
|
||||||
|
analogue.c)
|
||||||
|
|
||||||
|
if (USE_OPENGL)
|
||||||
|
include(GL3WHelper)
|
||||||
|
add_gl3w(gl3w)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
add_executable(${TARGET} ${SOURCES})
|
||||||
|
target_link_libraries(${TARGET}
|
||||||
|
$<$<PLATFORM_ID:Windows>:SDL2::SDL2main>
|
||||||
|
SDL2::SDL2
|
||||||
|
$<$<OR:$<BOOL:${USE_OPENGL}>,$<BOOL:${USE_OPENGL_LEGACY}>>:OpenGL::GL>
|
||||||
|
$<$<BOOL:${USE_OPENGL}>:gl3w>
|
||||||
|
$<$<BOOL:${GNU}>:m>)
|
||||||
|
target_compile_options(${TARGET} PRIVATE
|
||||||
|
$<$<BOOL:${GNU}>:-Wall -Wextra -pedantic -Wno-unused-parameter>)
|
||||||
|
target_compile_definitions(${TARGET} PRIVATE
|
||||||
|
$<$<OR:$<BOOL:${USE_OPENGL}>,$<BOOL:${USE_OPENGL_LEGACY}>>:USE_OPENGL>)
|
11
src/draw.c
11
src/draw.c
@ -62,11 +62,6 @@ void DrawLine(int x1, int y1, int x2, int y2)
|
|||||||
SDL_RenderDrawLine(rend, x1, y1, x2, y2);
|
SDL_RenderDrawLine(rend, x1, y1, x2, y2);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawCircle(int x, int y, int r)
|
|
||||||
{
|
|
||||||
DrawCircleSteps(x, y, r, (int)(sqrt((double)r) * 8.0));
|
|
||||||
}
|
|
||||||
|
|
||||||
void DrawCircleSteps(int x, int y, int r, int steps)
|
void DrawCircleSteps(int x, int y, int r, int steps)
|
||||||
{
|
{
|
||||||
double stepsz = (double)TAU / steps;
|
double stepsz = (double)TAU / steps;
|
||||||
@ -87,12 +82,6 @@ void DrawCircleSteps(int x, int y, int r, int steps)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawArc(int x, int y, int r, int startAng, int endAng)
|
|
||||||
{
|
|
||||||
const int steps = (int)(sqrt((double)r) * (double)abs(endAng - startAng) / 360.0 * 8.0);
|
|
||||||
DrawArcSteps(x, y, r, startAng, endAng, steps);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DrawArcSteps(int x, int y, int r, int startAng, int endAng, int steps)
|
void DrawArcSteps(int x, int y, int r, int startAng, int endAng, int steps)
|
||||||
{
|
{
|
||||||
const double fstart = (double)startAng * DEG2RAD;
|
const double fstart = (double)startAng * DEG2RAD;
|
||||||
|
15
src/draw_common.c
Normal file
15
src/draw_common.c
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#include "draw.h"
|
||||||
|
#include "maths.h"
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
void DrawCircle(int x, int y, int r)
|
||||||
|
{
|
||||||
|
const int steps = (int)(sqrt((double)r) * 8.0);
|
||||||
|
DrawCircleSteps(x, y, r, steps);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawArc(int x, int y, int r, int startAng, int endAng)
|
||||||
|
{
|
||||||
|
const int steps = (int)(sqrt((double)r) * (double)abs(endAng - startAng) / 360.0 * 8.0);
|
||||||
|
DrawArcSteps(x, y, r, startAng, endAng, steps);
|
||||||
|
}
|
@ -150,11 +150,6 @@ void DrawLine(int x1, int y1, int x2, int y2)
|
|||||||
glEnd();
|
glEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawCircle(int x, int y, int r)
|
|
||||||
{
|
|
||||||
DrawCircleSteps(x, y, r, (int)(sqrt((double)r) * 8.0));
|
|
||||||
}
|
|
||||||
|
|
||||||
void DrawCircleSteps(int x, int y, int r, int steps)
|
void DrawCircleSteps(int x, int y, int r, int steps)
|
||||||
{
|
{
|
||||||
// Circles look better when offset negatively by half a pixel w/o MSAA
|
// Circles look better when offset negatively by half a pixel w/o MSAA
|
||||||
@ -178,12 +173,6 @@ void DrawCircleSteps(int x, int y, int r, int steps)
|
|||||||
glEnd();
|
glEnd();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawArc(int x, int y, int r, int startAng, int endAng)
|
|
||||||
{
|
|
||||||
const int steps = (int)(sqrt((double)r) * (double)abs(endAng - startAng) / 360.0 * 8.0);
|
|
||||||
DrawArcSteps(x, y, r, startAng, endAng, steps);
|
|
||||||
}
|
|
||||||
|
|
||||||
void DrawArcSteps(int x, int y, int r, int startAng, int endAng, int steps)
|
void DrawArcSteps(int x, int y, int r, int startAng, int endAng, int steps)
|
||||||
{
|
{
|
||||||
// Arcs look better when offset negatively by half a pixel w/o MSAA
|
// Arcs look better when offset negatively by half a pixel w/o MSAA
|
||||||
|
152
src/draw_opengl_core.c
Normal file
152
src/draw_opengl_core.c
Normal file
@ -0,0 +1,152 @@
|
|||||||
|
#include "draw.h"
|
||||||
|
#include "maths.h"
|
||||||
|
#include <GL/gl3w.h>
|
||||||
|
#include <SDL_video.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#define OPENGL_VERSION_MAJOR 3
|
||||||
|
#define OPENGL_VERSION_MINOR 3
|
||||||
|
|
||||||
|
static SDL_GLContext* ctx = NULL;
|
||||||
|
static SDL_Window* window = NULL;
|
||||||
|
static uint32_t colour = 0x00000000;
|
||||||
|
static uint32_t clrColour = 0x00000000;
|
||||||
|
static bool antialias = false;
|
||||||
|
|
||||||
|
#pragma clang diagnostic push
|
||||||
|
#pragma clang diagnostic ignored "-Wunused-function"
|
||||||
|
static void GlErrorCb(
|
||||||
|
GLenum source,
|
||||||
|
GLenum type,
|
||||||
|
GLuint id,
|
||||||
|
GLenum severity,
|
||||||
|
GLsizei length,
|
||||||
|
const GLchar* message,
|
||||||
|
const GLvoid* userParam)
|
||||||
|
{
|
||||||
|
if (severity != GL_DEBUG_SEVERITY_NOTIFICATION)
|
||||||
|
printf("%s\n", message);
|
||||||
|
}
|
||||||
|
#pragma clang diagnostic pop
|
||||||
|
|
||||||
|
|
||||||
|
void DrawWindowHints(void)
|
||||||
|
{
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); // Enable MSAA
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 8); // 8x MSAA
|
||||||
|
|
||||||
|
// Legacy OpenGL profile
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, OPENGL_VERSION_MAJOR);
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, OPENGL_VERSION_MINOR);
|
||||||
|
SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_CORE);
|
||||||
|
}
|
||||||
|
|
||||||
|
int InitDraw(SDL_Window* _window)
|
||||||
|
{
|
||||||
|
window = _window;
|
||||||
|
ctx = SDL_GL_CreateContext(window);
|
||||||
|
if (ctx == NULL || window == NULL || SDL_GL_MakeCurrent(window, ctx))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "%s\n", SDL_GetError());
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load Core profile extensions
|
||||||
|
if (gl3wInit() != GL3W_OK)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Failed to init Core profile\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if (!gl3wIsSupported(OPENGL_VERSION_MAJOR, OPENGL_VERSION_MINOR))
|
||||||
|
{
|
||||||
|
fprintf(stderr, "OpenGL %d.%d unsupported\n", 3, 3);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set debug callback
|
||||||
|
#if !defined NDEBUG && !defined __APPLE__
|
||||||
|
glDebugMessageCallback(GlErrorCb, nullptr);
|
||||||
|
glEnable(GL_DEBUG_OUTPUT);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
SDL_GL_SetSwapInterval(1); // Enable vsync
|
||||||
|
|
||||||
|
// Detect if MSAA is available & active
|
||||||
|
int res;
|
||||||
|
if (SDL_GL_GetAttribute(SDL_GL_MULTISAMPLEBUFFERS, &res) == 0 && res == 1)
|
||||||
|
if (SDL_GL_GetAttribute(SDL_GL_MULTISAMPLESAMPLES, &res) == 0 && res > 0)
|
||||||
|
antialias = true;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void QuitDraw(void)
|
||||||
|
{
|
||||||
|
SDL_GL_MakeCurrent(window, NULL);
|
||||||
|
SDL_GL_DeleteContext(ctx);
|
||||||
|
ctx = NULL;
|
||||||
|
window = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
size GetDrawSizeInPixels(void)
|
||||||
|
{
|
||||||
|
size out;
|
||||||
|
SDL_GL_GetDrawableSize(SDL_GL_GetCurrentWindow(), &out.w, &out.h);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SetDrawViewport(size size)
|
||||||
|
{
|
||||||
|
glViewport(0, 0, size.w, size.h);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void SetDrawColour(uint32_t c)
|
||||||
|
{
|
||||||
|
colour = c;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawClear(void)
|
||||||
|
{
|
||||||
|
if (clrColour != colour)
|
||||||
|
{
|
||||||
|
const float mul = 1.0f / 255.0f;
|
||||||
|
glClearColor(
|
||||||
|
(GLclampf)((colour & 0xFF000000) >> 24) * mul,
|
||||||
|
(GLclampf)((colour & 0x00FF0000) >> 16) * mul,
|
||||||
|
(GLclampf)((colour & 0x0000FF00) >> 8) * mul,
|
||||||
|
(GLclampf)((colour & 0x000000FF)) * mul);
|
||||||
|
clrColour = colour;
|
||||||
|
}
|
||||||
|
glClear(GL_COLOR_BUFFER_BIT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawPoint(int x, int y)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawRect(int x, int y, int w, int h)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawLine(int x1, int y1, int x2, int y2)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
void DrawCircleSteps(int x, int y, int r, int steps)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawArcSteps(int x, int y, int r, int startAng, int endAng, int steps)
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawPresent(void)
|
||||||
|
{
|
||||||
|
SDL_GL_SwapWindow(window);
|
||||||
|
}
|
430
tools/gl3w_gen.py
Normal file
430
tools/gl3w_gen.py
Normal file
@ -0,0 +1,430 @@
|
|||||||
|
#!/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 argparse
|
||||||
|
import os
|
||||||
|
import re
|
||||||
|
|
||||||
|
# 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 = r'''/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
'''
|
||||||
|
|
||||||
|
EXT_SUFFIX = ['ARB', 'EXT', 'KHR', 'OVR', 'NV', 'AMD', 'INTEL']
|
||||||
|
|
||||||
|
def is_ext(proc):
|
||||||
|
return any(proc.endswith(suffix) for suffix in EXT_SUFFIX)
|
||||||
|
|
||||||
|
def write(f, s):
|
||||||
|
f.write(s.encode('utf-8'))
|
||||||
|
|
||||||
|
def touch_dir(path):
|
||||||
|
if not os.path.exists(path):
|
||||||
|
os.makedirs(path)
|
||||||
|
|
||||||
|
def download(url, dst):
|
||||||
|
if os.path.exists(dst):
|
||||||
|
print('Reusing {0}...'.format(dst))
|
||||||
|
return
|
||||||
|
|
||||||
|
print('Downloading {0}...'.format(dst))
|
||||||
|
web = urllib2.urlopen(urllib2.Request(url, headers={'User-Agent': 'Mozilla/5.0'}))
|
||||||
|
with open(dst, 'wb') as f:
|
||||||
|
f.writelines(web.readlines())
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description='gl3w generator script')
|
||||||
|
parser.add_argument('--ext', action='store_true', help='Load extensions')
|
||||||
|
parser.add_argument('--root', type=str, default='', help='Root directory')
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
# Create directories
|
||||||
|
touch_dir(os.path.join(args.root, 'include/GL'))
|
||||||
|
touch_dir(os.path.join(args.root, 'include/KHR'))
|
||||||
|
touch_dir(os.path.join(args.root, 'src'))
|
||||||
|
|
||||||
|
# Download glcorearb.h and khrplatform.h
|
||||||
|
download('https://www.khronos.org/registry/OpenGL/api/GL/glcorearb.h',
|
||||||
|
os.path.join(args.root, 'include/GL/glcorearb.h'))
|
||||||
|
download('https://www.khronos.org/registry/EGL/api/KHR/khrplatform.h',
|
||||||
|
os.path.join(args.root, 'include/KHR/khrplatform.h'))
|
||||||
|
|
||||||
|
# Parse function names from glcorearb.h
|
||||||
|
print('Parsing glcorearb.h header...')
|
||||||
|
procs = []
|
||||||
|
p = re.compile(r'GLAPI.*APIENTRY\s+(\w+)')
|
||||||
|
with open(os.path.join(args.root, 'include/GL/glcorearb.h'), 'r') as f:
|
||||||
|
for line in f:
|
||||||
|
m = p.match(line)
|
||||||
|
if not m:
|
||||||
|
continue
|
||||||
|
proc = m.group(1)
|
||||||
|
if args.ext or not is_ext(proc):
|
||||||
|
procs.append(proc)
|
||||||
|
procs.sort()
|
||||||
|
|
||||||
|
# Generate gl3w.h
|
||||||
|
print('Generating {0}...'.format(os.path.join(args.root, 'include/GL/gl3w.h')))
|
||||||
|
with open(os.path.join(args.root, 'include/GL/gl3w.h'), 'wb') as f:
|
||||||
|
write(f, UNLICENSE)
|
||||||
|
write(f, r'''#ifndef __gl3w_h_
|
||||||
|
#define __gl3w_h_
|
||||||
|
|
||||||
|
#include <GL/glcorearb.h>
|
||||||
|
|
||||||
|
#ifndef GL3W_API
|
||||||
|
#define GL3W_API
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifndef __gl_h_
|
||||||
|
#define __gl_h_
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define GL3W_OK 0
|
||||||
|
#define GL3W_ERROR_INIT -1
|
||||||
|
#define GL3W_ERROR_LIBRARY_OPEN -2
|
||||||
|
#define GL3W_ERROR_OPENGL_VERSION -3
|
||||||
|
|
||||||
|
typedef void (*GL3WglProc)(void);
|
||||||
|
typedef GL3WglProc (*GL3WGetProcAddressProc)(const char *proc);
|
||||||
|
|
||||||
|
/* gl3w api */
|
||||||
|
GL3W_API int gl3wInit(void);
|
||||||
|
GL3W_API int gl3wInit2(GL3WGetProcAddressProc proc);
|
||||||
|
GL3W_API int gl3wIsSupported(int major, int minor);
|
||||||
|
GL3W_API GL3WglProc gl3wGetProcAddress(const char *proc);
|
||||||
|
|
||||||
|
/* gl3w internal state */
|
||||||
|
''')
|
||||||
|
write(f, 'union GL3WProcs {\n')
|
||||||
|
write(f, '\tGL3WglProc ptr[{0}];\n'.format(len(procs)))
|
||||||
|
write(f, '\tstruct {\n')
|
||||||
|
for proc in procs:
|
||||||
|
write(f, '\t\t{0: <55} {1};\n'.format('PFN{0}PROC'.format(proc.upper()), proc[2:]))
|
||||||
|
write(f, r''' } gl;
|
||||||
|
};
|
||||||
|
|
||||||
|
GL3W_API extern union GL3WProcs gl3wProcs;
|
||||||
|
|
||||||
|
/* OpenGL functions */
|
||||||
|
''')
|
||||||
|
for proc in procs:
|
||||||
|
write(f, '#define {0: <48} gl3wProcs.gl.{1}\n'.format(proc, proc[2:]))
|
||||||
|
write(f, r'''
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
''')
|
||||||
|
|
||||||
|
# Generate gl3w.c
|
||||||
|
print('Generating {0}...'.format(os.path.join(args.root, 'src/gl3w.c')))
|
||||||
|
with open(os.path.join(args.root, 'src/gl3w.c'), 'wb') as f:
|
||||||
|
write(f, UNLICENSE)
|
||||||
|
write(f, r'''#include <GL/gl3w.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
|
||||||
|
|
||||||
|
#if defined(_WIN32)
|
||||||
|
#ifndef WIN32_LEAN_AND_MEAN
|
||||||
|
#define WIN32_LEAN_AND_MEAN 1
|
||||||
|
#endif
|
||||||
|
#include <windows.h>
|
||||||
|
|
||||||
|
static HMODULE libgl;
|
||||||
|
typedef PROC(__stdcall* GL3WglGetProcAddr)(LPCSTR);
|
||||||
|
static GL3WglGetProcAddr wgl_get_proc_address;
|
||||||
|
|
||||||
|
static int open_libgl(void)
|
||||||
|
{
|
||||||
|
libgl = LoadLibraryA("opengl32.dll");
|
||||||
|
if (!libgl)
|
||||||
|
return GL3W_ERROR_LIBRARY_OPEN;
|
||||||
|
|
||||||
|
wgl_get_proc_address = (GL3WglGetProcAddr)GetProcAddress(libgl, "wglGetProcAddress");
|
||||||
|
return GL3W_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void close_libgl(void)
|
||||||
|
{
|
||||||
|
FreeLibrary(libgl);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GL3WglProc get_proc(const char *proc)
|
||||||
|
{
|
||||||
|
GL3WglProc res;
|
||||||
|
|
||||||
|
res = (GL3WglProc)wgl_get_proc_address(proc);
|
||||||
|
if (!res)
|
||||||
|
res = (GL3WglProc)GetProcAddress(libgl, proc);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
#elif defined(__APPLE__)
|
||||||
|
#include <dlfcn.h>
|
||||||
|
|
||||||
|
static void *libgl;
|
||||||
|
|
||||||
|
static int open_libgl(void)
|
||||||
|
{
|
||||||
|
libgl = dlopen("/System/Library/Frameworks/OpenGL.framework/OpenGL", RTLD_LAZY | RTLD_LOCAL);
|
||||||
|
if (!libgl)
|
||||||
|
return GL3W_ERROR_LIBRARY_OPEN;
|
||||||
|
|
||||||
|
return GL3W_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void close_libgl(void)
|
||||||
|
{
|
||||||
|
dlclose(libgl);
|
||||||
|
}
|
||||||
|
|
||||||
|
static GL3WglProc get_proc(const char *proc)
|
||||||
|
{
|
||||||
|
GL3WglProc res;
|
||||||
|
|
||||||
|
*(void **)(&res) = dlsym(libgl, proc);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
#include <dlfcn.h>
|
||||||
|
|
||||||
|
static void *libgl; /* OpenGL library */
|
||||||
|
static void *libglx; /* GLX library */
|
||||||
|
static void *libegl; /* EGL library */
|
||||||
|
static GL3WGetProcAddressProc gl_get_proc_address;
|
||||||
|
|
||||||
|
static void close_libgl(void)
|
||||||
|
{
|
||||||
|
if (libgl) {
|
||||||
|
dlclose(libgl);
|
||||||
|
libgl = NULL;
|
||||||
|
}
|
||||||
|
if (libegl) {
|
||||||
|
dlclose(libegl);
|
||||||
|
libegl = NULL;
|
||||||
|
}
|
||||||
|
if (libglx) {
|
||||||
|
dlclose(libglx);
|
||||||
|
libglx = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int is_library_loaded(const char *name, void **lib)
|
||||||
|
{
|
||||||
|
*lib = dlopen(name, RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD);
|
||||||
|
return *lib != NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int open_libs(void)
|
||||||
|
{
|
||||||
|
/* On Linux we have two APIs to get process addresses: EGL and GLX.
|
||||||
|
* EGL is supported under both X11 and Wayland, whereas GLX is X11-specific.
|
||||||
|
* First check what's already loaded, the windowing library might have
|
||||||
|
* already loaded either EGL or GLX and we want to use the same one.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (is_library_loaded("libEGL.so.1", &libegl) ||
|
||||||
|
is_library_loaded("libGLX.so.0", &libglx)) {
|
||||||
|
libgl = dlopen("libOpenGL.so.0", RTLD_LAZY | RTLD_LOCAL);
|
||||||
|
if (libgl)
|
||||||
|
return GL3W_OK;
|
||||||
|
else
|
||||||
|
close_libgl();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (is_library_loaded("libGL.so.1", &libgl))
|
||||||
|
return GL3W_OK;
|
||||||
|
|
||||||
|
/* Neither is already loaded, so we have to load one. Try EGL first
|
||||||
|
* because it is supported under both X11 and Wayland.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* Load OpenGL + EGL */
|
||||||
|
libgl = dlopen("libOpenGL.so.0", RTLD_LAZY | RTLD_LOCAL);
|
||||||
|
libegl = dlopen("libEGL.so.1", RTLD_LAZY | RTLD_LOCAL);
|
||||||
|
if (libgl && libegl)
|
||||||
|
return GL3W_OK;
|
||||||
|
|
||||||
|
/* Fall back to legacy libGL, which includes GLX */
|
||||||
|
close_libgl();
|
||||||
|
libgl = dlopen("libGL.so.1", RTLD_LAZY | RTLD_LOCAL);
|
||||||
|
if (libgl)
|
||||||
|
return GL3W_OK;
|
||||||
|
|
||||||
|
return GL3W_ERROR_LIBRARY_OPEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int open_libgl(void)
|
||||||
|
{
|
||||||
|
int res = open_libs();
|
||||||
|
if (res)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
if (libegl)
|
||||||
|
*(void **)(&gl_get_proc_address) = dlsym(libegl, "eglGetProcAddress");
|
||||||
|
else if (libglx)
|
||||||
|
*(void **)(&gl_get_proc_address) = dlsym(libglx, "glXGetProcAddressARB");
|
||||||
|
else
|
||||||
|
*(void **)(&gl_get_proc_address) = dlsym(libgl, "glXGetProcAddressARB");
|
||||||
|
|
||||||
|
if (!gl_get_proc_address) {
|
||||||
|
close_libgl();
|
||||||
|
return GL3W_ERROR_LIBRARY_OPEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GL3W_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GL3WglProc get_proc(const char *proc)
|
||||||
|
{
|
||||||
|
GL3WglProc res = NULL;
|
||||||
|
|
||||||
|
/* Before EGL version 1.5, eglGetProcAddress doesn't support querying core
|
||||||
|
* functions and may return a dummy function if we try, so try to load the
|
||||||
|
* function from the GL library directly first.
|
||||||
|
*/
|
||||||
|
if (libegl)
|
||||||
|
*(void **)(&res) = dlsym(libgl, proc);
|
||||||
|
|
||||||
|
if (!res)
|
||||||
|
res = gl_get_proc_address(proc);
|
||||||
|
|
||||||
|
if (!libegl && !res)
|
||||||
|
*(void **)(&res) = dlsym(libgl, proc);
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static struct {
|
||||||
|
int major, minor;
|
||||||
|
} version;
|
||||||
|
|
||||||
|
static int parse_version(void)
|
||||||
|
{
|
||||||
|
if (!glGetIntegerv)
|
||||||
|
return GL3W_ERROR_INIT;
|
||||||
|
|
||||||
|
glGetIntegerv(GL_MAJOR_VERSION, &version.major);
|
||||||
|
glGetIntegerv(GL_MINOR_VERSION, &version.minor);
|
||||||
|
|
||||||
|
if (version.major < 3)
|
||||||
|
return GL3W_ERROR_OPENGL_VERSION;
|
||||||
|
return GL3W_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void load_procs(GL3WGetProcAddressProc proc);
|
||||||
|
|
||||||
|
int gl3wInit(void)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
|
||||||
|
res = open_libgl();
|
||||||
|
if (res)
|
||||||
|
return res;
|
||||||
|
|
||||||
|
atexit(close_libgl);
|
||||||
|
return gl3wInit2(get_proc);
|
||||||
|
}
|
||||||
|
|
||||||
|
int gl3wInit2(GL3WGetProcAddressProc proc)
|
||||||
|
{
|
||||||
|
load_procs(proc);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const char *proc_names[] = {
|
||||||
|
''')
|
||||||
|
for proc in procs:
|
||||||
|
write(f, '\t"{0}",\n'.format(proc))
|
||||||
|
write(f, r'''};
|
||||||
|
|
||||||
|
GL3W_API union GL3WProcs gl3wProcs;
|
||||||
|
|
||||||
|
static void load_procs(GL3WGetProcAddressProc proc)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < ARRAY_SIZE(proc_names); i++)
|
||||||
|
gl3wProcs.ptr[i] = proc(proc_names[i]);
|
||||||
|
}
|
||||||
|
''')
|
Reference in New Issue
Block a user